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 = §ion_headers[i]; // 通过sh_link获取符号表对应的字符串表 string_table_header = §ion_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 = §ion_headers[i]; // 通过sh_link获取符号表对应的字符串表 string_table_header = §ion_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
相关产品推荐
相关产品推荐

