ELF文件包括三个索引表:(常用elf文件: .a文件、.o文件、.so文件以及可执行文件)
1、ELF header: 描述整个文件的组织
2、Program header table: 告诉系统如何创建进程映像
3、Section header table: 包含各个section的属性信息
可以 vi /usr/include/elf.h 查看各个头格式,以及各section 表的格式
1、读取ELF header: readelf -h app
[root@localhost l1]# readelf -h app
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x407f40
Start of program headers: 64 (bytes into file)
Start of section headers: 12200016 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 10
Size of section headers: 64 (bytes)
Number of section headers: 45
Section header string table index: 44
[root@localhost l1]#
elf header格式
/* ELF Header */
typedef struct elfhdr {
unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
Elf32_Half e_type; /* object file type */
Elf32_Half e_machine; /* machine */
Elf32_Word e_version; /* object file version */
Elf32_Addr e_entry; /* virtual entry point */
Elf32_Off e_phoff; /* program header table offset */
Elf32_Off e_shoff; /* section header table offset */
Elf32_Word e_flags; /* processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size */
Elf32_Half e_phentsize; /* program header entry size */
Elf32_Half e_phnum; /* number of program header entries */
Elf32_Half e_shentsize; /* section header entry size */
Elf32_Half e_shnum; /* number of section header entries */
Elf32_Half e_shstrndx; /* section header table's "section
header string table" entry offset */
} Elf32_Ehdr;
2、查看elf文件的头64个字节
[root@localhost l1]# hexdump -x -n 64 app
0000000 457f 464c 0102 0001 0000 0000 0000 0000
0000010 0002 003e 0001 0000 7f40 0040 0000 0000
0000020 0040 0000 0000 0000 2850 00ba 0000 0000
0000030 0000 0000 0040 0038 000a 0040 002d 002c
0000040
[root@localhost l1]#
3、读取Program header table: readelf --segments app
[root@localhost l1]# readelf --segments app
Elf file type is EXEC (Executable file)
Entry point 0x407f40
There are 10 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x0000000000000230 0x0000000000000230 R E 8
INTERP 0x0000000000000270 0x0000000000400270 0x0000000000400270 0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x000000000071d5d8 0x000000000071d5d8 R E 200000
LOAD 0x000000000071de40 0x0000000000d1de40 0x0000000000d1de40 0x0000000000021800 0x0000000014ec5700 RW 200000
DYNAMIC 0x000000000071ebc0 0x0000000000d1ebc0 0x0000000000d1ebc0 0x0000000000000300 0x0000000000000300 RW 8
NOTE 0x000000000000028c 0x000000000040028c 0x000000000040028c 0x0000000000000044 0x0000000000000044 R 4
TLS 0x000000000071de40 0x0000000000d1de40 0x0000000000d1de40 0x0000000000000018 0x0000000000000880 R 40
GNU_EH_FRAME 0x00000000006215e0 0x0000000000a215e0 0x0000000000a215e0 0x000000000000c164 0x000000000000c164 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x000000000071de40 0x0000000000d1de40 0x0000000000d1de40 0x00000000000011c0 0x00000000000011c0 R 1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text text.unlikely .fini .rodata .eh_frame_hdr .eh_frame .gcc_except_table
03 .tdata .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss .lbss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .tdata .tbss
07 .eh_frame_hdr
08
09 .tdata .init_array .fini_array .jcr .data.rel.ro .dynamic .got
[root@localhost l1]#
头格式
/* Program segment header. */
typedef struct
{
Elf32_Word p_type; /* Segment type */
Elf32_Off p_offset; /* Segment file offset */
Elf32_Addr p_vaddr; /* Segment virtual address */
Elf32_Addr p_paddr; /* Segment physical address */
Elf32_Word p_filesz; /* Segment size in file */
Elf32_Word p_memsz; /* Segment size in memory */
Elf32_Word p_flags; /* Segment flags */
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;
4、读取section header table: readelf -S app
[root@localhost l1]# readelf -S app
There are 45 section headers, starting at offset 0xba2850:
Section Headers:
[Nr] Name Type Address Offset Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400270 00000270 000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 000000000040028c 0000028c 0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 00000000004002ac 000002ac 0000000000000024 0000000000000000 A 0 0 4
[ 4] .hash HASH 00000000004002d0 000002d0 00000000000009ec 0000000000000004 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000400cc0 00000cc0 00000000000022b0 0000000000000018 A 6 4 8
[ 6] .dynstr STRTAB 0000000000402f70 00002f70 00000000000015ac 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 000000000040451c 0000451c 00000000000002e4 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000404800 00004800 0000000000000220 0000000000000000 A 6 9 8
[ 9] .rela.dyn RELA 0000000000404a20 00004a20 0000000000000528 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000404f48 00004f48 0000000000001c98 0000000000000018 AI 5 28 8
[11] .init PROGBITS 0000000000406be0 00006be0 000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 0000000000406c00 00006c00 0000000000001320 0000000000000010 AX 0 0 16
[13] .text PROGBITS 0000000000407f40 00007f40 00000000005009a2 0000000000000000 AX 0 0 64
[14] text.unlikely PROGBITS 00000000009088f0 005088f0 0000000000008af0 0000000000000000 AX 0 0 16
[15] .fini PROGBITS 00000000009113e0 005113e0 0000000000000009 0000000000000000 AX 0 0 4
[16] .rodata PROGBITS 0000000000911400 00511400 00000000001101e0 0000000000000000 A 0 0 64
[17] .eh_frame_hdr PROGBITS 0000000000a215e0 006215e0 000000000000c164 0000000000000000 A 0 0 4
[18] .eh_frame PROGBITS 0000000000a2d748 0062d748 00000000000eed24 0000000000000000 A 0 0 8
[19] .gcc_except_table PROGBITS 0000000000b1c46c 0071c46c 000000000000116c 0000000000000000 A 0 0 4
[20] .tdata PROGBITS 0000000000d1de40 0071de40 0000000000000018 0000000000000000 WAT 0 0 64
[21] .tbss NOBITS 0000000000d1de80 0071de58 0000000000000840 0000000000000000 WAT 0 0 64
[22] .init_array INIT_ARRAY 0000000000d1de80 0071de80 00000000000003d0 0000000000000008 WA 0 0 8
[23] .fini_array FINI_ARRAY 0000000000d1e250 0071e250 0000000000000008 0000000000000008 WA 0 0 8
[24] .jcr PROGBITS 0000000000d1e258 0071e258 0000000000000008 0000000000000000 WA 0 0 8
[25] .data.rel.ro PROGBITS 0000000000d1e260 0071e260 0000000000000960 0000000000000000 WA 0 0 32
[26] .dynamic DYNAMIC 0000000000d1ebc0 0071ebc0 0000000000000300 0000000000000010 WA 6 0 8
[27] .got PROGBITS 0000000000d1eec0 0071eec0 0000000000000128 0000000000000008 WA 0 0 8
[28] .got.plt PROGBITS 0000000000d1f000 0071f000 00000000000009a0 0000000000000008 WA 0 0 8
[29] .data PROGBITS 0000000000d1f9c0 0071f9c0 000000000001fc80 0000000000000000 WA 0 0 64
[30] .bss NOBITS 0000000000d3f640 0073f640 000000000f0a0fa8 0000000000000000 WA 0 0 64
[31] .lbss NOBITS 000000000fde0600 0073f640 0000000005e02f40 0000000000000000 WAl 0 0 64
[32] .comment PROGBITS 0000000000000000 0073f640 000000000000002d 0000000000000001 MS 0 0 1
[33] .debug_aranges PROGBITS 0000000000000000 0073f66d 0000000000000030 0000000000000000 0 0 1
[34] .debug_info PROGBITS 0000000000000000 0073f69d 000000000019598a 0000000000000000 0 0 1
[35] .debug_abbrev PROGBITS 0000000000000000 008d5027 00000000000108d8 0000000000000000 0 0 1
[36] .debug_line PROGBITS 0000000000000000 008e58ff 000000000011511c 0000000000000000 0 0 1
[37] .debug_frame PROGBITS 0000000000000000 009faa1b 0000000000024ca0 0000000000000000 0 0 1
[38] .debug_str PROGBITS 0000000000000000 00a1f6bb 0000000000080d2c 0000000000000001 MS 0 0 1
[39] .debug_loc PROGBITS 0000000000000000 00aa03e7 0000000000004230 0000000000000000 0 0 1
[40] .debug_ranges PROGBITS 0000000000000000 00aa4617 0000000000043990 0000000000000000 0 0 1
[41] .debug_opt_report PROGBITS 0000000000000000 00ae7fa7 0000000000032118 0000000000000000 0 0 1
[42] .symtab SYMTAB 0000000000000000 00b1a0c0 0000000000045b70 0000000000000018 43 6898 8
[43] .strtab STRTAB 0000000000000000 00b5fc30 0000000000042a64 0000000000000000 0 0 1
[44] .shstrtab STRTAB 0000000000000000 00ba2694 00000000000001bc 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
[root@localhost l1]#
Section header 头格式
/* 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;
5、由elf header可知:Start of section headers: 12200016
即section表的起始地址为 0xba2850(12200016)
大小为:64*45 = 2880
Size of section headers: 64 (bytes)
Number of section headers: 45
hexdump -s 12200016 -n 2880 -C l1app
6、查看反汇编代码: objdump -d app
7、由以上分析可以得出app结构为
------------------------------
|Section header table |
------------------------------- -->>addr:0xba2850
| . . . |
| . . . |
| . . . |
------------------------------- -->>addr:4002ac
| .note.ABI-tag |
------------------------------- -->>addr:40028c
| .interp |
------------------------------- -->> addr:400270
| |
| |
------------------------------- -->>addr:0x270
|Program header table|
------------------------------- -->> addr:0x40
| ELF header |
------------------------------- -->> addr:0x00
借用其它文章的图片:
8、动态库so文件中重要的Section:符号表、重定位表、GOT表
a)动态符号表(.dynsym) 可用 nm 命令查看符号表
typedef struct {
Elf32_Word st_name; //符号表项名称。如果该值非0,则表示符号名的字符串表索引(offset),否则符号表项没有名称。
Elf32_Addr st_value; //符号的取值。依赖于具体的上下文,可能是一个绝对值、一个地址等等。
Elf32_Word st_size; //符号的尺寸大小。例如一个数据对象的大小是对象中包含的字节数。
unsigned char st_info; //符号的类型和绑定属性。
unsigned char st_other; //该成员当前包含 0,其含义没有定义。
Elf32_Half st_shndx; //每个符号表项都以和其他节区的关系的方式给出定义。此成员给出相关的节区头部表索引。
} Elf32_sym;
b)字符串表(.dynstr)
c)全局偏移表(.got)
d)符号表(.symtab) .dynsym 是 .symtab 的一个子集
[root@localhost l1]# gdb l1app
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/lihongfu/Flexran1910_test_oamok/bin/nr5g/gnb/l1/l1app...done.
(gdb) info func phy_gnb_bbupool_unlock_ul_tasks
All functions matching regular expression "phy_gnb_bbupool_unlock_ul_tasks":
File nr5g/gnb_ul/gnb_ul_phy_bbu_tasks.c:
uint32_t phy_gnb_bbupool_unlock_ul_tasks(uint16_t, uint32_t, uint32_t, TaskBypassEnum);
(gdb)