15

コードで SIGSEGV を処理します。

int C()
{
  int *i = NULL;
  *i = 10; // Crash there
}

int B()
{
  return C();
}

int A()
{
   return B();
}

int main(void)
{
  struct sigaction handler;
  memset(&handler,0,sizeof(handler));
  handler.sa_sigaction = handler_func;
  handler.sa_flags = SA_SIGINFO;
  sigaction(SIGSEGV,&handler,NULL);
  return(C());
}

ハンドラー コードは次のとおりです。

static int handler_func(int signal, siginfo_t info, void* rserved)
{
  const void* stack[MAX_DEPTH];
  StackCrowlState state;
  state.addr = stack;
  state.count = MAX_DEPTH;

  _Unwind_Reason_Code code = _Unwind_Backtrace(trace_func,&state);
  printf("Stack trace count: %d, code: %d\n",MAX_DEPTH - state.count, code);

  kill(getpid(),SIGKILL);
}

static _Unwind_Reason_Code trace_func(void* context, void* arg)
{
  StackCrowlState *state = (StackCrowlState *)arg;
  if(state->count>0)
  {
     void *ip = (void *)_Unwind_GetIP(context);
     if(ip)
     {
       state->addr[0] = ip;
       state->count--;
       state->addr++;
     }
  }
  return(_URC_NO_REASON);
}

ただし、trace_func は 1 回だけ呼び出され、_Unwind_Backtrace 呼び出しでのみ表示されます。_Unwind_Backtrace を使用して SIGSEGV シグナルを発生させるコードのスタックトレースを取得することはできますか?

thnx

4

4 に答える 4

5

シグナルトリガー関数からバックトレースしたいが、シグナルハンドラー関数からバックトレースしたい。これは2つの異なるスタックです。(sigactionのSA_ONSTACKフラグはあなたの質問とは無関係であることに注意してください。)

トリガー関数ののスタックポインターを見つけるには、ハンドラーの3番目のパラメーター、つまりvoid*rservedを使用します。この質問の答えを参照できます:シグナルハンドラから保存された命令ポインタアドレスを取得する

于 2012-11-01T02:09:04.583 に答える
0

backtrace と backtrace_symbols_fd を使用して、シグナル ハンドラーからスタック トレースを取得することをお勧めします。

于 2012-07-21T18:56:43.293 に答える