<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>Debug - 标签 - 有价值炮灰</title>
        <link>https://evilpan.com/tags/debug/</link>
        <description>Debug - 标签 - 有价值炮灰</description>
        <generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>i@pppan.net (evilpan)</managingEditor>
            <webMaster>i@pppan.net (evilpan)</webMaster><copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright><lastBuildDate>Wed, 28 Oct 2015 22:40:00 &#43;0800</lastBuildDate><atom:link href="https://evilpan.com/tags/debug/" rel="self" type="application/rss+xml" /><item>
    <title>GDB调试笔记</title>
    <link>https://evilpan.com/2015/10/28/gdb-tips/</link>
    <pubDate>Wed, 28 Oct 2015 22:40:00 &#43;0800</pubDate><author>
        <name>evilpan</name>
    </author><guid>https://evilpan.com/2015/10/28/gdb-tips/</guid>
    <description><![CDATA[<p>GDB是在Linux命令行下对C/C++的程序进行调试常用的一个命令，
现将平时记录在本子上的笔记整理记录一下.</p>
<h1 id="一断点" class="headerLink">
    <a href="#%e4%b8%80%e6%96%ad%e7%82%b9" class="header-mark"></a>一、断点</h1><p>断点类型有breakpoints, watchpoints, catchpoints.</p>
<h2 id="1breakpoints" class="headerLink">
    <a href="#1breakpoints" class="header-mark"></a>1).breakpoints:　</h2><p>普通断点，程序运行到该点时暂停（此时此行尚未运行），是gdb中最常用的断点，相关命令为：</p>
<blockquote>
  <p><em>break [函数名，行数或者指令地址]  [condi]</em></p>
</blockquote><p>在指定地方加上断点
例：</p>
<blockquote>
  <p><em>(gdb) set $counter = 0</em><br>
<em>(gdb) break 26 if ++$counter == 99</em></p>
</blockquote><p>在第26行设置断点，每次触发断点的时候执行判断条件，仅在判断条件为真的时候使程序在断点处停止。在循环的debug中很好用。
类似的命令还有condition等。
<em>rbreak RE:</em><br>
在所有符合正则表达式RE的函数上加上断点</p>
<h2 id="2watchpoints" class="headerLink">
    <a href="#2watchpoints" class="header-mark"></a>2).watchpoints：</h2><p>也称为data breakpoints，在表达式值变化时停止执行的断点。</p>
<blockquote>
  <p><em>watch expr[thread threadnum]</em><br>
表达式可以是变量值，地址（如*(int *)0x12345678)或数学表达式。</p>
</blockquote><h2 id="3catchpoints" class="headerLink">
    <a href="#3catchpoints" class="header-mark"></a>3).catchpoints:</h2><p>程序事件断点，如c++异常</p>
<blockquote>
  <p><em>catch event</em> 　　:event可以是 throw或catch事件</p>
</blockquote><p><strong>查看断点：</strong></p>
<blockquote>
  <p><em>info breakpoint[n]</em>　
打印所有（或者第n个）断点信息，同 info break
<em>info watchpoints[n]</em>　　: 同上</p>
</blockquote><p><strong>删除断点：</strong></p>
<blockquote>
  <p><em>delete [断点号] [range&hellip;]</em>　　：range是断点号，空格分割</p>
<p><em>clear location</em> 　　:location是函数名，行数等</p>
<p><em>enable/disable</em>　　:使能/使失效断点，不删除</p>
</blockquote><p><strong>其他</strong></p>
<p>为断点号bnum写一个命令列表，程序运行到断点时gdb会依次运行列表中的命令:</p>
<blockquote>
  <p>commands [bnums]
　　&hellip;command list&hellip;
end</p>
</blockquote><h1 id="二单步调试" class="headerLink">
    <a href="#%e4%ba%8c%e5%8d%95%e6%ad%a5%e8%b0%83%e8%af%95" class="header-mark"></a>二、单步调试</h1><h2 id="1基本命令" class="headerLink">
    <a href="#1%e5%9f%ba%e6%9c%ac%e5%91%bd%e4%bb%a4" class="header-mark"></a>1）基本命令：</h2><blockquote>
  <p>*step:*运行下一步（即step into，进入调用的函数体内）
*next：*同上，但是不进入函数体
*finish：*往下运行直至当前栈帧（下面解释）中的函数返回
*continue：*往下运行直至遇到断点</p>
</blockquote><p><strong>打印信息：</strong></p>
<blockquote>
  <p><em>print/x data：</em>
以x（十六进制）格式打印数据data的值（或者缩写为p/x data）;
输出格式有x、d、u、o、t（二进制，two，因为b已经用来表示byte）、a（address）、c（char）、f（float）、s（string）、r（raw）　　　　　</p>
</blockquote><p>查看数据类型： ptype data;</p>
<p>打印数组： p *array@len</p>
<p>　　　　</p>
<h2 id="2栈帧stack-frame" class="headerLink">
    <a href="#2%e6%a0%88%e5%b8%a7stack-frame" class="header-mark"></a>2）栈帧（stack frame）</h2><p>stack frame 是在栈中为参数、返回地址和局部变量保留的一块内存区，必要时在过程调用中使用，相关命令：</p>
<blockquote>
  <p><em>frame[args]：</em>
从一个栈帧移动到另一个，并打印选择的栈帧。args可以是栈帧号或其地址。
<em>info frame []：</em>
查看栈帧的详细信息
<em>backtrace：</em>
向后追踪栈帧（调用）</p>
</blockquote><p>##3）底层信息：</p>
<p>**查看汇编：**disassemble [option] [range]</p>
<p>接收一个参数时，打印该地址周围的函数的汇编，接收两个参数时，表示需要dump的范围</p>
<p>**查看内存：**x  /nfu addr</p>
<p>n：重复数。默认为1,表示要显示多少内存（以单元u为基数）</p>
<p>f：显示格式。同print，默认为x， i表示机器指令</p>
<p>u：单元大小。分别可以是b（byte）、h（halfwords，=2byte）、w（words，=4byte）和g（gaint words，=8byte）;默认为w</p>
<p>　　寄存器：</p>
<p>$pc：程序计数器，值为下一条指令的地址</p>
<p>$ps：程序状态寄存器</p>
<p>$sp：stack pointer栈指针</p>
<p>$fp：frame pointer 指向当前栈帧的指针</p>
<h1 id="三变更执行" class="headerLink">
    <a href="#%e4%b8%89%e5%8f%98%e6%9b%b4%e6%89%a7%e8%a1%8c" class="header-mark"></a>三、变更执行</h1><h2 id="1修改变量" class="headerLink">
    <a href="#1%e4%bf%ae%e6%94%b9%e5%8f%98%e9%87%8f" class="header-mark"></a>1）修改变量</h2><blockquote>
  <p>print i=num，赋值并打印变量i
set i=num，仅赋值</p>
</blockquote><h2 id="2修改内存" class="headerLink">
    <a href="#2%e4%bf%ae%e6%94%b9%e5%86%85%e5%ad%98" class="header-mark"></a>2）修改内存</h2><p>　　用&rsquo;{&hellip;}&lsquo;结构来生成地址。如：</p>
<blockquote>
  <p><em>set {int}0x83040 = 4;　　//将4存储到地址0x83040中</em></p>
</blockquote><h2 id="3跳转" class="headerLink">
    <a href="#3%e8%b7%b3%e8%bd%ac" class="header-mark"></a>3）跳转</h2><blockquote>
  <p>jump [location]</p>
</blockquote><p>location可以是行号或者地址。注意jump命令仅仅改变$pc的值，而不改变当前栈帧、堆栈指针或上下文，效果相当于set $pc = {int}location</p>
<h2 id="4中断" class="headerLink">
    <a href="#4%e4%b8%ad%e6%96%ad" class="header-mark"></a>4）中断</h2><blockquote>
  <p><em>signal sig</em>
立即将信号sig发给程序</p>
</blockquote><h2 id="5其他" class="headerLink">
    <a href="#5%e5%85%b6%e4%bb%96" class="header-mark"></a>5）其他</h2><blockquote>
  <p>return：使（函数）返回</p>
</blockquote>]]></description>
</item></channel>
</rss>
