GDB修改内存的内容
  • 向变量中写入内容
    gdb中的set命令可以用来向内存地址写入内容。但使用set命令有一些语法需要注意。
    If the beginning of the argument string of the set command appears identical to a set subcommand, use the set variable command instead of just set. This command is identical to set except for its lack of subcommands. For example, if your program has a variable width, you get an error if you try to set a new value with just ‘set width=13’, because GDB has the command set width:
    因为GDB的set命令参数有可能与你定义的变量重名,写入的时候会提示表达式无效。
(gdb) whatis width
type = double
(gdb) p width
$4 = 13
(gdb) set width=47
Invalid syntax in expression.

这里无效的表达式就是“=47”,想要向变量写入内容,正确的写法是在变量名前加上variable,可以简写为var

(gdb) set var width=47

因为该set命令有许多子命令可能与程序变量的名称冲突,所以最好使用该 set variable命令而不是set。例如,如果你的程序定义有变量g,仅使用’set g = 4’在运行的时候就会出错,因为GDB具有命令set gnutarget,缩写为set g:

(gdb) whatis g
type = double
(gdb) p g
$1 = 1
(gdb) set g=4
(gdb) p g
$2 = 1
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/smith/cc_progs/a.out
"/home/smith/cc_progs/a.out": can't open to read symbols:
                                 Invalid bfd target.
(gdb) show g
The current BFD target is "=4".

程序变量g未更改,并且为无效值。为了将内容写入变量 g,使用

(gdb) set var g=4
  • 向任意内存地址中写入内容
    GDB比C允许更多的隐式转换。你可以将整数值自由地存储到指针变量中,反之亦然,并且可以将任何结构转换为长度相同或更短的任何其他结构。
    要将值存储到内存中的任意位置,可以使用’{…}'结构,以在指定的地址生成指定类型的值。

例如,{int}0x83040将内存位置0x83040表示为整数(表示内存中的特定大小和表示形式),然后

set {int}0x83040 = 4

将值4存储到该存储位置。

f是显示方式:x16进制、d 10进制、u 6进制无符号、c 字符格式、f 浮点数格式。u是一种地址的单元长度:b 单字节、h 双字节、w 四字节、g 八字节;x /4d 地址名: 以十进制形式显示改地址的4个bytes。2、x /nb 地址: 查看该地址n个bytes的内容。3、 x /s 地址名:该地址以字符串形式的内容。1、 p &变量名:查看变量的地址。或者 x /30b 结构体地址。格式: x /选项 内存地址。n是要显示的内存单元个数。 当你面对内存泄露的时候, 该程序时刻监视着你程序的内存使用情况. 你甚至可以用gdb 单步执行你的程序,来观察监视程序所报的内存使用量. 如此便能找到是谁(哪个函数?哪行代码)占用了内存. linux 下的程序, 有源代码, 你可以修改程序成更顺手的工具. C++的同学想必有太多和内存打交道的血泪经验了,常常被 C++的内存问题搅的焦头烂额。( core 的经验了)有很多同学一见到 core 就两眼一抹黑,不知所措了。笔者 入"坑"C++之后,在调试 C++代码的过程之中,学习了不少调试代码内存的工具。希望借这个机会来介绍一下笔者常用的工具,GDB,Valgrind等等,相信大家通过好好运用这些工具,能更好的驯服内存这匹"野马"... GDB 中为我们提供了查看内存的命令 x,它是 examine 命令的简,使用 x 命令查看内存数据的格式有很多种,这里的内存数据可以是任意类型。命令的详细介绍如下。 参数 f 的可选值: x 按十六进制格式显示变量。 d 按十进制格式显示变量。 u 按十六进制格式显示无符号整型。 o 按八进制格式显示变量。 t 按二进制格式显示变量。 a 按十六进制格式显示变量。 c 按字符格式显示变量。 f 按浮点数格式显示变量。 参数 u 的可选值: b 表示单字节 h 表示双字节 w 表示四字节 g 表示八 Linux/amd64的调用规则 为了方便调试,笔者在PC机上直接调试简单的内存相关的应用;这需要了解x86_64的ABI,该文档对函数调用制定了一些限定规则,其中重要的有两点,第一点是参数的传参(非浮点参数): User-level applications use as integer registers for passing the sequence: %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, 文章目录一、前言二、GDB 的定义三、一个例子四、总结 前文提到了分析的思路是从 OS 级别到代码的级别。但是到了代码级别之后呢,可能还需要动态调试代码,之前了 Java 的应用的代码动态调试工具。 性能工具之调试工具 GDB(你以为性能分析中用不到吗?) 并且之前在群里也有说要关于如何修改内存变量值的。所以这里也就一下。 后续系列文章的思路也是将我工作中遇得到的性能分析思路一一出来。 二、GDB 的定义 这次我们来 GDB 这个工具。来看看官方如何定义这个工具的: 样例代码 int age= 20; int *p_age = &age; NSLog(@"p_age = %p", p_age); //输出指针变量p_age指向值20所在内存的地址 NSLog(@"&p_age = %p", &p_age); //输出指针变量p_age本身的地址 2017-07-19 15:54:07.048 Test07 内存访问越界的定位 去年笔者分享了两篇内存访问越界的定位方法,第一种方法用到了mprotect系统调用设置内存属性,第二种方法则未用到该系统调用。两种方法对于调试用的简单应用都有效,不过笔者编的调试应用是单线程的。在具体的工作实践中,只用到过第一种方法;因此不确定第二种方法效果如何。笔者认为这两种方法有一些缺点,某些情况下甚至可能会失效,例如系统调用产生的内存访问越界:read(fd, buf, buflen + overflowsize)。此外,第二种方法需要知晓具体的内存分配的数据结构,笔者希望通过本 Overview:![examine指令参数](http://img.blog.csdn.net/20170629170625941?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFpZmVuZ19ndQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEa