千里之行始于足下——编译器助手(binutils与elf文件)
任何技艺的提升都在于积累与总结;而对工具与流程的认识,有利于我们更深入的理解系统结构与执行环境。
任何东西都要硬币一样有正反两面:
感谢GNU,为我们提供了一整套完整的开发工具与运行环境,让我们能够更容易地开发与理解软件系统。
唾弃GNU,为我们提供了一整套完整的开发工具与执行环境,让我们在复杂的软件环境中沉重的学习,同时也丧失了自我的“创造力”。
然而对于工具与环境的把控,也正是提升与提炼自己的好机会,能让我们更加深入的理解软件系统,从而才能创造出更完备,更精炼的程序与系统。
认识ELF文件与Binutils工具,是我们熟悉编译工具的基本步骤;因为在Linux平台或者说GNU环境下的编译器——GCC,只是工具中重要的一环与很友善的接口界面而已。
一.ELF文件(在linux上的可执行与链接的二进制文件)的要点:
1.在linux平台中存在的主要形式:*.o(编译与汇编后的目标文件),*.so(链接之后的动态链接库),*.out(链接之后的可执行文件),*.ko(编译链接之后的驱动模块);
2.分析二进制文件的一个很有效的方式,就是用对应的头文件进行数据模块化的读取,而ELF文件的完整描述方式为elf.h文件:http://linux.die.net/include/elf.h;
3.ELF文件简介,该文件主要由ELF头信息与程序头信息表或者段表组成,详细的描述见:http://linux.die.net/man/5/elf;或者http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic.html#ELF-GENERIC
二.Binutils工具(该工具一般不需要编译,只有在制作交叉编译工具时)介绍http://www.sourceware.org/binutils/:
1.主要内容,参考LFS7.6(Linux From Scratch)6.13.2:
a)工具集——默认的命令行有很多参数,但是实际使用的确很少,用如下表简单总结一下
命令 |
功能 |
常用参数 |
意义 |
实例 |
说明 |
ar |
创建、修改、抽取静态库(*.a归档文件) |
r |
创建 |
ar -r libXX.a YY.o |
|
d |
删除obj |
ar -d libXX.a YY.o |
|||
x |
抽取obj |
ar -x libXX.a YY.o |
|||
t |
查看有哪些成员 |
ar -t libXX.a |
|||
nm |
列举obj文件的符号表 |
nm XXX |
|||
objcopy |
拷贝与转换格式obj文件中的部分内容 |
j |
提取elf文件分区 |
objcopy -j XX YY |
|
R |
删除elf文件分区 |
objcopy -R XX YY |
|||
S |
删除符号表 |
objcopy -S XX YY |
|||
I |
输入文件bfd格式 |
objcopy -I binary -O bfd -B arch XX YY |
将二进制文件编入程序的方法,如何得到bfd格式(objdump -i) |
||
O |
输出文件bfd格式 |
||||
B |
输出目标函数构架 |
||||
objcopy -O binary -j sec objfile obj-sec.bin |
抽取obj文件的某部分为bin文件 |
||||
objdump |
读取odj文件中具体信息 |
i |
读取所支持的bfd格式 |
objdump -i |
|
d/D |
反汇编 |
objdump -d -j .text XXX |
反汇编且将源码嵌入到汇编中:objdump -S -l -D/-z -j obj |
||
t |
符号表 |
objdump -t XXX |
|||
S |
添加源码 |
objdump -d -j .text XXX -S |
|||
m |
指定执行的平台 |
objdump -d -j .text XXX -S -m YYY |
通过它可以将Intel汇编与AT&T汇编互换 |
||
j |
某个段 |
objdump -d -j .text XXX |
|||
ranlib |
为静态库生成符号索引表 |
ranlib libXX.a |
nm -s 查看,等价于ar -s |
||
size |
读取文件的代码段、数据段大小 |
size objfile |
|||
strings |
列出elf文件中所有的字符串 |
strings elffile |
|||
strip |
清除obj文件的符号信息 |
s |
所有的字符串 |
strip objfile |
|
c++filt |
通过编译之后的符号名得到它实际被声明的函数 |
j |
也支持java的语法 |
c++filt symbol |
|
addr2line |
得到带debug信息的elf文件的某个地址,所在源文件的行 |
e |
输入源文件 |
addr2line -e elf addr |
一定要gcc -g |
readelf |
分析elf文件的基本结构 |
h |
读取elf头 |
readelf -h XX |
|
l |
读取程序头 |
readelf -l XX |
|||
S |
读取分区表 |
readelf -S XX |
|||
d |
读取动态表 |
readelf -d XX |
ldd 查看elf文件所依赖的动态库,并且可以得到加载地址 |
||
s |
读取符号表 |
readelf -s XX |
libiberty.a可以看作一个很有用的库,用于内存管理(obstack),命令行参数的统一实现等。
c)默认链接脚本,安装与ldscript的目录下。链接脚本的主要目的是被链接器(ld)将输入的BFD文件根据脚本规则,映射成输出的文件。如下整理的图,描述其语法:
三.Binutils工具在一般人看来是没有多少用,而且非常复杂,难以理解;但是对于想去理解与分析系统的人,确是必备的基础;以下就是这些命令常用的一些场合总结用于进一步理解与熟练使用它们
编译程序时,用-g参数,添加相关的debug信息到elf文件中。
objdump -j.text -d -S elf-file
为什么要用反汇编的方式呢?因为这样可以将各种宏定义给去掉,方便直接查看源代码。
2.objcopy将普通文件作为资源文件编译到程序中被使用,比如:
b)将hello.txt转换为bfd文件(hello.o),用于gcc链接,以x86_64的处理器构架为例(查询构架名与bfd名的方法为:objcopy --info):
objcopy -I binary -O elf64-x86-64 -B i386 hello.txt hello.o
extern char _binary_hello_txt_start[];//数据开始
extern char _binary_hello_txt_end[];//数据结束
printf("start : 0x%x\n",_binary_hello_txt_start);
printf("end : 0x%x\n",_binary_hello_txt_end);
for(i=0;i<_binary_hello_txt_end-_binary_hello_txt_start;i++)
printf("%c",*((char*)_binary_hello_txt_start+i));
3.objdump反汇编某个函数(objdump_func.sh elf-file fun_name):
echo "input obj-elf file is empty";
objdump -j.text -d $target_elf
#通过readelf 读取函数的基本信息开始地址与占用的大小
func_info=`readelf -s $target_elf|egrep "\b$func_name\b"`;
start_addr=`echo $func_info|awk '{print $2}'`
size=`echo $func_info|awk '{print $3}'`
stop_addr=$((16#$start_addr+16#$size))
echo $func_name at $target_elf: 0x$start_addr -- $stop_addr
#通过计算的start_addr(开始地址)与stop_addr(结束地址)进行直接
objdump -j.text -d $target_elf --start-address=0x$start_addr --stop-address=$stop_addr
4.用strip工具为编译生成的elf文件进行“瘦身”操作,去掉符号表;在嵌入式系统中,很有意义,减少生产的bin档占用的空间。
5.用addr2line去分析程序死掉的地方(程序是由gcc -g生成的,带debug信息)。
$(OBJDIR)/boot/boot: $(BOOT_OBJS)
#用ld链接成的obj文件 进入点位 start标记,代码段的开始点位0x7c00.
$(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o $@.out $^
#用objdump将生产的elf文件,代码反汇编为$(OBJDIR)/boot/boot.asm, #而且带源 码 信息
$(V)$(OBJDUMP) -S $@.out >$@.asm
#用objcopy 将 代码段拷贝为$(OBJDIR)/boot/boot,用于烧写到MBR引导 #操作系统
$(V)$(OBJCOPY) -S -O binary -j .text $@.out $@
#修改512byte的boot最后分区为0x55AA用于指明该分区用于引导系统
$(V)perl boot/sign.pl $(OBJDIR)/boot/boot
a)链接脚本的使用(以arm处理器为例:u-boot-2014.10\arch\arm\cpu):
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
9.用c++filt得到c++与java在源代码中的实际名称。
b)通过readelf得到关于A::add()的编译生成最后的名称为:
57: 0000000000400656 25 FUNC WEAK DEFAULT 13 _ZN1A3addEv
58: 0000000000601038 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__
59: 00000000004006f8 0 OBJECT GLOBAL HIDDEN 15 __dso_handle
60: 0000000000400670 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init
61: 0000000000601034 0 NOTYPE GLOBAL DEFAULT 25 __bss_start
62: 0000000000400632 35 FUNC WEAK DEFAULT 13 _ZN1AC1Eii
63: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 25 _end
64: 0000000000400632 35 FUNC WEAK DEFAULT 13 _ZN1AC2Eii
c++filt _ZN1A3addEv --->A::add()
c++filt _ZN1AC1Eii ------>A::A(int, int)
千里之行始于足下——编译器助手(binutils与elf文件)相关推荐
- ELF文件中的各个节区
版权声明:本文为CSDN博主「ashimida@」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/lidan1 ...
- GCC的编译过程以及其同盟成员和ELF文件的分析
文章目录 一.GCC的同盟成员介绍 1.GCC的介绍 2.同盟成员之Binutils 3.同盟成员之C 运行库 二.GCC的详细编译过程 1.编译的简介 2.预处理(Preprocessing) 3. ...
- readelf和ldd分析elf文件
1. elf 文件格式 linux系统中,gcc编译器编译出的object文件.可执行文件都属于elf文件. elf文件由三个部分组成:elf header.program headers|secti ...
- 【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )
文章目录 一.ELF 文件简介 二.ELF 文件头 三.ELF 文件头标志 四.ELF 文件位数 五.ELF 文件大小端格式 一.ELF 文件简介 在上一篇博客 [Android 逆向]ELF 文件格 ...
- 【Android 逆向】ELF 文件格式 ( ELF 文件简介 | ELF 文件结构 )
文章目录 一.ELF 文件简介 二.ELF 文件结构 一.ELF 文件简介 ELF 文件是 Executable and Linkable Format ( 可执行 和 可链接 格式 ) 的文件 ; ...
- c语言书籍elf文件,扒一扒ELF文件
ELF文件(Executable Linkable Format)是一种文件存储格式.Linux下的目标文件和可执行文件都按照该格式进行存储,有必要做个总结. 1. 链接举例 2. ELF文件类型2. ...
- ELF文件装载链接过程及hook原理
ELF文件格式解析 可执行和可链接格式(Executable and Linkable Format,缩写为ELF),常被称为ELF格式,在计算机科学中,是一种用于执行档.目的档.共享库和核心转储的标 ...
- awx文件解析_Android so(ELF)文件解析
一.前言 so文件是啥?so文件是elf文件,elf文件后缀名是.so,所以也被chang常称之为so文件,elf文件是linux底下二进制文件,可以理解为windows下的PE文件,在Android ...
- Linux下的ELF文件、链接、加载与库(含大量图文解析及例程)
Linux下的ELF文件.链接.加载与库 链接是将将各种代码和数据片段收集并组合为一个单一文件的过程,这个文件可以被加载到内存并执行.链接可以执行与编译时,也就是在源代码被翻译成机器代码时:也可以执行 ...
最新文章
- 量化网络训练--Towards Effective Low-bitwidth Convolutional Neural Networks
- VTK:可视化算法之ExponentialCosine
- 优化函数html代码,CSS代码优化方法
- Embeded linux之移植iptables
- PoolTogether 奖池开奖一名用户赢得 43,760 美元,本金仅为 73 美元
- 【转】转贴 poj分类
- Magento2创建自定义Widget 并通过添加图片选择器插入图片
- Java 高级算法——数组中查询重复的数字之二
- 【matlab】元胞数组的创建
- 信息系统项目管理师 高级 论文备考专题 老师现场写论文
- 八 关于电机驱动芯片L298N使用心得
- 游戏开发--开源18---Volity|PhiloGL|impactJs|createjs|C...
- 【hibernate】idea利用maven搭建hibernate环境(创建hibernate配置文件(包括cfg和hbm))
- ug安装计算机用户名不能是汉字,win7系统下安装UG软件后打开提示计算机名不对怎么办...
- 最大子列和问题(C语言)
- Katana:1 PGP Workthrought
- U牌“唤醒生命,未来可7”
- 结算从业人员常用词典1.0
- uni-app小程序基础知识速览(上)
- Android手机cpu架构详解