为什么 .text 部分不在 "Entry point address" 附近?
Why .text section is not near by "Entry point address"?
我的 main.c 是:
#include <stdio.h>
#include <stdlib.h>
int bss_var;
int data_var0 = 1;
int main()
{
// stack
printf("_____________________________________\n");
printf("stack section:\n");
int stack_var = 3;
printf("\t%p\n",&stack_var);
printf("_____________________________________\n");
// heap
printf("heap section:\n");
char *p = (char*)malloc(10);
printf("\t%p\n",p);
printf("_____________________________________\n");
// .bss
printf(".bss section:\n");
printf("\t%p\n",&bss_var);
printf("_____________________________________\n");
// .data
printf(".data section:\n");
static int data_var1 = 4;
printf("\t%p\n",&data_var1);
printf("\t%p\n",&data_var0);
printf("_____________________________________\n");
// .text
printf(".text section:\n");
printf("\t%p\n",main);
printf("_____________________________________\n");
return 0;
}
结果是:
stack section: 0x7fffffffe1ec
heap section: 0x555555756670
.bss section: 0x55555575501c
.data section: 0x555555755014
.text section: 0x55555555473a
$ readelf -h a.out:
Entry point address: 0x630
为什么 0x630 处的 "Entry point address" 不在 0x55555555473a 处的“.text 部分”附近?
我的环境是:x86_64,linux-4.15.0
在位置无关的可执行文件中,入口点地址是相对于基映射地址的。默认情况下,内核为每个程序随机确定基映射地址运行。在 x86-64 上,它通常在 0x555555550000
.
左右
您可以 link 您的程序 -no-pie
创建位置相关的可执行文件(ELF 类型 ET_EXEC
而不是 ET_DYN
)。
入口点在 .text
部分的地址附近。
您在 $ readelf -h a.out
中看到的入口点是名义上的
在程序加载和重新定位之前由链接器静态分配的地址。
.text
段的地址不是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
段标称地址为0000000000000000.入口点
是 _start
的地址,在 .text
部分的偏移量 0x540 字节处,并且
main
位于偏移量 0x64a 处。报告的入口点:
$ 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 相同偏移量的符号。
我的 main.c 是:
#include <stdio.h>
#include <stdlib.h>
int bss_var;
int data_var0 = 1;
int main()
{
// stack
printf("_____________________________________\n");
printf("stack section:\n");
int stack_var = 3;
printf("\t%p\n",&stack_var);
printf("_____________________________________\n");
// heap
printf("heap section:\n");
char *p = (char*)malloc(10);
printf("\t%p\n",p);
printf("_____________________________________\n");
// .bss
printf(".bss section:\n");
printf("\t%p\n",&bss_var);
printf("_____________________________________\n");
// .data
printf(".data section:\n");
static int data_var1 = 4;
printf("\t%p\n",&data_var1);
printf("\t%p\n",&data_var0);
printf("_____________________________________\n");
// .text
printf(".text section:\n");
printf("\t%p\n",main);
printf("_____________________________________\n");
return 0;
}
结果是:
stack section: 0x7fffffffe1ec
heap section: 0x555555756670
.bss section: 0x55555575501c
.data section: 0x555555755014
.text section: 0x55555555473a
$ readelf -h a.out:
Entry point address: 0x630
为什么 0x630 处的 "Entry point address" 不在 0x55555555473a 处的“.text 部分”附近?
我的环境是:x86_64,linux-4.15.0
在位置无关的可执行文件中,入口点地址是相对于基映射地址的。默认情况下,内核为每个程序随机确定基映射地址运行。在 x86-64 上,它通常在 0x555555550000
.
您可以 link 您的程序 -no-pie
创建位置相关的可执行文件(ELF 类型 ET_EXEC
而不是 ET_DYN
)。
入口点在 .text
部分的地址附近。
您在 $ readelf -h a.out
中看到的入口点是名义上的
在程序加载和重新定位之前由链接器静态分配的地址。
.text
段的地址不是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
段标称地址为0000000000000000.入口点
是 _start
的地址,在 .text
部分的偏移量 0x540 字节处,并且
main
位于偏移量 0x64a 处。报告的入口点:
$ 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 相同偏移量的符号。