I have this program:
static int aux() {
return 1;
}
int _start(){
int a = aux();
return a;
}
When I compile it using GCC with flags -nostdlib -m32 -fpie
and generate an ELF binary, I get the following assembly code:
00001000 <aux>:
1000: f3 0f 1e fb endbr32
1004: 55 push %ebp
1005: 89 e5 mov %esp,%ebp
1007: e8 2d 00 00 00 call 1039 <__x86.get_pc_thunk.ax>
100c: 05 e8 2f 00 00 add $0x2fe8,%eax
1011: b8 01 00 00 00 mov $0x1,%eax
1016: 5d pop %ebp
1017: c3 ret
00001018 <_start>:
1018: f3 0f 1e fb endbr32
101c: 55 push %ebp
101d: 89 e5 mov %esp,%ebp
101f: 83 ec 10 sub $0x10,%esp
1022: e8 12 00 00 00 call 1039 <__x86.get_pc_thunk.ax>
1027: 05 cd 2f 00 00 add $0x2fcd,%eax
102c: e8 cf ff ff ff call 1000 <aux>
1031: 89 45 fc mov %eax,-0x4(%ebp)
1034: 8b 45 fc mov -0x4(%ebp),%eax
1037: c9 leave
1038: c3 ret
00001039 <__x86.get_pc_thunk.ax>:
1039: 8b 04 24 mov (%esp),%eax
103c: c3 ret
I know that the get_pc_thunk
function is used to implement position-independent code in x86, but in this case I can't understand why it is being used. My questions are:
- The function is returning the address of the next instruction in the
eax
register and, in both usages, anadd
instruction is being used to makeeax
point to the GOT. Normally, (at least when accessing global variables), thiseax
register would be immediately used to access a global variable in the table. In this case, however, theeax
is being completely ignored. What is going on? - I also don't understand why the
get_pc_thunk
is even present in the code, since bothcall
instructions are using relative addresses. Since the addresses are relative, shouldn't they already be position-independent out of the box?
Thanks!