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

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字段即可判断节类型,步骤如下:

  1. 先验证节索引symtab[i].st_shndx的有效性(需小于ELF文件的节总数sections_amount)
  2. 从节头数组section_h_arr中取出对应索引的节头
  3. 检查节头的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 02:52:45