gdb - ¿Cómo extraer prototipos de función de un archivo elf?
objdump function-prototypes (1)
GDB conoce la firma de una función a través de DWARF debuginfo. readelf -w ELF
arrojaría eso. Probablemente quiera leer Introducción al formato de depuración DWARF por Michael J. Eager. Usando pyelftools puedes explorar y experimentar con DWARF desde una sesión interactiva de Python.
Para extraer prototipos de función, desea las entradas de información de depuración del subprogram
. Un ejemplo en el tutorial de formato DWARF es:
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: }
Descripción DWARF para 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>
Para una implementación más completa de la muestra, eche un vistazo a esta biblioteca de reflexión C de Petr Machata. Tiene el código para hacer lo que quieras con la siguiente advertencia:
- La reflexión se ejecuta en proceso en lugar de fuera de proceso, como GDB
- Depende de
libdw
ylibdwfl
de elfutils . No estoy seguro de cómo se sentiría acerca de hacer crecer esas dependencias externas de la biblioteca.
No he tenido éxito en encontrar una respuesta sobre esta pregunta.
Usando GDB, puedo usar el comando "llamar" para obtener el prototipo de una función. Ejemplo:
(gdb) call fn
$1 = {void (int, int)} 0x8048414 <fn>
Entonces, GDB es capaz de descubrir, solo desde el archivo elf, que fn () devuelve vacío y toma dos enteros como argumentos.
Sin embargo, necesito usar alguna otra herramienta para extraer los prototipos de función de un archivo elf. Preferiblemente, quiero usar objdump / readelf.
¿Alguien sabe si esto es posible? Si no es posible, ¿cómo lo hace GDB? ¿En qué sección del archivo elf se almacenan los prototipos de función?