タグ

2009年7月21日のブックマーク (4件)

  • backtrace - 兼雑記

    で、そういう理由でこう、何度目かの backtrace 実装とかしてたんですが、 glibc の backtrace って DWARF2 使う実装とかあるんだなーと気付いた。 GCC ならこれ使うのが一番楽だし、 -fomit-frame-pointer ついてても大丈夫とか偉い。 // They are in libgcc (see glibc-2.7/sysdeps/ia64/backtrace.c) extern(C) int _Unwind_Backtrace(void* fn, void* a); extern(C) void* _Unwind_GetIP(void* ctx); struct Arg { void** buffer; int size; int cnt; } int backtrace_helper(void* ctx, void* data) { Arg* a

    backtrace - 兼雑記
  • 普通のやつらの下を行け: C でバックトレース表示 - bkブログ

    普通のやつらの下を行け: C でバックトレース表示 普通のやつらの下を行けの第2回として、今回は glibc の関数を使って C でバックトレース (スタックトレース) の表示を行ってみます。 バックトレースとは バックトレースとは、大ざっぱに言うと、現在の関数に至るまでの道筋です。たとえば、次の Ruby プログラムを実行すると、 1 / 0 の行で例外が発生して、バックトレースの表示とともにプログラムは異常終了します。 def foo 1 / 0 end def main foo end main この例では main から foo を呼び foo の中の 1 / 0 の部分で例外が発生しています。 % ruby divide-by-zero.rb divide-by-zero.rb:2:in `/': divided by 0 (ZeroDivisionError) from div

  • _Unwind_Backtrace()と-fomit-frame-pointer

    一つ前のエントリの続き。gccの_Unwind_Backtrace()には、フレームポインタなしでコンパイルされたコードに対しても動くという特長がある。はじめは、最初のフレームのときだけbuiltin関数に頼った後はレジスタの値を復元しながら巻き戻していくのでそういうこともできて当然、くらいに思っていたのだが、調べてみたらかなりtrickyだということが判明した: (少なくともFreeBSD/i386の場合)フレームポインタなしでコンパイルすると、gccは各フレームにおけるスタックの伸縮状況を細かく記録するFDEを作る。_Unwind_Backtrace()で巻き戻すときは、レジスタの状況にはほとんど頼らず、一つ前のフレームにおけるスタックの開始位置から、FDEに記録されている現在のフレームのスタックのサイズ分を差し引いて、直接現在フレームのスタックの位置を計算している。 単に_Unwi

  • gcc _Unwind_Backtrace()の謎

    ふと思い立ち、gccの秘密(?)関数_Unwind_Backtrace()を使って実行途中プロセスのbacktraceを取ってみようとしたら、驚くほど動かず、延々と調査するはめに。結局わかったことは以下: C++のコードの中から使った場合は(試した範囲内では)いつでも動く Cのコードから使った場合、x86_64(amd64)やIA64では動くが、x86(32ビット)とかsparcでは動かない。また、これらはOSにも依存しない Cの場合で、x86_64とx86の違いは、ELFの.eh_frame section内に実行コードのframeに関するcall frame information(CFI)が含まれているかどうか。含まれていれば動くが、そうでなければ動かない。 x86におけるC++とCの差もELFの.eh_frame sectionの中身の違い .eh_frame sectionに必要