You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

965 lines
58 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="zh-cn" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="GDB # GDBGNU symbolic Debugger是Linux系统下的强大的调试工具可以用来调试ada, c, c&#43;&#43;, asm, minimal, d, fortran, objective-c, go, java,pascal 等多种语言。
我们以调试 go 代码为示例来介绍GDB的使用。源码内容如下
package main import &#34;fmt&#34; func add(a, b int) int { sum := 0 sum = a &#43; b return sum } func main() { sum := add(10, 20) fmt.Println(sum) } 构建二进制应用:
go build -gcflags=&#34;-N -l&#34; -o test main.go 启动调试 # gdb ./test # 启动调试 gdb --args ./test arg1 arg2 # 指定参数启动调试 进入gdb调试界面之后执行 run 命令运行程序。若程序已经运行,我们可以 attach 该程序的进程id进行调试:">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#343a40">
<meta name="color-scheme" content="light dark"><meta property="og:title" content="GDB" />
<meta property="og:description" content="GDB # GDBGNU symbolic Debugger是Linux系统下的强大的调试工具可以用来调试ada, c, c&#43;&#43;, asm, minimal, d, fortran, objective-c, go, java,pascal 等多种语言。
我们以调试 go 代码为示例来介绍GDB的使用。源码内容如下
package main import &#34;fmt&#34; func add(a, b int) int { sum := 0 sum = a &#43; b return sum } func main() { sum := add(10, 20) fmt.Println(sum) } 构建二进制应用:
go build -gcflags=&#34;-N -l&#34; -o test main.go 启动调试 # gdb ./test # 启动调试 gdb --args ./test arg1 arg2 # 指定参数启动调试 进入gdb调试界面之后执行 run 命令运行程序。若程序已经运行,我们可以 attach 该程序的进程id进行调试:" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://go.cyub.vip/analysis-tools/gdb/" /><meta property="article:section" content="analysis-tools" />
<title>GDB | 深入Go语言之旅</title>
<link rel="manifest" href="/manifest.json">
<link rel="icon" href="/favicon.png" >
<link rel="stylesheet" href="/book.min.f06572240ce28e67eb332ac5cf5d59a696c47ad4c6f700d5842c5ed93dd8ec77.css" integrity="sha256-8GVyJAzijmfrMyrFz11ZppbEetTG9wDVhCxe2T3Y7Hc=" crossorigin="anonymous">
<script defer src="/flexsearch.min.js"></script>
<script defer src="/en.search.min.93e09a692e83129c8b0cc95c521eab7d4f5256b35651cf852c4ad4185bdc55a5.js" integrity="sha256-k&#43;CaaS6DEpyLDMlcUh6rfU9SVrNWUc&#43;FLErUGFvcVaU=" crossorigin="anonymous"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BQ229RRTTX"></script>
<script>
var doNotTrack = false;
if (!doNotTrack) {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-BQ229RRTTX', { 'anonymize_ip': false });
}
</script>
<!--
Made with Book Theme
https://github.com/alex-shpak/hugo-book
-->
</head>
<body dir="ltr">
<input type="checkbox" class="hidden toggle" id="menu-control" />
<input type="checkbox" class="hidden toggle" id="toc-control" />
<main class="container flex">
<aside class="book-menu">
<div class="book-menu-content">
<nav>
<h2 class="book-brand">
<a class="flex align-center" href="/"><img src="https://static.cyub.vip/images/202310/golang-480.png" alt="Logo" /><span>深入Go语言之旅</span>
</a>
</h2>
<div class="book-search">
<input type="text" id="book-search-input" placeholder="Search" aria-label="Search" maxlength="64" data-hotkeys="s/" />
<div class="book-search-spinner hidden"></div>
<ul id="book-search-results"></ul>
</div>
<ul>
<li>
<a href="https://www.cyub.vip/" target="_blank" rel="noopener">
个人博客
</a>
</li>
<li>
<a href="https://github.com/cyub" target="_blank" rel="noopener">
Github主页
</a>
</li>
<li>
<a href="https://www.topgoer.cn/?ref=go.cyub.vip" target="_blank" rel="noopener">
地鼠文档
</a>
</li>
</ul>
<ul>
<li>
<p><strong>
<a href="/">深入Go语言之旅</a></strong></p>
</li>
<li>
<p><strong>准备篇</strong></p>
<ul>
<li>
<a href="/compiler/">编译流程</a></li>
<li>
<a href="/analysis-tools/">分析工具</a>
<ul>
<li>
<a href="/analysis-tools/gdb/"class=active>GDB</a></li>
<li>
<a href="/analysis-tools/dlv/">Delve</a></li>
<li>
<a href="/analysis-tools/go-buildin-tools/">Go 内置工具</a></li>
</ul>
</li>
<li>
<a href="/go-assembly/">Go汇编</a></li>
</ul>
</li>
<li>
<p><strong>基础篇</strong></p>
<ul>
<li>
<a href="/type/">数据类型与数据结构</a>
<ul>
<li>
<a href="/type/string/">字符串</a></li>
<li>
<a href="/type/array/">数组</a></li>
<li>
<a href="/type/slice/">切片</a></li>
<li>
<a href="/type/nil/">nil</a></li>
<li>
<a href="/type/empty_struct/">空结构体</a></li>
<li>
<a href="/type/pointer/">指针</a></li>
<li>
<a href="/type/map/">映射</a></li>
</ul>
</li>
<li>
<a href="/function/">函数</a>
<ul>
<li>
<a href="/function/first-class/">一等公民</a></li>
<li>
<a href="/function/call-stack/">函数调用栈</a></li>
<li>
<a href="/function/pass-by-value/">值传递</a></li>
<li>
<a href="/function/closure/">闭包</a></li>
<li>
<a href="/function/method/">方法</a></li>
</ul>
</li>
<li>
<a href="/feature/">语言特性</a>
<ul>
<li>
<a href="/feature/comma-ok/">逗号ok模式</a></li>
<li>
<a href="/feature/for-range/">遍历 - for-range语法</a></li>
<li>
<a href="/feature/defer/">延迟执行 - defer语法</a></li>
<li>
<a href="/feature/select/">通道选择器 - select语法</a></li>
<li>
<a href="/feature/panic-recover/">恐慌与恢复 - panic/recover</a></li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong>运行时篇</strong></p>
<ul>
<li>
<a href="/concurrency/">并发编程</a>
<ul>
<li>
<a href="/concurrency/memory-model/">内存模型</a></li>
<li>
<a href="/concurrency/context/">上下文 - context</a></li>
<li>
<a href="/concurrency/channel/">通道 - channel</a></li>
<li>
<a href="/concurrency/atomic/">原子操作 - atomic</a></li>
<li>
<a href="/concurrency/sync-map/">并发Map - sync.Map</a></li>
<li>
<a href="/concurrency/sync-waitgroup/">等待组 - sync.WaitGroup</a></li>
<li>
<a href="/concurrency/sync-once/">一次性操作 - sync.Once</a></li>
<li>
<a href="/concurrency/sync-pool/">缓冲池 - sync.Pool</a></li>
<li>
<a href="/concurrency/sync-cond/">条件变量 - sync.Cond</a></li>
<li>
<a href="/concurrency/sync-mutex/">互斥锁 - sync.Mutex</a></li>
<li>
<a href="/concurrency/sync-rwmutex/">读写锁 - sync.RWMutex</a></li>
</ul>
</li>
<li>
<a href="/gmp/">G-M-P调度机制</a>
<ul>
<li>
<a href="/gmp/gmp-model/">调度机制概述</a></li>
<li>
<a href="/gmp/scheduler/">调度器</a></li>
</ul>
</li>
<li>
<a href="/memory/">内存管理</a>
<ul>
<li>
<a href="/memory/allocator/">内存分配器</a></li>
<li>
<a href="/memory/gc/">GC</a></li>
</ul>
</li>
<li>
<a href="/type-system/">类型系统</a>
<ul>
<li>
<a href="/type-system/type/">类型系统</a></li>
<li>
<a href="/type-system/interface/">接口</a></li>
<li>
<a href="/type-system/reflect/">反射</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
<script>(function(){var e=document.querySelector("aside .book-menu-content");addEventListener("beforeunload",function(){localStorage.setItem("menu.scrollTop",e.scrollTop)}),e.scrollTop=localStorage.getItem("menu.scrollTop")})()</script>
</div>
</aside>
<div class="book-page">
<header class="book-header">
<div class="flex align-center justify-between">
<label for="menu-control">
<img src="/svg/menu.svg" class="book-icon" alt="Menu" />
</label>
<strong>GDB</strong>
<label for="toc-control">
</label>
</div>
</header>
<article class="markdown"><h1 id="gdb">
GDB
<a class="anchor" href="#gdb">#</a>
</h1>
<p><strong>GDB</strong>GNU symbolic Debugger是Linux系统下的强大的调试工具可以用来调试ada, c, c++, asm, minimal, d, fortran, objective-c, go, java,pascal 等多种语言。</p>
<p>我们以调试 <code>go</code> 代码为示例来介绍GDB的使用。源码内容如下</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">a</span>, <span style="color:#a6e22e">b</span> <span style="color:#66d9ef">int</span>) <span style="color:#66d9ef">int</span> {
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">sum</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">sum</span> = <span style="color:#a6e22e">a</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">b</span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">sum</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">sum</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">add</span>(<span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">20</span>)
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">sum</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>构建二进制应用:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>go build -gcflags<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;-N -l&#34;</span> -o test main.go
</span></span></code></pre></div><h2 id="启动调试">
启动调试
<a class="anchor" href="#%e5%90%af%e5%8a%a8%e8%b0%83%e8%af%95">#</a>
</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>gdb ./test <span style="color:#75715e"># 启动调试</span>
</span></span><span style="display:flex;"><span>gdb --args ./test arg1 arg2 <span style="color:#75715e"># 指定参数启动调试</span>
</span></span></code></pre></div><p>进入gdb调试界面之后执行 <code>run</code> 命令运行程序。若程序已经运行,我们可以 <code>attach</code> 该程序的进程id进行调试:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ gdb
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> attach <span style="color:#ae81ff">1785</span>
</span></span></code></pre></div><p>当执行 <code>attach</code> 命令的时候GDB首先会在当前工作目录下查找进程的可执行程序如果没有找到接着会用源代码文件搜索路径。我们也可以用file命令来加载可执行文件。</p>
<p>或者通过命令设置进程id:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>gdb test <span style="color:#ae81ff">1785</span>
</span></span><span style="display:flex;"><span>gdb test --pid <span style="color:#ae81ff">1785</span>
</span></span></code></pre></div><p>若已运行的进程不含调试信息,我们可以使用同样代码编译出一个带调试信息的版本,然后使用 <code>file</code><code>attach</code> 命令进行运行调试。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ gdb
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> file test
</span></span><span style="display:flex;"><span>Reading symbols from test...done.
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> attach <span style="color:#ae81ff">1785</span>
</span></span></code></pre></div><h3 id="可视化窗口">
可视化窗口
<a class="anchor" href="#%e5%8f%af%e8%a7%86%e5%8c%96%e7%aa%97%e5%8f%a3">#</a>
</h3>
<p>GDB也支持多窗口图形启动运行一个窗口显示源码信息一个窗口显示调试信息</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>gdb test -tui
</span></span></code></pre></div><p>GDB支持在运行过程中使用 <code>Crtl+X+A</code> 组合键进入多窗口图形界面, GDB支持的快捷操作有</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Crtl+X+A // 多窗口与单窗口界面切换
</span></span><span style="display:flex;"><span>Ctrl + X + <span style="color:#ae81ff">2</span> // 显示两个窗口
</span></span><span style="display:flex;"><span>Ctrl + X + <span style="color:#ae81ff">1</span> // 显示一个窗口
</span></span></code></pre></div><h2 id="运行程序">
运行程序
<a class="anchor" href="#%e8%bf%90%e8%a1%8c%e7%a8%8b%e5%ba%8f">#</a>
</h2>
<p>通过 <code>run</code> 命令运行程序, <code>run</code> 命令可以简写成 <code>r</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> run
</span></span></code></pre></div><p>除了启动GDB时候设置程序的命令行参数外我们也可以在启动GDB后再指定程序的命令行参数</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> run arg1 arg2
</span></span></code></pre></div><p>或者通过 <code>set</code> 命令设置命令行参数:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> set args arg1 arg2
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> run
</span></span></code></pre></div><p>除了 <code>run</code> 命令外,我们也可以使用 <code>start</code> 命令运行程序。<code>start</code> 命令会在在 <code>main</code> 函数的第一条语句前面停下来。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> start
</span></span></code></pre></div><p><code>start</code> 命令相当于在Go程序的入口函数 <code>main.main</code> (<code>main.main</code> 代表 <code>main</code> 包的 <code>main</code> 函数)处设置断点,然后运行 <code>run</code> 命令:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> b main.main
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> run
</span></span></code></pre></div><h2 id="断点的设置查看删除禁用">
断点的设置、查看、删除、禁用
<a class="anchor" href="#%e6%96%ad%e7%82%b9%e7%9a%84%e8%ae%be%e7%bd%ae%e6%9f%a5%e7%9c%8b%e5%88%a0%e9%99%a4%e7%a6%81%e7%94%a8">#</a>
</h2>
<h3 id="设置断点">
设置断点
<a class="anchor" href="#%e8%ae%be%e7%bd%ae%e6%96%ad%e7%82%b9">#</a>
</h3>
<p>GDB中是通过 <code>break</code> 命令来设置断点(BreakPoint)<code>break</code> 可以简写成 <code>b</code></p>
<ul>
<li>
<p>break function</p>
<p>在指定函数出设置断点,设置断点后程序会在进入指定函数时停住</p>
</li>
<li>
<p><strong>break linenum</strong></p>
<p>在指定行号处设置断点</p>
</li>
<li>
<p>break +offset/-offset</p>
<p>在当前行号的前面或后面的offset行处设置断点。offset为自然数</p>
</li>
<li>
<p>break filename:linenum</p>
<p>在源文件filename的linenum行处设置断点</p>
</li>
<li>
<p>break filename:function</p>
<p>在源文件filename的function函数的入口处设置断点</p>
</li>
<li>
<p><strong>break *address</strong></p>
<p>在程序运行的内存地址处设置断点</p>
</li>
<li>
<p>break</p>
<p>break命令没有参数时表示在下一条指令处停住。</p>
</li>
<li>
<p>break &hellip; if <!-- raw HTML omitted --></p>
<p>&hellip;可以是上述的参数condition表示条件在条件成立时停住。比如在循环境体中可以设置break if i=100表示当i为100时停住程序</p>
</li>
</ul>
<h3 id="查看断点">
查看断点
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e6%96%ad%e7%82%b9">#</a>
</h3>
<p>我们可以通过 <code>info</code> 命令查看断点:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> info breakpoint <span style="color:#75715e"># 查看所有断点</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> info breakpoint <span style="color:#ae81ff">3</span> <span style="color:#75715e"># 查看3号断点</span>
</span></span></code></pre></div><h3 id="删除断点">
删除断点
<a class="anchor" href="#%e5%88%a0%e9%99%a4%e6%96%ad%e7%82%b9">#</a>
</h3>
<p>删除断点是通过 <code>delete</code> 命令删除的,<code>delete</code> 命令可以简写成 <code>d</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> delete <span style="color:#ae81ff">3</span> <span style="color:#75715e"># 删除3号断点</span>
</span></span></code></pre></div><h3 id="断点启用与禁用">
断点启用与禁用
<a class="anchor" href="#%e6%96%ad%e7%82%b9%e5%90%af%e7%94%a8%e4%b8%8e%e7%a6%81%e7%94%a8">#</a>
</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> disable <span style="color:#ae81ff">3</span> <span style="color:#75715e"># 禁用3号断点</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> enable <span style="color:#ae81ff">3</span> <span style="color:#75715e"># 启用3号断点</span>
</span></span></code></pre></div><h2 id="调试">
调试
<a class="anchor" href="#%e8%b0%83%e8%af%95">#</a>
</h2>
<h3 id="单步执行">
单步执行
<a class="anchor" href="#%e5%8d%95%e6%ad%a5%e6%89%a7%e8%a1%8c">#</a>
</h3>
<p><code>next</code> 用于单步执行,会一行行执行代码,运到函数时候,不会进入到函数内部,跳过该函数,但会执行该函数,即 <code>step over</code>。可以简写成 <code>n</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> next
</span></span></code></pre></div><h3 id="单步进入">
单步进入
<a class="anchor" href="#%e5%8d%95%e6%ad%a5%e8%bf%9b%e5%85%a5">#</a>
</h3>
<p><code>step</code> 用于单步进入执行,跟 <code>next</code> 命令类似,但是遇到函数时候,会进入到函数内部一步步执行,即 <code>step into</code>。可以简写成 <code>s</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> step
</span></span></code></pre></div><p><code>step</code> 相关的命令 <code>stepi</code>,用于每次执行每次执行一条机器指令。可以简写成 <code>si</code></p>
<h3 id="继续执行到下一个断点">
继续执行到下一个断点
<a class="anchor" href="#%e7%bb%a7%e7%bb%ad%e6%89%a7%e8%a1%8c%e5%88%b0%e4%b8%8b%e4%b8%80%e4%b8%aa%e6%96%ad%e7%82%b9">#</a>
</h3>
<p><code>continue</code> 命令会继续执行程序,直到再次遇到断点处。可以简写成 <code>c</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> <span style="color:#66d9ef">continue</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> <span style="color:#66d9ef">continue</span> <span style="color:#ae81ff">3</span> <span style="color:#75715e"># 跳过3个断点</span>
</span></span></code></pre></div><h3 id="继续运行到指定位置">
继续运行到指定位置
<a class="anchor" href="#%e7%bb%a7%e7%bb%ad%e8%bf%90%e8%a1%8c%e5%88%b0%e6%8c%87%e5%ae%9a%e4%bd%8d%e7%bd%ae">#</a>
</h3>
<p><code>until</code> 命令可以帮助我们实现运行到某一行停住,可以简写成 <code>u</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> <span style="color:#66d9ef">until</span> <span style="color:#ae81ff">5</span>
</span></span></code></pre></div><h3 id="跳过执行">
跳过执行
<a class="anchor" href="#%e8%b7%b3%e8%bf%87%e6%89%a7%e8%a1%8c">#</a>
</h3>
<p><code>skip</code> 命令可以在step时跳过一些不想关注的函数或者某个文件的代码:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> skip <span style="color:#66d9ef">function</span> add <span style="color:#75715e"># step时跳过add函数</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> info skip <span style="color:#75715e"># 查看skip列表</span>
</span></span></code></pre></div><p>其他相关的命令:</p>
<ul>
<li>skip delete [num] 删除skip</li>
<li>skip enable [num] 启动skip</li>
<li>skip disable [num] 关闭skip</li>
</ul>
<p><strong>注意:</strong> 当不带skip号时候是针对所有skip进行设置。</p>
<h3 id="执行完成当前函数">
执行完成当前函数
<a class="anchor" href="#%e6%89%a7%e8%a1%8c%e5%ae%8c%e6%88%90%e5%bd%93%e5%89%8d%e5%87%bd%e6%95%b0">#</a>
</h3>
<p><code>finish</code> 命令用来将当前函数执行完成,并打印函数返回时的堆栈地址、返回值、参数值等信息,即<code>step out</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> finish
</span></span></code></pre></div><h2 id="查看源码">
查看源码
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e6%ba%90%e7%a0%81">#</a>
</h2>
<p>GDB中的 <code>list</code> 命令用来显示源码信息。<code>list</code> 命令可以简写成 <code>l</code></p>
<ul>
<li>
<p><strong>list</strong></p>
<p>从第一行开始显示源码继续输入list可列出后面的源码</p>
</li>
<li>
<p><strong>list linenum</strong></p>
<p>列出linenum行附近的源码</p>
</li>
<li>
<p><strong>list function</strong></p>
<p>列出函数function的代码</p>
</li>
<li>
<p>list filename:linenum</p>
<p>列出文件filename文件中linenum行出的代码</p>
</li>
<li>
<p>list filename:function</p>
<p>列出文件filename中函数function的代码</p>
</li>
<li>
<p>list +offset/-offset</p>
<p>列出在当前行号的前面或后面的offset行附近的代码。offset为自然数。</p>
</li>
<li>
<p>list +/-</p>
<p>列出当前行后面或者前面的代码</p>
</li>
<li>
<p>list linenum1, linenum2</p>
<p>列出行linenum1和linenum2之间的代码</p>
</li>
</ul>
<h2 id="查看信息">
查看信息
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e4%bf%a1%e6%81%af">#</a>
</h2>
<p><code>info</code> 命令用来显示信息,可以简写成 <code>i</code></p>
<ul>
<li>
<p><strong>info files</strong></p>
<p>显示当前的调试的文件,包含程序入口地址,内存分段布局位置信息等</p>
</li>
<li>
<p>info breakpoints</p>
<p>显示当前设置的断点列表</p>
</li>
<li>
<p>info registers</p>
<p>显示当前寄存器的值,可以简写成 <code>i r</code>。指定寄存器名称,可以查看具体寄存器信息:<code>i r rsp</code></p>
</li>
<li>
<p>info all-registers</p>
<p>显示所有寄存器的值。GDB提供四个标准寄存器<code>pc</code> 是程序计数器寄存器,<code>sp</code> 是堆栈指针。<code>fp</code> 用于记录当前堆栈帧的指针,<code>ps</code> 用于记录处理器状态的寄存器。GDB会处理好不同架构系统寄存器不一致问题比如对于 <code>amd64</code> 架构,<code>pc</code> 对应就是 <code>rip</code> 寄存器。</p>
<p>引用寄存器内容是将寄存器名前置 <code>$</code> 符作为变量来用。比如 <code>$pc</code> 就是程序计数器寄存器值。</p>
</li>
<li>
<p>info args</p>
<p>显示当前函数参数</p>
</li>
<li>
<p>info locals</p>
<p>显示当前局部变量</p>
</li>
<li>
<p><strong>info frame</strong></p>
<p>查看当前栈帧的详细信息,包括 <code>rip</code> 信息,正在运行的指令所在文件位置</p>
</li>
<li>
<p>info variables</p>
<p>查看程序中的变量符号</p>
</li>
<li>
<p>info functions</p>
<p>查看程序中的函数符号</p>
</li>
<li>
<p>info functions regexp</p>
<p>通过正则匹配来查看程序中的函数符号</p>
</li>
<li>
<p>info goroutines</p>
<p>显示当前执行的 <code>goroutine</code> 列表,带 <code>*</code> 的表示当前执行的。注意需要加载 <code>go runtime</code> 支持。</p>
</li>
<li>
<p>info stack</p>
<p>查看栈信息</p>
</li>
<li>
<p>info proc mappings</p>
<p>可以简写成 <code>i proc m</code>。用来查看应用内存映射</p>
</li>
<li>
<p>info proc [procid]</p>
<p>显示进程信息</p>
</li>
<li>
<p>info proc status</p>
<p>显示进程相关信息包括user id和group id进程内有多少线程虚拟内存的使用情况挂起的信号阻塞的信号忽略的信号TTY消耗的系统和用户时间堆栈大小nice值</p>
</li>
<li>
<p>info display</p>
</li>
<li>
<p>info watchpoints</p>
<p>列出当前所设置了的所有观察点</p>
</li>
<li>
<p>info line [linenum]</p>
<p>查看第 <code>linenum</code> 的代码指令地址信息,不带 <code>linenum</code> 时,显示的是当前位置的指令地址信息</p>
</li>
<li>
<p>info source</p>
<p>显示此源代码的源代码语言</p>
</li>
<li>
<p>info sources</p>
<p>显示程序中所有有调试信息的源文件名,一共显示两个列表:一个是其符号信息已经读过的,一个是还未读取过的</p>
</li>
<li>
<p>info types</p>
<p>显示程序中所有类型符号</p>
</li>
<li>
<p>info types regexp</p>
<p>通过正则匹配来查看程序中的类型符号</p>
</li>
</ul>
<p>其他类似命令有:</p>
<ul>
<li>
<p>show args</p>
<p>查看命令行参数</p>
</li>
<li>
<p>show environment [envname]</p>
<p>查看环境变量信息</p>
</li>
<li>
<p>show paths</p>
<p>查看程序的运行路径</p>
</li>
<li>
<p>whatis var1</p>
<p>显示变量var1类型</p>
</li>
<li>
<p>ptype var1</p>
<p>显示变量 <code>var1</code> 类型,若是 <code>var1</code> 结构体类型,会显示该结构体定义信息。</p>
</li>
</ul>
<h2 id="查看调用栈">
查看调用栈
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e8%b0%83%e7%94%a8%e6%a0%88">#</a>
</h2>
<p>通过 <code>where</code> 可以查看调用栈信息:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> where
</span></span><span style="display:flex;"><span><span style="color:#75715e">#0 _rt0_amd64 ()</span>
</span></span><span style="display:flex;"><span> at /usr/lib/go/src/runtime/asm_amd64.s:15
</span></span><span style="display:flex;"><span><span style="color:#75715e">#1 0x0000000000000001 in ?? ()</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#2 0x00007fffffffdd2c in ?? ()</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#3 0x0000000000000000 in ?? ()</span>
</span></span></code></pre></div><h2 id="设置观察点">
设置观察点
<a class="anchor" href="#%e8%ae%be%e7%bd%ae%e8%a7%82%e5%af%9f%e7%82%b9">#</a>
</h2>
<p>通过 <code>watch</code> 命令,可以设置观察点。当观察点的变量发生变化时,程序会停下来。可以简写成 <code>wa</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> watch sum
</span></span></code></pre></div><h2 id="查看汇编代码">
查看汇编代码
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e6%b1%87%e7%bc%96%e4%bb%a3%e7%a0%81">#</a>
</h2>
<p>我们可以通过开启 <code>disassemble-next-line</code> 自动显示汇编代码。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> set disassemble-next-line on
</span></span></code></pre></div><p>当面我们可以查看指定函数的汇编代码:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> disassemble main.main
</span></span></code></pre></div><p><code>disassemble</code> 可以简写成 <code>disas</code>。我们也可以将源代码和汇编代码一一映射起来后进行查看</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> disas /m main.main
</span></span></code></pre></div><p>GDB默认显示汇编指令格式是 <code>AT&amp;T</code> 格式,我们可以改成 <code>intel</code> 格式:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> set disassembly-flavor intel
</span></span></code></pre></div><h2 id="自动显示变量值">
自动显示变量值
<a class="anchor" href="#%e8%87%aa%e5%8a%a8%e6%98%be%e7%a4%ba%e5%8f%98%e9%87%8f%e5%80%bc">#</a>
</h2>
<p><code>display</code> 命令支持自动显示变量值功能。当进行 <code>next</code> 或者 <code>step</code> 等调试操作时候GDB会自动显示 <code>display</code> 所设置的变量或者地址的值信息。</p>
<p><code>display</code> 命令格式:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>display &lt;expr&gt;
</span></span><span style="display:flex;"><span>display /&lt;fmt&gt; &lt;expr&gt;
</span></span><span style="display:flex;"><span>display /&lt;fmt&gt; &lt;addr&gt;
</span></span></code></pre></div><ul>
<li>expr是一个表达式</li>
<li>fmt表示显示的格式</li>
<li>addr表示内存地址</li>
</ul>
<p>其他相关命令:</p>
<ul>
<li>undisplay [num]: 不显示</li>
<li>delete display [num]: 删除</li>
<li>disable display [num]: 关闭自动显示</li>
<li>enable display [num] 开启自动显示</li>
<li>info display: 查看display信息</li>
</ul>
<p><strong>注意:</strong> 当不带display号时候是针对所有display进行设置。</p>
<h2 id="显示将要执行的汇编指令">
显示将要执行的汇编指令
<a class="anchor" href="#%e6%98%be%e7%a4%ba%e5%b0%86%e8%a6%81%e6%89%a7%e8%a1%8c%e7%9a%84%e6%b1%87%e7%bc%96%e6%8c%87%e4%bb%a4">#</a>
</h2>
<p>我们可以通过 <code>display</code> 命令可以实现当程序停止时,查看将要执行的汇编指令:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> display /i $pc
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> display /3i $pc <span style="color:#75715e"># 一次性显示3条指令</span>
</span></span></code></pre></div><p>取消显示可以用 <code>undisplay</code> 命令进行操作。</p>
<h2 id="查看backtrace信息">
查看backtrace信息
<a class="anchor" href="#%e6%9f%a5%e7%9c%8bbacktrace%e4%bf%a1%e6%81%af">#</a>
</h2>
<p><code>backtrace</code> 命令用来查看栈帧信息。可以简写成 <code>bt</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> backtrace <span style="color:#75715e"># 显示当前函数的栈帧以及局部变量信息</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> backtrace full <span style="color:#75715e"># 显示各个函数的栈帧以及局部变量值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> backtrace full n <span style="color:#75715e"># 从内向外显示n个栈桢及其局部变量</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> backtrace full -n <span style="color:#75715e"># 从外向内显示n个栈桢及其局部变量</span>
</span></span></code></pre></div><h2 id="切换栈帧信息">
切换栈帧信息
<a class="anchor" href="#%e5%88%87%e6%8d%a2%e6%a0%88%e5%b8%a7%e4%bf%a1%e6%81%af">#</a>
</h2>
<p><code>frame</code> 命令可以切换栈帧信息:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> frame n <span style="color:#75715e"># 其中n是层数最内层的函数帧为第0帧</span>
</span></span></code></pre></div><p>其他相关命令:</p>
<ul>
<li>info frame: 查看栈帧列表</li>
</ul>
<h2 id="调试多线程">
调试多线程
<a class="anchor" href="#%e8%b0%83%e8%af%95%e5%a4%9a%e7%ba%bf%e7%a8%8b">#</a>
</h2>
<p>GDB中有一组命令能够辅助多线程的调试</p>
<ul>
<li>
<p>info threads</p>
<p>显示当前可调式的所有线程,线程 ID 前有 “*” 表示当前被调试的线程。</p>
</li>
<li>
<p>thread threadid</p>
<p>切换线程到线程threadid</p>
</li>
<li>
<p>set scheduler-locking [on|off|step]</p>
<p>多线程环境下,会存在多个线程运行,这会影响调试某个线程的结果,这个命令可以设置调试的时候多个线程的运行情况,<code>on</code> 表示只有当前调试的线程会继续执行,<code>off</code> 表示不屏蔽任何线程,所有线程都可以执行,<code>step</code> 表示在单步执行时,只有当前线程会执行。</p>
</li>
<li>
<p>thread apply [threadid] [all] args</p>
<p>对线程列表执行命令。比如通过 <code>thread apply all bt full</code> 可以查看所有线程的局部变量信息。</p>
</li>
</ul>
<h2 id="查看运行时变量">
查看运行时变量
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e8%bf%90%e8%a1%8c%e6%97%b6%e5%8f%98%e9%87%8f">#</a>
</h2>
<p><code>print</code> 命令可以用来查看变量的值。<code>print</code> 命令可以简写成 <code>p</code><code>print</code> 命令格式如下:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>print <span style="color:#f92672">[</span>&lt;/format&gt;<span style="color:#f92672">]</span> &lt;expr&gt;
</span></span></code></pre></div><p><code>format</code> 用来设置显示变量的格式,是可选的选项。其可用值如下所示:</p>
<ul>
<li>x 按十六进制格式显示变量</li>
<li>d 按十进制格式显示变量</li>
<li>u 按十六进制格式显示无符号整型</li>
<li>o 按八进制格式显示变量</li>
<li>t 按二进制格式显示变量</li>
<li>a 按十六进制格式显示变量</li>
<li>c 按字符格式显示变量</li>
<li>f 按浮点数格式显示变量</li>
<li>z 按十六进制格式显示变量,左侧填充零</li>
</ul>
<p><code>expr</code> 可以是一个变量,也可以是表达式,也可以是寄存器:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> p var1 <span style="color:#75715e"># 打印变量var1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> p &amp;var1 <span style="color:#75715e"># 打印变量var1地址</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> p $rsp <span style="color:#75715e"># 打印rsp寄存器地址</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> p $rsp + <span style="color:#ae81ff">8</span> <span style="color:#75715e"># 打印rsp加8后的地址信息</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> p 0xc000068fd0 <span style="color:#75715e"># 打印0xc000068fd0转换成10进制格式</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> p /x <span style="color:#ae81ff">824634150864</span> <span style="color:#75715e"># 打印824634150864转换成16进制格式</span>
</span></span></code></pre></div><p><code>print</code> 也支持查看连续内存,<code>@</code> 操作符用于查看连续内存,<code>@</code> 的左边是第一个内存的地址的值,<code>@</code> 的右边则想查看内存的长度。</p>
<p>例如对于如下代码:<code>int arr[] = {2, 4, 6, 8, 10};</code>,可以通过如下命令查看 <code>arr</code> 前三个单元的数据:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> p *arr@3
</span></span><span style="display:flex;"><span>$2 <span style="color:#f92672">=</span> <span style="color:#f92672">{</span>2, 4, 6<span style="color:#f92672">}</span>
</span></span></code></pre></div><h2 id="查看内存中的值">
查看内存中的值
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e5%86%85%e5%ad%98%e4%b8%ad%e7%9a%84%e5%80%bc">#</a>
</h2>
<p><code>examine</code> 命令用来查看内存地址中的值,可以简写成 <code>x</code><code>examine</code> 命令的语法如下所示:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>examine /&lt;n/f/u&gt; &lt;addr&gt;
</span></span></code></pre></div><ul>
<li>
<p>n 表示显示字段的长度,也就是说从当前地址向后显示几个地址的内容。</p>
</li>
<li>
<p>f 表示显示的格式</p>
<ul>
<li>d 数字 decimal</li>
<li>u 无符号数字 unsigned decimal</li>
<li>s 字符串 string</li>
<li>c 字符 char</li>
<li>u 无符号整数 unsigned integer</li>
<li>t 二进制 binary</li>
<li>o 八进制格式 octal</li>
<li>x 十六进制格式 hex</li>
<li>f 浮点数格式 float</li>
<li>i 指令 instruction</li>
<li>a 地址 address</li>
<li>z 十六进制格式,左侧填充零 hex, zero padded on the left</li>
</ul>
</li>
<li>
<p>u 表示从当前地址往后请求的字节数默认是4个bytes</p>
<ul>
<li>b 一个字节 byte</li>
<li>h 两个字节 halfword</li>
<li>w 四个字节 word</li>
<li>g 八个字节 giantword</li>
</ul>
</li>
</ul>
<p>示例:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x/10c 0x4005d4 <span style="color:#75715e"># 打印前10个字符</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x/16xb a <span style="color:#75715e"># 以16进制格式打印数组前a16个byte的值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x/16ub a <span style="color:#75715e"># 以无符号10进制格式打印数组a前16个byte的值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x/16tb a <span style="color:#75715e"># 以2进制格式打印数组前16个abyte的值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x/16xw a <span style="color:#75715e"># 以16进制格式打印数组a前16个word4个byte的值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x $rsp <span style="color:#75715e"># 打印rsp寄存器执行的地址的值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x $rsp + <span style="color:#ae81ff">8</span> <span style="color:#75715e"># 打印rsp加8后的地址指向的值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x 0xc000068fd0 <span style="color:#75715e"># 打印内存0xc000068fd0指向的值</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> x/5i schedule <span style="color:#75715e"># 打印函数schedule前5条指令</span>
</span></span></code></pre></div><h2 id="修改变量或寄存器值">
修改变量或寄存器值
<a class="anchor" href="#%e4%bf%ae%e6%94%b9%e5%8f%98%e9%87%8f%e6%88%96%e5%af%84%e5%ad%98%e5%99%a8%e5%80%bc">#</a>
</h2>
<p><code>set</code> 命令支持修改变量以及寄存器的值:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> set var var1<span style="color:#f92672">=</span><span style="color:#ae81ff">123</span> <span style="color:#75715e"># 设置变量var1值为123</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> set var $rax<span style="color:#f92672">=</span><span style="color:#ae81ff">123</span> <span style="color:#75715e"># 设置寄存器值为123</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> set environment envname1<span style="color:#f92672">=</span><span style="color:#ae81ff">123</span> <span style="color:#75715e"># 设置环境变量envname1值为123</span>
</span></span></code></pre></div><h2 id="查看命令帮助信息">
查看命令帮助信息
<a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e5%91%bd%e4%bb%a4%e5%b8%ae%e5%8a%a9%e4%bf%a1%e6%81%af">#</a>
</h2>
<p><code>help</code> 命令支持查看GDB命令帮助信息。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> help status <span style="color:#75715e"># 查看所有命令使用示例</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> help x <span style="color:#75715e"># 查看x命令使用帮助</span>
</span></span></code></pre></div><h2 id="搜索源文件">
搜索源文件
<a class="anchor" href="#%e6%90%9c%e7%b4%a2%e6%ba%90%e6%96%87%e4%bb%b6">#</a>
</h2>
<p><code>search</code> 命令支持在当前文件中使用正则表达式搜索内容。<code>search</code> 等效于 <code>forward-search</code> 命令,是从当前位置向前搜索,可以简写成 <code>fo</code><code>reverse-search</code> 命令功能跟 <code>forward-search</code> 恰好相反,其可以简写成 <code>rev</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> search func add <span style="color:#75715e"># 从当前位置向前搜索add方法</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> rev func add <span style="color:#75715e"># 从当前为向后搜索add方法</span>
</span></span></code></pre></div><h2 id="执行shell命令">
执行shell命令
<a class="anchor" href="#%e6%89%a7%e8%a1%8cshell%e5%91%bd%e4%bb%a4">#</a>
</h2>
<p>我们可以通过 <code>shell</code> 指令来执行shell命令。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> shell cat /proc/27889/maps <span style="color:#75715e"># 查看进程27889的内存映射。若想查看当前进程id可以使用info proc命令获取</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> shell ls -alh
</span></span></code></pre></div><h2 id="gdb对go-runtime支持">
GDB对go runtime支持
<a class="anchor" href="#gdb%e5%af%b9go-runtime%e6%94%af%e6%8c%81">#</a>
</h2>
<ul>
<li>runtime.Breakpoint():触发调试器断点。</li>
<li>runtime/debug.PrintStack():显示调试堆栈。</li>
<li>log适合替代 print显示调试信息</li>
</ul>
<h2 id="为系统调用设置捕获点">
为系统调用设置捕获点
<a class="anchor" href="#%e4%b8%ba%e7%b3%bb%e7%bb%9f%e8%b0%83%e7%94%a8%e8%ae%be%e7%bd%ae%e6%8d%95%e8%8e%b7%e7%82%b9">#</a>
</h2>
<p>GDB支持为系统调用设置捕获点(catchpoint),我们可以通过 <code>catch</code> 指令,后面加上 <strong>系统调用号(syscall numbers)</strong><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> 或者<strong>系统调用助记符(syscall mnemonic names也称为系统调用名称)</strong> 来设置捕获点。如果不指定系统调用的话,默认是捕获所有系统调用。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> catch syscall <span style="color:#ae81ff">231</span>
</span></span><span style="display:flex;"><span>Catchpoint <span style="color:#ae81ff">1</span> <span style="color:#f92672">(</span>syscall <span style="color:#e6db74">&#39;exit_group&#39;</span> <span style="color:#f92672">[</span>231<span style="color:#f92672">])</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> catch syscall exit_group
</span></span><span style="display:flex;"><span>Catchpoint <span style="color:#ae81ff">2</span> <span style="color:#f92672">(</span>syscall <span style="color:#e6db74">&#39;exit_group&#39;</span> <span style="color:#f92672">[</span>231<span style="color:#f92672">])</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>gdb<span style="color:#f92672">)</span> catch syscall
</span></span><span style="display:flex;"><span>Catchpoint <span style="color:#ae81ff">3</span> <span style="color:#f92672">(</span>any syscall<span style="color:#f92672">)</span>
</span></span></code></pre></div><h2 id="设置源文件查找路径">
设置源文件查找路径
<a class="anchor" href="#%e8%ae%be%e7%bd%ae%e6%ba%90%e6%96%87%e4%bb%b6%e6%9f%a5%e6%89%be%e8%b7%af%e5%be%84">#</a>
</h2>
<p>在程序调试过程中构建程序的源文件位置更改之后gdb不能找到源文件位置我们可以使用 <code>directory</code>命令设置查找源文件的路径。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>directory ~/www/go/src/github.com/go-delve/
</span></span></code></pre></div><p><code>directory</code> 命令只使用相对路径下的源文件,若绝对路径下源文件找不到,我们可以使用 <code>set substitute-path</code> 设置路径替换。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>set substitute-path ~/www/go/src/github.com/go-delve/ ~/www/go/src/github.com/go-delve2/
</span></span></code></pre></div><h2 id="批量执行命令">
批量执行命令
<a class="anchor" href="#%e6%89%b9%e9%87%8f%e6%89%a7%e8%a1%8c%e5%91%bd%e4%bb%a4">#</a>
</h2>
<p>GDB支持以脚本形式运行命令我们可以使用下面的选项</p>
<ul>
<li><code>-ex</code>选项可以用来指定执行命令</li>
<li><code>-iex</code>选来用来指定加载应用程序之前需执行的命令</li>
<li><code>-x</code> 选项用来从指定文件中加载命令</li>
<li><code>-batch</code>类似<code>-q</code>支持安静模式会指示GDB在所有命令执行完成之后退出</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># 1. 打印提示语 2. 在main.main出设置断点 3. 运行程序 4. 执行完成程序退出gdb</span>
</span></span><span style="display:flex;"><span>gdb -iex <span style="color:#e6db74">&#39;echo 开始执行:\n&#39;</span> -ex <span style="color:#e6db74">&#34;b main.main&#34;</span> -ex <span style="color:#e6db74">&#34;run&#34;</span> -batch ./main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 设置exit/exit_group系统调用追踪点然后运行程序最后打印backtrace信息</span>
</span></span><span style="display:flex;"><span>gdb -ex <span style="color:#e6db74">&#34;catch syscall exit exit_group&#34;</span> -ex <span style="color:#e6db74">&#34;run&#34;</span> -ex <span style="color:#e6db74">&#34;bt&#34;</span> -batch ./main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 从文件中加载命令</span>
</span></span><span style="display:flex;"><span>gdb -batch -x /tmp/cmds --args executablename arg1 arg2 arg3
</span></span></code></pre></div><h2 id="gdb增强插件">
GDB增强插件
<a class="anchor" href="#gdb%e5%a2%9e%e5%bc%ba%e6%8f%92%e4%bb%b6">#</a>
</h2>
<ul>
<li>
<a href="https://github.com/gdbinit/gdbinit">gdbinit</a></li>
<li>
<a href="https://github.com/cyrus-and/gdb-dashboard">gdb-dashboard</a></li>
<li>
<a href="https://github.com/pwndbg/pwndbg">pwndbg</a></li>
<li>
<a href="https://github.com/longld/peda">peda</a></li>
</ul>
<h2 id="进一步阅读">
进一步阅读
<a class="anchor" href="#%e8%bf%9b%e4%b8%80%e6%ad%a5%e9%98%85%e8%af%bb">#</a>
</h2>
<ul>
<li>
<a href="http://beej.us/guide/bggdb/">Beej&rsquo;s Quick Guide to GDB</a></li>
<li>
<a href="https://wizardforcel.gitbooks.io/100-gdb-tips/content/index.html">100个gdb小技巧</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>
<a href="https://x64.syscall.sh/">https://x64.syscall.sh/</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
</article>
<footer class="book-footer">
<div class="flex flex-wrap justify-between">
</div>
<script>(function(){function e(e){const t=window.getSelection(),n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}document.querySelectorAll("pre code").forEach(t=>{t.addEventListener("click",function(){if(window.getSelection().toString())return;e(t.parentElement),navigator.clipboard&&navigator.clipboard.writeText(t.parentElement.textContent)})})})()</script>
</footer>
<div class="book-comments">
<script src="https://giscus.app/client.js" data-repo="cyub/go-1.14.13"
data-repo-id="MDEwOlJlcG9zaXRvcnkzMzc2ODUyMzQ=" data-category="Announcements"
data-category-id="DIC_kwDOFCCq8s4CZ3BC"
data-mapping="pathname" data-strict="0" data-emit-metadata="0"
data-input-position="bottom" data-reactions-enabled="0"
data-lang="zh-CN" data-theme="preferred_color_scheme" crossorigin="anonymous" async>
</script>
<noscript>Please enable JavaScript to view the comments powered by giscus.</noscript>
</div>
<label for="menu-control" class="hidden book-menu-overlay"></label>
</div>
</main>
</body>
</html>