1

システムの起動からシステムのクラッシュまで、呼び出された関数のアドレスまたは名前を保存したい。プログラムの実行中に呼び出されたときに、ハードウェア レジスタからこれらの関数アドレスを取得する方法はありますか?

4

4 に答える 4

2

gccのドキュメントから:

関数への入り口と出口のためのインストルメンテーション呼び出しを生成します。関数の入り口の直後と関数の出口の直前に、現在の関数のアドレスとその呼び出しサイトを使用して、次のプロファイリング関数が呼び出されます。(一部のプラットフォームでは、__builtin_return_address は現在の関数を超えて機能しないため、それ以外の場合はプロファイリング関数で呼び出しサイト情報を使用できない場合があります。)

     void __cyg_profile_func_enter (void *this_fn,
                                     void *call_site);
     void __cyg_profile_func_exit  (void *this_fn,
                                     void *call_site);

例:

#include <stdio.h>

void __cyg_profile_func_enter(void * this_fn, void * call_site)
{
  fprintf(stderr, "enter: %p %p\n", this_fn, call_site);
}

void __cyg_profile_func_exit(void * this_fn, void * call_site)
{
  fprintf(stderr, " exit: %p %p\n", this_fn, call_site);
}

void foo(void);
void bar(void);

void foo(void)
{
  bar();

  return;
}

void bar(void)
{
  return;
}

int main(void)
{
  bar();
  foo();

  return 0;
}

以下を使用してこれをコンパイルおよびリンクします。

gcc -finstrument-functions -finstrument-functions-exclude-function-list=__cyg_profile_func_enter,__cyg_profile_func_exit -Wall -g -o main main.c 

予想される出力は次のようになります。

enter: 0x400665 0x7fcfedaf6c8d
enter: 0x400643 0x400681
 exit: 0x400643 0x400681
enter: 0x40061c 0x400686
enter: 0x400643 0x400633
 exit: 0x400643 0x400633
 exit: 0x40061c 0x400686
 exit: 0x400665 0x7fcfedaf6c8d
于 2013-07-02T10:36:46.003 に答える
1

Linux を使用している場合:

ptraceを使用してプログラムをトレースし、レジスターを確認できます。

関数に関する情報を取得するには、libelfを使用できます。(または nm & objdump を使用)

于 2013-07-02T10:08:39.173 に答える
0

関数自体から関数アドレスを保存することはできず、実行中に関数名にアクセスすることはできませんが、関数を呼び出す前に保存することはできます。

 savefptr(myfunction);
 savefname("myfunction");
 myfunction(a,b,c);

と の適切な定義を使用savefptr()savefname()ます。

__FILE__これがトレース/デバッグのために行われる場合 (たとえば、コードで何が起こっているかを知るためにログを生成したい場合)、および__LINE__マクロを使用してファイル名とコード行をトレースするのに十分な場合があります。

 fprintf (stderr, "I'm in:'%s' line %d.",
                          __FILE__, __LINE__);

回避できる場合は、コンパイラまたは OS の仕様を使用しないことをお勧めします。

于 2013-07-02T10:20:09.337 に答える
0

私は* nixシステムでのみ同様の作業を行ったので、* nixに基づいたソリューションを提供します.

gccデフォルトのコンパイラとしてを使用すると仮定した場合は、makefile でと の両方-finstrument-functionsを有効にすることをお勧めします。次に例を示します。-fdump-rtl-expand

CFLAGS += -Wall -O -ggdb -Wstrict-prototypes -Wno-pointer-sign -finstrument-functions -fdump-rtl-expand

この後、your_trace.c などのトレース機能を実装できます。

#include <stdio.h>
#include <stdlib.h>

/* Function prototypes with attributes */
void main_constructor( void )
    __attribute__ ((no_instrument_function, constructor));

void main_destructor( void )
    __attribute__ ((no_instrument_function, destructor));

void __cyg_profile_func_enter( void *, void * ) 
    __attribute__ ((no_instrument_function));

void __cyg_profile_func_exit( void *, void * )
    __attribute__ ((no_instrument_function));


static FILE *fp;


void main_constructor( void )
{
  fp = fopen( "trace.txt", "w" );
  if (fp == NULL) exit(-1);
}


void main_deconstructor( void )
{
  fclose( fp );
}


void __cyg_profile_func_enter( void *this, void *callsite )
{
  fprintf(fp, "E%p\n", (int *)this);
}


void __cyg_profile_func_exit( void *this, void *callsite )
{
  fprintf(fp, "X%p\n", (int *)this);
}

これらの後、コードをコンパイルすると、関数情報を含む *.map ファイルが表示されます。また、trace.cでコンパイルされ、コンパイル後に出力ファイルを実行するだけで、関数呼び出し情報、つまりtrace.txtファイルが生成され、関数アドレスがあり、使用してそれぞれを表示したり、ツールをadd2line使用して取得したりできますpvtraceを使用した関数呼び出しtrace.txt、たとえば、という名前のコンパイル済みプログラムの場合、次のようDEMOになります。

-> pvtrace ./DEMO

graph.dot実行時の関数呼び出しを取得して記録します。

また

またはのような各関数アドレスを表示するには、単に有効-ggdbにしてデバッグ ツールを使用します。DDDGDB

于 2013-07-02T10:54:53.603 に答える