linux中ELF格式二进制程序( 三 )

 
Elf32_Shdr或Elf64_Shdr结构体用来描述位于磁盘上的程序中的一个节;

linux中ELF格式二进制程序

文章插图
 
sh_name
节名称sh_name的值是字符串的一个索引,节名称字符串以''结尾,字符串统一存放在字符串表中,使用sh_name的值作为字符串表的索引,找到对应的字符串即为节名称;
字符串表中包含多个以''结尾的字符串;在目标文件中,这些字符串通常是符号的名字或节的名字,需要引用某些字符串时,只需要提供该字符串在字符串表中的序号即可;
字符串表中的第一个字符串(序号为0)是空串,即'',可以用于表示没有名字或一个空的名字;如果字符串表为空,节头中的sh_size值为0;
sh_type:节的类型;
// include/uapi/linux/elf.h/* sh_flags */#define SHF_WRITE0x1// 可写#define SHF_ALLOC0x2// 该节包含内存在进程运行时需要占用内存单元#define SHF_EXECINSTR0x4 // 该节内容是指令代码#define SHF_MASKPROC0xf0000000 
sh_flags:节的标志;
// include/uapi/linux/elf.h/* sh_flags */#define SHF_WRITE0x1// 可写#define SHF_ALLOC0x2// 该节包含内存在进程运行时需要占用内存单元#define SHF_EXECINSTR0x4 // 该节内容是指令代码#define SHF_MASKPROC0xf0000000 
4. readelf命令 
readelf命令用于查看ELF格式的文件信息,
$ readelf -h file // 显示ELF文件头$ readelf -l file // 显示所有的程序头$ readelf -S file // 显示所有的节头$ readelf -e file // 显示ELF文件头、程序头、节头全部的头信息,相当于同时运行参数-h、-l、-S 
命令:
$ readelf -h file // 显示ELF文件头$ readelf -l file // 显示所有的程序头$ readelf -S file // 显示所有的节头$ readelf -e file // 显示ELF文件头、程序头、节头全部的头信息,相当于同时运行参数-h、-l、-S 
5. ELF文件实例 
针对32位系统,通过一个极为简单的C语言的编译和分析,进行ELF文件中各结构体成员功能分析;
代码示例:
int main(void){while (1);return 0;} 
5.0 生成可执行文件 
编译为中间文件,并链接为目标文件;
$ gcc -c -o main.o main.c$ ld main.o -Ttext 0xc0001500 -e main -o kernel.bin通过file命令查看main.o文件属性;main.o文件是32位大端可重定向的ELF文件,机器平台为PowerPC;
$ file main.o main.o: ELF 32-bit MSB relocatable, PowerPC or cisco 4500, version 1 (SYSV), not stripped通过file命令查看kernel.bin文件属性;kernel.bin文件是32位大端可执行的ELF文件,机器平台为PowerPC;
$ file kernel.bin kernel.bin: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), statically linked, not stripped通过nm命令查看main.o文件的符号表,符号表中仅有一个main函数符号;
$ nm main.o 00000000 T main通过nm查看kernel.bin文件的符号表,
$ nm kernel.bin c0011510 A __bss_start c0011510 A _edata c0011510 A _end c0001500 T main 
5.1 ELF header【linux中ELF格式二进制程序】 
$ xxd -u -a -g 1 -s 0 -l 0x100 kernel.bin0000000: 7F 45 4C 46 01 02 01 00 00 00 00 00 00 00 00 00.ELF............0000010: 00 02 00 14 00 00 00 01 C0 00 15 00 00 00 00 34...............40000020: 00 00 15 74 00 00 00 00 00 34 00 20 00 02 00 28...t.....4. ...(0000030: 00 06 00 03 00 00 00 01 00 00 00 00 C0 00 00 00................00~0x0F是e_ident数组,e_ident[0]~e_ident[3]的四个字节是固定的ELF魔数,0x7f, 0x45, 0x4c, 0x46;e_ident[4] = 1表示文件是32位的ELF文件,e_ident[5] = 2表示文件时大端字节序,e_ident[6] = 1表示默认版本,e_ident[7]~e_ident[15]的9个字节置为0;
0x10~0x11是e_type,2个字节,e_type = 0x00 02,表示类型是ET_EXEC,即可执行文件;
0x12~0x13是e_machine,2个字节,e_machine = 0x00 14,表示机器是EM_PPC,即power pc硬件平台;
0x14~0x17是e_version,4个字节,e_version = 0x00 00 00 01,表示版本信息;
0x18~0x1B是e_entry,4个字节,e_entry = 0xC0 00 15 00,表示程序的虚拟入口地址;
0x1C~0x1F是e_phoff ,4个字节,e_phoff = 0x00 00 00 34,表示程序头表在文件中的偏移量;
0x20~0x23是e_shoff,4个字节,e_shoff = 0x00 00 15 74,表示节头表在文件内的偏移量;
0x24~0x27是e_flags,4个字节,e_flags = 0x00 00 00 00,表示属性;
0x28~0x29是e_ehsize,2个字节,e_ehsize = 0x00 34,表示ELF header大小是0x34字节;程序头表紧跟ELF header之后;
0x2A~0x2B是e_phentsize,2个字节,e_phentsize = 0x00 20,表示program header结构ELF32_Phdr的大小,此处为0x20;


推荐阅读