Libelf 会创建损坏的输出文件,即使什么都不做

Libelf creates corrupted output file, even when changing nothing

我正在尝试使用 libelf 来编辑 ELF 二进制文件中的某些内容,但到目前为止,我什至无法在不破坏二进制文件的情况下将其写出。这个样本:

#include <libelf.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <gelf.h>

int main() {
    elf_version(EV_CURRENT);
    int fd = open("elftest", O_RDWR, 0);
    assert(fd >= 0);
    Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL);
    assert(elf != NULL);
    assert(elf_kind(elf) == ELF_K_ELF);
    assert(elf_update(elf, ELF_C_WRITE) != -1);
    elf_end(elf);
    close(fd);
}

应该只读入 elftest 并原样写回,而不是将工作中的 C hello world 转换为立即出现段错误的程序(根据 gdb,甚至在调用 main 之前)。 我注意到 readelf -h 的第一个差异是它把 headers 部分的开头往后移了一些,并且还报告说

readelf: Warning: the .dynamic section is not contained within the dynamic segment

是什么导致 libelf 更改可执行文件,即使实际上没有任何更改?

which should just read in elftest and write it back out unchanged instead converts a working C hello world into a program that segfaults immediately

这看起来确实像是 libelf 中的错误。

elf_open() 修复您的程序后立即添加此行:

    Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL);
    elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT);  // add this

但我认为没有必要。

P.S。我知道这只是一个示例,但是将程序的 功能 部分放在 assert() 中是一个非常糟糕的主意。这样做:

  assert(elf_update(elf, ELF_C_WRITE) != -1);

迟早会让你后悔的