断点在共享库未加载时设为pending,gdb通过监听dlopen等事件动态解析符号并写入0xcc;若符号名不匹配(如版本后缀不符)则断点失效,需用catch load捕获加载时机后立即按info sharedlibrary显示的完整路径设断点。

断点会自动挂起,等共享库加载后才真正生效——但前提是符号能对上,否则断点落空。
断点在共享库未加载时设了,GDB怎么记的
GDB 不是直接往内存里写 0xcc,而是把断点“注册”为一个待决请求:记录你想要在 libfoo.so:do_work 或地址 0x7ffff7bca123 下断。它会持续监听后续的 dlopen、dlclose 和共享库映射事件。
常见错误现象:
- 设了
break libcrypto.so:SSL_connect,run后没停,info breakpoints显示pending - 程序跑完也没触发,但
info sharedlibrary确实列出了libcrypto.so—— 很可能符号名不匹配(比如带版本后缀libcrypto.so.1.1,但你写的是libcrypto.so)
用 catch load 捕获加载时机再补断点
这是最稳的实操路径,尤其适合 dlopen 动态加载场景。
- 先启动 GDB:
gdb ./myapp - 设捕获点:
catch load libxyz.so(注意写对实际文件名,包括版本号如libxyz.so.2) -
run,GDB 会在libxyz.so映射进内存后自动中断 - 此时立刻设断点:
break xyz_init或break libxyz.so:xyz_init -
continue继续执行
为什么这样做?因为此时符号表已解析,地址已确定,break 能立刻转成有效内存断点。如果提前设,GDB 只能靠名字猜,一猜就错。
break 命令里共享库名写法必须严格匹配 info sharedlibrary 输出
info sharedlibrary 显示的是运行时实际加载的路径和名称,不是你编译链接时写的 -lxyz。
- 输出可能是:
0x00007ffff7bc9000 0x00007ffff7bd0000 Yes /usr/lib/x86_64-linux-gnu/libxyz.so.2 - 那么断点就得写:
break /usr/lib/x86_64-linux-gnu/libxyz.so.2:xyz_init,或简写为break libxyz.so.2:xyz_init - 写成
break libxyz.so:xyz_init或break xyz.so:xyz_init都会失败(GDB 找不到匹配项,保持 pending) - 如果不确定函数是否在符号表里,先
info functions xyz_看能否列出
静态链接符号缺失时,只能靠地址硬设
某些裁剪过的共享库(比如嵌入式环境)不带调试符号,或者 strip 过,break libfoo.so:func 会彻底失效。
- 用
readelf -s /path/to/libfoo.so | grep func查函数相对地址(如0x1a2b) - 用
info sharedlibrary找到该库的加载基址(如0x7ffff7bc9000) - 算出绝对地址:
0x7ffff7bc9000 + 0x1a2b = 0x7ffff7bcaa2b - 设断点:
break *0x7ffff7bcaa2b
这个过程容易出错的地方在于:基址每次运行都可能变(ASLR 开启时),所以必须在 catch load 中断后立刻查,不能提前算好存着复用。











