一步一步走进Linux HOOK API(二)
来源:互联网 发布:mmd麻烦鬼动作数据 编辑:程序博客网 时间:2024/06/05 04:01
从上一篇的ELF Head之后,想必很多读者已经对ELF文件开始感觉不是遥不可及了,今天这一节,主要是讲程序头(Program Headers),程序头主要是从加载执行的角度来看的,很多人想那里面到底是什么东西呢,其实程序头就是一个结构数组,每一个头保存着对应的不同的数据,有的数据是告诉系统把我放入内存,有的数据时告诉系统我是变量.等等...在系统加载程序的时候就要通过该程序头来加载不同的段.
下面就来看一下程序头的结构体:
- 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;
p_type: 段的类型
在elf.h头文件中,有很详细的说明段的类型,比如PT_LOAD 表示加载的程序段
p_offset: 文件偏移
该段在文件中的偏移。这个偏移是相对于整个文件的。
p_vaddr: 加载后的虚拟地址
该段加载后在进程空间中占用的内存起始地址。
p_paddr: 该段的物理地址
这个字段被忽略,因为在多数现代操作系统下物理地址是进程无法触及的。
p_filesz: 该段在文件中占用的字节大小
有些段可能在文件中不存在但却占用一定的内存空间,此时这个字段为0。
p_memsz: 该段在内存中占用的字节大小
有些段可能仅存在于文件中而不被加载到内存,此时这个字段为0。
p_flags: 段的属性
表示该段的读写执行等属性.elf.h文件中的定义是
- #define PF_X (1 << 0) /* Segment is executable */
- #define PF_W (1 << 1) /* Segment is writable */
- #define PF_R (1 << 2) /* Segment is readable */
- #define PF_MASKOS 0x0ff00000 /* OS-specific */
- #define PF_MASKPROC 0xf0000000 /* Processor-specific */
p_align: 对齐
现代操作系统都使用虚拟内存为进程序提供更大的空间,分页技术功不可没,页就成了最小的内存分配单位,不足一页的按一页算。所以加载程序数据一般也从一页的起始地址开始,这就属于对齐。
示例代码:
- typedef struct _SegmentType_
- {
- unsigned int type;
- char *typeName;
- }SegmentType;
- SegmentType segTyoe[] = {
- {0,"NULL"},{1,"LOAD"},
- {2,"DYNAMIC"},{3,"INTERP"},
- {4,"NOTE"},{5,"SHLIB"},
- {6,"PHDR"},{7,"TLS"},
- {8,"NUM"},{0x60000000,"LOOS"}, {0x6474e550,"GNU_EH_FRAME"},{0x6474e551,"PT_GNU_STACK"}, {0x6474e552,"PT_GNU_RELRO"},{0x6ffffffa,"PT_SUNWBSS"}, {0x6ffffffb,"PT_SUNWSTACK"},{0x6fffffff,"PT_HISUNW"},
- {0x70000000,"PT_HIOS"},{0x7fffffff,"PT_HIPROC"},
- };
- char* findSegTypeName(unsigned int type)
- {
- int i = 0;
- for(i = 0;i < sizeof(segTyoe) / sizeof(SegmentType);i++){
- if(segTyoe[i].type == type){
- return segTyoe[i].typeName;
- break;
- }
- }
- return segTyoe[0].typeName;
- }
- void displayPhdr(Elf32_Ehdr *ehdr,Elf32_Phdr *phdr)
- {
- printf("Program Headers:\n");
- printf("%-20s%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n",
- "Type","Offset","VirtAddr","PhysAddr","FileSiz",
- "MemSiz","Flg","Align");
- int i = 0;
- for(i = 0; i < ehdr->e_phnum;i++){
- printf("%-20s%-10x%-10x%-10x%-10x%-10x%-10x%-10x\n",
- findSegTypeName(phdr->p_type),
- phdr->p_offset,
- phdr->p_vaddr,
- phdr->p_paddr,
- phdr->p_filesz,
- phdr->p_memsz,
- phdr->p_flags,
- phdr->p_align
- );
- if(phdr->p_type == PT_INTERP){
- printf("\t[Requesting program interpreter: %s]\n",
- (char*)((char*)ehdr + phdr->p_offset));
- }
- phdr++;
- }
- }
- 一步一步走进Linux HOOK API(二)
- 一步一步走进Linux HOOK API(二)
- 一步一步走进Linux HOOK API(二)
- 一步一步走进Linux HOOK API
- 一步一步走进Linux HOOK API(一)
- 一步一步走进Linux HOOK API(三)
- 一步一步走进Linux HOOK API(四)
- 一步一步走进Linux HOOK API(五)
- 一步一步走进Linux HOOK API(六)
- 一步一步走进Linux HOOK API(七)
- 一步一步走进Linux HOOK API(八)
- 一步一步走进Linux HOOK API(一)
- 一步一步走进Linux HOOK API(三)
- 一步一步走进Linux HOOK API(四)
- 一步一步走进Linux HOOK API(五)
- 一步一步走进Linux HOOK API(六)
- 一步一步走进Linux HOOK API(七)
- 【链接】 一步一步走进Linux HOOK API
- js数组依据下标删除元素
- 商业模式论文2
- OpenFlow技术深入分析
- 一步一步走进Linux HOOK API(一)
- QT4.3.2在VC++ 6.0下安装过程
- 一步一步走进Linux HOOK API(二)
- 一步一步走进Linux HOOK API(三)
- fputc()和fgetc()
- 一步一步走进Linux HOOK API(四)
- 面向对象的程序设计-14-用虚函数实现价格的统计(实例)
- Hibernate注解使用以及Spring整合
- UVA 138 Street Numbers
- 杭电acm1028利用母函数求解数字拆分问题
- 高效会议原则