GDB knows the signature of a function through DWARF debuginfo. readelf -w ELF
would dump that. You'd probably want to read Introduction to the
DWARF Debugging Format by Michael J. Eager. Using pyelftools you can explore and experiment with DWARF from an interactive Python session.
To extract function prototypes, you want the subprogram
debug information entries. An example in the DWARF format tutorial is:
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: }
DWARF description for 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>
For a more complete sample implementation, take a look at this C reflection library by Petr Machata. It has the code to do what you want with the following caveats:
- Reflection runs in-process instead of out-of-process like GDB
- It depends on
libdw
and libdwfl
from elfutils. Not sure how you'd feel about growing those external library dependencies.