/ proc / pid / maps

时间:2020-08-10 12:05:40

标签: c linux memory memory-management shared-libraries

有一些类似的问题已经很好地回答了(请参阅:https://unix.stackexchange.com/questions/226283/shared-library-mappings-in-proc-pid-maps),但是我敢肯定这不是重复的问题。

几乎每个人都说具有r--p权限的页面是只读的,并且静态变量存储在该页面中。但是,一些快速实验表明,带有const的变量已被装入.text段的内存中,并被映射到r-xp页面中:

一个名为quick.c的简单测试程序:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <unistd.h>

int main()
{
    //load a shared object
    void *handle = dlopen("./lib2.so", RTLD_LAZY);
    sleep(-1);

    return 0;
}

动态库lib2.c:

#include <stdio.h>

const char* s = "Hello World!";
const int tmp = 2;

void p2()
{
    printf("Hello from lib2.so\n");
}

映射如下:

cat /proc/32098/maps
555555554000-555555555000 r-xp 00000000 08:01 1091238                    /home/expr/quick
555555754000-555555755000 r--p 00000000 08:01 1091238                    /home/expr/quick
555555755000-555555756000 rw-p 00001000 08:01 1091238                    /home/expr/quick
555555756000-555555777000 rw-p 00000000 00:00 0                          [heap]
**7ffff7611000-7ffff7612000 r-xp 00000000 08:01 1051677                    /home/expr/lib2.so**
7ffff7612000-7ffff7811000 ---p 00001000 08:01 1051677                    /home/expr/lib2.so
**7ffff7811000-7ffff7812000 r--p 00000000 08:01 1051677                    /home/expr/lib2.so**
7ffff7812000-7ffff7813000 rw-p 00001000 08:01 1051677                    /home/expr/lib2.so
7ffff7813000-7ffff79c6000 r-xp 00000000 08:01 1091224                    /home/expr/glibc-2.32/build/install/lib/libc-2.32.so
7ffff79c6000-7ffff7bc5000 ---p 001b3000 08:01 1091224                    /home/expr/glibc-2.32/build/install/lib/libc-2.32.so
7ffff7bc5000-7ffff7bc9000 r--p 001b2000 08:01 1091224                    /home/expr/glibc-2.32/build/install/lib/libc-2.32.so
7ffff7bc9000-7ffff7bcb000 rw-p 001b6000 08:01 1091224                    /home/expr/glibc-2.32/build/install/lib/libc-2.32.so
7ffff7bcb000-7ffff7bcf000 rw-p 00000000 00:00 0 
7ffff7bcf000-7ffff7bd2000 r-xp 00000000 08:01 1092231                    /home/expr/glibc-2.32/build/install/lib/libdl-2.32.so
7ffff7bd2000-7ffff7dd1000 ---p 00003000 08:01 1092231                    /home/expr/glibc-2.32/build/install/lib/libdl-2.32.so
7ffff7dd1000-7ffff7dd2000 r--p 00002000 08:01 1092231                    /home/expr/glibc-2.32/build/install/lib/libdl-2.32.so
7ffff7dd2000-7ffff7dd3000 rw-p 00003000 08:01 1092231                    /home/expr/glibc-2.32/build/install/lib/libdl-2.32.so
7ffff7dd3000-7ffff7dfc000 r-xp 00000000 08:01 1092782                    /home/expr/glibc-2.32/build/install/lib/ld-2.32.so
7ffff7ff3000-7ffff7ff8000 rw-p 00000000 00:00 0 
7ffff7ff8000-7ffff7ffb000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00029000 08:01 1092782                    /home/expr/glibc-2.32/build/install/lib/ld-2.32.so
7ffff7ffd000-7ffff7fff000 rw-p 0002a000 08:01 1092782                    /home/expr/glibc-2.32/build/install/lib/ld-2.32.so
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

使用gdb查看地址:

(gdb) p s
$1 = 0x7ffff76116ac "Hello World!"
(gdb) p &tmp
$2 = (const int *) 0x7ffff76116bc <tmp>
(gdb) p p2
$3 = {void ()} 0x7ffff761168a <p2>

这表明静态全局变量与代码一起被映射到同一r-xp页中。

那么为什么还有一个r--p页面?


有关其他信息,我试图这样查看程序头:

readelf -l lib2.so

Elf file type is DYN (Shared object file)
Entry point 0x5b0
There are 7 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000774 0x0000000000000774  R E    0x200000
  LOAD           0x0000000000000e00 0x0000000000200e00 0x0000000000200e00
                 0x0000000000000230 0x0000000000000238  RW     0x200000
  DYNAMIC        0x0000000000000e10 0x0000000000200e10 0x0000000000200e10
                 0x00000000000001d0 0x00000000000001d0  RW     0x8
  NOTE           0x00000000000001c8 0x00000000000001c8 0x00000000000001c8
                 0x0000000000000024 0x0000000000000024  R      0x4
  GNU_EH_FRAME   0x00000000000006d4 0x00000000000006d4 0x00000000000006d4
                 0x0000000000000024 0x0000000000000024  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000000e00 0x0000000000200e00 0x0000000000200e00
                 0x0000000000000200 0x0000000000000200  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 
   01     .init_array .fini_array .dynamic .got .got.plt .data .bss 
   02     .dynamic 
   03     .note.gnu.build-id 
   04     .eh_frame_hdr 
   05     
   06     .init_array .fini_array .dynamic .got 

我在elf / dl-load.c上进行了大量的阅读,发现程序头中的每个LOAD都对应一个mmap调用,可以完美地解释{{1} }和r-xp页(请参见上面的段映射)。 rw-p页在可执行数据和不可执行数据之间起到了空洞的作用,在此处已得到解答:/proc/$pid/maps shows pages with no rwx permissions on x86_64 linux

仍然,没有---p页的更多信息。

0 个答案:

没有答案