This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

x86-64 push / jmp / mov of undefined label results in bad relocation for position-independent code


Dear all,

I am having the following problem with gnu assembler:

When compiling an x86-64 assembly file which contains a `push`, `jmp`
or `mov` instruction having an undefined label as an operand, `as`
generates a relocation of type `R_X86_64_32S`, which is only 32bit
long, i.e., it is too short for position-independent code (since such
code might be loaded onto a position outside the 32-bit address
space).

Unsurprisingly, if I try to link such a code as a shared library, `ld`
will complain:

ld: tmp.o: relocation R_X86_64_32S against undefined symbol `mylabel'
can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output


Below this email I pasted a minimal example for you to verify this for
yourself, with the corresponding `objdump` and `ld` output.

I am doing a programming project that instruments gcc-compiled code,
and one of the things the instrumented code does is to jump to a label
belonging to the instrumentation code (for management purposes;
registers are saved etc, and the instrumented code will be resumed
later).

I would like to ask two things:

1. Is there a workaround that enforces the right type of relocation?
Maybe there is some command-line option or directive or whatever that
will do the trick?

2. Otherwise, what would be the right way of fixing this? Should a new
command-line option be used? Should I add a new i386 instruction
prefix  (along the lines of addr32/addr16 etc)?

I would be leaning on the latter. I have never touched the gnu `as`
code, so some pointers on what code/manual/article to read first would
be most welcome.


Thank you for all your work,
Bruno Loff



Here are the contents of tmp.s

.text
.globl main
.extern mylabel // makes no difference (which is according to docs)
.type main, @function
main:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6

// Actual program starts here
movq mylabel, %rax
pushq mylabel
popq %rax
jmpq *mylabel

// Actual program ends here
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc


After doing `as tmp.s -o tmp.o`, and then `objdump -drz tmp.o`, we see:

tmp.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0: 55                   push   %rbp
   1: 48 89 e5             mov    %rsp,%rbp
   4: 48 8b 04 25 00 00 00 mov    0x0,%rax
   b: 00
8: R_X86_64_32S mylabel
   c: ff 34 25 00 00 00 00 pushq  0x0
f: R_X86_64_32S mylabel
  13: 58                   pop    %rax
  14: ff 24 25 00 00 00 00 jmpq   *0x0
17: R_X86_64_32S mylabel
  1b: 90                   nop
  1c: 5d                   pop    %rbp
  1d: c3                   retq


As you may see above, the relocation type is too short (only 32 bits
are reserved for the address, but the label could in principle be
pointing outside the 32-bit address space). Then doing `ld -shared
tmp2.o` results in the following error message:

ld: tmp.o: relocation R_X86_64_32S against undefined symbol `mylabel'
can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]