如何在 ELF 文件中查找 .strtab?

How to find `.strtab` in an ELF file?

当 运行 readelf -S 我得到:

  [27] .strtab           STRTAB           0000000000000000  00001630
       00000000000001d7  0000000000000000           0     0     1
  [28] .shstrtab         STRTAB           0000000000000000  00001807
       0000000000000103  0000000000000000           0     0     1

如何获取.strtab的索引? 起初我尝试使用 Type 字段来检测它,但是如您所见(27 和 28 具有相同的类型),这不起作用。另外我不能确定它会是第一个出现的 STRTAB 类型。

我的结构和一些解释:

/*
 * Section header.
 */
typedef struct {
    Elf64_Word sh_name;    /* Section name (index into the
                       section header string table). */
    Elf64_Word sh_type;    /* Section type. */
    Elf64_Xword sh_flags;    /* Section flags. */
    Elf64_Addr sh_addr;    /* Address in memory image. */
    Elf64_Off sh_offset;    /* Offset in file. */
    Elf64_Xword sh_size;    /* Size in bytes. */
    Elf64_Word sh_link;    /* Index of a related section. */
    Elf64_Word sh_info;    /* Depends on section type. */
    Elf64_Xword sh_addralign;    /* Alignment in bytes. */
    Elf64_Xword sh_entsize;    /* Size of each entry in section. */
} Elf64_Shdr;

How can I get the index of .strtab?

您一一阅读 Elf64_Shdr。当你读完第28条,你就会读到.strtab,你就会知道它的索引。

通过将其名称与 ".strtab" 字符串文字进行比较,您将知道它是 .strtab 部分。

(你可能是想问一个不同的问题,但如果是这样,那是你没有表达好。)

更新:

Can't I do anything else rather than comparing strings

也许吧。如果您真正的问题是找到 .strtab 部分,那不是真的。

(which is somehow hard) can I assume it will be the first STRTAB in the file for example?

不能保证会是这种情况。

注意:如果你担心strcmp()的速度,请注意你只能在.sh_type == SHT_STRTABstrcmp(),因为通常最多有两个这样的部分在任何给定的文件中,对 strcmp() 速度的担忧很可能是错误的。您的代码类似于:

  if (shdr.sh_type == SHT_STRTAB) {
    const char *sh_name = contents_of_shstrab + shdr.sh_name;
    if (strcmp(sh_name, ".strtab") == 0) {
      /* found .strtab; do whatever you need with it */
    }
  }

更新 2:

your solution is wrong, please see:

你不能说我的解决方案是错误的,因为我没有提供完整的解决方案。也是错的。

这是完整的代码(省略了大部分错误检查):

#include <elf.h>
#include <fcntl.h>
#include <link.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
  if (argc < 1) return 1;

  int fd = open(argv[1], O_RDONLY);
  if (fd == -1) return 2;

  struct stat st_buf;
  if (fstat(fd, &st_buf) != 0) return 3;

  char *data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (data == MAP_FAILED) return 4;

  const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr) *)data;
  const ElfW(Shdr) *shdr = (const ElfW(Shdr) *)(data + ehdr->e_shoff);

  const char *shstrtab = data + shdr[ehdr->e_shstrndx].sh_offset;

  for (int j = 0; j < ehdr->e_shnum; j++) {
    printf("[%2d] %s\n", j, shstrtab + shdr[j].sh_name);
  }

  return 0;
}
$ gcc -g t.c -Wall
$ ./a.out ./a.out
[ 0]
[ 1] .interp
[ 2] .note.gnu.build-id
[ 3] .note.ABI-tag
[ 4] .gnu.hash
[ 5] .dynsym
[ 6] .dynstr
...
[32] .symtab
[33] .strtab
[34] .shstrtab