web-dev-qa-db-ja.com

共有オブジェクトライブラリ内の関数の関数パラメーターの検索

私は現在、ドキュメントのないいくつかのCライブラリをいじっています。 nm -Dまたはobjdump -T filename | grep textを呼び出すことによって提供されるもの以外に、パラメーターや戻り値などのより多くのメタデータを取得することはまったく可能かどうか疑問に思っています。これが可能かどうかはわかりませんが、それが可能であれば、図書館の担当者を探す手間を省くことができます。

編集:可能であれば、マシンコードを読み取らずにこれを実行できるようにしたいと思います。私がマシンコードの専門家なら簡単にそれを可能にするいくつかの解決策があるようですが、私はそのウサギの穴を飛び降りたいという現在の望みがないので、私は本当に別のものがあることを望んでいます仕方。

7
Edward Shen

非常によく似た質問がスタックオーバーフローで尋ねられました: ELFファイルから関数プロトタイプを抽出する方法?

つまり、一般的にはできません。実行可能ファイル(または共有ライブラリ)にデバッグ情報がない場合、引数の数とタイプに関する情報は実行可能ファイルに保存されません。

共有オブジェクトファイルにデバッグ情報がある場合は、_readelf -wi_を使用するか、デバッガを使用して情報を抽出できるはずです。

たとえば、デバッグ情報でコンパイルされた関数int foo(char a, long b)を含むELF実行可能ファイルがあります。 GDBは私に言っています:

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

そして_readelf -wi_(少し不可解です。自分でエントリを一致させる必要があります)は次のとおりです。

_ <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 
_

C++の場合、nmで表示されるシンボルがより多くの情報を運ぶことに注意してください(それらが_extern "C"_と宣言されていない限り-パラメーターの数と型は、オーバーロードを処理するためにリンカーで使用できる必要があります。ただし、戻りの型情報はtどちらかです(ただし、シンボルはマングルされています-_c++filt_を使用してデマングルできます)。

C++と同じソースファイルをコンパイルすると、_nm a.out | c++filt_に対して次の出力が得られます。

_...
0000000000400554 T foo(char, long)
...
_
8
Mat