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

如何实现类静态链接器:将自定义.o文件程序追加至ELF32可执行文件?

Great question! Building a tool that appends code from a .o file to an existing ELF32 executable is a deep dive into ELF internals—let's break this down step by step, focusing on the key challenges you've highlighted: section appending, symbol table merging, and relocation handling.


Step 1: Parse ELF32 Structures First

Before doing any modifications, you need to fully parse both the target .elf executable (type ET_EXEC) and the input .o relocatable file (type ET_REL). You’ll need to work with core ELF32 structures:

  • Elf32_Ehdr: The main ELF file header (tracks section count, section table offset, etc.)
  • Elf32_Shdr: Section headers (describes each section’s type, size, file offset, memory address, alignment, etc.)
  • Elf32_Sym: Symbol table entries (tracks symbol names, types, values, and associated sections)
  • Elf32_Rel: Relocation entries (marks which instructions need address fixes and how to apply them)

You can use the standard <linux/elf.h> header for these definitions, or reimplement them yourself if working cross-platform.

Step 2: Append .text and .data Sections to the Target ELF
  1. Prepare the target file:
    • Find the end of the target .elf file on disk. Calculate padding bytes to ensure the new sections meet their sh_addralign requirements (e.g., .text typically aligns to 16 bytes).
    • Write the .text and .data content from the .o file to the end of the target .elf, adding padding as needed.
  2. Update section headers:
    • Increment the target’s e_shnum (section count) by 2 in the Elf32_Ehdr.
    • Create new Elf32_Shdr entries for the added sections:
      • For .text: Set sh_type = SHT_PROGBITS, sh_flags = SHF_EXECINSTR | SHF_ALLOC, sh_offset to the file offset where you wrote the .text content, sh_addr to the next available executable memory address (calculate as the last loaded section’s sh_addr + sh_size, aligned to sh_addralign).
      • For .data: Set sh_type = SHT_PROGBITS, sh_flags = SHF_WRITE | SHF_ALLOC, with similar offset/address calculations (using writable memory addresses).
    • Adjust the target’s e_shoff (section table offset) if the section table needs to be moved to accommodate the new headers.
Step 3: Merge Symbol Tables

The .o file’s symbol table (usually .symtab) needs to be merged into the target .elf’s symbol table:

  1. Merge string tables:
    • Append the .o’s .strtab (symbol name strings) to the target’s .strtab. Update all .o symbol entries’ st_name values to reflect their new offset in the merged string table (add the original size of the target’s .strtab to each .o symbol’s st_name).
  2. Add symbols to the target’s symbol table:
    • Iterate over each symbol in the .o’s .symtab:
      • Local symbols (STB_LOCAL): Add them directly, updating st_shndx to match the new section indices of your appended .text/.data sections.
      • Global/weak symbols: Check if the target already has a symbol with the same name. Follow static linking rules:
        • A strong global symbol in the target overrides a weak/global symbol in the .o.
        • Duplicate strong global symbols are an error.
        • If the symbol doesn’t exist in the target, add it, updating st_value to the final memory address (.o symbol’s st_value + new section’s sh_addr).
  3. Update the target’s .symtab section header: Increase sh_size by number_of_new_symbols * sizeof(Elf32_Sym).
Step 4: Handle Relocations (Fixing Instruction Offsets)

This is the most critical part—you need to resolve the .o’s relocation entries to fix address references in the appended code:

  1. Process each relocation entry (.rel.text, .rel.data):
    • For every Elf32_Rel entry:
      • Extract the symbol index (ELF32_R_SYM(r_info)) and relocation type (ELF32_R_TYPE(r_info)).
      • Resolve the symbol’s final memory address:
        • If the symbol exists in the target, use its st_value.
        • If it’s a local symbol from the .o, use new_section_sh_addr + symbol_st_value.
      • Find the location in the target file to modify: new_section_sh_offset + r_offset (the r_offset from the .o is relative to its own .text/.data section).
  2. Apply the correct relocation based on type:
    For x86 32-bit ELF, common types include:
    • R_386_32: Direct 32-bit absolute address. Write the full symbol memory address into the 4-byte location.
    • R_386_PC32: PC-relative offset. Calculate as symbol_address - (current_instruction_address + 4) (x86 uses the next instruction’s address as the PC base). current_instruction_address is new_text_sh_addr + r_offset. Write this signed 32-bit offset into the instruction.
    • R_386_GOTPC/R_386_PLT: These are for dynamic linking—since you’re building a static-like tool, you can ignore these if your .o doesn’t use dynamic symbols.

Once relocations are applied, you don’t need to keep the .o’s relocation sections in the target .elf (executables don’t require runtime relocations).

Step 5: Critical Additional Fixes
  • Update program headers: The target’s Phdr (program header table) defines how sections are mapped into memory. You can either:
    • Add new PT_LOAD entries for your new .text/.data sections (matching permissions: PF_R | PF_X for .text, PF_R | PF_W for .data), or
    • Merge the new sections into existing PT_LOAD segments if their permissions and alignment match (e.g., append your .text to the target’s existing .text segment, then update the segment’s p_filesz and p_memsz).
  • Validate alignment: Double-check that all section offsets and memory addresses adhere to their sh_addralign requirements—misalignment will cause runtime crashes.
  • Update section links: Ensure fields like sh_link (e.g., symbol table’s link to the string table) point to the correct section indices after merging.
Key Notes on Determining Which Instructions to Fix

You don’t need to manually inspect instructions to find which ones need fixes—that’s exactly what the .o’s relocation tables are for! The compiler generates these entries to mark every location where an address reference (like a function call or global variable access) needs adjustment. Your tool only needs to iterate over these entries and apply the relocation logic as defined by the ELF spec.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:55:45