我的main.c是:
int bss_var;int data_var0 = 1;int main(){ //堆栈 的printf( “_____________________________________ \ n”); printf(“堆栈……
在与位置无关的可执行文件中,入口点地址相对于基本映射地址。默认情况下,内核为每个程序运行随机确定基本映射地址。在x86-64上,通常是在 0x555555550000 。
0x555555550000
您可以链接您的程序 -no-pie 创建一个位置相关的可执行文件(ELF类型 ET_EXEC 代替 ET_DYN )。
-no-pie
ET_EXEC
ET_DYN
切入点 是 靠近地址 .text 部分。
.text
您看到的入口点 $ readelf -h a.out 是名义上的 在加载和重新定位程序之前,链接器静态分配的地址。
$ readelf -h a.out
的地址 .text 部分不是地址 main ,作为你的程序 假设,它是符号的地址 __executable_start ,以及程序打印的内容 在运行时不是链接器分配的标称地址,而是之后的虚拟地址 程序已加载并重新定位。看到:
main
__executable_start
$ cat main.c #include <stdio.h> extern char __executable_start; extern char _start; int main(void) { printf("%p: address of `.text` section\n", &__executable_start); printf("%p: address of `_start` \n", &_start); printf("%p: address of `main` \n", &main); return 0; } $ gcc -Wall main.c $ readelf -s a.out | egrep -w '(main|_start|__executable_start)' 34: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.c 49: 0000000000000000 0 NOTYPE GLOBAL DEFAULT ABS __executable_start 57: 0000000000000540 43 FUNC GLOBAL DEFAULT 14 _start 59: 000000000000064a 83 FUNC GLOBAL DEFAULT 14 main
名义地址 .text section是0000000000000000.入口点 是的地址 _start ,在偏移量0x540字节 .text 部分和 main 位于偏移量0x64a处。报告的入口点:
_start
$ readelf -h a.out | grep 'Entry point' Entry point address: 0x540
是一样的。并运行该程序:
$ ./a.out 0x564c5d350000: address of `.text` section 0x564c5d350540: address of `_start` 0x564c5d35064a: address of `main`
显示与虚拟基址0x564c5d350000相同偏移的符号。