如何在运行时查找dynamic section(动态段)?
访问ELF动态段的实现代码
要读取ELF文件的动态段,核心是定位到段表中类型为SHT_DYNAMIC的条目,然后读取该段对应的内存区域,解析其中的Elf64_Dyn(或Elf32_Dyn)结构体数组。下面是兼容32位和64位ELF文件的完整C语言实现:
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <elf.h> // 你提供的段类型宏定义 #define SHT_NULL 0 #define SHT_PROGBITS 1 #define SHT_SYMTAB 2 #define SHT_STRTAB 3 #define SHT_RELA 4 #define SHT_HASH 5 #define SHT_DYNAMIC 6 #define SHT_NOTE 7 #define SHT_NOBITS 8 #define SHT_REL 9 #define SHT_SHLIB 10 #define SHT_DYNSYM 11 #define SHT_INIT_ARRAY 14 #define SHT_FINI_ARRAY 15 #define SHT_PREINIT_ARRAY 16 int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "用法: %s <ELF文件路径>\n", argv[0]); return 1; } int fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open失败"); return 1; } struct stat st; if (fstat(fd, &st) == -1) { perror("fstat失败"); close(fd); return 1; } void *elf_base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (elf_base == MAP_FAILED) { perror("mmap失败"); close(fd); return 1; } // 识别ELF类别(32位/64位) unsigned char *e_ident = (unsigned char *)elf_base; if (e_ident[EI_CLASS] == ELFCLASS32) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elf_base; Elf32_Shdr *shdr = (Elf32_Shdr *)(elf_base + ehdr->e_shoff); // 遍历段表找动态段 for (int i = 0; i < ehdr->e_shnum; i++) { if (shdr[i].sh_type == SHT_DYNAMIC) { Elf32_Dyn *dyn = (Elf32_Dyn *)(elf_base + shdr[i].sh_offset); Elf32_Shdr *str_shdr = &shdr[ehdr->e_shstrndx]; char *str_tab = (char *)(elf_base + str_shdr->sh_offset); printf("找到32位ELF动态段,段名: %s\n", str_tab + shdr[i].sh_name); printf("动态条目列表:\n"); // 遍历动态条目,直到遇到DT_NULL for (int j = 0; dyn[j].d_tag != DT_NULL; j++) { printf(" 条目[%d]: d_tag = 0x%x, d_val = 0x%x\n", j, dyn[j].d_tag, dyn[j].d_un.d_val); } break; } } } else if (e_ident[EI_CLASS] == ELFCLASS64) { Elf64_Ehdr *ehdr = (Elf64_Ehdr *)elf_base; Elf64_Shdr *shdr = (Elf64_Shdr *)(elf_base + ehdr->e_shoff); // 遍历段表找动态段 for (int i = 0; i < ehdr->e_shnum; i++) { if (shdr[i].sh_type == SHT_DYNAMIC) { Elf64_Dyn *dyn = (Elf64_Dyn *)(elf_base + shdr[i].sh_offset); Elf64_Shdr *str_shdr = &shdr[ehdr->e_shstrndx]; char *str_tab = (char *)(elf_base + str_shdr->sh_offset); printf("找到64位ELF动态段,段名: %s\n", str_tab + shdr[i].sh_name); printf("动态条目列表:\n"); // 遍历动态条目,直到遇到DT_NULL for (int j = 0; dyn[j].d_tag != DT_NULL; j++) { printf(" 条目[%d]: d_tag = 0x%lx, d_val = 0x%lx\n", j, dyn[j].d_tag, dyn[j].d_un.d_val); } break; } } } else { fprintf(stderr, "不支持的ELF类别\n"); } munmap(elf_base, st.st_size); close(fd); return 0; }
关键说明
- 代码通过
mmap将整个ELF文件映射到内存,比逐字节读取更高效 - 先判断ELF是32位还是64位,分别使用对应的结构体(
Elf32_*/Elf64_*) - 遍历段表时,通过
sh_type == SHT_DYNAMIC定位动态段 - 动态段由一系列
ElfXX_Dyn结构体组成,最后一个条目以DT_NULL结尾 - 编译方式:直接使用GCC编译即可,无需额外链接库:
gcc elf_dynamic.c -o elf_dynamic
内容的提问来源于stack exchange,提问作者user21677582
相关产品推荐
相关产品推荐

