I am learning about linking and found a small question that I could not understand.
Consider the following files:
main.c
#include "other.h"
extern int i;
int main() {
++i;
inci();
return 0;
}
other.c
int i = 0;
void inci() {
++i;
}
Then I compile these two files:
gcc -c main.c
gcc -shared -fpic other.c -o libother.so
gcc -o main main.o ./libother.so
Here is part of the dissasemble of main.o
:
f: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 15 <main+0x15>
15: 83 c0 01 add $0x1,%eax
18: 89 05 00 00 00 00 mov %eax,0x0(%rip) # 1e <main+0x1e>
1e: b8 00 00 00 00 mov $0x0,%eax
23: e8 00 00 00 00 call 28 <main+0x28>
Here is part of the disassemble of main
:
1148: 8b 05 ca 2e 00 00 mov 0x2eca(%rip),%eax # 4018 <i@@Base>
114e: 83 c0 01 add $0x1,%eax
1151: 89 05 c1 2e 00 00 mov %eax,0x2ec1(%rip) # 4018 <i@@Base>
1157: b8 00 00 00 00 mov $0x0,%eax
115c: e8 cf fe ff ff call 1030 <inci@plt>
They both correspond to C code:
++i;
According to the assembly, it seems that the linker has already decided the run-time address of i
, because it is using a PC-relative address to reference it directly, rather than using GOT. However, as far as I know, the shared library is only loaded into memory when the program uses it loads. Thus, the executable main
should have no knowledge about the address of i
at link time. Then, how does the linker determine that i
is located at 0x4020?
Also what does the comment i@@Base
mean?