打印符號表

 

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <link.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <elf.h>
#include <error.h>
#include <errno.h>

#define ELFW(type)	_ELFW (ELF, __ELF_NATIVE_CLASS, type)
#define _ELFW(e,w,t)	_ELFW_1 (e, w, _##t)
#define _ELFW_1(e,w,t)	e##w##t

static const char *st_type(unsigned int stype)
{
    switch (stype) {
        case STT_NOTYPE: return "NOTYPE";
        case STT_OBJECT: return "OBJECT";
        case STT_FUNC: return "FUNC";
        case STT_SECTION: return "SECTION";
        case STT_FILE: return "FILE";
        case STT_COMMON: return "COMMON";
        case STT_TLS: return "TLS";
        case STT_LOOS ... STT_HIOS: return "OS_SPEC";
        case STT_LOPROC ... STT_HIPROC: return "PROC_SPEC";
        default: return "<unknown symbol type>";
    }
}

static const char *st_bind(unsigned int stbind)
{
    switch (stbind) {
        case STB_LOCAL: return "LOCAL";
        case STB_GLOBAL: return "GLOBAL";
        case STB_WEAK: return "WEAK";
//		case STB_GNU_UNIQUE: return "UNIQUE";
        case STB_LOOS ... STB_HIOS: return "OS";
        case STB_LOPROC ... STB_HIPROC: return "PROC";
        default: return "<unknown symbol bind>";
    }
}

static const char *st_vis(unsigned int svis)
{
    switch (svis) {
        case STV_DEFAULT: return "DEFAULT";
        case STV_INTERNAL: return "INTERNAL";
        case STV_HIDDEN: return "HIDDEN";
        case STV_PROTECTED: return "PROTECTED";
        default: return "<unknown symbol vis>";
    }
}

static const char *st_shndx(unsigned int shndx)
{
    static char s_shndx[32];

    switch (shndx) {
        case SHN_UNDEF: return "UND";
        case SHN_ABS: return "ABS";
        case SHN_COMMON: return "COMMON";
        case SHN_LOPROC ... SHN_HIPROC: return "PRC";
        case SHN_LOOS ... SHN_HIOS: return "OS";
        default:
            (void)snprintf(s_shndx, sizeof(s_shndx), "%u", shndx);
            return (const char *)s_shndx;
    }
}

static void print_syms(ElfW(Shdr) *shdrs, const char *shstrtab,
        const char *shname, ElfW(Sym) *syms, size_t entries, const char *strtab)
{
    printf("Symbol table '%s' contains %zu entries:\n", shname, entries);
    printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type",
        "Bind", "Vis", "Ndx", "Name");

    for (size_t i = 0; i < entries; i++) {
        ElfW(Sym) *sym = &syms[i];

        printf("%6zu:", i);
        printf(" %16.16jx", (uintmax_t)sym->st_value);
        printf(" %5ju", (uintmax_t)sym->st_size);
        printf(" %-7s", st_type(ELFW(ST_TYPE)(sym->st_info)));
        printf(" %-6s", st_bind(ELFW(ST_BIND)(sym->st_info)));
        printf(" %-8s", st_vis(ELFW(ST_VISIBILITY)(sym->st_other)));
        printf(" %3s", st_shndx(sym->st_shndx));
        if (strcmp("SECTION", st_type(ELFW(ST_TYPE)(sym->st_info))) == 0) {
            printf(" %s", shstrtab + shdrs[sym->st_shndx].sh_name);
        } else {
            printf(" %s", strtab + sym->st_name);
        }
        printf("\n");
    }
}

int main(int argc, char *argv[])
{
    int fd;
    char *file_mmbase;
    struct stat file_status;
    size_t fsize;
    ElfW(Ehdr) *ehdr;
    ElfW(Shdr) *shdrs;
    size_t shnum, shstrndx;
    const char *shstrtab;

//	[ 6] .dynstr           STRTAB          0000000000000468 000468 0000dd 00   A  0   0  1
//	[32] .strtab           STRTAB          0000000000000000 003d28 000322 00      0   0  1
//	[33] .shstrtab         STRTAB          0000000000000000 00404a 00013e 00      0   0  1

    if (argc != 2) {
        error(EXIT_FAILURE, 0, "Usage: %s file-name", argv[0]);
    }

    if ((fd = open(argv[1], O_RDONLY)) < 0) {
        error(EXIT_FAILURE, errno, "open %s failed", argv[1]);
    }

    if (fstat(fd, &file_status) < 0) {
        error(EXIT_FAILURE, errno, "get file %s info err", argv[1]);
    }
    fsize = (size_t)file_status.st_size;

    if ((file_mmbase = (char*)mmap(NULL, fsize, PROT_READ,
                MAP_PRIVATE, fd, (off_t)0)) == MAP_FAILED) {
        error(EXIT_FAILURE, errno, "mmap file %s err", argv[1]);
    }

    ehdr = (ElfW(Ehdr) *)file_mmbase;
    shdrs = (ElfW(Shdr) *)(file_mmbase + ehdr->e_shoff);
    shnum = ehdr->e_shnum == 0 ? shdrs[0].sh_size : ehdr->e_shnum;
    shstrndx = ehdr->e_shstrndx == SHN_XINDEX ? shdrs[0].sh_link : ehdr->e_shstrndx;
    shstrtab = file_mmbase + shdrs[shstrndx].sh_offset;

    for (size_t i = 0; i < shnum; i++) {
        ElfW(Shdr) *shdr = &shdrs[i];

        if (shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_DYNSYM) {
            const char *shname = shstrtab + shdr->sh_name;
            ElfW(Sym) *syms = (ElfW(Sym *))(file_mmbase + shdr->sh_offset);
            size_t entries = shdr->sh_size / shdr->sh_entsize;
            // sh_info: One greater than the symbol table index of
            // 			the last local symbol (binding STB_LOCAL).
            // printf("shdr->sh_info = %u\n", shdr->sh_info);
            // sh_link: .strtab or .dynstr (The section header index of
            // 			the associated string table.)
            const char *strtab = file_mmbase + shdrs[shdr->sh_link].sh_offset;
            print_syms(shdrs, shstrtab, shname, syms, entries, strtab);
        }
    }

    (void)munmap(file_mmbase, fsize);
    (void)close(fd);

    exit(EXIT_SUCCESS);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章