【问题标题】:libc.so has four segments mapped in a process, why?libc.so 在一个进程中映射了四个段,为什么?
【发布时间】:2010-01-20 13:39:12
【问题描述】:

为了查看正在运行的程序包含哪些内存映射区域,我编写了一个简单的 C 程序来从 /proc/self/maps 读取数据:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
    char buf[1024];
    int fd;
    ssize_t n;

    fd = open("/proc/self/maps", O_RDONLY);
    if (fd < 0) {
        perror("");
    }
    while ((n = read(fd, buf, 1000)) > 0) {
        buf[n] = 0;
        printf("%s", buf);
    }
    close(fd);

    return 0;
}

程序的输出看起来像这样(标记):

1. 08048000-08049000 r-xp 00000000 08:01 2323014    /tmp/a.out
2. 08049000-0804a000 rw-p 00000000 08:01 2323014    /tmp/a.out
3. b7f69000-b7f6a000 rw-p b7f69000 00:00 0
4. b7f6a000-b80c6000 r-xp 00000000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
5. b80c6000-b80c7000 ---p 0015c000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
6. b80c7000-b80c9000 r--p 0015c000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
7. b80c9000-b80ca000 rw-p 0015e000 08:01 1826975    /lib/tls/i686/cmov/libc-2.9.so
8. b80ca000-b80cd000 rw-p b80ca000 00:00 0
9. b80dd000-b80df000 rw-p b80dd000 00:00 0
10.b80df000-b80e0000 r-xp b80df000 00:00 0          [vdso]
11.b80e0000-b80fc000 r-xp 00000000 08:01 1826830    /lib/ld-2.9.so
12.b80fc000-b80fd000 r--p 0001b000 08:01 1826830    /lib/ld-2.9.so
13.b80fd000-b80fe000 rw-p 0001c000 08:01 1826830    /lib/ld-2.9.so
14.bfee9000-bfefe000 rw-p bffeb000 00:00 0          [stack]

从执行位和可写位可以推断,前两行分别与程序的代码段和数据段相关联。

但让我感到困惑的是 libc.so,有一些区域是从 libc.so 映射的。其中一个甚至只有私有位,无法写入、读取或执行。 另一个有趣的事情是 ld.so 只有三个段。与 libc.so 的段相比,缺少了仅打开私有位的段。

所以我想知道这四个部分实际上是做什么的?我正在使用内核 2.6.28、gcc 3.4.6 和 binutils 2.19 的 Ubuntu SMP。

【问题讨论】:

    标签: c memory linker kernel dynamic-linking


    【解决方案1】:

    r-xpr--prw-p 映射只是需要不同权限的区域。

    神秘的---p 映射是由 ELF 文件描述的部分的虚拟内存偏移量不一定与文件中的物理偏移量匹配的结果(出于对齐原因,可能存在填充)。

    即ELF 文件本身可能如下所示:

    | .... sections .... | .... more sections .... |
    

    ...但是描述一个看起来像这样的内存布局:

    | .... sections .... |     gap     | .... more sections .... |
    

    (您可以使用objdump -hreadelf -e 来查看。)

    所以,总的原则是ld.so需要为所有东西分配足够的内存:

    |                                                            |
    

    ...然后为第一部分制作一个映射:

    | .... sections .... |                                       |
    

    ...然后进行第二次映射以将第二部分放在正确的位置:

    | .... sections .... |             | .... more sections .... |
    

    然后它会保护留在虚拟地址空间中的“洞”。这是你看到的神秘地图:

    | .... sections .... |XXXXXXXXXXXXX| .... more sections .... |
    

    我相信这个漏洞是受到保护的 - 而不是被释放以供重复使用 - 以保持简单:它确保每个库只有一个虚拟地址范围,它属于它而不属于其他任何人。

    【讨论】:

    • 很好的答案。不过,它确实让我想到了一个后续问题,您提到的“差距”的原因是什么?
    猜你喜欢
    • 2021-05-11
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 2020-12-20
    • 2016-08-11
    • 2019-03-14
    相关资源
    最近更新 更多