在這個輸出中,能夠很容易看到一個so文件中有一個"---p"屬性的區間段,它們對應哪些文件內容,數據從哪裏來?在stackoverflow網站上也有一個這樣的提問,只是尚未人解答。
tsecer@harry: cat /proc/self/maps
00400000-0040b000 r-xp 00000000 fd:01 15433 /usr/bin/cat
0060b000-0060c000 r--p 0000b000 fd:01 15433 /usr/bin/cat
0060c000-0060d000 rw-p 0000c000 fd:01 15433 /usr/bin/cat
00877000-00898000 rw-p 00000000 00:00 0 [heap]
7fab3ae42000-7fab4136b000 r--p 00000000 fd:01 24801 /usr/lib/locale/locale-archive
7fab4136b000-7fab4136d000 r-xp 00000000 fd:01 25150 /usr/lib64/libdl-2.17.so
7fab4136d000-7fab4156d000 ---p 00002000 fd:01 25150 /usr/lib64/libdl-2.17.so
7fab4156d000-7fab4156e000 r--p 00002000 fd:01 25150 /usr/lib64/libdl-2.17.so
7fab4156e000-7fab4156f000 rw-p 00003000 fd:01 25150 /usr/lib64/libdl-2.17.so
7fab4156f000-7fab41729000 r-xp 00000000 fd:01 25054 /usr/lib64/libc-2.17.so
7fab41729000-7fab41928000 ---p 001ba000 fd:01 25054 /usr/lib64/libc-2.17.so
7fab41928000-7fab4192c000 r--p 001b9000 fd:01 25054 /usr/lib64/libc-2.17.so
7fab4192c000-7fab4192e000 rw-p 001bd000 fd:01 25054 /usr/lib64/libc-2.17.so
7fab4192e000-7fab41933000 rw-p 00000000 00:00 0
7fab41933000-7fab41954000 r-xp 00000000 fd:01 24864 /usr/lib64/ld-2.17.sohtml
從生成的so文件來看,兩個LOAD節的Align都是0x20000,也就是2Mb的對齊,而且在第二個LOAD中,它的VirtAddr地址0x0000000000200db8,和文件偏移量0x0000000000000db8的起始地址相差了2M,而"---p"的區間段就是兩個LOAD區間中空閒的內存空間。
tsecer@harry: cat -n maps---p.cpp
1 int gx = 1;
2 int gy;
3 int foo()
4 {
5 return gx + gy;
6 }
tsecer@harry: g++ maps---p.cpp -shared -fpic -o libmaps.so
tsecer@harry: readelf -l libmaps.so linux
Elf 文件類型爲 DYN (共享目標文件)
入口點 0x630
共有 7 個程序頭,開始於偏移量64c++
程序頭:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000007c4 0x00000000000007c4 R E 200000
LOAD 0x0000000000000db8 0x0000000000200db8 0x0000000000200db8
0x0000000000000274 0x0000000000000280 RW 200000
DYNAMIC 0x0000000000000dd8 0x0000000000200dd8 0x0000000000200dd8
0x00000000000001f0 0x00000000000001f0 RW 8
NOTE 0x00000000000001c8 0x00000000000001c8 0x00000000000001c8
0x0000000000000024 0x0000000000000024 R 4
GNU_EH_FRAME 0x0000000000000740 0x0000000000000740 0x0000000000000740
0x000000000000001c 0x000000000000001c R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x0000000000000db8 0x0000000000200db8 0x0000000000200db8
0x0000000000000248 0x0000000000000248 R 1redis
能夠看到,這個對齊實際上是在連接器中設置的,估計是爲了兼容SO能夠運行的平臺,例若有些頁面爲2M的平臺。這個大小能夠經過連接器選項來設置
tsecer@harry: g++ maps---p.cpp -shared -fpic -o libmaps.so -Wl,-z,max-page-size=4096
tsecer@harry: readelf -l libmaps.so shell
Elf 文件類型爲 DYN (共享目標文件)
入口點 0x630
共有 7 個程序頭,開始於偏移量64佈局
程序頭:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000007c4 0x00000000000007c4 R E 1000
LOAD 0x0000000000000db8 0x0000000000001db8 0x0000000000001db8
0x0000000000000274 0x0000000000000280 RW 1000
DYNAMIC 0x0000000000000dd8 0x0000000000001dd8 0x0000000000001dd8
0x00000000000001f0 0x00000000000001f0 RW 8網站
能夠看到中間已經沒有"---p"屬性區間段
tsecer@harry: cat -n main.cpp
1 int main()
2 {
3 int foo();
4 return foo();
5 }
tsecer@harry: g++ main.cpp -L`pwd` -lmaps -g
tsecer@harry: LD_LIBRARY_PATH=`pwd` gdb ./a.out
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/harry/study/maps---p/a.out...done.
(gdb) b main
Breakpoint 1 at 0x4006c4: file main.cpp, line 4.
(gdb) r
Starting program: /home/harry/study/maps---p/./a.out spa
Breakpoint 1, main () at main.cpp:4
4 return foo();
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.tl2.3.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64
(gdb) info proc
process 21541
cmdline = '/home/harry/study/maps---p/./a.out'
cwd = '/home/harry/study/maps---p'
exe = '/home/harry/study/maps---p/a.out'
(gdb) shell cat /proc/21541/maps
00400000-00401000 r-xp 00000000 fd:10 31719450 /home/harry/study/maps---p/a.out
00600000-00601000 r--p 00000000 fd:10 31719450 /home/harry/study/maps---p/a.out
00601000-00602000 rw-p 00001000 fd:10 31719450 /home/harry/study/maps---p/a.out
……
7ffff7eef000-7ffff7ef0000 r-xp 00000000 fd:10 31719449 /home/harry/study/maps---p/libmaps.so
7ffff7ef0000-7ffff7ef1000 r--p 00000000 fd:10 31719449 /home/harry/study/maps---p/libmaps.so
7ffff7ef1000-7ffff7ef2000 rw-p 00001000 fd:10 31719449 /home/harry/study/maps---p/libmaps.sodebug
能夠看到,在這個區間段的最後有兩段,這一點也容易理解:
由於一些全局爲初始化變量是位於bss段的,它們並不在文件中佔用空間,須要在加載時清零。因此作文件映射就不能實現該功能(由於文件裏沒有對應的內容),因此這裏實際上是映射到了一個匿名的私有空間,邏輯地址空間和前面的連續。
7ffff7ad3000-7ffff7bbc000 r-xp 00000000 fd:01 25828 /usr/lib64/libstdc++.so.6.0.19
7ffff7bbc000-7ffff7dbc000 ---p 000e9000 fd:01 25828 /usr/lib64/libstdc++.so.6.0.19
7ffff7dbc000-7ffff7dc4000 r--p 000e9000 fd:01 25828 /usr/lib64/libstdc++.so.6.0.19
7ffff7dc4000-7ffff7dc6000 rw-p 000f1000 fd:01 25828 /usr/lib64/libstdc++.so.6.0.19
7ffff7dc6000-7ffff7ddb000 rw-p 00000000 00:00 0 code