有一些类似的问题已经很好地回答了(请参阅: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
页的更多信息。