Linux下gdb调试打印进程内存信息方式
作者:凌肖战
Linux下gdb调试打印进程内存信息
以下面代码为例,打印进程的内存信息。
代码如下:
#include <stdio.h> int main(void) { int i = 0; char data[100] = {0}; for(i = 0; i < (sizeof(data)/sizeof(char)); i++) { data[i] = i; } return 0; }
在 gdb 调试中,也可以打印进程的内存信息。
命令如下:i proc mappings
下面进行 gdb 调试,打印进程的内存信息。
操作如下:
- 首先,在程序某一行打断点。
- 其次,输入 r 命令运行程序。
- 最后,输入 i proc mappings 命令打印进程的内存信息。
如下所示:
(gdb) i proc mappings
process 4261
Mapped address spaces:Start Addr End Addr Size Offset objfile
0x555555554000 0x555555555000 0x1000 0x0 /home/wangtian/Code_Learns/C_Learns/debug/debug2/main.out
0x555555555000 0x555555556000 0x1000 0x1000 /home/wangtian/Code_Learns/C_Learns/debug/debug2/main.out
0x555555556000 0x555555557000 0x1000 0x2000 /home/wangtian/Code_Learns/C_Learns/debug/debug2/main.out
0x555555557000 0x555555558000 0x1000 0x2000 /home/wangtian/Code_Learns/C_Learns/debug/debug2/main.out
0x555555558000 0x555555559000 0x1000 0x3000 /home/wangtian/Code_Learns/C_Learns/debug/debug2/main.out
0x7ffff7dc3000 0x7ffff7de5000 0x22000 0x0 /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x7ffff7de5000 0x7ffff7f5d000 0x178000 0x22000 /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x7ffff7f5d000 0x7ffff7fab000 0x4e000 0x19a000 /usr/lib/x86_64-linux-gnu/libc-2.31.so
可以看到,输出了进程的内存映射信息。
也可显示更详细的进程内存信息。
命令为:i files 命令 或者 i target 命令
包括引用的动态链接库等等。。。
如下所示:
Linux之gdb基本调试命令与总结
一、常见gdb调试命令
表1 gdb基本调试指令
命令 | 描述 |
backtrace(或bt) | 查看各级函数调用及参数 |
finish | 连续运行到当前函数返回为止,然后停下来等待命令 |
frame(或f) 帧编号 | 选择栈帧 |
info(或i) locals | 查看当前栈帧局部变量的值 |
list(或l) | 列出源代码,接着上次的位置往下列,每次列10行 |
continue(c) | 列出从第几行开始的源代码 |
list 函数名 | 继续执行 |
next(或n) | 执行下一行语句 |
print(或p) | 打印表达式的值,通过表达式可以修改变量的值或者调用函数 |
quit(或q) | 退出 gdb 调试环境 |
set var | 修改变量的值 |
start | 开始执行程序,停在 main 函数第一行语句前面等待命令 |
step(或s) | 执行下一行语句,如果有函数调用则进入到函数中 |
break(b) | 设置断点 |
delete(d) | 删除断点 |
attach <pid> | attach到进程 ID 为 pid 的进程 |
二、info调试指令
表2 info调试命令
命令 | 描述 |
info registers | 查看除了浮点寄存器以外的寄存器 |
info all-registers | 查看所有寄存器,包括浮点寄存器 |
info registers <regname …> | 查看所指定的寄存器 |
info break | 查看断点信息 |
info watchpoints | 列出当前所设置的所有观察点 |
info signals info handle | 查看有哪些信号正在被GDB检测 |
info frame | 查看当前程序栈的信息 |
info threads | 可以看多线程 |
info args | 查看当前函数参数信息 |
info locals | 查看当前程序栈的局部变量 |
三、内存查看
3.1 打印内存数据
gdb查看指定地址的内存地址的值:examine 简写 x-----使用gdb> help x 来查看使用方式
x/ (n,f,u为可选参数)
n
: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义f
:显示格式
x(hex) 按十六进制格式显示变量。
d(decimal) 按十进制格式显示变量。
u(unsigned decimal) 按十进制格式显示无符号整型。
o(octal) 按八进制格式显示变量。
t(binary) 按二进制格式显示变量。
a(address) 按十六进制格式显示变量。
c(char) 按字符格式显示变量。
f(float) 按浮点数格式显示变量
u
:每个单元的大小,按字节数来计算。默认是4 bytes。GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示
b:1 byte h:2 bytes w:4 bytes g:8 bytes
比如x/3uh 0x54320表示从内存地址0x54320读取内容,h表示以双字节为单位,3表示输出3个单位,u表示按照十六进制显示。
3.2 打印数组
比如我有一个数组的定义 :int a[] = {1, 2, 3, 4, 5};
那么想要显示的时候就可以写:
p *a@5
这样就会显示数组a中的所有元素。
也可以使用display在一部调试的时候都显示:
display *a@5
四、多线程调试命令
表4 多线程调试命令
命令 | 描述 |
info threads | 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。 前面有*的是当前调试的线程 |
thread ID(1,2,3…) | 切换当前调试的线程为指定ID的线程 |
break thread_test.c:123 thread all(例:在相应函数的位置设置断点break pthread_run1) | 在所有线程中相应的行上设置断点 |
thread apply ID1 ID2 command | 让一个或者多个线程执行GDB命令command |
thread apply all command | 让所有被调试线程执行GDB命令command |
set scheduler-locking 选项 command | 设置线程是以什么方式来执行命令 |
set scheduler-locking off | 不锁定任何线程,也就是所有线程都执行,这是默认值 |
set scheduler-locking on | 只有当前被调试程序会执行 |
set scheduler-locking on step | 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行 |
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。