シンボルを解決(というか逆かな?)してみようと思い立って、libbfdを使ってsymlib(mydns.jp)を作ってみた。ちょっとした遊び。
使い方は、
:
struct symtable *st;
char *sym;
int offset;
st=symbol_load(“some-executable”, 0);
if(st==NULL) exit(1);
sym=symbol_get(st, some-symbol, &offset);
if(sym==NULL) exit(1);
printf(“%p = %s+%d\n”, some-symbol, sym, offset);
symbol_close(st);
みたいな感じ。現実的には、main()
でargv[0]
を読み込ませればいいんじゃないかな。
しかしシンボルの解決というのはまあまあ重要な問題かと思う。わけのわからんポインタを与えられたときに、しかしヒープやスタックではなく関数ポインタだったりするのだが、そこが果たして何者であるのか、というのはデバッグに必要な情報だ。printfの%pをオーバーライドしたいくらいだがそこまではなし。
今は指定したファイルのシンボルしか読み込まないのだが、これから拡張するとしたらリンクされているシェアードライブラリのシンボルまで読み込むようにしたり、自分のexecutableを勝手に読み込むとか、ksymoopsみたくするとか、いろいろ考えられる。やはりprintfの%pを奪って環境変数LD_PRELOADの設定だけで使えるようにするというのが本命かもしれない。しかしprintf奪うなんてのはかなり気乗りのしない出来事。
冗談でPythonからも使えるようにしたが全く意味ないね(笑)
(追記) 2003-11-17 23:53
用途をあんまり書いてなかったな。関数ポインタを引数に取る関数で、与えられた関数ポインタが何という名前の関数であるかをログに残すときに使える。デバッガで見りゃいいんだけど、そうもいかないときにどうぞ。
(追記) 2003-11-17 25:00
こういう、ある種の「逆eval」ってのはおもしろいかも。ちょっとPrologっぽい? …そこまで言うと飛躍しすぎだな。
(追記) 2003-11-18 15:56
あと、ヒープのアドレスから「どの関数でいつ割り当てられたメモリか」を求めるとか、スタックのアドレスを渡されてスタックフレームを表示するとか、バックトレースを表示するとか、そういう機能ってあるといいと思う。
私はバックトレースに関してはデバッガを使っているが、この程度のことを知るためにいちいちデバッガかと思うと納得がいかないのだ。
あとデバッガが構造体を探る様子が楽しいので、その機能もライブラリにしたいなぁと日頃思っていたことを思い出した。いわゆるprintfデバッグだと構造体のダンプってみんなよくやると思うけど、こんなの人力で書かせるなよと思う。Pythonで言うところの__repr__みたいなのをCで使いたい人がいるとして。…__repr__ってレプリケーションのことかな。
(追記) 2004-10-04 12:06
__builtin_return_addressとかのスタックフレームを操作する関数と組み合わせれば、スタックフレームをシンボルで表示できるな。けっこう使えるのかもしれない。