Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Linux program.text部分从0x0804800开始,堆栈顶部从0xbffffff开始?_Linux_Assembly_Virtual Memory - Fatal编程技术网

为什么Linux program.text部分从0x0804800开始,堆栈顶部从0xbffffff开始?

为什么Linux program.text部分从0x0804800开始,堆栈顶部从0xbffffff开始?,linux,assembly,virtual-memory,Linux,Assembly,Virtual Memory,根据,Linux程序.text部分从0x0804800开始,堆栈顶部从0xbfffff开始。这些数字的意义是什么?为什么不在0x0000000处启动.text(或0x0000020或0x0000040以使下一个32位或64位超过NULL)?为什么不从堆栈顶部的0xfffffff?没有太大意义 堆栈通常向下增长(到较低的地址),因此将其放置在较高的地址是合理的(但不是强制性的),并且有一些空间向较低的地址扩展 至于程序段不使用地址0,这里有一些逻辑。首先,很多软件使用了0的代码 null >代码>

根据,Linux程序
.text
部分从
0x0804800
开始,堆栈顶部从
0xbfffff
开始。这些数字的意义是什么?为什么不在
0x0000000
处启动
.text
(或
0x0000020
0x0000040
以使下一个32位或64位超过
NULL
)?为什么不从堆栈顶部的
0xfffffff

没有太大意义

堆栈通常向下增长(到较低的地址),因此将其放置在较高的地址是合理的(但不是强制性的),并且有一些空间向较低的地址扩展

至于程序段不使用地址0,这里有一些逻辑。首先,很多软件使用了0的代码<代码> null >代码>,这是C和C++中的合法无效指针,不应该被取消引用。很多软件都有缺陷,因为它实际上试图在没有正确的指针验证的情况下读取或写入地址0处的内存。如果使程序无法访问地址0周围的内存区域,则可以发现其中一些错误(程序将在调试器中崩溃或停止)。此外,由于
NULL
是合法的无效指针,因此该地址不应有任何数据或代码(如果有,则无法区分指向该地址的指针与
NULL

在x86平台上,地址0周围的内存通常通过虚拟到物理地址转换而不可访问。页表的设置方式是,虚拟地址0的条目不由一页物理内存备份,一页的大小通常为4KB,而不仅仅是几个字节。这就是为什么如果你去掉地址0,你也会去掉地址1到4095。在地址0处占用超过4KB的地址空间也是合理的。其原因是指针指向C和C++中的结构。您可以有一个指向结构的
NULL
指针,当您取消引用它时,尝试的内存访问发生在指针中包含的地址(0)加上您尝试访问的结构成员与结构开头之间的距离(第一个成员为0,其余成员大于0)


在为程序选择特定的地址范围时,可能还有其他一些考虑因素,但我不能代表所有这些考虑因素。操作系统可能希望在程序本身中保留一些与程序相关的内容(数据结构),那么为什么不在地址空间可访问部分的一端附近使用固定位置呢?

让我们从这句话开始:大多数情况下,不同的部分不需要放置在特定的位置,更重要的是布局。如今,堆栈顶部实际上是随机的,参见

0x08048000是默认地址,在Linux/x86上,ld在其上启动第一个
PT\u加载
段。在Linux/amd64上,默认值为0x400000,您可以使用自定义链接器脚本更改默认值。您还可以将.text部分以
-Wl,-Ttext,0xNNNNNNNN
标志开头的位置更改为gcc。要理解.text未映射到地址0的原因,请记住,为方便起见,空指针通常映射到((void*)0)。因此,将零页映射到空指针的陷阱使用是很有用的。开始之前的记忆。文本实际上被很多东西使用;以
cat/proc/self/maps
为例:

$ cat /proc/self/maps 
001c0000-00317000 r-xp 00000000 08:01 245836     /lib/libc-2.12.1.so
00317000-00318000 ---p 00157000 08:01 245836     /lib/libc-2.12.1.so
00318000-0031a000 r--p 00157000 08:01 245836     /lib/libc-2.12.1.so
0031a000-0031b000 rw-p 00159000 08:01 245836     /lib/libc-2.12.1.so
0031b000-0031e000 rw-p 00000000 00:00 0 
00376000-00377000 r-xp 00000000 00:00 0          [vdso]
00852000-0086e000 r-xp 00000000 08:01 245783     /lib/ld-2.12.1.so
0086e000-0086f000 r--p 0001b000 08:01 245783     /lib/ld-2.12.1.so
0086f000-00870000 rw-p 0001c000 08:01 245783     /lib/ld-2.12.1.so
08048000-08051000 r-xp 00000000 08:01 2244617    /bin/cat
08051000-08052000 r--p 00008000 08:01 2244617    /bin/cat
08052000-08053000 rw-p 00009000 08:01 2244617    /bin/cat
09ab5000-09ad6000 rw-p 00000000 00:00 0          [heap]
b7502000-b7702000 r--p 00000000 08:01 4456455    /usr/lib/locale/locale-archive
b7702000-b7703000 rw-p 00000000 00:00 0 
b771b000-b771c000 r--p 002a1000 08:01 4456455    /usr/lib/locale/locale-archive
b771c000-b771e000 rw-p 00000000 00:00 0 
bfbd9000-bfbfa000 rw-p 00000000 00:00 0          [stack]

这里我们看到的是C库、动态加载程序ld.so和内核VDSO(内核映射的动态代码库,它为内核提供了一些接口)。请注意,堆的开始也是随机的。

这一切都是有意义的,但这比
NULL
(0x0004096与0x804800)高出200个数量级。您也没有提到堆栈没有从内存的文字顶部(0xfffffff)开始的原因,我不知道为什么。文本开始的位置那么高。但为什么不能呢?在最后一段中我已经提到了堆栈位置。通常32位linux内核使用0xC0000000以上的地址。通常,在用户模式下访问此地址范围的任何尝试都会导致seg故障。@通常是。然而,请注意,问题中的所有十六进制数都是奇怪的28位(7个十六进制数字)。