7

Solarisプロセスがあります。これは、いくつかのライブラリldとともにロードされるC++アプリケーションです。.soこのアプリケーションには、呼び出し元の関数でリターンアドレスを取得し、その呼び出し元の関数の名前を判別しようとする関数があります。

そのために使用する場合dladdr(3)、Dl_info::dli_snameに期待するものが常に表示されるとは限りません。ポインタ値の下またはポインタ値に最も近くない関数の名前を返すように見えます。ポインタ値を取得しての出力を見ると、nmその値を期待どおりの関数に一致させることができます。

プロセスのシンボルマップを取得し、を使用せずに関数名を検索する方法があるかどうか疑問に思っていますdladdr(3)。実行可能ファイル自体だけでなく、実行可能ファイルがロードしたすべての.soライブラリのシンボルマップを取得することに特に興味があります。

Solaris10 / SPARCで実行していて、gcc4.2.xを使用しています。

ありがとうございました!

4

2 に答える 2

4

Solaris 10/SPARCを使用して簡単なテストを試みましたdladdr()(ただし、注意: GCC 3.4、ストレート C)。

#include <dlfcn.h>
#include <stdio.h>

void print_name(char *name, void *addr);
void print_name_by_dladdr(void *addr);

int main(int argc, const char *argv[])
{
    print_name("main", (void *)&main);
    print_name("print_name", (void *)&print_name);
    print_name("printf", (void *)&printf);
    return 0;
}

void print_name(char *name, void *addr)
{
    (void)printf("Getting name of function %s() at 0x%x\n", name, addr);
    print_name_by_dladdr(addr);
}

void print_name_by_dladdr(void *addr)
{
    Dl_info dli;
    if(!dladdr(addr, &dli)) {
        perror("dladdr()");
        exit(1);
    }
    (void)printf("  %s\n", dli.dli_sname);
}

出力:

Getting name of function main() at 0x10714
  main
Getting name of function print_name() at 0x10778
  print_name
Getting name of function printf() at 0x209b8
  _PROCEDURE_LINKAGE_TABLE_

これは、私が書いた場合にも正しく機能します(たとえば)

    print_name("main", (void *)&main + 4);

の出力に対して正しく解決できると言うnmので、可能性は限られているようです...リターンアドレスが導出されているか、リゾルバ関数に正しく渡されていることは確かですか? これにGCCビルトインを使用していると思いますか?私はテスト__builtin_return_address(0)しましたが、これも私にとってはうまくいきます。GCC ビルトインを使用している場合、電話しましたか__builtin_extract_return_address()(詳細については上記のページを参照してください。明示的に SPARC について言及しています)。あなたのコードを投稿できますか?

「独自のバイナリ/共有オブジェクトファイルを再読み込みするプロセス」に少し手を伸ばすことはできますか? もしそうなら、libelfは前進する方法かもしれません. これは、あなたが言及したユーティリティの一部が使用しているものですnm

sun.com のこの紹介記事は役に立つかもしれません (警告: 記事は 10 年前のものです)。

これは、ネイティブのイントロスペクションを行うほど良くはなく、dladdr(3C)機能しないのは奇妙です:(

代替の中間:RTLD_DL_SYMENTフラグを試しましたかdladdr1(3C)(そしてnm.c、返された ELF sym で上記のように借用した可能性があります)?

于 2011-08-12T00:03:17.803 に答える
3

少し遅れましたが、まだ助けになるかもしれません: elf-object ファイルには、通常 2 つのシンボル テーブルがあります: .symtab と .dynsym nm はデフォルトで .symtab を読み取り、nm -D を使用して .dynsym テーブルを読み取ります。dladdr (およびダイナミック ローダー) は .dynsym テーブルを使用します。.symtab テーブルはより完全です。-rdynamic リンカー フラグを使用して、.dynsym テーブルにあるすべてのシンボルを強制することもできます。ただし、これによりリンクが大幅に遅くなります (たとえば、現在のプロジェクトでは約 200 ミリ秒)。(注意: 上記は Linux を参照していますが、シンボルの処理は、sunos でも基本的に同じように機能します。コマンド ライン オプションは異なる場合があります)

于 2011-09-15T10:22:03.223 に答える