"Relocation R_X86_64_32S Against " Linking Error

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 setting eax appropriately.
  • enter and leave 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



Leave a reply



Submit