- gdb 调试ld
- gdb tui模式
- gdb看所有线程的调用栈
- 远程调试app, 用gdbserver和gdb远程调试板子
- 远程调试uboot, 用jtag做gdb server
- 远程调试, over串口
- gdb调试nand
- gdb基本
1. gdb 调试ld
- 先准备代码, 我放在
/root/musl/1.2.4
下面 - 启动gdb
- 指定源码位置
-d /root/musl/1.2.4
- 这里我想调试
/lib/ld-musl-x86_64.so.1
, 而它的参数是/rl/sbin/apk -h
- 指定源码位置
/lib/ld-musl-x86_64.so.1 --library-path /rebornlinux/lib:/rebornlinux/usr/lib /rl/usr/bin/gdb -d /root/musl/1.2.4 --args /lib/ld-musl-x86_64.so.1 /rl/sbin/apk -h
b load_library
r
n
p env_path
$6 = 0x7ffe10651e5a "/lib:/usr/lib:/isam/slot_default/lib"
musl libc的load是/lib/ld-musl-x86_64.so.1
, 它同时也是c库.
~ # ls -lh /rl/lib
...
-rwxr-xr-x 1 root root 602.6K Oct 6 2023 ld-musl-x86_64.so.1
lrwxrwxrwx 1 root root 19 Aug 13 01:05 libc.musl-x86_64.so.1 -> ld-musl-x86_64.so.1
...
/lib/ld-musl-x86_64.so.1
是一个动态链接的bin的interpreter:
~ # rl /rl/usr/bin/patchelf --print-interpreter /rl/sbin/apk
/lib/ld-musl-x86_64.so.1
直接启动/rl/sbin/apk
的效果和用interpreter启动是一样的:
rl /rl/sbin/apk -h
rl /lib/ld-musl-x86_64.so.1 /rl/sbin/apk -h
1.1. /lib/ld-musl-x86_64.so.1 load .so的过程
- 优先搜索环境变量LD_LIBRARY_PATH指定的路径
- 如果有rpath, 搜索rpath路径
- 如果没找到, 搜索
/etc/ld-musl-x86_64.path
指定的路径 - 如果没有
/etc/ld-musl-x86_64.path
, 则默认从/lib:/usr/lib
下面找
1.2. loader支持的选项
--list: ldd就是调用它
--library-path: 覆盖LD_LIBRARY_PATH
--preload: 覆盖LD_PRELOAD
--argv0: 设置arg0
1.3. 一些命令记录
LD_LIBRARY_PATH=/rebornlinux/lib:/rebornlinux/usr/lib /rebornlinux/usr/bin/patchelf --set-rpath /rebornlinux/lib:/rebornlinux/usr/lib /rebornlinux/sbin/apk
/rebornlinux/lib/ld-musl-x86_64.so.1 --library-path /rebornlinux/lib:/rebornlinux/usr/lib /rebornlinux/sbin/apk -h
2. gdb tui模式
tui模式下更像个ide调试界面, 信息更丰富.
#可以先gdb program core来启动, 在gdb里面用layout命令来显示源码 asm和reg窗口
#Ctrl + x,再按a:回到传统模式,即退出layout,回到执行layout之前的调试窗口
#Ctrl + x, o: 切换激活窗口, 切换到命令窗口可以上下翻历史命令
layout split
layout src
layout reg
#刷新窗口
refresh 或Ctrl + L
#上一条命令快捷键: Ctrl+p
3. gdb看所有线程的调用栈
(gdb) info threads
(gdb) thread apply all bt full
4. 远程调试app, 用gdbserver和gdb远程调试板子
板子上配好ip: 192.168.2.12
#直接带好参数
~ # gdbserver :9123 /isam/user/eoe_filter -n eth0 -t tap-fwd -E
我在mint上, 用sshfs mount了服务器的buildroot目录; 所以我在mint上就能操作:
export PATH=$PATH:~/work/share/buildroot73/output/host/opt/ext-toolchain/bin
#cd到被调试的app目录下
yingjieb@yingjieb-VirtualBox ~/work/share/buildroot73/output/build/isam-linux-target-apps-22ef847b216e5d579c016ed9dd9795d393b56001
#这个eoe_filter是带符号表的
#能自动找到sysroot:/home/yingjieb/work/share/buildroot73/output/host/opt/ext-toolchain/mips64-octeon-linux-gnu/sys-root/
Linux Mint 19.1 Tessa $ mips64-octeon-linux-gnu-gdb eoe_filter
#板子上的程序会停在__start, __start是lib32/ld.so.1的符号
(gdb) target remote 192.168.2.12:9123
(gdb) handle SIG42 nostop noprint
(gdb) set print pretty on
#先断点到这个函数:
(gdb) b openTapItf
#继续执行直到断点
(gdb) c
#结合代码, 我要看tap设备是否创建成功:
(gdb) b eoe_filter.c:116
#在另外一个窗口ip a能看到tap-fwd
(gdb) info locals
#再往下跟, 发现是子线程调用了exit(), 导致tap设备被注销了.
(gdb) next
5. 远程调试uboot, 用jtag做gdb server
cd /repo2/yingjieb/cavium/sdk31_508/usr/local/Cavium_Networks/OCTEON-SDK/tools/bin
//gdb调试elf文件
mipsisa64-octeon-elf-gdb /repo2/yingjieb/u-boot-octeon-sdk3.1/u-boot-octeon_fpxtb
//启动空的gdb后, 再加载elf文件
file /repo2/yingjieb/u-boot-octeon-sdk3.1/u-boot-octeon_fpxtb
//可以设置architecture, 如果直接加载elf文件则不用设置
set architecture mips:octeon3
//启动远程调试
target remote 135.251.9.60:30000
//使用monitor指令
monitor help
monitor B::break.set 0xc00a2ff8 /program
//查看程序地址?
info line eth_send
//设置程序参数
gdb --args prog args
set args --ddr0spd=fpxtbspd --ddr_clock_hz=667000000
b init_octeon3_ddr3_interface
6. 远程调试, over串口
在板子上:
board:
stty -F /dev/ttyS0 115200
stty -F /dev/ttyS0 460800
stty -F /dev/ttyS0 -a
( taskset 1 gdbserver /dev/ttyS0 ./isam_app useSTDIO) &
在服务器上:
ASBLX28:/repo/yingjieb/fdt063/sw/vobs/esam/build/reborn/buildroot-isam-reborn-cavium-fgltb/output/host/usr/bin
$ mips64-octeon-linux-gnu-gdb /repo/yingjieb/fdt063/sw/vobs/esam/build/fglt-b/OS/application/isam_app.nostrip
#这个135.251.199.198:2009是串口服务器地址
(gdb) target remote 135.251.199.198:2009
(gdb) set sysroot /repo/yingjieb/fdt063/sw/vobs/esam/build/reborn/buildroot-isam-reborn-cavium-fgltb/output/staging
(gdb) set remotetimeout 60
(gdb) handle SIG42 nostop noprint
(gdb) set print pretty on
(gdb) detach
7. gdb调试nand
target:
devmem 0x1070000000500 64 0
devmem 0x1070000000508 64 0
devmem 0x1070000000510 64 0
devmem 0x1070000000518 64 0
echo ttyS1 > /sys/module/kgdboc/parameters/kgdboc
echo g > /proc/sysrq-trigger
从kgdb切换到kdb, 盲敲$3#33
host:
mips64-octeon-linux-gnu-gdb vmlinux
target remote 135.251.199.198:2114
set print pretty on
set sysroot /repo/yingjieb/fdt063/sw/vobs/esam/build/reborn/buildroot-isam-reborn-cavium-fgltb/output/staging
set remotetimeout 20
detach
bt
c
8. gdb基本
8.1. 查看当前要执行的行
frame, 简写f
8.2. 临时变量
set $i="hello"
8.3. 自动显示变量, 每次c后或n后, 自动显示其值
display 变量名
8.4. 按结构体方式查看内存地址
p *(struct mtd_info *)0x80000000885dc018
(gdb) p ((struct txq *)0xffff8119f800)->elts_n
8.5. 显示内存内容
#从priv->data这个地址开始, 显示2048个单位(2048), 每个单位一个字节(b), 按16进制显示(x)
x/2048xb priv->data
8.6. 计算数值, 16进制显示
(gdb) p /x 0xffff90c8c430+1914*8
$7 = 0xffff90c90000
8.7. 指定显示格式
#有时候, gdb不能准确显示一个uint16_t类型的变量的值, 比如
(gdb) p nb_pkt_per_burst
$19 = 65568
#此时需要用x加FMT来看, 8xh是说显示8个, 安装16进制halfword显示
(gdb) x/8xh &nb_pkt_per_burst
0x9f0c36 <nb_pkt_per_burst>: 0x0020 0x0001 0x0000 0x0000 0x0000 0x0040 0x0000 0x0000
#如果知道这个变量是uint16_t, 下面的也可以; 相当于x/1dh
(gdb) x/dh &nb_pkt_per_burst
0x9f0c36 <nb_pkt_per_burst>: 32
8.8. 执行任意函数
(gdb) p system("nandtest -k -o0x0 -l0x20000 /dev/mtd6")
$1 = 1
8.9. 查看结构体定义
(gdb) ptype trx_sys_t
8.10. 汇编和C混合显示
(gdb) disassemble /m function
(gdb) disassemble /m lj_meta_lookup
(gdb) disassemble /m dp_netdev_input__
8.11. info命令族
#源码信息
info source
#当前局部变量
info locals
info files
info threads
info sharedlibrary
info signals
info line
info tasks
info variables
info symbol
info stack
info registers
#还有不少
help info
8.12. 加入libc符号表
#必须使/repo/yingjieb/glibc-2.16.0能够被板子访问到
gdb oflt.nostrip
set args useSTDIO
set print pretty on
set sysroot /repo/yingjieb/fdt063/sw/vobs/esam/build/reborn/buildroot-isam-reborn-cavium-fgltb/output/staging
#dir的意思是增加源文件的search path到gdb
dir /repo/yingjieb/glibc-2.16.0
dir /repo/yingjieb/glibc-2.16.0/nptl
dir /repo/yingjieb/glibc-ports-2.16.0
handle SIG42 nostop noprint
b cs_dpll_resetTest
b oak_spi_datatransfer
b board_commands.c:153
b fork.c:133
b do_system
8.13. 调试模块, 加载符号表
#加载ko符号表
/sys/module/spi_oak_island/sections # cat .text
0xffffffffc0002000
/sys/module/spi_oak_island/sections # cat .data
0xffffffffc0000000
(gdb) add-symbol-file /repo/yingjieb/fdt063/sw/vobs/esam/build/reborn/buildroot-isam-reborn-cavium-fgltb/output/build/isam-linux-drivers-custom/misc/spi-oak-island.ko 0xffffffffc0002000 -s .data 0xffffffffc000000
8.14. 查看地址处的代码
# source file and line number for an instruction address
info line *0x<target_addr>
# source lines around an instruction address
list *0x<target_addr>
# assembly instructions at an address
disas 0x<target_addr>, or
x/20i 0x<target_addr>
8.15. 显示内存布局
#显示所有内存section
info files
#比上面命令显示更全
maintenance info sections