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.

  • C/C++ libraries, right? – slm Dec 10 '13 at 2:33
  • yes I mean C libraries. Sorry that wasn't clear, I'll edit my question – Edward Shen Dec 10 '13 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. – Gilles 'SO- stop being evil' Dec 10 '13 at 21:16

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)
  • 1
    Where is the mapping from something like 0x6c to an actual type? – mowwwalker Jun 28 '18 at 0:23
  • It's shown in the output, the DW_TAG_base_type sections with that id. – Mat Jun 28 '18 at 4:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.