用GNU READELF工具分析ELF文件

readelf命令是Linux下的分析ELF文件的命令,在分析ELF文件时非常方便,在此记录:

  • 使用方法:
linux> readelf -h test.o
linux> readelf -l test.o
linux> readelf -S swap.o
  • 参数选项

选项

描述

-a

–all 显示全部信息,等价于 -h -l -S -s -r -d -V -A -I.

-h

–file-header 显示elf文件开始的文件头信息.

-l

–program-headers

-S

–section-headers –sections 显示节头信息(如果有的话)。

-g

–section-groups 显示节组信息(如果有的话)。

-t

–section-details 显示节的详细信息(-S的)。

-s

–syms –symbols 显示符号表段中的项(如果有的话)。

-e

–headers 显示全部头信息,等价于: -h -l -S

-n

–notes 显示note段(内核注释)的信息。

-r

–relocs 显示可重定位段的信息。

-u

–unwind 显示unwind段信息。当前只支持IA64 ELF的unwind段信息。

-d

–dynamic 显示动态段的信息。

-V

–version-info 显示版本段的信息。

-A

–arch-specific 显示CPU构架信息。

-D

–use-dynamic 使用动态段中的符号表显示符号,而不是使用符号段。

-I

–histogram 显示符号的时候,显示bucket list长度的柱状图。

-v

–version 显示readelf的版本信息。

-H

–help 显示readelf所支持的命令行选项。

-W

–wide 宽行输出。

分析举例:

  • 有如下两段程序:
/*main.c*/
void swap();
int buf[2] = {1, 2};
int main() {
	swap(); 
	return 0;
}
/*swap.c*/
extern int buf [];
int *bufp0 = &buf[0] ; 
int *bufp1;
void swap() {
	int temp;
	bufp1 = &buf[1]; 
	temp =*bufp0; 
	*bufp0 = *bufp1; 
	*bufp1 = temp;
}

对于每个在 swap.o 中定义或引用的符号, 请指出它是否在模块 swap.o 中的 .symtab 节中有一个符号表条目。如果是,请指出定义该符号的 模块 (swap.o 或者 main.o)、符号类型(本地、全局或者外部)和它在模块中占据的节 (.text .data 或者 .bss)?

  • 符号类型可以结合代码查看,注意在.symtab中只能看到global的变量名

  • 对于变量储存的节,可以查看Ndx的编号来获取:编号参考:

  [Nr] Name        
  [ 0]                 
  [ 1] .text           
  [ 2] .rel.text     
  [ 3] .data         
  [ 4] .bss          
  [ 5] .comment     
  [ 6] .note.GNU-stack  
  [ 7] .eh_frame    
  [ 8] .rel.eh_frame
  [ 9] .shstrtab      
  [10] .symtab      
  [11] .strtab      
  • 执行指令:
linux> gcc -c swap.c -o swap.o
linux> gcc -c mian.c -o main.o
linux> gcc -g swap.o main.o -o run
linux> readelf -a swap.o 
linux> readelf -a main.o
  • 得到结果
    swap.o.symTable:
    在这里插入图片描述
    main.o .symTable:
    在这里插入图片描述

extern是计算机语言中的一个关键字,可置于变量或者函数前,以表示变量或者函数的定义在别的文件中。提示编译器遇到此变量或函数时,在其它模块中寻找其定义,另外,extern也可用来进行链接指定。

  • buf,是swap.o.symTable的条目,extern 类型的符号,在main.o模块中定义!,我们看到一个关于全局符号 buf 定义的条目,它是从 .data 中偏移为 0 处开始的一个 8 字节的已初始化目标.
  • bufp0:是swap.o.symTable的条目,global类型符号,在swap.o中定义,我们看到一个关于全局符号 bufpO 定义的条目,它是从 .data 中偏移为 0 处开始的一个 4 字节的已初始化目标
  • bufp1:是swap.o.symTabl的条目,global类型的符号,在swap.o中定义,它是一个未初始化的 4 字节数据目标(要求 4 字节对齐),最终当 这个模块被链接时它将作为一个 .bss 目标分配
  • swap:是swap.o.symTable的条目,func类型的符号,在swap.o中定义,它是一个位于 .text 中偏移为零处的 39 字节的函数。
  • temp:不属于swap.o.symTable条目,int类型的符号,在swap.o中定义,局部变量位于栈中管理。

注:symtab存放在程序中被定义和引用的函数和全局变量的信息。Tmp不是全局变量而是本地变量,没有符号表条目
分析结果如下:

在这里插入图片描述

原创文章 236 获赞 430 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_44307065/article/details/106156575
GNU