Linux二进制代码的阅读
大多数时候,我们研究的是如何阅读源代码。但在一些情况下,比如源代码不公开 或得到源代码的代价很高的情况下,我们又不得不需要了解程序的行为,这 时阅读二进制文件就非常重要。假设现在有一个二进制可执行文件,我们木有源代码,但要了解它的实现,这里仅简单列出一些常用的工具。 阅读方式可分为两个方面:静态阅读和动态阅读。
静态阅读
首先,file命
令可以查看可执行文件的大体信息。比如是哪种格式的,哪个体系结构的,有没有调试信息等。这些决定了需要用哪个版本的工具进行进一
步查看。比如如果是arm体系的可执行文件就可用arm
toolchain里的工具,如arm-eabi-objdump,arm-eabi-gdb等。
众所周知,GNU Binutils提供了一系列解析和操作二进制文件的工具,最常用的如objdump,其最主要的功能之一是反汇编:
objdump -d libxxx.so
其它常用选项包括:
-x 打印所有头信息
-s 打印所有段的内容
-S 将反汇编和源代码一起打印
-r 打印重定位表
-R 打印动态重定位表
-D 打印所有段,即不止代码段
-t 打印符号表,和nm的功能类似,但格式不一样
-T 只打印动态链接的符号表项
等等。
readelf命令主要用于查看elf文件的元信息(如段信息等)。如查看可执行文件的头信息:
readelf -h libxxx.so
其它常用选项包括:
-s 打印符号表
-r 打印重定位表
-l 打印装载属性
-S 打印段表
等等。
除了以上两个用得最多的,其它一些辅助工具有时也必不可少:
nm 打印符号表
c++filt 把c++符号unmangle
strip 把调试信息删除
strings 看文件中的字符串
ldd: 查看依赖关系
等等
动态阅读
要了解可程序的行为,最可靠的还是看二进制文件跑起来时的样子。很多时候,由于运行环境复杂,特别是多线程情况下,动态阅读能发现很多静态阅读所不可能发现的东西。
首先,在/proc/pid(pid为进程号)下记录了二进制文件跑起来后的很多信息,如通过/proc/pid/maps可以知道该程序链接了哪些库,
分别被加载在了什么地方(这样,知道了错误地址,理论上就可以找到相应库的对应反汇编代码。),/proc/pid/mem是进程所用的内存镜像,
/proc/pid/stat则记录了中断统计信息等。/proc/pid/cmdline则记录了启动程序的命令行。
其次,通过trace(strace,lstrace)可以看程序有哪些系统调用。strace用于跟踪系统调用,ltrace用于跟踪动态库调用。
如对于在/proc/pid/maps中看到的一些匿名内存映射,想要看它们是在什么时候或是在哪被创建可以用:
strace -f -p 3742 -e trace=mmap2,open,mprotect |tee tmp.trace
其中3742为进程ID。这里只过滤出关于内存映射的函数。
最后,指令级动态阅读的神器还属gdb。
在gdb中查看寄存器信息可用:
(gdb) i r
在调试过程中打印出反汇编代码可用
或者
(gdb) x/10i addr
然后就可以和objdump出来的反汇编结合着看了。如GOT表之类的信息在静态阅读时是无意义的,只有这时才能看。
各种break point能让我们迅速定位到我们关注的地方:
watch point 在指定数据被访问时程序停止。
break point 在指定代码被执行时程序停止。 因为很多时候库不带symbol,所以得直接设在地址上 break *addr。
catch point 在指定事件发生时程序停止,如进程创建,动态链接库加载及异常。
条件断点有时很有用:break ... if <condition>,但这玩意一旦设上不是一般的慢啊。。。
gdb中的bt和info frame命令常用来看堆栈信息和函数调用关系。但有时因为bug栈被写坏了,但如果不是被写得很坏,查看栈的内容常通常能找到一些线索:
(gdb) x/40x $sp
该命令是查看$sp指向区域的40个byte的内存内容。该命令也可用来查看任意指定地址的内存内容。
关于gdb常用的功能:http://wiki.ubuntu.org.cn/%E7%94%A8GDB%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F
其它的一些gdb使用备忘:http://blog.csdn.net/ariesjzj/article/details/6913671
一些相关资料
http://www.linuxforums.org/articles/understanding-elf-using-readelf-and-objdump_125.html
http://bbs.chinaunix.net/thread-1972423-1-1.html
elfutils-0.148: http://www.linux.it/~rubini/docs/binfmt/binfmt.html
GNU binutils & libbfd: http://www.gnu.org/software/binutils/
参考:
Linux二进制代码的阅读的更多相关文章
- 关于linux上pdf阅读器
今天也是倒腾linux 上pdf阅读器好久. 1.okular是挺好的,但是却太大了,好多功能,我没有细看.我简单的打开了几个pdf文件,发现加载速度还是太慢了.所以基于种种,我给卸载掉了. 安装直接 ...
- Linux协议栈代码阅读笔记(二)网络接口的配置
Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...
- [置顶] Linux协议栈代码阅读笔记(一)
Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...
- Linux版EPUB阅读器
Linux版EPUB阅读器 如果说用平板电脑看书尚属主流的话,那么在电脑上读书就非常少见了.专注阅读16世纪的书是非常困难的了,没人希望后台蹦出QQ聊天窗口.但是如果你非要在电脑上打开电子书的话,那么 ...
- Linux下如何阅读开源项目
标签(空格分隔): code SLAM是一个大型的项目,而且通常都是基于linux平台的.对于大部分没有linux经验的人来说,如何在linux下拥有vs代码阅读体验就非常重要了.这篇博客就简答的介绍 ...
- Linux 源码阅读 进程管理
Linux 源码阅读 进程管理 版本:2.6.24 1.准备知识 1.1 Linux系统中,进程是最小的调度单位: 1.2 PCB数据结构:task_struct (Location:linux-2. ...
- [置顶] Linux协议栈代码阅读笔记(二)网络接口的配置
Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...
- 转载~Linux 平台下阅读源码的工具
Linux 平台下阅读源码的工具 前言 看源代码是一个程序员必须经历的事情,也是可以提升能力的一个捷径.个人认为: 要完全掌握一个软件的方法只有阅读源码在Windows下有sourceinsight这 ...
- Linux下pdf阅读器推荐
由于需要在pdf文件上做标记,所以自带的文档查看器根本满足了需求,之前去网上查了查,Okular评价挺高,就安装了一个,确实能基本满足我的需求,但是 1.界面感觉还是不太友好,书签栏一直在那. 2.而 ...
随机推荐
- Tomcat 7优化配置
Tomcat 的优化不像其它软件那样,简简单单的修改几个参数就可以了,它的优化主要有三方面,分为系统优化,Tomcat 本身的优化,Java 虚拟机(JVM)调优.系统优化就不在介绍了,接下来就详细的 ...
- RT-thread内核之线程调度器
一.前言 RT-Thread中提供的线程调度器是基于全抢占式优先级的调度,在系统中除了中断处理函数.调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自 ...
- 【bzoj1026】[SCOI2009]windy数 数位dp
题目描述 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? 输入 包含两个整数 ...
- 【bzoj1692】[Usaco2007 Dec]队列变换 贪心+后缀数组
题目描述 FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. ...
- Python 嵌套函数和闭包
Python 嵌套函数和闭包 1.函数嵌套 如果在一个函数内部定义了另一个函数,我们称外部的函数为外函数,内部的函数为内函数,如下代码: def out_func(): def inner_func1 ...
- BZOJ4565 HAOI2016字符合并(区间dp+状压dp)
设f[i][j][k]为将i~j的字符最终合并成k的答案.转移时只考虑最后一个字符是由哪段后缀合成的.如果最后合成为一个字符特殊转移一下. 复杂度看起来是O(n32k),实际常数极小达到O(玄学). ...
- POJ2195:Going Home——题解
http://poj.org/problem?id=2195 题目大意: 有些人和房子,一个人只能进一个房子,人走到房子的路程即为代价. 求所有人走到房子后的最小代价. ——————————————— ...
- BZOJ2301:[HAOI2011]Problem b——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2301 https://www.luogu.org/problemnew/show/P2522 对于给 ...
- UVA.548 Tree(二叉树 DFS)
UVA.548 Tree(二叉树 DFS) 题意分析 给出一棵树的中序遍历和后序遍历,从所有叶子节点中找到一个使得其到根节点的权值最小.若有多个,输出叶子节点本身权值小的那个节点. 先递归建树,然后D ...
- [学习笔记]分治FFT
一般的分治FFT是指: https://www.luogu.org/problemnew/show/P4721 考虑后面的f和前面的f有关系,但是贡献可以分着计算,逐一累计上去. 考虑cdq分治.算出 ...