2013-03-05 14 views
7

Sto studiando il formato ELF in questo momento. Devo codificare un semplice nm fonction (senza le opzioni). Sto già stampando sull'output il valore del simbolo e il nome del simbolo.Come visualizzare il tipo di simbolo come il comando nm?

ecco l'output nm:

value    type name 
0000000000600e30 D  __DTOR_END__ 

Ho lo stesso, ma senza il 'tipo'. Sto usando la struttura ELF64_Sym, come segue:

typedef struct { 
    Elf64_Word  st_name; 
    unsigned char st_info; 
    unsigned char st_other; 
    Elf64_Half  st_shndx; 
    Elf64_Addr  st_value; 
    Elf64_Xword  st_size; 
} Elf64_Sym; 

So che devo usare la variabile st_info e questa macro:

#define ELF64_ST_TYPE(info)   ((info) & 0xf) 

per ottenere il tipo di simbolo. Ma, il tipo di simbolo può essere una macro come segue:

NAME   VALUE 
STT_NOTYPE  0 
STT_OBJECT  1 
STT_FUNC  2 
STT_SECTION  3 
STT_FILE  4 
STT_LOPROC  13 
STT_HIOPROC  15 

e vorrei sapere è come posso ottenere da queste macro le lettere stampate dal nm, ad esempio:

U, u, A, a, T, t, R, r, W, w 
+0

Una dichiarazione 'switch', forse? –

+0

Prendi questo uomo in considerazione man nm (1): http://linux.die.net/man/1/nm – EGOrecords

risposta

6

Ok ho fatto alcune ricerche ed ecco la mia funzione per ottenere il carattere corretto in base al simbolo. Sentiti libero di aggiungere/modificare alcuni personaggi.

char   print_type(Elf64_Sym sym, Elf64_Shdr *shdr) 
{ 
    char c; 

    if (ELF64_ST_BIND(sym.st_info) == STB_GNU_UNIQUE) 
    c = 'u'; 
    else if (ELF64_ST_BIND(sym.st_info) == STB_WEAK) 
    { 
     c = 'W'; 
     if (sym.st_shndx == SHN_UNDEF) 
     c = 'w'; 
    } 
    else if (ELF64_ST_BIND(sym.st_info) == STB_WEAK && ELF64_ST_TYPE(sym.st_info) == STT_OBJECT) 
    { 
     c = 'V'; 
     if (sym.st_shndx == SHN_UNDEF) 
     c = 'v'; 
    } 
    else if (sym.st_shndx == SHN_UNDEF) 
    c = 'U'; 
    else if (sym.st_shndx == SHN_ABS) 
    c = 'A'; 
    else if (sym.st_shndx == SHN_COMMON) 
    c = 'C'; 
    else if (shdr[sym.st_shndx].sh_type == SHT_NOBITS 
     && shdr[sym.st_shndx].sh_flags == (SHF_ALLOC | SHF_WRITE)) 
    c = 'B'; 
    else if (shdr[sym.st_shndx].sh_type == SHT_PROGBITS 
     && shdr[sym.st_shndx].sh_flags == SHF_ALLOC) 
    c = 'R'; 
    else if (shdr[sym.st_shndx].sh_type == SHT_PROGBITS 
     && shdr[sym.st_shndx].sh_flags == (SHF_ALLOC | SHF_WRITE)) 
    c = 'D'; 
    else if (shdr[sym.st_shndx].sh_type == SHT_PROGBITS 
     && shdr[sym.st_shndx].sh_flags == (SHF_ALLOC | SHF_EXECINSTR)) 
    c = 'T'; 
    else if (shdr[sym.st_shndx].sh_type == SHT_DYNAMIC) 
    c = 'D'; 
    else 
    c = '?'; 
    if (ELF64_ST_BIND(sym.st_info) == STB_LOCAL && c != '?') 
    c += 32; 
    return c; 
} 

Mi mancano le s, n, pe i. Sono abbastanza sicuro che la 'R' non è buona. Lo modificherò quando lo trovo.

3

Il ELF64_ST_TYPE fa non mappa direttamente nelle lettere che nm stampe.

Per eseguire la mappatura, è necessario prestare attenzione a entrambi ELF64_ST_BIND, e alla sezione cui si riferisce il simbolo. Per esempio:

bool weak = (ELF64_ST_BIND(sym) == STB_WEAK); 
bool unresolved = (sym->st_shndx == SHN_UNDEF); 

if (unresolved) { 
    printf(" %c ", weak ? 'w' : 'U'); 
} 

Per t vs T, ti consigliamo di guardare ELF64_ST_BIND(sym) == STB_LOCAL o ELF64_ST_BIND(sym) == STB_GLOBAL, e si vorrà scoprire se la sezione fa riferimento st_shndx è un "testo" uno (ha SHF_EXECINSTR nelle sue bandiere).

P.S. Per quanto ne so, non esiste lo u. Se la tua pagina man nm elenca u, sono curioso di sapere che tipo di simbolo è.

+0

Grazie, questo è quello che dovevo fare. Sto usando la macro ELF64_ST_BIND per scoprire se il simbolo è locale o globale (MIN o MAJ) e poi con il tipo di sezione e i flag di sezione ottengo alcuni caratteri come, B, D, T. Ma ci sono ancora più caratteri trovare ! Continuerò e pubblicherò tutti i risultati. Ecco l'uomo nm con tutti i personaggi: http://linux.die.net/man/1/nm –

+0

@ JérémieCharrier Ah, ho dimenticato: 'u' è' ELF64_ST_BIND (sym) == STB_GNU_UNIQUE'. –