Accessing ELF symbol table in C

Alex picture Alex · Sep 4, 2012 · Viewed 13.3k times · Source

I'm writing a program to mimic elfdump -ecps

It currently prints out the elf header, program headers, and section headers correctly, but I'm stuck on the last few parts of the symbol table.

the desired output is in the format of:

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
...

can you tell me where the oth, ver, shndx, and name are found?

so far, I am printing it out with the following:

//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

}

I have been reading through http://docs.oracle.com/cd/E19457-01/801-6737/801-6737.pdf (chapter 5) but have not been able to find anything helpful

Answer

paxdiablo picture paxdiablo · Sep 4, 2012

This is mostly covered under Symbol Table starting on page 119 of that document you link to.

It actually has the structure you need:

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;

along with details on how to find the information for linked entries (specifically the means for finding the name from the st_name structure field).

Unfortunately, that document doesn't seem to cover where certain things come from (version, for example) so, when I'm trying to emulate another program that has the source available, I go to the source - there really isn't anything more definitive than that :-)

Starting on line 1665 of that file, you find the elf_print_symtab() function, which is responsible for outputting the information you're interested in. It calls get_versym() to get that information and, from that code on line 1632, you can see it uses a different section for that (the version symbol section).

And, as can be seen here, that section type is considered one of the OS-specific ones, which is why you won't find it in the base standard, which concerns itself only with the common stuff.