---
# System prepended metadata

title: 'Day 2 - [INFO] GDB 基礎操作'
tags: [ithome2020]

---

# Day 2 - [INFO] GDB 基礎操作
###### tags: `ithome2020`

GDB 這東西已經有太多人介紹過怎麼操作，這部分是有點無聊，但在了解原理前，還是學會怎麼使用吧

## 我常用的指令

* 主要參考資料
    * [[轉貼]GDB 介紹](http://b8807053.pixnet.net/blog/post/336154079-%5B%E8%BD%89%E8%B2%BC%5Dgdb-%E4%BB%8B%E7%B4%B9)
    * [遠端除錯 - 基礎 gdb](http://www.study-area.org/cyril/opentools/opentools/x1253.html)
    * [遠端除錯 - 進階 gdb](http://www.study-area.org/cyril/opentools/opentools/x1265.html)
    * [Debugging with GDB](https://sourceware.org/gdb/onlinedocs/gdb/index.html#Top)
* run
    * file 若是一開始沒載入檔案用這個指令載入，再來 run
    * set args
* break/br: break point 設定中斷點
    * `b main` breakpoint by function
    * `b *main+10` breakpoint by address
    * `b 40` breakpoint at line 40
    * 斷點操作
        * clear
        * delete
        * disable
        * enable
        * condition
    * continue/c: 繼續執行直到下個斷點
    * step      : 在這個斷點時，一步一步執行
    * stepi 追進副程式
    * next 執行完副程式
    * until 直到跑完一個迴圈
```shell
b 目前位置
b 100
b function
b 100 if (var == 5)
br 100
commands
    silent
    printf "x is %d\n", x
end
clear 1 清除1號中斷點
```

* print/p : 印出變數
    * whatis var
    * ptype var(看 struct)
    * p/x 印出 hex 值
    * p/u
    * p/d
    * display 一直顯示某個變數
    * undisplay

```shell
p variable
p variable[1]@5    印出 variable[1] - variable[5]
p variable=5       要修改變數可以直接使用 print，它也有 eval 的功能然後就只是多了印出
```
* x 看記憶體位置的數值
    * convience variable
        * $_ :    x指令的最後一個位置
        * $__:    x指令最後一個位置的值
```shell=
x/4 &a
x/4 0x8000000
```

* info: info break, info frame
* show: show os, show args
* backtrace/bt: 回溯
* 看程式碼
    * list
    * disas 看 machine code
    * examine/x 看記憶體
* convience variable
    * $pc: program counter
* 進入 process
    * signal process-id
    * attach process-id
    * detach process-id

## 完整的操作

* [sample.c](https://github.com/ian910297/ithome2020/blob/master/day2/sample.c)
```clike=
#include <stdio.h>

int main() {
    int x = 10;
    x = 12;
    printf("x = %d\n", x);
    printf("x = %d\n", x);
    return 0;
}
```

可以拿編譯出來的檔案，用 GDB 下去跑跑看，編譯的時候記得下 `-g` ，才會有 debug info

下面做的事很簡單，有兩行輸出，我把斷點下在第七行，這時只有第一個 printf 會執行，接著我使用 print 來修改 x 的數值，再讓他繼續執行，就可以發現 x 數值真的被改動了

GDB debug 通常不是拿來改數值，而是拿來觀看數值，以及 function 之間是如何呼叫，也就是 backtrace 來看 stack 的內容，這可以自行下去摸索
```shell
> gdb ./sample 
(gdb) list
1	#include <stdio.h>
2	
3	int main() {
4	    int x = 10;
5	    x = 12;
6	    printf("x = %d\n", x);
7	    printf("x = %d\n", x);
8	    return 0;
9	}
(gdb) b 7
Breakpoint 1 at 0x676: file sample.c, line 7.
(gdb) r
Starting program: /home/chungyi/gitPro/ithome2020/day1/sample 
x = 12

Breakpoint 1, main () at sample.c:7
7	    printf("x = %d\n", x);
(gdb) p x=133
$1 = 133
(gdb) c
Continuing.
x = 133
[Inferior 1 (process 5043) exited normally]
```


## Misc

像是 `.bashrc` 一樣，GDB 也有設定檔可以使用，那就是 `.gdbinit`，根據 [gdbinit man](https://sourceware.org/gdb/current/onlinedocs/gdb/gdbinit-man.html) 裡所敘述，我們可以把 `.gdbinit` 放在在家目錄或是當前目錄，都會被自動讀取，以下就介紹一些，我常用到的功能

* 指令歷史紀錄
```shell
set history save on
set history filename ~/.gdb-history
set history size 1000
```

* Remote Protocol Debug
```shell
set debug remote 1
```

## Next

明天打算講 Bomb Lab ，我會寫一個非常簡單的版本，不會像 CS:APP 課程那麼麻煩，像這篇文章([Bomb Lab 實作紀錄](https://hackmd.io/@posutsai/SyNzl72f4?type=view)) 的簡化版本，但我們不玩 ARM 就玩 x86_64 

