バックトレースの実装

Cのプログラムでバックトレースを表示したい場合,Linux(glibc)にはbacktrace(3),Solarisにはprintstack(3)なんてライブラリ関数が用意されているので,それらを使えばいい.なければsetjmp(3)やgetcontext(3)を使って,自力でスタックをたどることになる.と言ってもスタックフレームの構造がわかっていれば簡単で,見栄えを気にしなければ,こんな感じになる.

void
mybacktrace()
{
  jmp_buf env;
  void **fp, **ip;

  setjmp(env);
  fp = (void **)env[0].__jmpbuf[JB_BP];

  while (fp != NULL) {
    ip = (void **)fp[1];
    fp = (void **)fp[0];

    printf("%p\n", ip);
  }
}

後はdladdr(3)使って,関数名やオフセットを調べれば,十分使いものになる.

こんなのをPlan9で書いてみようかなと思ったんだけど,jmp_bufにはPCとSPしか保存されないのね...

(追記:2007-02-04) 最近のglibcは,PCやSPはエンコードされているのでこれじゃ動かないらしい.setjmp用の__jmpbuf の スタックポインタがエンコードされている件