|
| 1 | +--- |
| 2 | +title: GDB/GCC/Binutils NOTE |
| 3 | +tags: gdb gcc binutils |
| 4 | +--- |
| 5 | + |
| 6 | +# GCC |
| 7 | + |
| 8 | +```bash |
| 9 | +-g3 -ggdb -O0 # 加入调试符号,关闭优化 |
| 10 | +-fno-stack-protector -no-pie |
| 11 | +``` |
| 12 | +<!--more--> |
| 13 | + |
| 14 | +```sh |
| 15 | +-Wl,-dynamic-linker=/data/local/tmp/gentoo/home/glibc-2.38_bin/lib/ld-linux-aarch64.so.1 |
| 16 | +-Wl,-rpath=/data/local/tmp/gentoo/home/glibc-2.38_bin/lib |
| 17 | +``` |
| 18 | + |
| 19 | +```sh |
| 20 | +-fno-builtin-printf |
| 21 | +-fstack-protector-all |
| 22 | +-fpic |
| 23 | +-pie |
| 24 | +-march=armv8-a+crc |
| 25 | +-pipe |
| 26 | + |
| 27 | +``` |
| 28 | + |
| 29 | + |
| 30 | +在某些使用 CMAKE 构建的项目中,如有需要可以直接设置 `CFLAGS,CXXFLAGS` 环境变量,CMAKE会找到这些环境变量并加入最终生成的 Makefile 中。而链接时的尝试可以通过 `DCMAKE_MODULE_LINKER_FLAGS/DCMAKE_MODULE_LINKER_FLAGS/DCMAKE_SHARED_LINKER_FLAGS/DCMAKE_EXE_LINKER_FLAGS` 来控制: |
| 31 | + |
| 32 | +```cmake |
| 33 | +$ set -x CFLAGS "-ggdb -g3 -gdwarf -gdwarf-5" |
| 34 | +$ set -x CXXFLAGS "-ggdb -g3 -gdwarf -gdwarf-5" |
| 35 | +
|
| 36 | +$ cmake -B build \ |
| 37 | + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ |
| 38 | + -DCMAKE_MODULE_LINKER_FLAGS="-Wl,-rpath=/home/ihexon/glibc-2.35_bin/lib/ -Wl,-dynamic-linker=/home/ihexon/glibc-2.35_bin/lib/ld-linux-aarch64.so.1" \ |
| 39 | + -DCMAKE_SHARED_LINKER_FLAGS="-Wl,-rpath=/home/ihexon/glibc-2.35_bin/lib/ -Wl,-dynamic-linker=/home/ihexon/glibc-2.35_bin/lib/ld-linux-aarch64.so.1" \ |
| 40 | + -DCMAKE_EXE_LINKER_FLAGS="-Wl,-rpath=/home/ihexon/glibc-2.35_bin/lib/ -Wl,-dynamic-linker=/home/ihexon/glibc-2.35_bin/lib/ld-linux-aarch64.so.1" |
| 41 | +``` |
| 42 | + |
| 43 | +# GDB |
| 44 | + |
| 45 | +## 常见警告 |
| 46 | +由于 gdb 的安全性设定禁止加载外部的 libs,需要配置 auto-load safe-path 路径否则 gdb 无法加载到外部库如 libthread_db.so.1 等。写入这条语句到 ~/.gdbinit 中: |
| 47 | +```sh |
| 48 | +set auto-load safe-path /data/local/tmp/gentoo/home/glibc-2.38_bin/lib/ |
| 49 | +``` |
| 50 | +如果要使用独立的 libpthread_db.so 需要设置 libthread-db-search-path ,如: |
| 51 | +```sh |
| 52 | +set libthread-db-search-path /data/local/tmp/gentoo/home/glibc-2.38_bin/lib/ |
| 53 | +``` |
| 54 | + |
| 55 | +**注意**:`set libthread-db-search-path /data/local/tmp/gentoo/home/glibc-2.38_bin/lib/` 不能写成 `set libthread-db-search-path "/data/local/tmp/gentoo/home/glibc-2.38_bin/lib/"` (没有 \" \") ! |
| 56 | + |
| 57 | + |
| 58 | +gdb 调试遇到警告: |
| 59 | +> warning: Error disabling address space randomization: Operation not permitted |
| 60 | +
|
| 61 | +``` |
| 62 | +gdb$ set disable-randomization off |
| 63 | +``` |
| 64 | +If you running gdb inside docker: |
| 65 | +``` |
| 66 | +docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined |
| 67 | +``` |
| 68 | + |
| 69 | + |
| 70 | +## call/print [expr] 指令 |
| 71 | +评估表达式 expr 并显示结果值,expr 也包括对程序中函数的调用。 |
| 72 | + |
| 73 | +gdb 会为 expr 创建 dummy frame,这个 frame 不属于被调试程序的 frame。 |
| 74 | +但是 expr 可以访问和修改程序的运行时数据,所以 expr 编写不当会对程序产生一些非预期的副作用。 |
| 75 | + |
| 76 | + |
| 77 | +通过 print 或 call 命令调用的函数可能会生成信号(例如,如果函数中存在错误,或者传递了不正确的参数)。在这种情况下,可以通过 set unwindonsignal 命令来控制发生的情况,比如 |
| 78 | +```c |
| 79 | +call printf("%s", 0x111111) |
| 80 | +``` |
| 81 | +这显然会造成程序 Segmentation fault,因为 0x11111 并不受有效的VMA地址,gdb eval 这条代码后 gdb 立即收到 SIGSEGV 信号,此时 gdb 有两种行为取决于 unwindonsignal 的开关状态, |
| 82 | +```c |
| 83 | +set unwindonsignal off |
| 84 | +``` |
| 85 | +GDB 将停在接收信号的帧中,此时尝试 continue 可以发现 gdb 停在了这里 |
| 86 | + |
| 87 | +但异常处理又是另外的话题了不在这里解释。 |
| 88 | + |
| 89 | +```c |
| 90 | +set unwindonsignal on |
| 91 | +``` |
| 92 | +GDB将展开其为调用创建的堆栈,并将上下文恢复到收到 SIGSEGV 信号之前的状态。 |
| 93 | + |
| 94 | + |
| 95 | +If a called function is interrupted for **any reason**, including **hitting a breakpoint, or triggering a watchpoint**, and the stack is not unwound due to set unwind-on-terminating-exception on or set unwindonsignal on (see stack unwind settings), then the dummy-frame, created by GDB to facilitate the call to the program function, will be visible in the backtrace, for example frame #3 in the following backtrace: |
| 96 | + |
| 97 | +``` |
| 98 | +(gdb) backtrace |
| 99 | +#0 0x00007ffff7b3d1e7 in nanosleep () from /lib64/libc.so.6 |
| 100 | +#1 0x00007ffff7b3d11e in sleep () from /lib64/libc.so.6 |
| 101 | +#2 0x000000000040113f in deadlock () at test.cc:13 |
| 102 | +#3 <function called from gdb> |
| 103 | +#4 breakpt () at test.cc:20 |
| 104 | +#5 0x0000000000401151 in main () at test.cc:25 |
| 105 | +At this point it is possible to examine the state of the inferior just like any other stop. |
| 106 | +``` |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | +## TUI |
| 117 | +如果你不想安装 pwndbg 或者环境受限,gdb 也自带 tui 界面帮助调试。 |
| 118 | + |
| 119 | +https://sourceware.org/gdb/current/onlinedocs/gdb.html/TUI.html#TUI |
| 120 | + |
| 121 | +```bash |
| 122 | +C-x C-a :Enter or leave the TUI mode. |
| 123 | +C-x o :Change the active window. |
| 124 | +C-L :Refresh the screen. |
| 125 | + |
| 126 | +gdb > set style tui-current-position on |
| 127 | +``` |
| 128 | + |
| 129 | +gdb 可以自定义 Layout,比如我想让窗口变成 4 栏,分别是 src,asm,regs。每个窗口大小为 10 height,layout 的名字叫 ihexon_layout。 |
| 130 | + |
| 131 | +```bash |
| 132 | +tui new-layout ihexon_layout src 10 regs 10 asm 10 status 1 cmd 10 |
| 133 | +tui layout ihexon_layout |
| 134 | + |
| 135 | +# 改变 src 和 asm 排列方式,高度为20行 |
| 136 | +tui new-layout ihexon_layout { -horizontal src 10 asm 10 } 20 regs 10 status 1 cmd 30 |
| 137 | +``` |
| 138 | +
|
| 139 | +分离窗口后想要再次回到 cmd 窗口中需要:`focus cmd` |
| 140 | +
|
| 141 | +
|
| 142 | +
|
| 143 | +
|
| 144 | +## breakpoint |
| 145 | +`b` 没什么好说的,断点就是乱打,打不中就继续瞎JB下断点。 |
| 146 | +
|
| 147 | +
|
| 148 | +`_dl_fixup` 在 hit 到 `main` 函数后中断: |
| 149 | +
|
| 150 | +``` |
| 151 | +break main |
| 152 | +commands |
| 153 | +silent |
| 154 | +tbreak _dl_fixup |
| 155 | +end |
| 156 | +``` |
| 157 | +
|
| 158 | + |
| 159 | +
|
| 160 | +
|
| 161 | +
|
| 162 | +
|
| 163 | + |
| 164 | +
|
| 165 | +layout 可能会因为Terminal 变得混乱,使用 `tui refresh` 重新绘制 layout。 |
| 166 | +
|
| 167 | +
|
| 168 | +```bash |
| 169 | +# 使用 GDB 的内置计算器进行十六进制相加 |
| 170 | +# 例如,计算 0x10 + 0x20 |
| 171 | +> p/x 0x10 + 0x20 |
| 172 | +> printf "0x%x\n", 0x10 + 0x20 |
| 173 | + |
| 174 | +# 如果你想查看函数 + 偏移量处的汇编代码,使用具体的地址 |
| 175 | +# 这里的地址是函数地址 + 偏移量 |
| 176 | +> disassemble _dl_audit_preinit+0xfc8 |
| 177 | + |
| 178 | + |
| 179 | +# 使用 print 来打印 0x000000000400200 字符串 |
| 180 | +> print -- (char*)0x000000000400200 |
| 181 | +# print 支持额外的打印参数,可以通过 help print 查看,注意 -- 分隔符的位置 |
| 182 | +> print -pretty on -address on -null-stop on -array on -array-indexes on -- (char*)0x000000000400200 |
| 183 | +# 使用 x 来打印 0x000000000400200 字符串 |
| 184 | +> x/s 0x000000000400200 |
| 185 | +0x400200: "/lib/ld-linux-aarch64.so.1" |
| 186 | +# 当然也可以单个字符串打印 |
| 187 | +> x/c 0x000000000400200 |
| 188 | +0x400200: 47 '/' |
| 189 | +``` |
| 190 | +
|
| 191 | +
|
| 192 | +
|
| 193 | +
|
| 194 | +
|
| 195 | +
|
0 commit comments