如何手工展开函数栈来定位问题

简介: 作者:gfree.wind@gmail.com 博客:blog.focus-linux.net     linuxfocus.blog.chinaunix.net 当程序crash的时候,我们可以通过coredump文件,来定位问题。
作者:gfree.wind@gmail.com
博客:blog.focus-linux.net     linuxfocus.blog.chinaunix.net

当程序crash的时候,我们可以通过coredump文件,来定位问题。比如使用bt命令可以完整的展开函数的调用栈。但是有些时候,部分栈的数据可能被损坏,导致gdb无法直接显示函数的调用栈。那么这时就需要我们手工展开函数栈。

关于x86的函数调用栈的示意图基本如下图所示:

关于参数的压栈顺序,上图为cdecl方式,这个可以通过编译选项修改。GCC默认使用cdecl。

下面看一下例子:
  1. #include <stdlib.h>
  2. #include <stdio.h>


  3. static int test(int a, int b, int c)
  4. {
  5.     return a+b+c;
  6. }

  7. int main()
  8. {
  9.     int a = 1;
  10.     int b = 2;
  11.     int c = 3;

  12.     int d = test(a, b, c);

  13.     printf("%d\n", d);

  14.     return 0;
  15. }
编译:gcc -g -Wall test.c
进入test,查看函数调用栈:
  1. Breakpoint 1, test (a=1, b=2, c=3) at test.c:7
  2. 7 return a+b+c;
  3. Missing separate debuginfos, use: debuginfo-install glibc-2.11-2.i686
  4. (gdb) bt
  5. #0 test (a=1, b=2, c=3) at test.c:7
  6. #1 0x08048412 in main () at test.c:16
那么现在查看一下寄存器:
  1. eax 0x1 1
  2. ecx 0x2c0187d8 738297816
  3. edx 0x1 1
  4. ebx 0x73fff4 7602164
  5. esp 0xbffff048 0xbffff048
  6. ebp 0xbffff048 0xbffff048
  7. esi 0x0 0
  8. edi 0x0 0
  9. eip 0x80483c7 0x80483c7 <test+3>
  10. eflags 0x286 [ PF SF IF ]
  11. cs 0x73 115
  12. ss 0x7b 123
  13. ds 0x7b 123
  14. es 0x7b 123
  15. fs 0x0 0
  16. gs 0x33 51
得到ebp的地址为0xbffff048,现在检查这个地址的内存
  1. (gdb) x /8x 0xbffff048
  2. 0xbffff048: 0xbffff078 0x08048412 0x00000001 0x00000002
  3. 0xbffff058: 0x00000003 0x0073fff4 0x00000001 0x00000002
下面分析一下这些内存的内容:
1. 0xbffff078:为test的调用者,即main函数的bp地址;BP地址即为该函数的栈顶指针。
2. 0x08048412:为test的返回地址,与前面的bt的输出相符;
3. 后面的0x00000001,0x00000002,0x00000003,为传给test的三个参数,且参数顺序为由右向左压栈——注意这个顺序是可以通过改变编译参数改变的。

回到main中,验证一下bp寄存器的内容:
  1. 0x08048412 in main () at test.c:16
  2. 16 int d = test(a, b, c);
  3. Value returned is $2 = 6
  4. (gdb) info registers
  5. eax 0x6 6
  6. ecx 0x39ff7a48 973044296
  7. edx 0x1 1
  8. ebx 0x73fff4 7602164
  9. esp 0xbffff050 0xbffff050
  10. ebp 0xbffff078 0xbffff078
可见BP的地址确实为0xbffff078,与之前的分析相符。

注:关于压栈顺序,参数的传递方式等等,都可以通过编译选项来指定或者禁止的。本文的情况为GCC的默认行为。
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
3天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
5529 7
|
1天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
918 1
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
15天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
3152 9
|
14天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1767 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
16天前
|
缓存 人工智能 自然语言处理
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
本文是阿里云百炼平台Qwen3.8-Flash大模型的选型接入指南,作为兼顾性能与响应速度的高性价比多模态模型,它支持百万级上下文窗口、全场景多模态输入与完整智能体能力矩阵,适配编程辅助、智能体协作等核心场景。文中同步梳理了最新下调的阶梯定价、夜间4折等优惠活动,搭配OpenAI兼容流式调用示例,帮助开发者低成本快速落地高并发AI应用。
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
|
10天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
1114 1
|
16天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
2022 15