You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在运行时查找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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 08:17:45