免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 24621895 | 回复: 24621895
打印 上一主题 下一主题

关于cat /proc/<pid>/maps输出条目的几个问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-09-16 15:28 |只看该作者 |倒序浏览
网上有很多对这方面的介绍,基本内容和字段的含义我也都了解,还有一些无法解决的问题。

X86-64下,以一个bash进程为例(其他很多进程有类似的疑问),maps输出为:

[root@localhost ~]# cat /proc/7446/maps
00400000-004b2000 r-xp 00000000 fd:00 1987181                            /bin/bash
006b2000-006bc000 rw-p 000b2000 fd:00 1987181                            /bin/bash
006bc000-006c1000 rw-p 00000000 00:00 0
008bb000-008c3000 rw-p 000bb000 fd:00 1987181                            /bin/bash
008c3000-00905000 rw-p 00000000 00:00 0                                  [heap]
3becc00000-3becc1c000 r-xp 00000000 fd:00 945302                         /lib64/ld-2.5.so
3bece1b000-3bece1c000 r--p 0001b000 fd:00 945302                         /lib64/ld-2.5.so
3bece1c000-3bece1d000 rw-p 0001c000 fd:00 945302                         /lib64/ld-2.5.so
3bed000000-3bed14d000 r-xp 00000000 fd:00 945303                         /lib64/libc-2.5.so
3bed14d000-3bed34d000 ---p 0014d000 fd:00 945303                         /lib64/libc-2.5.so
3bed34d000-3bed351000 r--p 0014d000 fd:00 945303                         /lib64/libc-2.5.so
3bed351000-3bed352000 rw-p 00151000 fd:00 945303                         /lib64/libc-2.5.so
3bed352000-3bed357000 rw-p 00000000 00:00 0
3bed800000-3bed802000 r-xp 00000000 fd:00 945305                         /lib64/libdl-2.5.so
3bed802000-3beda02000 ---p 00002000 fd:00 945305                         /lib64/libdl-2.5.so
3beda02000-3beda03000 r--p 00002000 fd:00 945305                         /lib64/libdl-2.5.so
3beda03000-3beda04000 rw-p 00003000 fd:00 945305                         /lib64/libdl-2.5.so
3bef800000-3bef803000 r-xp 00000000 fd:00 945333                         /lib64/libtermcap.so.2.0.8
3bef803000-3befa02000 ---p 00003000 fd:00 945333                         /lib64/libtermcap.so.2.0.8
3befa02000-3befa03000 rw-p 00002000 fd:00 945333                         /lib64/libtermcap.so.2.0.8
7f6741f8f000-7f6741f99000 r-xp 00000000 fd:00 944731                     /lib64/libnss_files-2.5.so
7f6741f99000-7f6742198000 ---p 0000a000 fd:00 944731                     /lib64/libnss_files-2.5.so
7f6742198000-7f6742199000 r--p 00009000 fd:00 944731                     /lib64/libnss_files-2.5.so
7f6742199000-7f674219a000 rw-p 0000a000 fd:00 944731                     /lib64/libnss_files-2.5.so
7f674219a000-7f6745772000 r--p 00000000 fd:00 3229139                    /usr/lib/locale/locale-archive
7f6745772000-7f6745774000 rw-p 00000000 00:00 0
7f6745790000-7f6745792000 rw-p 00000000 00:00 0
7f6745792000-7f6745799000 r--s 00000000 fd:00 3355345                    /usr/lib64/gconv/gconv-modules.cache
7f6745799000-7f674579b000 rw-p 00000000 00:00 0
7fff1cddc000-7fff1cdfd000 rw-p 00000000 00:00 0                          [stack]
7fff1cdff000-7fff1ce00000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

有三点疑问:
1. 标红色的匿名映射区间是什么?

2. 红色标注的上下两个区间应该是数据段,可是他们的访问属性是一样的,为什么会分开?跟中间的匿名映射区有关吗?

3. 像ld库这种有3个区间,是否第一个为代码段,后两个分别为只读和读写的数据段?记得《深入理解计算机系统》中介绍ELF可执行文件中只读数据节是被映射到代码段的,是这种架构上的处理不同了吗?
另外,像libc这类库有4个区间,从属性上判断,也只有第一个是代码段,第3、4个分别为只读和读写数据段,那第二个是什么?

论坛徽章:
0
2 [报告]
发表于 2011-09-16 15:29 |只看该作者
对红色标注的地方,我理解的出现匿名映射的情况可能有:
  a. 不在堆中的通过mmap调用生成的一段共享或私有的匿名区间。
  b. 为线程作为栈使用的匿名区间。
  c. 申请较大的栈或堆空间时创建的额外的匿名区间。
  不知道理解的是否正确,应该还有其他一些复杂的情况,不知道红色标注的在数据段中间的匿名区间属于哪个,类似的在libc库和libdl库中间也有一个,这种匿名区间出现的位置是否无限制?

论坛徽章:
0
3 [报告]
发表于 2011-09-16 20:29 |只看该作者
红色区对应bbs.

ld的第二个区似乎多余,因为和代码段重了,bug?

libc还没看明白

论坛徽章:
0
4 [报告]
发表于 2011-09-17 10:35 |只看该作者
根据《linkers and loaders》的描述,bss段在逻辑上应该是跟在数据段可读写区段的后面的,这里竟然是插在中间的,不理解。

ld的第二个区没有跟代码段重吧,区间是不同。

论坛徽章:
0
5 [报告]
发表于 2011-09-17 14:19 |只看该作者
readelf -l /bin/bash

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000b1acc 0x00000000000b1acc  R E    200000
  LOAD           0x00000000000b2000 0x00000000006b2000 0x00000000006b2000
                 0x0000000000009338 0x000000000000e968  RW     200000
  LOAD           0x00000000000bb338 0x00000000008bb338 0x00000000008bb338
                 0x0000000000007643 0x0000000000007643  RW     200000

第二个ph,FileSiz=9338,MemSiz=e968,FileSiz<MemSiz,因此被映射成两个区.
一个6b2000,6b2000+9338(上取整)=6bc000(有文件映射)
一个6bc000,6b2000+e968(上取整)=6c1000(无文件映射,bbs)

论坛徽章:
0
6
发表于 2011-09-19 15:43
回复 5# qtdszws

那第三个LOAD类型应该也是加载到数据段的,为什么他在地址空间的起始地址不是接着上面bss段呢?难道这里也要预留一定的间隔防止越界?

另外,根据libc的ELF文件的程序头信息:
LOAD           0x0000000000000000 0x0000003bed000000 0x0000003bed000000
                    0x000000000014ced8 0x000000000014ced8  R E    200000
LOAD           0x000000000014d778 0x0000003bed34d778 0x0000003bed34d778
                    0x0000000000004620 0x00000000000089e0  RW     200000

它对应的maps:
3bed000000-3bed14d000 r-xp 00000000 fd:00 945303                         /lib64/libc-2.5.so
3bed14d000-3bed34d000 ---p 0014d000 fd:00 945303                         /lib64/libc-2.5.so
3bed34d000-3bed351000 r--p 0014d000 fd:00 945303                         /lib64/libc-2.5.so
3bed351000-3bed352000 rw-p 00151000 fd:00 945303                         /lib64/libc-2.5.so

应该如何解释呢?
程序头的Flags只注明了RW,那映射到区间的更细致的属性是在哪里判断的呢?

论坛徽章:
0
7 [报告]
发表于 2011-09-20 15:36 |只看该作者
怎么回复显示不正确呢?看不到我最后的回复。。。?

论坛徽章:
0
8 [报告]
发表于 2011-09-20 15:44 |只看该作者
回复 5# qtdszws

晕啊,再回复5楼一次。先多谢回复 : )

第二个LOAD类型包含了bss段,那第三个LOAD类型加载的地址为什么不是接着上一个区域的,也是为了防止越界特意预留的间隔吗?

根据libc库的程序头信息:
LOAD           0x0000000000000000 0x0000003bed000000 0x0000003bed000000
               0x000000000014ced8 0x000000000014ced8  R E    200000
LOAD           0x000000000014d778 0x0000003bed34d778 0x0000003bed34d778
               0x0000000000004620 0x00000000000089e0  RW     200000

和其对应maps的信息:
3bed000000-3bed14d000 r-xp 00000000 fd:00 945303                         /lib64/libc-2.5.so
3bed14d000-3bed34d000 ---p 0014d000 fd:00 945303                         /lib64/libc-2.5.so
3bed34d000-3bed351000 r--p 0014d000 fd:00 945303                         /lib64/libc-2.5.so
3bed351000-3bed352000 rw-p 00151000 fd:00 945303                         /lib64/libc-2.5.so

程序头中代码段只有RW属性,但对应却有3个vma,这个更细致的属性判断是在哪里处理的?
这种现象又应该怎么解释呢?

论坛徽章:
0
9 [报告]
发表于 2011-09-21 10:48 |只看该作者
>>那第三个LOAD类型加载的地址为什么不是接着上一个区域的,也是为了防止越界特意预留的间隔吗?

这个不太清楚,不知道ld的用意如何?,搞两个r/w ph好像也没有必要,还是bash自身有特殊要求?

值得注意的是,/bin/bash第三个load对应于.dynstr节,在/bin/ls中,.dynstr节是直接在bss后.

.dynstr节的作用是用于动态链接,程序加载成功后,应该可以废弃.

如果使用显示连接,.dynstr节应该保留,估计是因为这个原因,导致将.dynstr节独立出来,并且刻意和bss保持距离,防止被覆盖。

对于第二个问题,答案是因为ld动态链接导致的,ld加载/bin/bash用到的动态连接库时,先计算要加载的load ph的总区间,即第一个load ph的start地址,和最后一个load的结束地址,并一次性mmap,然后再将其区间调整为不能读写执行.再根据每个load ph执行各自的mmap.

因此下面这个vma如何来的就清楚了
3bed14d000-3bed34d000 ---p 0014d000 fd:00 945303                         /lib64/libc-2.5.so

论坛徽章:
0
10 [报告]
发表于 2011-09-21 11:44 |只看该作者
而这个
3bed34d000-3bed351000 r--p 0014d000 fd:00 945303                         /lib64/libc-2.5.so
对应
  GNU_RELRO      0x000000000014d778 0x000000378134d778 0x000000378134d778
                 0x0000000000003888 0x0000000000003888  R      1
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP