在C语言中访问ELF符号表

8

我正在编写一个程序来模拟 elfdump -ecps

它目前可以正确打印出 elf 头、程序头和段头,但是在符号表的最后几个部分我卡住了。

期望的输出格式为:

Symbol Table Section:  .dynsym
 index    value      size      type bind oth ver shndx          name
   [0]  0x00000000 0x00000000  NOTY LOCL  D    0 UNDEF          
   [1]  0x00025c0c 0x00000000  FUNC GLOB  D    2 UNDEF          .udiv
   [2]  0x00025e00 0x00000140  OBJT WEAK  D    1 .bss           _iob
   [3]  0x00025b24 0x00000000  OBJT GLOB  P    1 .got           _GLOBAL_OFFSET_TABLE_
   [4]  0x00013a44 0x0000001c  FUNC GLOB  D    1 .init          _init
...

你能告诉我oth、ver、shndx和name在哪里找到吗?

目前,我正在使用以下代码将其打印出来:

//for each entry in the symbol table
for(i=0; i<num_sym; i++)
{
    //read the current symbol
    fread(&mysym,sizeof(Elf32_Sym),1,fp);
idx=mysym.st_name;

    //multiple lines to get formatting correct
    //prints index in brackets right aligned
    char buf[12];
    sprintf(buf, "[%d]", i);
    printf("%10s", buf);

    //value
    printf("  0x%.8x", mysym.st_value);
    //size
    printf(" 0x%.8x", mysym.st_size);

    //type
    switch (ELF32_ST_TYPE(mysym.st_info)) {
        case 0:
            printf("  NOTY");
            break;
        case 1:
            printf("  OBJT");
            break;
        case 2:
            printf("  FUNC");
            break;
        case 3:
            printf("  SECT");
            break;
        case 4:
            printf("  FILE");
            break;

        default:
            break;
    }

    //bind
    switch(ELF32_ST_BIND(mysym.st_info))
    {
        case 0: printf(" LOCL");
            break;
        case 1: printf(" GLOB");
            break;
        case 2: printf(" WEAK");
            break;
        case 3: printf("  NUM");
            break;

        default:
            break;
    }
    //TODO: oth
    //TODO: ver
    //TODO: shndx
    //TODO: name

}

我一直在阅读http://docs.oracle.com/cd/E19457-01/801-6737/801-6737.pdf(第5章),但没有找到有用的东西。


你能分享一下模仿elfdump的代码吗? - Ursa Major
2个回答

11

这在你链接的文档中主要涵盖在第119页开始的符号表下面讲述。

它实际上具备你需要的结构:

typedef struct {
    Elf32_Word    st_name;
    Elf32_Addr    st_value;
    Elf32_Word    st_size;
    unsigned char st_info;
    unsigned char st_other;
    Elf32_Half    st_shndx;
} Elf32_Sym;

同时提供如何查找关联条目的信息(具体来说是从st_name结构字段中找到名称的方法)。

不幸的是,该文档似乎没有涵盖某些信息的来源(例如版本),因此当我试图模拟另一个具有源代码可用的程序时,我去参考了源代码 - 没有比这更明确的东西了 :-)

在该文件的第1665行开始,您会找到elf_print_symtab()函数,它负责输出您感兴趣的信息。 它调用get_versym()获取该信息,并从1632行的代码中可以看出它使用了不同的部分(版本符号部分)。

正如此处所示,该部分类型被认为是操作系统特定的部分之一,因此您在基本标准中找不到它,基本标准仅涉及常见内容。


0
对于名称,还有另一个部分包含了所有的字符串。你应该使用"Section Header Table"中的第一个字段作为索引,在节头中获取真实的字符串。你可以在谷歌上找到很多关于这个的文章。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接