Linux如何读取进程某一块内存的数据呢?
例如,进程发生段错误了:
do_page_fault(): sending SIGSEGV to managePlugin for invalid read access from 76e3ddbc
epc = 7738d83c in libc.so[77319000+92000]
ra = 77390a00 in libc.so[77319000+92000]
如何读取,libc.so映射内存段的内容。可以通过/proc/<pid>/mem接口。这个文件是一个虚拟文件,它的偏移和内存的偏移一样。
首先,读取/proc/<pid>/maps获得进程的地址映射范围:
# cat /proc/1/maps
00400000-0040b000 r-xp 00000000 1f:08 2995 /sbin/procd
0041a000-0041b000 r-xp 0000a000 1f:08 2995 /sbin/procd
0041b000-0041c000 rwxp 0000b000 1f:08 2995 /sbin/procd
0041c000-0041e000 rwxp 00000000 00:00 0
00943000-0096f000 rwxp 00000000 00:00 0 [heap]
7771f000-77742000 r-xp 00000000 1f:08 3860 /lib/libgcc_s.so.1
77742000-77743000 rwxp 00013000 1f:08 3860 /lib/libgcc_s.so.1
77743000-77755000 r-xp 00000000 1f:08 3876 /lib/libjson_script.so
77755000-77756000 r-xp 00002000 1f:08 3876 /lib/libjson_script.so
77756000-77757000 rwxp 00003000 1f:08 3876 /lib/libjson_script.so
77757000-77768000 r-xp 00000000 1f:08 3854 /lib/libblobmsg_json.so
77768000-77769000 r-xp 00001000 1f:08 3854 /lib/libblobmsg_json.so
77769000-7776a000 rwxp 00002000 1f:08 3854 /lib/libblobmsg_json.so
7776a000-77780000 r-xp 00000000 1f:08 992 /usr/lib/libjson-c.so.2.0.2
77780000-77781000 r-xp 00006000 1f:08 992 /usr/lib/libjson-c.so.2.0.2
77781000-77782000 rwxp 00007000 1f:08 992 /usr/lib/libjson-c.so.2.0.2
77782000-77796000 r-xp 00000000 1f:08 3852 /lib/libubus.so
77796000-77797000 r-xp 00004000 1f:08 3852 /lib/libubus.so
77797000-77798000 rwxp 00005000 1f:08 3852 /lib/libubus.so
77798000-777af000 r-xp 00000000 1f:08 3843 /lib/libubox.so
777af000-777b0000 r-xp 00007000 1f:08 3843 /lib/libubox.so
777b0000-777b1000 rwxp 00008000 1f:08 3843 /lib/libubox.so
777b1000-77843000 r-xp 00000000 1f:08 3800 /lib/libc.so
7784f000-77851000 r--p 00000000 00:00 0 [vvar]
77851000-77852000 r-xp 00000000 00:00 0 [vdso]
77852000-77854000 rwxp 00091000 1f:08 3800 /lib/libc.so
77854000-77856000 rwxp 00000000 00:00 0
7fb12000-7fb33000 rw-p 00000000 00:00 0 [stack]
7ffff000-80000000 rwxp 00000000 00:00 0
比如,我们要读取
00400000-0040b000 r-xp 00000000 1f:08 2995 /sbin/procd
那么只要读取/proc/1/mem文件,先将偏移跳转到00400000,然后都这个地址段长度即可,对应dd命令如下:
# dd if=/proc/1/mem of=/tmp/procd.mem bs=256 skip=$((0x4000)) count=$((0xb0))
bs设置为256,也就是0x100,那么读的时候,把地址范围的16进制的后面2位去掉即可。
同样的方法,可以读堆和栈的内容。