首页 > 解决方案 > Libelf 将条目添加到现有精灵的字符串表

问题描述

我正在尝试使用libelf. 现在,我正在使用elf_getdata获取数据描述符,分配一个新的更大的d_buf并更改它的d_size,将字符串复制到缓冲区的末尾,更改sh_size适用的 shdr,然后使用gelf_update_shdr然后elf_update写入它。这不会出错,并且成功地增加了字符串表的大小,但它无法实际写入新数据:readelf报告新字符串是.sym如果我尝试分配一个四字符的字符串 - 即它只是从值中读取在字符串表之后的任何内容中。

这是一些可以复制的代码 - 它读取 ELF 数据,然后尝试将值添加到 strtab:

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

size_t strtab_put(Elf_Scn** scns, GElf_Shdr* shdrs, int which, char *string) { // put value into strtab
    for (; *scns; scns++) {
        if (shdrs->sh_type == SHT_STRTAB) {
            if (which) {
                which--; // just refer to strtabs by numeric index
            } else {
                break;
            }
        }
        shdrs++;
    }
    if (!*scns) return -1;
    Elf_Data *strtab;
    strtab = elf_getdata(*scns, NULL);
    for (int i = 0; i < strtab->d_size; i++) {
        if (!strcmp((char*)strtab->d_buf + i, string)) { // if it's already there don't allocate a new one
            return i;
        }
    }   
    strtab->d_buf = (char*)realloc((char*)strtab->d_buf, strtab->d_size + strlen(string) + 1); // realloc enough space for the new string
    strcpy((char*)strtab->d_buf + strtab->d_size, string);
    size_t oldsize = strtab->d_size; // also the offset into the buffer
    strtab->d_size += strlen(string) + 1; // update data and shdr size
    shdrs->sh_size += strlen(string) + 1;
    gelf_update_shdr(*scns, shdrs);
    return oldsize;
}

int main() {
    elf_version(EV_CURRENT);
    int fd = open("elftest", O_RDWR, 0);
    Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL); // load in elf from file
    elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT);
    GElf_Ehdr ehdr;
    gelf_getehdr(elf, &ehdr);
    size_t numphdrs;
    elf_getphdrnum(elf, &numphdrs);
    GElf_Phdr phdrs[numphdrs]; // read in phdrs
    for (int i = 0; i < numphdrs; i++) {
        gelf_getphdr(elf, i, &phdrs[i]);
    }
    Elf_Scn* scns[32];
    GElf_Shdr shdrs[32]; // read in shdrs
    size_t numshdrs;
    Elf_Scn* curscn = NULL;
    while ((curscn = elf_nextscn(elf, curscn)) != NULL) {
        scns[numshdrs] = curscn;
        gelf_getshdr(curscn, &shdrs[numshdrs]);
        numshdrs++;
    }
    scns[numshdrs] = NULL;
    printf("Offset of test: %lx\n", strtab_put(scns, shdrs, 1, "test"));
    elf_update(elf, ELF_C_WRITE);
    elf_end(elf);
    close(fd);
}

这甚至是正确的方法吗?我是否忘记了一些我必须更新的属性、一些gelf_update_foo调用等?我必须sh_offset在它之后更新每个部分的值吗?

标签: celf

解决方案


推荐阅读