任何技艺的提升都在于积累与总结;而对工具与流程的认识,有利于我们更深入的理解系统结构与执行环境。

任何东西都要硬币一样有正反两面:

感谢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

更具体的命令分析,见附件。

b)相关函数库:

libbfd.a用于描述与操作可执行二进制文件(BFD)。

libopcodes.a用于实现汇编与反汇编的操作。

libiberty.a可以看作一个很有用的库,用于内存管理(obstack),命令行参数的统一实现等。

c)默认链接脚本,安装与ldscript的目录下。链接脚本的主要目的是被链接器(ld)将输入的BFD文件根据脚本规则,映射成输出的文件。如下整理的图,描述其语法:

三.Binutils工具在一般人看来是没有多少用,而且非常复杂,难以理解;但是对于想去理解与分析系统的人,确是必备的基础;以下就是这些命令常用的一些场合总结用于进一步理解与熟练使用它们

1.objdump的反汇编有助于查看c语言源代码:

编译程序时,用-g参数,添加相关的debug信息到elf文件中。

objdump -j.text -d -S elf-file

为什么要用反汇编的方式呢?因为这样可以将各种宏定义给去掉,方便直接查看源代码。

2.objcopy将普通文件作为资源文件编译到程序中被使用,比如:

a)编译hello.txt文件:hello world。

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

c)在程序中引用该文件生成的段。

extern char _binary_hello_txt_start[];//数据开始

extern char _binary_hello_txt_end[];//数据结束

int main()

{

int i;

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));

printf("\n");

}

3.objdump反汇编某个函数(objdump_func.sh elf-file fun_name):

target_elf=$1

func_name=$2

if [ -z "$target_elf" ];then

echo "input obj-elf file is empty";

exit;

fi

if [ -z "$func_name" ];then

objdump -j.text -d $target_elf

exit;

Fi

#通过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档占用的空间。

strip elf-file

5.用addr2line去分析程序死掉的地方(程序是由gcc -g生成的,带debug信息)。

程序运行在虚拟地址空间,而对于某种构架的编译器生成的程序地址一般都是固定的(默认的程序进入点);当linux的kernel崩溃时或者应用程序崩溃时,会将堆栈信息与寄存器信息打印出来。其中就有很多地址信息,通过addr2line就可以将地址映射成源代码中的某一行。

6.理解bootloader的脚本,在MIT的操作系统实践项目(http://pdos.csail.mit.edu/6.828/2012/labs/lab1/)中,在MBR中引导操作系统的代码编译make中有如下信息:

$(OBJDIR)/boot/boot: $(BOOT_OBJS)

@echo + ld boot/boot

#用ld链接成的obj文件 进入点位 start标记,代码段的开始点位0x7c00.

#因为bios加载MBR之后,会在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

7.uboot的编译过程的脚本分析

a)链接脚本的使用(以arm处理器为例:u-boot-2014.10\arch\arm\cpu):

#include <config.h>

/*代码最终输出格式*/

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

/*处理器构架*/

OUTPUT_ARCH(arm)

/*程序进入点*/

ENTRY(_start)

SECTIONS

{

/*代码段,从0x0开始*/

. = 0x00000000;

. = ALIGN(4);

/*定义代码段的链接内容*/

.text :

{

*(.__image_copy_start)

*(.vectors)

CPUDIR/start.o (.text*)

*(.text*)

}

...

}

b)Makefile中有各种格式转换与链接到特定的地址

8.用ar命令打包obj文件,生成静态链接库

ar rcs lib$fn.a $fn.o

9.用c++filt得到c++与java在源代码中的实际名称。

a)写一个测试demo:

#include <stdio.h>

class A{

private: int a;

private: int b;

public:

A(int a,int b){

this->a =a;

this->b = b;

}

int add()

{

return a+b;

}

};

int main()

{

A Test(3,5);

printf("%d\n",Test.add());

}

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)通过c++flit得到正常的名称:

c++filt _ZN1A3addEv --->A::add()

c++filt _ZN1AC1Eii ------>A::A(int, int)

千里之行始于足下——编译器助手(binutils与elf文件)相关推荐

  1. ELF文件中的各个节区

    版权声明:本文为CSDN博主「ashimida@」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/lidan1 ...

  2. GCC的编译过程以及其同盟成员和ELF文件的分析

    文章目录 一.GCC的同盟成员介绍 1.GCC的介绍 2.同盟成员之Binutils 3.同盟成员之C 运行库 二.GCC的详细编译过程 1.编译的简介 2.预处理(Preprocessing) 3. ...

  3. readelf和ldd分析elf文件

    1. elf 文件格式 linux系统中,gcc编译器编译出的object文件.可执行文件都属于elf文件. elf文件由三个部分组成:elf header.program headers|secti ...

  4. 【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )

    文章目录 一.ELF 文件简介 二.ELF 文件头 三.ELF 文件头标志 四.ELF 文件位数 五.ELF 文件大小端格式 一.ELF 文件简介 在上一篇博客 [Android 逆向]ELF 文件格 ...

  5. 【Android 逆向】ELF 文件格式 ( ELF 文件简介 | ELF 文件结构 )

    文章目录 一.ELF 文件简介 二.ELF 文件结构 一.ELF 文件简介 ELF 文件是 Executable and Linkable Format ( 可执行 和 可链接 格式 ) 的文件 ; ...

  6. c语言书籍elf文件,扒一扒ELF文件

    ELF文件(Executable Linkable Format)是一种文件存储格式.Linux下的目标文件和可执行文件都按照该格式进行存储,有必要做个总结. 1. 链接举例 2. ELF文件类型2. ...

  7. ELF文件装载链接过程及hook原理

    ELF文件格式解析 可执行和可链接格式(Executable and Linkable Format,缩写为ELF),常被称为ELF格式,在计算机科学中,是一种用于执行档.目的档.共享库和核心转储的标 ...

  8. awx文件解析_Android so(ELF)文件解析

    一.前言 so文件是啥?so文件是elf文件,elf文件后缀名是.so,所以也被chang常称之为so文件,elf文件是linux底下二进制文件,可以理解为windows下的PE文件,在Android ...

  9. Linux下的ELF文件、链接、加载与库(含大量图文解析及例程)

    Linux下的ELF文件.链接.加载与库 链接是将将各种代码和数据片段收集并组合为一个单一文件的过程,这个文件可以被加载到内存并执行.链接可以执行与编译时,也就是在源代码被翻译成机器代码时:也可以执行 ...

最新文章

  1. 量化网络训练--Towards Effective Low-bitwidth Convolutional Neural Networks
  2. VTK:可视化算法之ExponentialCosine
  3. 优化函数html代码,CSS代码优化方法
  4. Embeded linux之移植iptables
  5. PoolTogether 奖池开奖一名用户赢得 43,760 美元,本金仅为 73 美元
  6. 【转】转贴 poj分类
  7. Magento2创建自定义Widget 并通过添加图片选择器插入图片
  8. Java 高级算法——数组中查询重复的数字之二
  9. 【matlab】元胞数组的创建
  10. 信息系统项目管理师 高级 论文备考专题 老师现场写论文
  11. 八 关于电机驱动芯片L298N使用心得
  12. 游戏开发--开源18---Volity|PhiloGL|impactJs|createjs|C...
  13. 【hibernate】idea利用maven搭建hibernate环境(创建hibernate配置文件(包括cfg和hbm))
  14. ug安装计算机用户名不能是汉字,win7系统下安装UG软件后打开提示计算机名不对怎么办...
  15. 最大子列和问题(C语言)
  16. Katana:1 PGP Workthrought
  17. U牌“唤醒生命,未来可7”
  18. 结算从业人员常用词典1.0
  19. uni-app小程序基础知识速览(上)
  20. Android手机cpu架构详解

热门文章

  1. HBase整合MR本地IDEA运行
  2. php如何把网页存成图片格式,php怎么生成图片 网页快照?
  3. 无人驾驶技术入门(八)| 被严重低估的传感器超声波雷达
  4. 用Python画大学物理实验曲线
  5. 什么是CT 技术。。。你懂了么?
  6. 百度搜索引擎 - 搜索关键字排名 API
  7. 把时间当作朋友——第3章 管理
  8. 一起做激光SLAM[六]isam于SLAM位姿因子图优化的使用
  9. 阿里云easy-excel的使用(springboot整合)
  10. 100BASE-TX、100Base-FX等含义