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

修复手动构建ELF文件时"output has a corrupt string table index"警告

错误核心原因

你写的ELF结构完全不符合ELF可重定位文件的规范,几个致命错误直接触发字符串表损坏报错:

  • 没有构造节名字符串表(.shstrtab),但ELF头里e_shstrndx = 1声明节名表的节头索引为1,实际根本不存在对应节
  • 节头数量配置完全错误:ELF规范要求第一个节头必须是全0的NULL节头,你现在e_shnum = 1注释却写有2个节头,实际也没有预留NULL节头、.shstrtab节头的位置
  • .text节的sh_name赋值错误:sh_name是节名字符串在.shstrtab中的偏移,你误用了动态标签宏DT_TEXTREL,完全不相关
  • 代码段长度错误:你给出的汇编指令只有12字节,定义code[13]会多写入一个无效的\0到代码段
  • 写入文件时缺了NULL节头、.shstrtab节头、.shstrtab字符串内容三个关键部分
修复方案

按照规范补全缺失的ELF结构即可,修改后的完整代码如下:

#include <iostream>
#include <elf.h>
#include <cstdio>
#include <cstring>

int main() {
    // 1. 构造节名字符串表
    // 结构:0字节留空 + ".shstrtab" + '\0' + ".text" + '\0'
    const char shstrtab[] = "\0.shstrtab\0.text";
    const int shstrtab_size = sizeof(shstrtab);

    // 2. ELF头
    Elf64_Ehdr ELFheader = {0};
    ELFheader.e_ident[EI_MAG0] = ELFMAG0;
    ELFheader.e_ident[EI_MAG1] = ELFMAG1;
    ELFheader.e_ident[EI_MAG2] = ELFMAG2;
    ELFheader.e_ident[EI_MAG3] = ELFMAG3;
    ELFheader.e_ident[EI_CLASS] = ELFCLASS64;
    ELFheader.e_ident[EI_DATA] = ELFDATA2LSB;
    ELFheader.e_ident[EI_VERSION] = EV_CURRENT;
    ELFheader.e_ident[EI_OSABI] = ELFOSABI_SYSV;
    ELFheader.e_ident[EI_ABIVERSION] = 0;
    
    ELFheader.e_type = ET_REL;
    ELFheader.e_machine = EM_X86_64;
    ELFheader.e_version = EV_CURRENT;
    ELFheader.e_entry = 0;
    ELFheader.e_phoff = 0;
    ELFheader.e_shoff = sizeof(Elf64_Ehdr); // 节头紧跟ELF头
    ELFheader.e_flags = 0;
    ELFheader.e_ehsize = sizeof(Elf64_Ehdr);
    ELFheader.e_phentsize = 0;
    ELFheader.e_phnum = 0;
    ELFheader.e_shentsize = sizeof(Elf64_Shdr);
    ELFheader.e_shnum = 3; // 共3个节头:NULL、.shstrtab、.text
    ELFheader.e_shstrndx = 1; // 节名表的节头索引是1

    // 3. 节头表:共3个
    Elf64_Shdr shdrs[3] = {0};
    // 第一个是必须的NULL节头,全0即可
    // 第二个是.shstrtab节头
    shdrs[1].sh_name = 1; // ".shstrtab"在字符串表的偏移是1
    shdrs[1].sh_type = SHT_STRTAB;
    shdrs[1].sh_flags = 0;
    shdrs[1].sh_addr = 0;
    shdrs[1].sh_offset = sizeof(Elf64_Ehdr) + 3 * sizeof(Elf64_Shdr); // 紧跟节头表之后
    shdrs[1].sh_size = shstrtab_size;
    shdrs[1].sh_link = 0;
    shdrs[1].sh_info = 0;
    shdrs[1].sh_addralign = 1;
    shdrs[1].sh_entsize = 0;
    // 第三个是.text节头
    shdrs[2].sh_name = 11; // ".text"在字符串表的偏移是11
    shdrs[2].sh_type = SHT_PROGBITS;
    shdrs[2].sh_flags = SHF_EXECINSTR | SHF_ALLOC;
    shdrs[2].sh_addr = 0;
    shdrs[2].sh_offset = shdrs[1].sh_offset + shstrtab_size; // 紧跟.shstrtab之后
    shdrs[2].sh_size = 12; // 实际指令长度是12字节
    shdrs[2].sh_link = 0;
    shdrs[2].sh_info = 0;
    shdrs[2].sh_addralign = 16;
    shdrs[2].sh_entsize = 0;

    // 4. 代码段:12字节的exit(2)系统调用
    unsigned char code[12] = "\xb8\x3c\x00\x00\x00\xbf\x02\x00\x00\x00\x0f\x05";

    // 5. 一次性写入所有内容,避免多次追加偏移出错
    FILE *fout = fopen("output.o", "wb");
    fwrite(&ELFheader, sizeof(ELFheader), 1, fout);
    fwrite(shdrs, sizeof(shdrs), 1, fout);
    fwrite(shstrtab, shstrtab_size, 1, fout);
    fwrite(code, sizeof(code), 1, fout);
    fclose(fout);

    return 0;
}
验证步骤
  1. 编译生成器:g++ elf_generator.cpp -o elf_generator
  2. 运行生成.o文件:./elf_generator
  3. 查看汇编:objdump -d output.o,可以正常看到exit系统调用的汇编代码
  4. 链接生成可执行文件:ld output.o -o test_exec
  5. 运行验证:./test_exec,执行echo $?会输出2,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:45:10