《coredump问题原理探究》Linux x86版4.1节函数的逆向之序言
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/details/8557761
在产品的生命周期中,会遇到各种coredump,如果在调试版本出现coredump,定位它是非常简单的事情,因为从栈就可以知道是哪一行代码出现了问题。如:
(gdb) bt
#0 0x4365b569 in vfprintf () from /lib/libc.so.6
#1 0x436629ff in printf () from /lib/libc.so.6
#2 0x080485b9 in main (argc=3, argv=0xbfe21504) at xuzhina_dump_c4_s4.cpp:20
即使是main函数多次调用printf,从上面栈可以是第20行代码出了问题。
但,生活并不是这么容易。在产品生命周期中,发布版本的时间应该是最长,在发布版本的时间里出现的coredump或许不多,但都很难重现,也很难定位,且大多数是在客户环境上出现,解决它的优先级就非常高,影响也很大。但在发布版本出现的coredump,栈往往是这样的。
(gdb) bt
#0 0x4365b569 in vfprintf () from /lib/libc.so.6
#1 0x436629ff in printf () from /lib/libc.so.6
#2 0x080485b9 in main ()
如果main函数多次调用printf,究竟是哪个?如果手头上有对应的调试版本,可能会很好。但如果没有,怎么定位?难道只能一个个地试?每修改一个,就要开发人员修改,提供补丁,测试人员测试,一个来回可能就要几天时间。如果main函数调用10次printf,那么可能要花上一两个月的时间,这种研发成本是无法让人忍受的。虽然有些经验丰富的代码高手,会从代码审核中来猜出哪一行。就本人的工作经历所遇到的,也是不尽人意的,特别是非常难重现的场景。
再考虑一种情况,如果从客户环境返回来的并不是一个dump文件,只是把一些栈和寄存器的,那么又如何定位是哪一行代码出现问题?
由于C、C++代码的逻辑,即使编译成了可执行文件,它的逻辑仍然保留,完全可以在汇编里体现出来。也就是说,可执行文件的汇编和源代码是有对应关系。但由于源代码和汇编是一对多的关系,一行代码可以编译成几条甚至十几条指令,出现coredump的函数可能只有十几行代码,但对应的汇编指令却有几百行,怎么从coredump的指令来推断出出错的代码行?
每种编程语言都有几种结构:顺序结构,条件结构,循环结构。这些结构就构成了代码的骨架。汇编语言也不例外。如果能够把出错函数的汇编指令的骨架快速找出来,把这些骨架逆向成相关的结构语句,然后看coredump的指令位于骨架的哪一部分,就能够很快推断出出错的代码行了。
现在开始探究C,C++语言代码结构在汇编里对应的特征。
- 熔断器 Hystrix 源码解析 —— 命令执行(二)之执行隔离策略
- phalapi-入门篇4(国际化高可用和自动生成文档)
- 用JavaScript动态输出的JS脚本不能执行
- Dubbo源码解析 —— 服务暴露原理
- [Golang软件推荐] RSA公私钥加解密(解决Golang私钥加密公钥解密问题)
- [喵咪大数据]Hive+Hbase关联
- 再战子域共享Cookie问题
- [喵咪大数据]Presto查询引擎
- 如何在5分钟内做出你的第一个开源贡献
- [喵咪大数据]HUE大数据管理工具
- Dubbo源码解析 —— Zookeeper 订阅
- 注册中心 Eureka 源码解析 —— 项目结构简介
- 【平台】Seldon.io发布新开源平台,用于Kubernetes上的机器学习
- 分布式事务 TCC-Transaction 源码分析 —— TCC 实现
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于Electron的touchbar开发
- Redis数据结构-简单动态字符串
- 使用new Function创建async方法
- Canvas系列(14):实战-小球碰撞
- IOC CreateBean
- Hugo搭建博客(二)— Hugo+Github Pages搭建博客
- 创建bean的实例
- Spring-IOC-默认标签的解析
- Spring-IoC -加载 Bean-总览
- Spring-IOC-创建Bean-属性填充
- vi与vim如何修改tab为4个空格方法示例
- Linux使用Crontab定时访问某个路由地址的方法
- jmeter 在linux服务器的安装和运行教程图解
- Linux中改变文件权限的chmod命令详析
- Ubuntu常用指令及用法详解