ELF 文件,可分为:
可重定位文件(Relocatable File) | 这类文件包含了代码和数据,可以被用来连接成可执行文件或共享目标文件,静态库也归为这一类 | Linux的 *.o/Windows 的 *.obj 文,及静态库 |
可执行文件(Executable File) | 包含了可以直接执行的程序 | Linux下的可执行二进制文件及windows下的exe文件 |
共享目标文件(Shared Object File) | 这类文件包含了代码和数据,可以在以下两种情况下使用。 一种是连接器可以使用这种文件跟其他的可重定位文件和共享目标文件链接,产生新的目标文件。第二种是动态库连接器可以把将几个这种共享目标文件与可执行文件结合,作为进程映像的一部分来运作 | linux下的 *.so 和windows下的 *.dll |
核心转储文件(Core Dump File) | 当进程意外终止时,系统可以将该进程的地址空间的内容及终止的一些其他的信息转储到 core dump File文件 | linux下的 core dump文件 |
1. file命令: 可以使用在linux下面是用 file 命令来查看相应的文件格式,上面几种文件在file命令下显示出相应的类型:
2. objdump 命令, 可以显示ELF文件的段信息(例如:代码存放在 .text段信息, 全局变量存放到.data和.bss段)。
3. readelf 命令,开业用来详细参考ELF文件的文件头信息。
[sundh@SSDEV005 temp]$ readelf -h SimpleSection.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V //程序运行平台
ABI Version: 0
Type: REL (Relocatable file) //ELF文件类型
Machine: Advanced Micro Devices X86-64 //cpu平台
Version: 0x1
Entry point address: 0x0 //入口地址,一般*.o文件没有入口地址,这个值为0
Start of program headers: 0 (bytes into file)
Start of section headers: 392 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes) //段表的大小
Number of section headers: 13 //段表描述符数量,即ELF文件中拥有段的数量
Section header string table index: 10 //字符串段表 所在整个段表中的下标
[sundh@SSDEV005 temp]$ readelf -S SimpleSection.o //读出的段表信息
There are 13 section headers, starting at offset 0x188:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
000000000000004f 0000000000000000 AX 0 0 4
[ 2] .rela.text RELA 0000000000000000 000006b0
0000000000000078 0000000000000018 11 1 8
[ 3] .data PROGBITS 0000000000000000 00000090
0000000000000008 0000000000000000 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 00000098
0000000000000004 0000000000000000 WA 0 0 4
[ 5] .rodata PROGBITS 0000000000000000 00000098
0000000000000004 0000000000000000 A 0 0 1
[ 6] .eh_frame PROGBITS 0000000000000000 000000a0
0000000000000058 0000000000000000 A 0 0 8
[ 7] .rela.eh_frame RELA 0000000000000000 00000728
0000000000000030 0000000000000018 11 6 8
[ 8] .comment PROGBITS 0000000000000000 000000f8
000000000000002e 0000000000000000 0 0 1
[ 9] .note.GNU-stack PROGBITS 0000000000000000 00000126
0000000000000000 0000000000000000 0 0 1
[10] .shstrtab STRTAB 0000000000000000 00000126
0000000000000061 0000000000000000 0 0 1
[11] .symtab SYMTAB 0000000000000000 000004c8
0000000000000180 0000000000000018 12 11 8
[12] .strtab STRTAB 0000000000000000 00000648
0000000000000066 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
4. nm 命令: 可以查看符号表信息, 例如C++ 符号: _ZN1N1C4funcEi, 所有符号都是以 _Z 开头,对于嵌套的名字(在名称空间或在类里面的),后面紧跟 N,然后是各个命名空间及类名(它们前面是名字字符串的长度),最好以 E 介绍,后面接着的是形参。
5. c++filt : 可以通过命令 c++filt 进行解析nm出来的符号:
[sundh@SSDEV005 temp]$ c++filt _ZN1N1C4funcEi
N::C::func(int)
Microsoft也提供了一个类似的接口, UnDecorateSymboName() 可以将window版本的符号解析成函数签名。
int main( int argc, char * argv[])
{
char buffer[256];
UnDecorateSymbolName("?func@@YAHH@Z", buffer, 256, 0 );
}
上面buffer 里面的数据就是 int func(int)
6. ldd 命令,可以用来查看可执行程序 和 动态库 依赖于哪些其他的动态库。