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不是全局变量而是本地变量,没有符号表条目
分析结果如下: