9

I am currently fiddling around with some c libraries without documentation. I am wondering if it is at all possible to retrieve more metadata, such as parameters and return values, outside of what is provided by calling nm -D or objdump -T filename | grep text. I'm not sure if this is possible, but if it is, it saves me from hunting down whoever was in charge of the library!

Edit: I'd like to be able to do this without reading machine code if possible. It appears that there are some solutions that allow me to do so easily if I was an expert at machine code, but since I am not and do not have the current desire to jump down that rabbit hole, I'm really hoping there is another way.

3
  • C/C++ libraries, right?
    – slm
    Commented Dec 10, 2013 at 2:33
  • yes I mean C libraries. Sorry that wasn't clear, I'll edit my question Commented Dec 10, 2013 at 2:33
  • 1
    With C, you can't. The information simply isn't there. (There is partial information if the libraries were compiled with debugging symbols.) This is a reverse engineering job. If you decide to undertake it, you can get help on Reverse Engineering. Commented Dec 10, 2013 at 21:16

1 Answer 1

11

A very similar question was asked on Stack Overflow: How to extract function prototype from an ELF file?

In short: generally you can't. If the executable (or shared library) doesn't have debug information, the information on the number and type of arguments is not stored in the executable.

If the shared object file does have debug information, then you should be able to extract the information with readelf -wi, or by using a debugger.

For example, I've got an ELF executable that contains a function int foo(char a, long b), compiled with debug info. GDB tells me:

(gdb) p foo
$1 = {int (char, long int)} 0x40051c <foo>

And readelf -wi (a bit cryptic, you'll have to match up the entries yourself) has:

 <1><2d>: Abbrev Number: 2 (DW_TAG_subprogram)            <= function
    <2e>   DW_AT_external    : 1    
    <2f>   DW_AT_name        : foo                        <= func name
    <33>   DW_AT_decl_file   : 1    
    <34>   DW_AT_decl_line   : 1    
    <35>   DW_AT_prototyped  : 1    
    <36>   DW_AT_type        : <0x6c>                     <= return type
    <3a>   DW_AT_low_pc      : 0x40051c 
    <42>   DW_AT_high_pc     : 0x400532 
    <4a>   DW_AT_frame_base  : 0x0  (location list)
    <4e>   DW_AT_GNU_all_call_sites: 1  
    <4f>   DW_AT_sibling     : <0x6c>   
 <2><53>: Abbrev Number: 3 (DW_TAG_formal_parameter)      <= parameter
    <54>   DW_AT_name        : a    
    <56>   DW_AT_decl_file   : 1    
    <57>   DW_AT_decl_line   : 1    
    <58>   DW_AT_type        : <0x73>   
    <5c>   DW_AT_location    : 2 byte block: 91 6c  (DW_OP_fbreg: -20)
 <2><5f>: Abbrev Number: 3 (DW_TAG_formal_parameter)      <= other param
    <60>   DW_AT_name        : b    
    <62>   DW_AT_decl_file   : 1    
    <63>   DW_AT_decl_line   : 1    
    <64>   DW_AT_type        : <0x7a>   
    <68>   DW_AT_location    : 2 byte block: 91 60  (DW_OP_fbreg: -32)
 <1><6c>: Abbrev Number: 4 (DW_TAG_base_type)
    <6d>   DW_AT_byte_size   : 4    
    <6e>   DW_AT_encoding    : 5    (signed)
    <6f>   DW_AT_name        : int  
 <1><73>: Abbrev Number: 5 (DW_TAG_base_type)
    <74>   DW_AT_byte_size   : 1    
    <75>   DW_AT_encoding    : 6    (signed char)
    <76>   DW_AT_name        : (indirect string, offset: 0x2e): char    
 <1><7a>: Abbrev Number: 5 (DW_TAG_base_type)
    <7b>   DW_AT_byte_size   : 8    
    <7c>   DW_AT_encoding    : 5    (signed)
    <7d>   DW_AT_name        : (indirect string, offset: 0x0): long int 

Note that for C++, the symbols you see with nm carry more information (unless they've been declared extern "C" - the number and type of parameters must be available to the linker to handle overloading. But the return type information isn't there either. (But the symbols are mangled - c++filt can be used to demangle.)

Compiling the same source file as C++ gives the following output for nm a.out | c++filt:

...
0000000000400554 T foo(char, long)
...
2
  • 1
    Where is the mapping from something like 0x6c to an actual type?
    – mowwwalker
    Commented Jun 28, 2018 at 0:23
  • It's shown in the output, the DW_TAG_base_type sections with that id.
    – Mat
    Commented Jun 28, 2018 at 4:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .