gdb チートシート
[History] [Last Modified] (2019/10/28 15:13:15)
ここは
趣味のプログラミングを楽しむための情報共有サービス。記事の一部は有料設定にして公開できます。 詳しくはこちらをクリック📝
Recent posts
Popular pages

概要

GNU Debugger (GDB) の簡単な使い方を記載します。

起動方法

main.cpp

#include <iostream>
#include <unistd.h>
using namespace std;

int main() {
    int i = 0;
    while(true) {
        sleep(1);
        cout << ++i << endl;
    }
    return 0;
}

実行プログラムを指定

-g -O0 オプションを指定してデバッグモードでコンパイルします。

g++ -Wall -g -O0 main.cpp
gdb ./a.out
(gdb) run
(gdb) run 引数

プロセスID を指定

gdb ./a.out -p 1234

コアファイルを指定

gcore 1528
gdb ./a.out -c core.1528

実行プログラムの確認

file core.1528
core.1528: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './a.out', real uid: 1000, effective uid: 1000, real gid: 1000, effective gid: 1000, execfn: './a.out', platform: 'x86_64'

共有ライブラリの確認 (ldd でも確認できる情報)

(gdb) info share

別環境でコアファイルを解析する場合は、必要に応じて共有ライブラリのパスを追加する必要があります。

(gdb) set solib-absolute-prefix /tmp/lib
(gdb) set solib-search-path /tmp/lib
(gdb) file ./myhello
(gdb) core-file ./core.1234

別環境でコアファイルを解析する場合は、ソースコードのパスを追加すると便利です。

(gdb) directory /tmp/src

操作方法

ステップ実行

cs 等のコマンドは、エンターを入力するだけで繰り返し実行できます。

現在位置の確認 (list)

bt
l 123

一行進める (next)

n

ステップを進める (step; 関数の中にも入っていきます)

s

変数の値を確認、設定 (print)

p myvar
p myvar = myvar + 1

次のブレークポイントまで進める (continue)

c

バックトレースを表示

bt

関数内で実行すると、関数を抜けるまで進める。

(gdb) finish

for/while で実行すると、for/while を抜けるまで進める。

(gdb) until

シェルコマンドを実行

(gdb) shell pwd
(gdb) shell g++ -g -O0 main.cpp
(gdb) shell
$ pwd

作業ログの出力

./gdb.txt にログ出力されます。

(gdb) set loggin on
(gdb) set loggin overwrite on

ブレークポイント

(gdb) b ファイル名:行数
(gdb) break ファイル名:行数 if i == j
(gdb) break main
(gdb) info breakpoints
(gdb) info breakpoints ブレークポイント番号
(gdb) delete
(gdb) delete ブレークポイント番号
(gdb) disable ブレークポイント番号
(gdb) enable ブレークポイント番号

変数の値の監視

値が変更される度にデバッガが停止します。

(gdb) watch i

読み込み時の監視

(gdb) rwatch i

書き込みと読み込みの監視

(gdb) awatch i

関数引数、ローカル変数、例外情報の表示

(gdb) info args
(gdb) info locals
(gdb) info catch

スタックフレームの移動

up
down
frame フレーム番号
(f フレーム番号)

シグナル処理情報の確認

info signals
info signals シグナル名

シグナルの送信

signal シグナル名

コアファイルの生成

(gdb) generate-core-file

コアファイルの最大サイズの確認および最大サイズの解除

ulimit -c
sudo su -l
ulimit -c unlimited

スレッド一覧の表示

(gdb) info threads

実行ファイルのないプロセスへのアタッチおよび制御

gdb -p 1234
(gdb) ...何らかの制御
(gdb) detach
(gdb) quit

型を調査

(gdb) whatis 変数名

CPython のコアダンプを解析したい場合

gdb python -c core.xxxx

参考: Python の実装を確認

$ python
>>> import platform
>>> print platform.python_implementation()
CPython

CPython の NSMALLPOSINTS が 257 となっている場合、0-256 の整数は同じメモリのデータが使い回される。

In : id(256)
Out: 94652018165808

In : id(256)
Out: 94652018165808 ←同じ

In : id(257)
Out: 94652020901008

In : id(257)
Out: 94652020900864 ←異なる

インスタンスのメソッドを実行

(gdb) p obj
$9 = {px = 0x557bb8d30c60, pn = {pi_ = 0x557bb8cf28d0}}
(gdb) p (obj.px)->MyIsOk()
$8 = false

全スレッドに対して bt を適用

thread apply all bt

Python を gdb でデバッグ

CPython 実装の Python は gdb でデバッグできます。必要なパッケージをインストールします

sudo apt install python-dbg

threads.py

from threading import Thread
from time import sleep

threads = []

def mysleep(x):
    print x
    sleep(999)

def target():
    mysleep('hi')
    print 'done'

for i in range(2):
    thread = Thread(target=target)
    threads.append(thread)
    thread.start()

mysleep('hi main')

for thread in threads:
    thread.join()

ソースコードの存在するディレクトリでアタッチ

gdb -p `pgrep -f threads.py`

スレッド一覧の確認

(gdb) thread apply all py-list

Thread 3 (Thread 0x7f4a9f5f8700 (LWP 21559)):
   3
   4    threads = []
   5
   6    def mysleep(x):
   7        print x
  >8        sleep(999)
   9
  10    def target():
  11        mysleep('hi')
  12        print 'done'
  13

Thread 2 (Thread 0x7f4a9fdf9700 (LWP 21558)):
   3
   4    threads = []
   5
   6    def mysleep(x):
   7        print x
  >8        sleep(999)
   9
  10    def target():
  11        mysleep('hi')
  12        print 'done'
  13

Thread 1 (Thread 0x7f4aa0290740 (LWP 21557)):
   3
   4    threads = []
   5
   6    def mysleep(x):
   7        print x
  >8        sleep(999)
   9
  10    def target():
  11        mysleep('hi')
  12        print 'done'
  13

(gdb) thread apply all py-locals

Thread 3 (Thread 0x7fd4ccbb4700 (LWP 21985)):
x = 'hi'

Thread 2 (Thread 0x7fd4cd3b5700 (LWP 21984)):
x = 'hi'

Thread 1 (Thread 0x7fd4cd84c740 (LWP 21983)):
x = 'hi main'

スレッドを選択する場合

info threads
thread 2

バックトレースの確認およびフレームの移動

py-bt
py-up
py-down

変数の値の確認

py-local
py-print x

デバッグシンボルを外部ファイルに分ける

main.cpp

#include <iostream>

int main() {
    std::cout << "hi" << std::endl;
    return 0;
}

デバッグシンボルを含めるようにコンパイル

g++ -g -O0 main.cpp
du -h a.out 
40K a.out

デバッグシンボルを外部ファイルに切り出す

objcopy --only-keep-debug a.out a.debug
objcopy --remove-section .gnu_debuglink a.out
objcopy --add-gnu-debuglink a.debug a.out
objcopy --strip-all --discard-all --preserve-dates a.out

du -hs *
28K a.debug
16K a.out
4.0K    main.cpp

a.out と同じディレクトリにデバッグシンボル a.debug が存在すれば gdb が利用できます。更にソースコード main.cpp が存在すればファイル内容や行番号の確認も行えます。

$ ls
a.debug  a.out  main.cpp

$ gdb a.out

(gdb) b main.cpp:4
Breakpoint 1 at 0x1169: file main.cpp, line 4.

(gdb) run
Starting program: /home/path/to/a.out 
Breakpoint 1, main () at main.cpp:4
4           std::cout << "hi" << std::endl;

(gdb) l
1       #include <iostream>
2
3       int main() {
4           std::cout << "hi" << std::endl;
5           return 0;
6       }
Related pages
    概要 よく使う python ライブラリのサンプルコード集です。 JSON #!/usr/bin/python # -*- coding: utf-8 -*- import json arr = [1, 2, {'xxx': 3}] # オブジェクト ←→ JSON 文字列 jsonStr = json.dumps(arr) arr2 = json.loads(jsonStr) # オ
    バイナリファイルから文字列を抽出する (strings) 文字列らしい部分をバイナリファイルから抽出して出力するコマンドです。得体の知れないコマンドのオプションを調べたり strings /usr/bin/gcc | grep ^-- --help --target-help --sysroot= --all-warnings --ansi --assemble --assert --cla