当前位置: 首页 > news >正文

调试去符号化/strip 过的二进制的调试方法

看到的现象:

(gdb) b main
Breakpoint 1 at 0x4130f4 (4 locations)
(gdb) run -D -e -ddd -f /mnt/mtd/openssh6/sshd_config
warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.Breakpoint 1, 0x00000000004130f4 in main ()
(gdb) n
Single stepping until exit from function main,
which has no line number information.
[Inferior 1 (process 2492) exited with code 01]


🔍 逐步解析:

1️⃣ Breakpoint 1 at 0x4130f4 (4 locations)
  • 说明 GDB 通过符号或猜测找到了“main”这个符号(可能是多个副本,例如静态链接时多个对象中定义了 main)。

  • 已经正确断在 main

2️⃣ (gdb) n 之后出现:

“Single stepping until exit from function main, which has no line number information.”

这句意思是:

“main 函数没有行号信息(即没有调试符号),GDB 将尝试单步直到函数返回。”

也就是说:

  • 由于我的二进制是 去掉了 -g 调试信息 或被 strip 过的静态库合并产物,GDB 没法逐行执行

  • 它只知道 main 的入口地址(0x4130f4),不知道 main 内部每一行对应的地址。

  • 所以 n(next)无法逐行运行,只能整个函数执行完(即 main 返回)再停。

3️⃣ [Inferior 1 (process 2492) exited with code 01]

这表示程序正常返回 exit(1),即执行过程中发生了错误并退出(不是崩溃)。


✅ 结论:

GDB 确实已经进入了 main,但:

  • 因为没有符号表 / 行号信息(比如缺少 -g 编译),所以 n 不能逐行执行;

  • 程序执行到 main 的结尾或某个错误点后调用了 exit(1),所以直接退出;

  • GDB 显示 “exited with code 01” 即表示 程序自己退出了(非崩溃)

建议调试方法:

✅ 方法1:重新编译带符号版本

在编译 openssh 时加:

CFLAGS += -g -O0
LDFLAGS += -g

并确保不要执行 strip

然后重新执行:

gdb ./sshd
(gdb) break main
(gdb) run -D -e -ddd -f /mnt/mtd/openssh6/sshd_config

这样我就能看到源码级调试信息(行号、变量等)。

✅ 方法2:查看退出点

如果暂时不能重新编译,可以这样:

(gdb) run ...
(gdb) bt

或者

(gdb) catch syscall exit
(gdb) run ...

看看是哪个函数触发了退出。

✅ 方法3:设置更多断点

在没有符号的情况下可以:

(gdb) info functions | grep ssh
(gdb) break sshd_main

或直接断在 _startmainsshd_mainserver_listen 等函数上。

一、调试目标与问题背景

场景:

  • 二进制(例如 /usr/bin/dlz_sshd)是 strip 过的无符号版本

  • 无法直接看到源码行、变量名;

  • 程序启动后马上退出(exit code 1);

  • 想定位是初始化流程哪里出问题。


 二、准备阶段

1️⃣ 启动 GDB:

gdb /usr/bin/dlz_sshd

2️⃣ 设置运行参数(例如在设备上的启动方式):

set args -D -e -ddd -f /mnt/mtd/openssh6/sshd_config

3️⃣ 关闭自动分页,避免输出中断:

set pagination off


 三、断点与入口分析

1. 主入口断点

break main
run

即便没有符号,GDB 仍可能识别出 main(通过 ELF symbol header)。
若找不到,可尝试:

info functions | grep main

或直接断在程序入口:

break *_start

_start 是程序最早的入口,由 glibc 提供,负责调用 __libc_start_main(main,...)


2. 运行后若立刻退出:

查看退出码:

info inferiors

若显示 [Inferior 1 exited with code 01],说明程序自行 exit(1)。


 四、查找退出点

方法1:捕获 exit 调用

catch syscall exit
run

程序调用 exit() 时会中断,GDB 停下来,显示退出位置。

可以查看调用栈:

bt

即便无符号,也能看到地址序列,比如:

#0  0x0000007ff7a12f40 in exit () from /lib/libc.so.6
#1  0x00000000004156b0 in ?? ()
#2  0x00000000004130f4 in main ()

这就能定位出大致的调用层级。


方法2:跟踪函数调用(退化追踪)

如果 exit 没抓到,可以:

catch syscall write

查看程序最后输出的日志位置(常用于看 crash 前的输出)。


 五、结合系统日志验证

通常 OpenSSH 的内部错误也会通过 stderr 输出。
可以在 GDB 中让输出重定向:

set logging file sshd_debug.log
set logging on
run
set logging off

然后在 log 文件中查找 fatal:error:failed 等关键字。


六、实战定位思路

目标GDB命令作用
看程序在哪退出catch syscall exit + bt定位 exit 调用点
看初始化执行到哪disassemble main / x/20i $pc对比汇编逻辑
推测失败函数info symbol 0xaddr / strings 对照推断逻辑块
验证是否加载到依赖库info sharedlibrary检查 libssl、libcrypto 是否加载
检查 errnoprint errno如果调用失败,errno 可能提示原因

八、总结:最小调试工作流(推荐顺序)

gdb /usr/bin/dlz_sshd
set args -D -e -ddd -f /mnt/mtd/openssh6/sshd_config
catch syscall exit
run
bt
info sharedlibrary
disassemble main
strings /usr/bin/dlz_sshd | grep fatal

这样能知道:

  • 程序是否进入 main;

  • 在哪个函数退出;

  • 退出时的调用栈;

  • 可能的出错字符串;

  • 是否因为库缺失或初始化失败导致。

http://www.dtcms.com/a/470584.html

相关文章:

  • 大连建设局网站地址怎么将自己房子投入网站做民宿
  • 新河网站旅游网站策划方案
  • 建网站备案好麻烦长春市建设工程造价管理协会网站
  • 东莞设计网站建设方案南京网站建设排名
  • Dirty COW容器逃逸漏洞渗透实战:原理+复现 (CVE-2016-5195)
  • 2010 866数据结构 算法设计题——链表,二叉树
  • 对海尔网站建设水平的评价长沙网站备案
  • Codeforces Round 1057 (Div. 2)(A-D)
  • 微信网站备案wordpress step2
  • XSS 漏洞全解析:从原理到实战
  • 傻瓜式 建网站软件外包公司人数
  • Nestjs service 对应token的作用范围
  • Google 智能体设计模式:评估与监控
  • 如何屏蔽网站ipwordpress 商城模板下载
  • OpenMM 8 安装与上手指南
  • 网站建设跟网站开发有什么区别吗832网络销售平台
  • 力扣热题100道49字母异位词分组
  • sql优化进阶
  • 网站灰色建设网销怎么找客户资源
  • 库易网网站郑州网站关键词优化公司
  • n8n Code节点模式选择指南:Run Once for All Items与Run Once for Each Item
  • 河南怎样做网站推广怎样设置自己的网站
  • 手写MyBatis第102弹:MapperBuilder与MapperAnnotationBuilder的双重解析机制深度剖析
  • Java知识点储备
  • C++ : AVL 树之 左右双旋(第三章)
  • 查询类网站开发建设网站公司怎么收费
  • 电影发布网站模板WordPress云虚拟空间
  • Android获取外部存储目录
  • AUTOSAR模块架构
  • 简单易做的网站一级域名二级域名区别