2013-03-05 13 views
7

Ich studiere gerade das ELF-Format. Ich muss eine einfache nm-Funktion codieren (ohne die Optionen). Ich drucke bereits auf der Ausgabe den Wert des Symbols und den Namen des Symbols.Wie wird der Symboltyp wie der nm-Befehl angezeigt?

Hier ist der Ausgang nm:

value    type name 
0000000000600e30 D  __DTOR_END__ 

ich das gleiche, aber ohne den 'Typ'. Ich bin mit dem ELF64_Sym Struktur, wie folgt:

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; 

Ich weiß, dass ich die st_info Variable und dieses Makro verwenden:

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

das Symbol der Art zu erhalten. Aber kann das Symboltyp ein Makro wie folgt sein:

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

Und ich würde gerne wissen, wie kann ich von diesen Makros erhalten die Buchstaben gedruckt von nm, Beispiel:

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

Eine 'switch' Aussage, vielleicht? –

+0

Nehmen Sie diesen Mann in Betracht man nm (1): http://linux.die.net/man/1/nm – EGOrecords

Antwort

6

Ok ich habe ein paar Recherchen gemacht und hier ist meine Funktion, um das richtige Zeichen abhängig vom Symbol zu bekommen. Fühlen Sie sich frei, einige Charaktere hinzuzufügen/zu redigieren.

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; 
} 

Ich vermisse die s, n, p und ich. Ich bin mir ziemlich sicher, dass das "R" nicht gut ist. Ich werde das bearbeiten, wenn ich es finde.

3

Die ELF64_ST_TYPE tut nicht Karte direkt in die Buchstaben, die nm druckt.

Um das Mapping durchzuführen, müssen Sie sowohl auf ELF64_ST_BIND, als auch auf den Abschnitt achten, auf den sich das Symbol bezieht. Zum Beispiel:

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

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

für t vs T, werden Sie bei ELF64_ST_BIND(sym) == STB_LOCAL oder ELF64_ST_BIND(sym) == STB_GLOBAL aussehen wollen, und Sie wollen herausfinden, ob die von st_shndx verwiesen Abschnitt ist ein „Text“ ein (hat SHF_EXECINSTR in seinen Flags).

P.S. Soweit ich weiß, gibt es keine u. Wenn Ihre nm man-Seite Liste u auflistet, bin ich neugierig zu wissen, welche Art von Symbol das ist.

+0

Vielen Dank, das ist, was ich tun musste. Ich benutze den Makro ELF64_ST_BIND, um herauszufinden, ob das Symbol lokal oder global ist (MIN oder MAJ), und dann mit den Abschnittstyp- und Abschnittsflags einige Zeichen wie B, D, T erhalten. Aber es gibt noch mehr Zeichen finden ! Ich werde fortfahren und alle Ergebnisse veröffentlichen. Hier ist der nm Mann mit allen Charakteren: http://linux.die.net/man/1/nm –

+0

@ JérémieCharrier Ah, ich habe vergessen: 'du'' ELF64_ST_BIND (sym) == STB_GNU_UNIQUE'. –