2014-03-19 20 views
5

Ich habe keine Antwort auf diese Frage gefunden.Wie man Funktionsprototypen aus einer Elf-Datei extrahiert?

Mit GDB kann ich den Befehl "call" verwenden, um den Prototyp einer Funktion zu erhalten. Beispiel:

(gdb) call fn 
$1 = {void (int, int)} 0x8048414 <fn> 

So ist GDB der Lage, herauszufinden, nur von der Elf-Datei, dass fn() void zurückgibt und nimmt zwei ganze Zahlen als Argumente.

Allerdings muss ich ein anderes Tool verwenden, um die Funktionsprototypen aus einer Elf-Datei zu extrahieren. Vorzugsweise möchte ich objdump/readelf verwenden.

Weiß jemand, ob das möglich ist? Wenn es nicht möglich ist, wie macht GDB das? In welchem ​​Abschnitt der Elf-Datei ist die Funktion Prototypen gespeichert?

Antwort

4

GDB kennt die Signatur einer Funktion über DWARF debuginfo. readelf -w ELF würde das dump. Wahrscheinlich möchten Sie Introduction to the DWARF Debugging Format von Michael J. Eager lesen. Mit pyelftools können Sie mit DWARF von einer interaktiven Python-Sitzung aus experimentieren und experimentieren.

Um Funktionsprototypen zu extrahieren, möchten Sie die Debug-Informationen subprogram Einträge. Ein Beispiel im ZWERG Format Tutorial:

strndup.c

1: #include "ansidecl.h" 
2: #include <stddef.h> 
3: 
4: extern size_t strlen (const char*); 
5: extern PTR malloc (size_t); 
6: extern PTR memcpy (PTR, const PTR, size_t); 
7: 
8: char * 
9: strndup (const char *s, size_t n) 
10: { 
11: char *result; 
12: size_t len = strlen (s); 
13: 
14: if (n < len) 
15: len = n; 
16: 
17: result = (char *) malloc (len + 1); 
18: if (!result) 
19: return 0; 
20: 
21: result[len] = '\0'; 
22: return (char *) memcpy (result, s, len); 
23: } 

ZWERG Beschreibung für strndup.c

<1>: DW_TAG_base_type 
    DW_AT_name = int 
    DW_AT_byte_size = 4 
    DW_AT_encoding = signed 
<2>: DW_TAG_typedef 
    DW_AT_name = size_t 
    DW_AT_type = <3> 
<3>: DW_TAG_base_type 
    DW_AT_name = unsigned int 
    DW_AT_byte_size = 4 
    DW_AT_encoding = unsigned 
<4>: DW_TAG_base_type 
    DW_AT_name = long int 
    DW_AT_byte_size = 4 
    DW_AT_encoding = signed 
<5>: DW_TAG_subprogram 
    DW_AT_sibling = <10> 
    DW_AT_external = 1 
    DW_AT_name = strndup 
    DW_AT_prototyped = 1 
    DW_AT_type = <10> 
    DW_AT_low_pc = 0 
    DW_AT_high_pc = 0x7b 
<6>: DW_TAG_formal_parameter 
    DW_AT_name = s 
    DW_AT_type = <12> 
    DW_AT_location = 
    (DW_OP_fbreg: 0) 
<7>: DW_TAG_formal_parameter 
    DW_AT_name = n 
    DW_AT_type = <2> 
    DW_AT_location = 
    (DW_OP_fbreg: 4) 
<8>: DW_TAG_variable 
    DW_AT_name = result 
    DW_AT_type = <10> 
    DW_AT_location = 
    (DW_OP_fbreg: -28) 
<9>: DW_TAG_variable 
    DW_AT_name = len 
    DW_AT_type = <2> 
    DW_AT_location = 
    (DW_OP_fbreg: -24) 
<10>: DW_TAG_pointer_type 
    DW_AT_byte_size = 4 
    DW_AT_type = <11> 
<11>: DW_TAG_base_type 
    DW_AT_name = char 
    DW_AT_byte_size = 1 
    DW_AT_encoding = 
    signed char 
<12>: DW_TAG_pointer_type 
    DW_AT_byte_size = 4 
    DW_AT_type = <13> 
<13>: DW_TAG_const_type 
    DW_AT_type = <11> 

Für eine vollständigere Beispielimplementierung, einen Blick unter this C reflection library von Petr Machata. Es hat den Code zu tun, was Sie mit der folgenden Einschränkung wollen:

  • Reflexion läuft in-Prozess statt Out-of-Process wie GDB
  • es auf libdw und libdwfl von elfutils abhängt. Nicht sicher, wie Sie diese externen Bibliotheksabhängigkeiten erweitern würden.