linker load elf(1)
Linux Windows Dynamic Linking Library .so .dll Static Linking Library .a .lib //so的全称是shared object
//SimpleSection.c #include <stdio.h> int global_init_var = 84; int global_uninit_var; void func1(int i) { printf("%d\n", i); } int main(void) { static int static_var = 85; static int static_var2; int a = 1; int b; func1(static_var + static_var2 + a + b); return a; }
mutian@mutian:~/share/test$ gcc -c SimpleSection.c -o SimpleSection.o mutian@mutian:~/share/test$ objdump -h SimpleSection.o // objdump只能显示关键的段,如果要显示所有段请使用readelf命令 SimpleSection.o: file format elf64-x86-64 Sections: Idx Name Size VMA LMA File off Algn 0 .text 00000053 0000000000000000 0000000000000000 00000040 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 00000008 0000000000000000 0000000000000000 00000094 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000004 0000000000000000 0000000000000000 0000009c 2**2 ALLOC 3 .rodata 00000004 0000000000000000 0000000000000000 0000009c 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .comment 0000002b 0000000000000000 0000000000000000 000000a0 2**0 CONTENTS, READONLY 5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000cb 2**0 CONTENTS, READONLY 6 .eh_frame 00000058 0000000000000000 0000000000000000 000000d0 2**3 CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA mutian@mutian:~/share/test$ size SimpleSection.o text data bss dec hex filename 175 8 4 187 bb SimpleSection.o
175 + 8 + 4 = 187 = 0xbb
//175 = 0x53 + 0x4 + 0x58 why?
//存放指令 只读 代码段 .text //存放初始化的数据,data段是要占可执行文件空间的 数据段 .data //存放未初始化的全局变量/局部静态变量,自动被初始化为0(或者初始化为0的全局变量/局部静态变量) //BSS段只是记录数据所需空间的大小,它不占可执行文件空间的 BSS(Block Started by Symbol)段 .bss 只读数据段 .rodata 注释信息段 .comment 堆栈提示段 .note.GNU-stack
.eh_frame: When gcc generates code that handles exceptions, it produces tables that describe how to unwind the stack. These tables are found in the .eh_frame section. The format of the .eh_frame section is very similar to the format of a DWARF .debug_frame section.
mutian@mutian:~/share/test$ objdump --help
Usage: objdump <option(s)> <file(s)>
Display information from object <file(s)>.
At least one of the following switches must be given:
-h, --[section-]headers Display the contents of the section headers
-x, --all-headers Display the contents of all headers
-d, --disassemble Display assembler contents of executable sections
// -d 将所有包含指令的段反汇编
-D, --disassemble-all Display assembler contents of all sections
-S, --source Intermix source code with disassembly
-s, --full-contents Display the full contents of all sections requested
// -s 将所有段的内容以十六进制格式打印出来
mutian@mutian:~/share/test$ objdump -s -d SimpleSection.o SimpleSection.o: file format elf64-x86-64 Contents of section .text: 0000 554889e5 4883ec10 897dfcb8 00000000 UH..H....}...... 0010 8b55fc89 d64889c7 b8000000 00e80000 .U...H.......... 0020 0000c9c3 554889e5 4883ec10 c745f801 ....UH..H....E.. 0030 0000008b 15000000 008b0500 00000001 ................ 0040 d00345f8 0345fc89 c7e80000 00008b45 ..E..E.........E 0050 f8c9c3 ... Contents of section .data: 0000 54000000 55000000 T...U... Contents of section .rodata: 0000 25640a00 %d.. Contents of section .comment: 0000 00474343 3a202855 62756e74 752f4c69 .GCC: (Ubuntu/Li 0010 6e61726f 20342e36 2e332d31 7562756e naro 4.6.3-1ubun 0020 74753529 20342e36 2e3300 tu5) 4.6.3. Contents of section .eh_frame: 0000 14000000 00000000 017a5200 01781001 .........zR..x.. 0010 1b0c0708 90010000 1c000000 1c000000 ................ 0020 00000000 24000000 00410e10 8602430d ....$....A....C. 0030 065f0c07 08000000 1c000000 3c000000 ._..........<... 0040 00000000 2f000000 00410e10 8602430d ..../....A....C. 0050 066a0c07 08000000 .j...... Disassembly of section .text: 0000000000000000 <func1>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 83 ec 10 sub $0x10,%rsp 8: 89 7d fc mov %edi,-0x4(%rbp) b: b8 00 00 00 00 mov $0x0,%eax 10: 8b 55 fc mov -0x4(%rbp),%edx 13: 89 d6 mov %edx,%esi 15: 48 89 c7 mov %rax,%rdi 18: b8 00 00 00 00 mov $0x0,%eax 1d: e8 00 00 00 00 callq 22 <func1+0x22> 22: c9 leaveq 23: c3 retq 0000000000000024 <main>: 24: 55 push %rbp 25: 48 89 e5 mov %rsp,%rbp 28: 48 83 ec 10 sub $0x10,%rsp 2c: c7 45 f8 01 00 00 00 movl $0x1,-0x8(%rbp) 33: 8b 15 00 00 00 00 mov 0x0(%rip),%edx # 39 <main+0x15> 39: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 3f <main+0x1b> 3f: 01 d0 add %edx,%eax 41: 03 45 f8 add -0x8(%rbp),%eax 44: 03 45 fc add -0x4(%rbp),%eax 47: 89 c7 mov %eax,%edi 49: e8 00 00 00 00 callq 4e <main+0x2a> 4e: 8b 45 f8 mov -0x8(%rbp),%eax 51: c9 leaveq 52: c3 retq
函数的第一个字节0x55就是"push %rbp"指令
0xc3是最后一条指令"retq"
Contents of section .data: 0000 54000000 55000000 T...U... int global_init_var = 84; //0x00000054 static int static_var = 85; //0x00000055
//.rodata 存放的是只读数据,如只const修饰的变量和字符串 Contents of section .rodata: 0000 25640a00 %d.. printf("%d\n", i); // "%d\n" 四个字节
Contents of section .comment: 0000 00474343 3a202855 62756e74 752f4c69 .GCC: (Ubuntu/Li 0010 6e61726f 20342e36 2e332d31 7562756e naro 4.6.3-1ubun 0020 74753529 20342e36 2e3300 tu5) 4.6.3. .comment存放编译器版本信息,比如字符串“GCC:(GUN)4.2.0”
Note: 有时候编译器会把字符串常量放到.data段
mutian@mutian:~/share/test$ 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) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 400 (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 Section header string table index: 10
// SimpleSection.o 0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............ 0000010: 0100 3e00 0100 0000 0000 0000 0000 0000 ..>............. 0000020: 0000 0000 0000 0000 9001 0000 0000 0000 ................ 0000030: 0000 0000 4000 0000 0000 4000 0d00 0a00 ....@.....@..... 0000040: 5548 89e5 4883 ec10 897d fcb8 0000 0000 UH..H....}...... 0000050: 8b55 fc89 d648 89c7 b800 0000 00e8 0000 .U...H.......... 0000060: 0000 c9c3 5548 89e5 4883 ec10 c745 f801 ....UH..H....E.. 0000070: 0000 008b 1500 0000 008b 0500 0000 0001 ................ 0000080: d003 45f8 0345 fc89 c7e8 0000 0000 8b45 ..E..E.........E 0000090: f8c9 c300 5400 0000 5500 0000 2564 0a00 ....T...U...%d.. 00000a0: 0047 4343 3a20 2855 6275 6e74 752f 4c69 .GCC: (Ubuntu/Li 00000b0: 6e61 726f 2034 2e36 2e33 2d31 7562 756e naro 4.6.3-1ubun 00000c0: 7475 3529 2034 2e36 2e33 0000 0000 0000 tu5) 4.6.3...... 00000d0: 1400 0000 0000 0000 017a 5200 0178 1001 .........zR..x.. 00000e0: 1b0c 0708 9001 0000 1c00 0000 1c00 0000 ................ 00000f0: 0000 0000 2400 0000 0041 0e10 8602 430d ....$....A....C. 0000100: 065f 0c07 0800 0000 1c00 0000 3c00 0000 ._..........<... 0000110: 0000 0000 2f00 0000 0041 0e10 8602 430d ..../....A....C. 0000120: 066a 0c07 0800 0000 002e 7379 6d74 6162 .j........symtab 0000130: 002e 7374 7274 6162 002e 7368 7374 7274 ..strtab..shstrt 0000140: 6162 002e 7265 6c61 2e74 6578 7400 2e64 ab..rela.text..d 0000150: 6174 6100 2e62 7373 002e 726f 6461 7461 ata..bss..rodata 0000160: 002e 636f 6d6d 656e 7400 2e6e 6f74 652e ..comment..note. 0000170: 474e 552d 7374 6163 6b00 2e72 656c 612e GNU-stack..rela. 0000180: 6568 5f66 7261 6d65 0000 0000 0000 0000 eh_frame........ 0000190: 0000 0000 0000 0000 0000 0000 0000 0000 ................ ......................................................
unsigned char e_ident[EI_NIDENT]; /* 16 Magic number and other info */
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
ELF文件的魔数: 7f45 4c46 .ELF
0x7f => DEL控制符的ASCII码
0x45 => E
0x4c => L
0x46 => F
0x02 =>表示是64位 //0x01表示32位
0x01 =>表示是小端 //0x2表示大端
0x01 =>表示ELF文件的主板本号,一般是1(ELF标准1.2以后就没有再出新版本)
00 0000 0000 0000 0000 => 后面9个字节ELF标准没有定义,一般填0(有的平台可能将它作为扩展标志)
Elf64_Half e_type; /*Object file type */ 2 byte
3种类型的elf格式文件
ET_REL 1 可重定位文件, 一般为.o文件
ET_EXEC 2 可执行文件
ET_DYN 3 共享目标文件
这里这个值为01,显然SimpleSection.o是可重定位文件
// /usr/include/elf.h /* Standard ELF types. */ #include <stdint.h> /* Type for a 16-bit quantity. */ typedef uint16_t Elf32_Half; typedef uint16_t Elf64_Half; /* Types for signed and unsigned 32-bit quantities. */ typedef uint32_t Elf32_Word; typedef int32_t Elf32_Sword; typedef uint32_t Elf64_Word; typedef int32_t Elf64_Sword; /* Types for signed and unsigned 64-bit quantities. */ typedef uint64_t Elf32_Xword; typedef int64_t Elf32_Sxword; typedef uint64_t Elf64_Xword; typedef int64_t Elf64_Sxword; /* Type of addresses. */ typedef uint32_t Elf32_Addr; typedef uint64_t Elf64_Addr; /* Type of file offsets. */ typedef uint32_t Elf32_Off; typedef uint64_t Elf64_Off; /* Type for section indices, which are 16-bit quantities. */ typedef uint16_t Elf32_Section; typedef uint16_t Elf64_Section; /* Type for version symbol information. */ typedef Elf32_Half Elf32_Versym; typedef Elf64_Half Elf64_Versym; /* The ELF file header. This appears at the start of every ELF file. */ #define EI_NIDENT (16) typedef struct { unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ Elf32_Half e_type; /* Object file type */ Elf32_Half e_machine; /* Architecture */ Elf32_Word e_version; /* Object file version */ Elf32_Addr e_entry; /* Entry point virtual address */ Elf32_Off e_phoff; /* Program header table file offset */ Elf32_Off e_shoff; /* Section header table file offset */ Elf32_Word e_flags; /* Processor-specific flags */ Elf32_Half e_ehsize; /* ELF header size in bytes */ Elf32_Half e_phentsize; /* Program header table entry size */ Elf32_Half e_phnum; /* Program header table entry count */ Elf32_Half e_shentsize; /* Section header table entry size */ Elf32_Half e_shnum; /* Section header table entry count */ Elf32_Half e_shstrndx; /* Section header string table index */ } Elf32_Ehdr; typedef struct { unsigned char e_ident[EI_NIDENT]; /* 16 Magic number and other info */ Elf64_Half e_type; /* 2 Object file type */ Elf64_Half e_machine; /* 2 Architecture */ Elf64_Word e_version; /* 4 Object file version */ Elf64_Addr e_entry; /* 8 Entry point virtual address */ Elf64_Off e_phoff; /* 8 Program header table file offset */ Elf64_Off e_shoff; /* 8 Section header table file offset */ Elf64_Word e_flags; /* 4 Processor-specific flags */ Elf64_Half e_ehsize; /* 2 ELF header size in bytes */ Elf64_Half e_phentsize; /* 2 Program header table entry size */ Elf64_Half e_phnum; /* 2 Program header table entry count */ Elf64_Half e_shentsize; /* 2 Section header table entry size */ Elf64_Half e_shnum; /* 2 Section header table entry count */ Elf64_Half e_shstrndx; /* 2 Section header string table index */ } Elf64_Ehdr;
段的说明
readelf命令可以读出elf格式文件的所有段
mutian@mutian:~/share/test$ readelf -S SimpleSection.o
There are 13 section headers, starting at offset 0x190:
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
0000000000000053 0000000000000000 AX 0 0 4
[ 2] .rela.text RELA 0000000000000000 000006b8
0000000000000078 0000000000000018 11 1 8
[ 3] .data PROGBITS 0000000000000000 00000094
0000000000000008 0000000000000000 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 0000009c
0000000000000004 0000000000000000 WA 0 0 4
[ 5] .rodata PROGBITS 0000000000000000 0000009c
0000000000000004 0000000000000000 A 0 0 1
[ 6] .comment PROGBITS 0000000000000000 000000a0
000000000000002b 0000000000000001 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 000000cb
0000000000000000 0000000000000000 0 0 1
[ 8] .eh_frame PROGBITS 0000000000000000 000000d0
0000000000000058 0000000000000000 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 00000730
0000000000000030 0000000000000018 11 8 8
[10] .shstrtab STRTAB 0000000000000000 00000128
0000000000000061 0000000000000000 0 0 1
[11] .symtab SYMTAB 0000000000000000 000004d0
0000000000000180 0000000000000018 12 11 8
[12] .strtab STRTAB 0000000000000000 00000650
0000000000000066 0000000000000000 0 0 1
13个段的数组,其中第一个段是无效的描述符,也就是说一共13个段,单只有12个有效的段。
Elf64_Shdr是一个结构体,用来描述段描述符Section Description
// /usr/include/elf.h
/* Section header. */
typedef struct
{
Elf32_Word sh_name; /* Section name (string tbl index) */
Elf32_Word sh_type; /* Section type */
Elf32_Word sh_flags; /* Section flags */
Elf32_Addr sh_addr; /* Section virtual addr at execution */
Elf32_Off sh_offset; /* Section file offset */
Elf32_Word sh_size; /* Section size in bytes */
Elf32_Word sh_link; /* Link to another section */
Elf32_Word sh_info; /* Additional section information */
Elf32_Word sh_addralign; /* Section alignment */
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
typedef struct
{
Elf64_Word sh_name; /* Section name (string tbl index) */
Elf64_Word sh_type; /* Section type */
Elf64_Xword sh_flags; /* Section flags */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Section size in bytes */
Elf64_Word sh_link; /* Link to another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;

浙公网安备 33010602011771号