C语言下如何通过符号及节索引判断节类型?ELF符号处理问题
ELF文件处理相关问题
问题一
已知节的符号及其索引时,如何在C语言中判断该节的类型?
问题二
处理ELF文件的全局符号时,需要实现以下逻辑:找到目标全局符号后,若该符号不在共享对象中则返回symtab[i].st_value;若在共享对象中则将*error_val设为-4并返回0。尝试使用section_h_arr[symtab[i].st_shndx].sh_type!=ET_DYN未生效,求正确的if条件写法。
相关代码
Elf64_Shdr* section_h_arr = (Elf64_Shdr*)((char*)elf + elf_header->e_shoff); Elf64_Shdr sh_str_section = section_h_arr[elf_header->e_shstrndx]; char *sh_str_tbl = (char*)elf + sh_str_section.sh_offset; Elf64_Half sections_amount = elf_header->e_shnum; Elf64_Sym *symtab; char *strtab; int symbols_amount = 0; char* section_name; for(int i = 0; i < sections_amount; i++) { section_name = sh_str_tbl + section_h_arr[i].sh_name; if(!strcmp(".symtab", section_name) || section_h_arr[i].sh_type == 2){ symtab = (Elf64_Sym*)((char*)elf + section_h_arr[i].sh_offset); symbols_amount = section_h_arr[i].sh_size / section_h_arr[i].sh_entsize; } else if(!strcmp(".strtab", section_name) || section_h_arr[i].sh_type == 3){ if((char*)elf + section_h_arr[i].sh_offset != sh_str_tbl) strtab = ((char*)elf + section_h_arr[i].sh_offset); } } char* curr_symbol_name; for(int i = 0; i < symbols_amount; i++){ curr_symbol_name = strtab + symtab[i].st_name; if(!strcmp(symbol_name, curr_symbol_name)) { if(ELF64_ST_BIND(symtab[i].st_info) == STB_GLOBAL) { close(elf_fd); *error_val=1; if (///////////////////////////////// ) { return symtab[i].st_value; } *error_val=-4; return 0; }
解答
问题一解答
直接通过符号的节索引获取对应节头结构体,读取其sh_type字段即可判断节类型,步骤如下:
- 先验证节索引
symtab[i].st_shndx的有效性(需小于ELF文件的节总数sections_amount) - 从节头数组
section_h_arr中取出对应索引的节头 - 检查节头的
sh_type字段,常见取值如SHT_PROGBITS(程序段)、SHT_SYMTAB(符号表)、SHT_DYNAMIC(动态链接信息)等
示例代码:
if (symtab[i].st_shndx < sections_amount) { Elf64_Word sec_type = section_h_arr[symtab[i].st_shndx].sh_type; if (sec_type == SHT_PROGBITS) { // 程序段类型处理逻辑 } else if (sec_type == SHT_SYMTAB) { // 符号表类型处理逻辑 } }
问题二解答
你之前的错误是混淆了ELF文件类型和节类型:ET_DYN是ELF文件头e_type的取值(表示共享对象文件),并非节头的sh_type字段值。正确的判断逻辑需要结合文件类型和符号属性:
基础版判断(检查整个文件是否为非共享对象)
直接判断ELF文件头的e_type,如果不是共享对象则返回符号值:
if (elf_header->e_type != ET_DYN) { return symtab[i].st_value; }
严谨版判断(结合符号自身属性)
考虑到共享对象中的未定义符号(st_shndx为SHN_UNDEF),以及可执行文件中的公共符号(st_shndx为SHN_COMMON),更严谨的条件:
if ((symtab[i].st_shndx != SHN_UNDEF || symtab[i].st_shndx == SHN_COMMON) && elf_header->e_type != ET_DYN) { return symtab[i].st_value; }
将上述代码替换你原代码中的/////////////////////////////////部分即可生效。
内容的提问来源于stack exchange,提问作者a boi
相关产品推荐
相关产品推荐

