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

如何获取ELF可执行文件中RELA跳转槽的符号名称

获取ELF RELA跳转槽对应的符号名称

我看了你的代码,问题主要出在字符串表索引的使用错误,还有一些RELA段遍历的小问题,下面给你一步步修正:

关键错误分析

  1. elf_strptr参数错误:你现在用了shdr_rela.sh_link和sym.st_shndx,但正确的应该是用符号表段(DYNSYM)的sh_link(这个值指向存储符号名的字符串表节),然后传入sym.st_name(符号名在字符串表中的偏移),而不是sym.st_shndx。
  2. RELA段遍历逻辑错误:你找到第一个RELA段后又调用了elf_nextscn,这会跳过当前找到的RELA段,直接处理下一个节,这会导致你漏过第一个RELA段(比如.rela.plt)。
  3. 未检查符号索引有效性:GELF_R_SYM(rela.r_info)可能返回无效索引(比如0,对应未定义符号的占位符),需要先判断再处理。
  4. 符号表遍历逻辑:你只找第一个DYNSYM段,但其实应该确保找到正确的符号表,不过一般可执行文件里DYNSYM只有一个,这个问题不大,但可以加个判断确保找到。

修正后的完整代码

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <libelf.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gelf.h>

#define LIB_PATH "/tmp/a.out"

int main(void) {
    int fd = open(LIB_PATH, O_RDONLY);
    Elf *elf;
    Elf_Scn *scn = NULL;
    Elf_Data *rela_data = NULL;
    Elf_Data *sym_data = NULL;
    GElf_Shdr shdr_rela;
    GElf_Shdr shdr_sym;
    GElf_Rela rela;
    GElf_Sym sym;
    size_t sym_strtab_idx; // 符号字符串表的节索引

    // 初始化libelf版本
    elf_version(EV_CURRENT);
    elf = elf_begin(fd, ELF_C_READ, NULL);
    if (!elf) {
        fprintf(stderr, "ERROR: %s\n", elf_errmsg(elf_errno()));
        close(fd);
        return EXIT_FAILURE;
    }

    // 查找DYNSYM段
    for (scn = elf_getscn(elf, 0); scn; scn = elf_nextscn(elf, scn)) {
        gelf_getshdr(scn, &shdr_sym);
        if (shdr_sym.sh_type == SHT_DYNSYM) {
            sym_data = elf_getdata(scn, sym_data);
            sym_strtab_idx = shdr_sym.sh_link; // 保存符号字符串表的索引
            break;
        }
    }
    if (!sym_data) {
        fprintf(stderr, "ERROR: Could not find DYNSYM section\n");
        elf_end(elf);
        close(fd);
        return EXIT_FAILURE;
    }

    // 遍历所有RELA段(处理.rela.plt和.rela.dyn等)
    for (scn = elf_getscn(elf, 0); scn; scn = elf_nextscn(elf, scn)) {
        gelf_getshdr(scn, &shdr_rela);
        if (shdr_rela.sh_type != SHT_RELA) {
            continue;
        }

        printf("=== Processing RELA section: %s ===\n", elf_strptr(elf, elf_getshdrstrndx(elf), shdr_rela.sh_name));
        rela_data = elf_getdata(scn, rela_data);
        if (!rela_data) {
            fprintf(stderr, "ERROR: Could not get RELA data\n");
            continue;
        }

        // 遍历当前RELA段的所有条目
        size_t rela_count = shdr_rela.sh_size / shdr_rela.sh_entsize;
        for (size_t it = 0; it < rela_count; ++it) {
            if (gelf_getrela(rela_data, it, &rela) != &rela) {
                fprintf(stderr, "ERROR: Failed to get RELA entry at index %zu\n", it);
                continue;
            }

            // 获取符号索引
            size_t sym_idx = GELF_R_SYM(rela.r_info);
            // 检查符号索引是否有效(0是未定义符号的占位符,一般对应外部符号)
            if (sym_idx == 0 || sym_idx >= shdr_sym.sh_size / shdr_sym.sh_entsize) {
                printf("[%p]: (sym_idx=%zu) UNDEFINED\n", (void*)rela.r_offset, sym_idx);
                continue;
            }

            // 获取符号信息
            if (gelf_getsym(sym_data, sym_idx, &sym) != &sym) {
                fprintf(stderr, "ERROR: Failed to get symbol at index %zu\n", sym_idx);
                continue;
            }

            // 获取符号名称
            const char *sym_name = elf_strptr(elf, sym_strtab_idx, sym.st_name);
            if (!sym_name) {
                sym_name = "(unknown)";
            }

            printf("[%p]: (sym_idx=%zu) %s\n", (void*)rela.r_offset, sym_idx, sym_name);
        }
    }

    elf_end(elf);
    close(fd);
    return EXIT_SUCCESS;
}

关键修改说明

  • 符号名获取逻辑:用elf_strptr(elf, sym_strtab_idx, sym.st_name)来获取符号名,其中sym_strtab_idx是DYNSYM段的sh_link,指向存储符号名的字符串表(一般是.dynstr),sym.st_name是符号名在字符串表中的偏移。
  • 遍历所有RELA段:不再找到第一个就break,而是处理所有类型为SHT_RELA的段,这样不会漏过.rela.plt(PLT跳转槽)和.rela.dyn(动态重定位)。
  • 有效性检查:增加了对符号索引、RELA条目、符号信息的有效性检查,避免程序崩溃或输出错误信息。
  • 修复RELA段跳过问题:移除了错误的scn = elf_nextscn(elf, scn)调用,确保找到的RELA段被正确处理。

编译与运行

编译时需要链接libelf库:

gcc -o rela_sym rela_sym.c -lelf

运行后就能看到每个RELA条目对应的符号名称了。

内容的提问来源于stack exchange,提问作者Ra'Jiska

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:57:33