I'm looking for a gcc
command-line flag or other settings to produce GOTOFF
relocations rather than GOT
relocations for my statically linked, position-independent i386 executable. More details on what I was trying below.
My source file g1.s
looks like this:
extern int answer;
int get_answer1() { return answer; }
My other source file g2.s
looks like this:
extern int answer;
int get_answer2() { return answer; }
I compile them with gcc -m32 -fPIE -Os -static -S -ffreestanding -fomit-frame-pointer -fno-unwind-tables -fno-asynchronous-unwind-tables g1.c
for i386.
I get the following assembly output:
.file "g1.c"
.text
.globl get_answer1
.type get_answer1, @function
get_answer1:
call __x86.get_pc_thunk.cx
addl $_GLOBAL_OFFSET_TABLE_, %ecx
movl answer@GOT(%ecx), %eax
movl (%eax), %eax
ret
.size get_answer1, .-get_answer1
.section .text.__x86.get_pc_thunk.cx,"axG",@progbits,__x86.get_pc_thunk.cx,comdat
.globl __x86.get_pc_thunk.cx
.hidden __x86.get_pc_thunk.cx
.type __x86.get_pc_thunk.cx, @function
__x86.get_pc_thunk.cx:
movl (%esp), %ecx
ret
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",@progbits
Here is how to reproduce this behavior online with GCC 7.2: https://godbolt.org/g/XXkxJh
Instead of GOT
above, I'd like to get GOTOFF
, and the movl %(eax), %eax
should disappear, so the assembly code for the function should look like this:
get_answer1:
call __x86.get_pc_thunk.cx
addl $_GLOBAL_OFFSET_TABLE_, %ecx
movl answer@GOTOFF(%ecx), %eax
ret
I have verified that this GOTOFF
assembly version is what works, and the GOT
version doesn't work (because it has an extra pointer indirection).
How can I convince gcc
to generate the GOTOFF
version? I've tried various combinations of -fPIC
, -fpic
, -fPIE
, -fpie
, -pie
, -fno-plt
. None of them worked, all of them made gcc
produce the GOT
version.
I couldn't find any i386-specific flag on https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html or any generic flag here: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
In fact, I'm getting GOTOFF
relocations for "..."
string literals, and I also want to get them for extern
variables.
The final output is a statically linked executable in a custom binary format (for which I've written a GNU ld linker script). There is no dynamic linking and no shared libraries. The address randomization is performed by a custom loader, which is free to load the executable to any address. So I do need position-independent code. There is no per-segment memory mapping: the entire executable is loaded as is, contiguously.
All the documentation I've been able to find online talk about position-independent executables which are dynamically linked, and I wasn't able to find anything useful there.