如何在 C 中编写与打印节标题的 readelf -S 相同的程序?

Posted

技术标签:

【中文标题】如何在 C 中编写与打印节标题的 readelf -S 相同的程序?【英文标题】:How to write a program in C donig the same thing as readelf -S that print the section header? 【发布时间】:2022-01-22 22:42:08 【问题描述】:

我正在尝试用 c 编写一个字体,它采用一个 elf 文件并预测命令 readelf -S 的相同输出:

$ readelf -S prog.o
There are 10 section headers, starting at offset 0x7d8:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .strtab           STRTAB           0000000000000000  00000730
       00000000000000a6  0000000000000000           0     0     1
  [ 2] .text             PROGBITS         0000000000000000  00000040
       000000000000022c  0000000000000000  AX       0     0     16
  [ 3] .rela.text        RELA             0000000000000000  00000520
       00000000000001f8  0000000000000018           9     2     8
  [ 4] .rodata.str1.1    PROGBITS         0000000000000000  0000026c
       0000000000000128  0000000000000001 AMS       0     0     1
  [ 5] .comment          PROGBITS         0000000000000000  00000394
       0000000000000031  0000000000000001  MS       0     0     1
  [ 6] .note.GNU-stack   PROGBITS         0000000000000000  000003c5
       0000000000000000  0000000000000000           0     0     1
  [ 7] .eh_frame         X86_64_UNWIND    0000000000000000  000003c8
       0000000000000038  0000000000000000   A       0     0     8
  [ 8] .rela.eh_frame    RELA             0000000000000000  00000718
       0000000000000018  0000000000000018           9     7     8
  [ 9] .symtab           SYMTAB           0000000000000000  00000400
       0000000000000120  0000000000000018           1     4     8
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)````

我编写了这段代码,但我不知道如何继续,因为我无法提取所需的信息,因此我可以打印它们,例如 sh_name、sh_type、地址、标志等...

int main(int argc,char *argv[])
    if(argc < 2)
        printf("Error: no elf-file\n ");
        exit(1);
    
    FILE *elfFile=fopen(argv[1],"rb");
    if(elfFile==NULL)
        printf("File open error!\n");
        exit(1);
    
    Elf32_Ehdr elfHeader;
    Elf32_Shdr elfShdr;
    fread(&elfHeader,1,sizeof(elfHeader),elfFile);
    printf("There are %d section headers, starting at offset 
            0x%lx:\n\n",elfHeader.e_shnum,elfHeader.e_shoff);
    printf("Section Headers:\n  [Nr] Name              Type             Address           
           Offset\n       Size              EntSize          Flags  Link  Info  Align\n");
    
    for(int i=0;i<elfHeader.e_shnum;i++)
        fread(&elfShdr,1,sizeof(header),elfFile);
        printf("\t[%d] %s      %s       %016x %08x\n",elfShdr.sh_name,elfShdr.type);
        printf("\t     %016x  %016x  %s      %d      %d      %d\n");
    
    printf("Key to Flags:\n");
    printf("  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),\n");
    printf("  L (link order), O (extra OS processing required), G (group), T (TLS),\n");
    printf("  C (compressed), x (unknown), o (OS specific), E (exclude),\n");
    printf("  l (large), p (processor specific)\n");



    return 0;

【问题讨论】:

【参考方案1】:

我不知道如何继续,因为我无法提取所需的信息,因此我可以打印它们,例如 sh_name、sh_type、地址、标志等...

This answer 显示如何打印.sh_name

对于sh_type,您只需将各种SHT_... 值转换回它们的符号表示。这是实现这一目标的一种方法:

const char *sht_to_name(Elf32_Word sh_type)

  const char *names[] = 
    "NULL",
    "PROGBITS",
    "SYMTAB",
    "STRTAB",
    "RELA",
    .... etc.
  ;
  if (sh_type < sizeof(names) / sizeof(names[0])) 
    return names[sh_type];
  
  return "UNKNOWN";

标志的类似代码:

// Append decoded flags to the given buffer
void decode_flags(Elf32_Word flags, char buf[], size_t bufsz)

  char *p = buf + strlen(buf);
  char *end = buf + bufsz;
  if (flags & SHF_WRITE) 
    // Append "WRITE" if there is space
  
  if (flags & SHF_ALLOC) 
    // Append "ALLOC" if there is space
  
  ... etc.

【讨论】:

以上是关于如何在 C 中编写与打印节标题的 readelf -S 相同的程序?的主要内容,如果未能解决你的问题,请参考以下文章

Mac OS X 的类似 readelf 的工具? [关闭]

readelf -s 不输出完整的变量名

使用readelf和objdump解析目标文件 ***

C程序打印直角三角形

binutils工具集

如何以漂亮的打印风格在 JSON 中编写数据框?