relocation R_X86_64_32S against linking Error
Assuming you are generating a shared library, most probably what happens is that the variant of liblog4cplus.a
you are using wasn't compiled with -fPIC
. In linux, you can confirm this by extracting the object files from the static library and checking their relocations:
ar -x liblog4cplus.a
readelf --relocs fileappender.o | egrep '(GOT|PLT|JU?MP_SLOT)'
If the output is empty, then the static library is not position-independent and cannot be used to generate a shared object.
Since the static library contains object code which was already compiled, providing the -fPIC flag won't help.
You need to get ahold of a version of liblog4cplus.a
compiled with -fPIC
and use that one instead.
Compilation fails with relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object
Do what the compiler tells you to do, i.e. recompile with -fPIC
. To learn what does this flag do and why you need it in this case, see Code Generation Options of the GCC manual.
In brief, the term position independent code (PIC) refers to the generated machine code which is memory address agnostic, i.e. does not make any assumptions about where it was loaded into RAM. Only position independent code is supposed to be included into shared objects (SO) as they should have an ability to dynamically change their location in RAM.
Finally, you can read about it on Wikipedia too.
Linker error: relocation R_X86_64_PC32 against symbol `xmlFree' ... recompile with -fPIC but offending library was already compiled with -fPIC
You haven't misunderstood the error message, or at least not significantly.
However, according to this question, /usr/local/lib/lxml2.a was already compiled fPIC
You conclude this because the command:
/usr/local/lib$ readelf -d libxml2.a | grep TEXT
outputs nothing, which shows that you chose the second most popular answer to
that question, although at this writing it is not nearly as up-voted as the most popular answer
I guess you did that because the most popular answer tells you how to test an object file for
PIC-ness, and you want to a test a library, as the second most popular answer does. Or
perhaps because you tried the most popular answer first and it indicated that your libxml2.a
was PIC.
But the second most popular answer tests a shared library, and you use it to test
the object files in a static library. A shared library is very different from
an object file, or a static library of such, and the question to which this answer was given asks how to test
the PIC-ness of an object file. So this answer does not answer the question: really
it suggests how to test whether a file that has a name like a shared library actually is
a shared library.
The most popular answer does answer the question, and if was a correct answer then
it would be the right one for you too, because what the linker has diagnosed:
/usr/local/lib/libxml2.a(uri.o): relocation R_X86_64_PC32 against symbol `xmlFree' \
can not be used when making a shared object; recompile with -fPIC
is that the object file uri.o
archived in libxml2.a
is not PIC.
But the most popular answer, notwithstanding its popularity, is invalid.
The PIC-ness test that it proposes - with no supporting argument - can
misidentify non-PIC object files as PIC (as perhaps you observed).
None of the answers to that question
is a correct answer for you, and it doesn't really matter why. The system linker itself
is the ultimate authority on whether an object file is or is not position-independent.
Any one-liner test other than attempting to link the object file into a DSO is just an attempt
to second-guess the linker: if its verdict differs from
the linker's it implies that the test is broken, not the linker.
And you already know the linker's verdict. It has tried to link libxml2.a(uri.o)
into a DSO and found that it can't, because the it contains a non-position-independent
relocation record.
The /usr/local/lib/libxml2.a
you've got was built on the traditional
default assumption that the object files archived therein need not be compiled to
position-independent code (with -fPIC
) because the static library would only
be input to the linkage of non-position-independent executables. If you want to
link some PI binary, then you'll link it with the shared libary libxml2.so
,
which is PI by definition. Your libxml2.a
was furthermore built with a compiler
that does not emit PI object code by default. It is possible that your current
compiler still has that increasingly antiquated trait, but you don't need to find
out.
You need to replace your local libxml2
install with one in which the object
files in libxml2
have been compiled with fPIC
. If you already know how to do that you can skip the rest of this and get on with it.
If you have somewhere got the source package of libxml2
that was built
and installed and you want to stick with that revision, then cd
into its root directory and run:
make uninstall
Otherwise, remove the installation by deleting, as root, all files and symlinks matching/usr/local/lib/libxml2
and the directory /usr/local/include/libxml2
If you want to stick with a source package you've already got (where you ran make uninstall
),
then, in its root directory, run:
make distclean
to restore to its pristine state.
If you don't have a source package you want to stick with, then clone or download-and-extract the latest from https://gitlab.gnome.org/GNOME/libxml2/
,
then cd
into the root directory and run:
./autogen.sh
to generate the build-system.
Whatever you've done thus far, in the package root directory then run:
./configure CFLAGS=-fPIC [any other non-default configuration options]
If that completes successfully, then run:
make
If that completes successfully, then as root run:
make install
If that completes successfully, then /usr/local/lib/libxml2.a
will
be recreated containing PI object files and you will be able to link your
shared library against it.
If you are unsure about [any other non-default configuration options]
for
the ./configure
command, then run:
./configure -h
beforehand for help, and/or seek advice.
GCC promotes weird relocation R_X86_64_32S error but not in manually linking
The immediate move instruction movq $S, %rsi
, despite taking a 64-bit register, takes only a 32-bit signed immediate. When building a position-independent executable which is to run with ASLR, as is the default on most Linux systems, your program is typically not located in the low or high 31 bits of virtual memory, so the address of a global or static object like S
won't fit in a signed 32-bit immediate.
One fix is to use movabs
instead, which does take a full 64-bit immediate. Replacing movq %0, %%rsi
with movabs %0, %%rsi
lets the code build. However, the better approach is to use RIP-relative addressing lea S(%rip), %rsi
, which is a shorter instruction and avoids the need for a relocation at load time. This is a little awkward to do inside inline asm, so you can let the compiler load the address into the register for you, with an input operand like "S" (S)
(confusingly the constraint for the rsi
register is S
, which happens to coincide with the name you chose for your array variable).
When you linked manually, you built a non-position-independent executable, which meant that treating the address as a constant worked. You can get the same effect by passing -no-pie
to gcc
.
There is another serious problem with your code, in that it doesn't declare the registers it clobbers - not only those which you explicitly mov
into, but also rcx
and r11
which syscall
modifies implicitly. You should take a look at How to invoke a system call via syscall or sysenter in inline assembly? which has a correct example. It would be wise to study those examples carefully - GCC inline asm is powerful, but also very easy to get wrong in subtle ways that the compiler will not help you detect, and which may appear to work in a simple program but fail unpredictably in a more complex one.
relocation R_X86_64_32S against symbol `stdout@@GLIBC_2.2.5' can not be used when making a PIE object
Let me show you how to fix up the assembly language from your book so it works with your compiler's default settings.
As the comments on the question say, the problem is that your compiler defaults to generating position-independent executables. This means the addresses of stdout
, fprintf
, and output
are not known at link time, so the linker is unable to "relocate" the instructions that refer to them.
What is known at link time, however, is the offsets between the addresses of these things and the program counter. That means, if you just write the assembly a little differently, it will work. Like this:
.globl main
.section .data
output:
.ascii "Yeet\n\0"
.section .text
main:
enter $0, $0
movq stdout(%rip), %rdi
leaq output(%rip), %rsi
call fprintf@PLT
movq $0, %rax
leave
ret
Notice that the change is a little different for all three. mov stdout, %rdi
becomes mov stdout(%rip), %rdi
-- just a different addressing mode for the same instruction. Loading from memory at the fixed address stdout
becomes loading from memory at the fixed displacement stdout
from the RIP register (aka the program counter). Loading the fixed address output
with mov $output, %rsi
, on the other hand, becomes lea output(%rip), %rsi
. I would suggest you think of this one as always having been a load-effective-address operation, but the old code, with the executable at a fixed address, was able to express that operation with move-immediate instead of an actual lea instruction. Finally, call fprintf
becomes call fprintf@PLT
. This is telling the linker that the call needs to go through the procedure linkage table -- your book should explain what this is and why it's needed.
Incidentally, I see several other problems with this assembly language, of which the most important are:
- The string
"Yeet\n\0"
belongs in the read-only data section. - The x86-64 ABI says that variadic functions like
fprintf
need to be told the number of floating point arguments they are receiving, by settingeax
appropriately. enter
andleave
are unnecessary on x86-64. (Also,enter
is a painfully slow microcoded instruction that shouldn't be used at all.)
I would have written something like this instead:
.section .rodata, "a", @progbits
.output:
.string "Yeet\n"
.section .text, "ax", @progbits
.globl main
.type main, @function
main:
sub $8, %rsp
mov stdout(%rip), %rdi
lea .output(%rip), %rsi
xor %eax, %eax
call fprintf@PLT
xor %eax, %eax
add $8, %rsp
ret
(You need to subtract 8 from %rsp
at the beginning of the function, and add it back afterward, because the ABI says that %rsp
must always be a multiple of 16 at the point of a call
instruction -- which means that it's not a multiple of 16 on entry to any function, but instead %rsp
mod 16 is 8, because call
pushes eight bytes (the return address). You were getting this for free as a side effect of the enter
and leave
, but take those out and you have to do it by hand.)
error: lib.a: relocation R_X86_64_PC32 against symbol `...' can not be used when making a shared object; recompile with -fPIC
The error cause might be this. It got resolved by:
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
As suggested here.
Related Topics
Know If .Lib Is Static or Import
How to Read-Write Into/From Text File with Comma Separated Values
What's the Behavior of an Uninitialized Variable Used as Its Own Initializer
Calling a Function for Each Variadic Template Argument and an Array
How Does Modulus and Rand() Work
Error Lnk1104: Cannot Open File 'Debug\Myprojectlib.Lib'
How to Get the Size of a Memory Block Allocated Using Malloc()
How to Store Objects of Differing Types in a C++ Container
Implementing a No-Op Std::Ostream
C++ Compiler Error C2280 "Attempting to Reference a Deleted Function" in Visual Studio 2013 and 2015
Create a Function to Check for Key Press in Unix Using Ncurses
How to Declare a Member Vector of the Same Class
When and How to Use Exception Handling