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

C代码读取ELF文件符号表存在条目缺失问题求助

ELF符号表读取代码缺失符号问题分析

你的代码存在三个关键错误,导致无法正确读取完整的ELF符号表:

1. 自定义Elf64_Sym结构体不符合标准规范

你修改了标准ELF64符号表项的结构:

  • 将st_value从64位(uint64_t)改成了32位(uint32_t)
  • 新增了多余的st_name2字段

这直接破坏了结构体的内存对齐和字段偏移,读取符号表时数据完全错位,导致大部分符号无法被正确解析。

标准的ELF64符号表项结构体应该是:

typedef struct {
    uint32_t      st_name;    // 符号名在字符串表中的偏移
    unsigned char st_info;    // 符号类型和绑定属性
    unsigned char st_other;   // 符号可见性
    uint16_t      st_shndx;   // 符号所在节的索引
    uint64_t      st_value;   // 符号值(地址或偏移)
    uint64_t      st_size;    // 符号大小
} Elf64_Sym;

2. 错误关联字符串表

你通过遍历找到第一个SHT_STRTAB类型的节作为符号表的字符串表,但ELF规范中:

  • 符号表节(SHT_SYMTAB)的sh_link字段,明确指向该符号表对应的字符串表的节索引
  • 第一个SHT_STRTAB通常是节头字符串表(.shstrtab,用于存储节名称),而非符号表的字符串表(.symstrtab)

正确的字符串表获取方式应该是:

// 查找符号表并关联对应字符串表
Elf64_Shdr* symbol_table_header = NULL;
Elf64_Shdr* string_table_header = NULL;
for (int i = 0; i < elf_header.e_shnum; i++) {
    if (section_headers[i].sh_type == 0x2) { // SHT_SYMTAB
        symbol_table_header = &section_headers[i];
        // 通过sh_link获取符号表对应的字符串表
        string_table_header = &section_headers[symbol_table_header->sh_link];
        break;
    }
}

3. 64位地址打印格式错误

你用%08x打印st_value,但ELF64的地址是64位,会导致地址截断显示,虽然这不是符号缺失的直接原因,但会影响输出正确性,应该改为%016lx:

printf("0x%016lx\t%s\n", (unsigned long)symbol_table[j].st_value, symbol_name);

修复后的核心代码片段

修正结构体定义

// 标准ELF64符号表项结构体
typedef struct {
    uint32_t      st_name;
    unsigned char st_info;
    unsigned char st_other;
    uint16_t      st_shndx;
    uint64_t      st_value;
    uint64_t      st_size;
} Elf64_Sym;

修正符号表与字符串表关联逻辑

// 查找符号表并关联对应字符串表
Elf64_Shdr* symbol_table_header = NULL;
Elf64_Shdr* string_table_header = NULL;
for (int i = 0; i < elf_header.e_shnum; i++) {
    if (section_headers[i].sh_type == 0x2) { // SHT_SYMTAB
        symbol_table_header = &section_headers[i];
        // 通过sh_link获取符号表对应的字符串表
        string_table_header = &section_headers[symbol_table_header->sh_link];
        break;
    }
}

修正打印逻辑

void printTables(){
    printf("Address\t\tName\n");
    printf("------------------------\n");

    for (size_t j = 0; j < num_symbols; j++) {
        if (symbol_table[j].st_name < stringSize) {
            char* symbol_name = &string_table[symbol_table[j].st_name];
            // 打印64位地址
            printf("0x%016lx\t%s\n", (unsigned long)symbol_table[j].st_value, symbol_name);
        }
    }
}

修复后重新编译运行,就能得到和nm -n trace.elf一致的完整符号表输出。

内容的提问来源于stack exchange,提问作者needshelp23

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:47:01