なぜ誰もがそれが不可能だと言うのか、私は驚いています。非静的関数については Linux で可能です。
これを達成する方法を少なくとも 2 つ知っています。
バックトレース印刷用の GNU 関数があります:backtrace()
と backtrace_symbols()
(man
を参照) )。あなたの場合、 backtrace()
は必要ありません 既に関数ポインタがあるので、それを backtrace_symbols()
に渡すだけです .
例 (作業コード):
#include <stdio.h>
#include <execinfo.h>
void foo(void) {
printf("foo\n");
}
int main(int argc, char *argv[]) {
void *funptr = &foo;
backtrace_symbols_fd(&funptr, 1, 1);
return 0;
}
gcc test.c -rdynamic
でコンパイル
出力:./a.out(foo+0x0)[0x8048634]
解析できるように、バイナリ名、関数名、関数の開始点からのポインター オフセット、およびポインター値が得られます。
別の方法は dladdr()
を使用することです (別の拡張子) print_backtrace()
だと思います dladdr()
を使用 . dladdr()
Dl_info
を返します dli_sname
に関数名を持つ構造体 分野。ここではコード例を提供しませんが、明らかです - man dladdr
を参照してください 詳細はこちら
注意!どちらのアプローチも、関数が非静的である必要があります!
libdwarf
を使用してデバッグ情報を使用する方法はもう 1 つあります。 しかし、これにはストリップされていないバイナリが必要であり、実行するのは簡単ではないため、お勧めしません.
追加の支援がなければ、それは直接不可能です。
次のことができます:
<オール> <リ>関数ポインターを名前にマッピングするプログラム内のテーブルを維持します
<リ>実行可能ファイルのシンボル テーブルがある場合は、それを調べます。
ただし、後者は難しく、移植性がありません。この方法は、オペレーティング システムのバイナリ形式 (ELF、a.out、.exe など) と、リンカーによって行われる再配置によって異なります。
編集:実際のユースケースが何であるかを説明したので、答えは実際にはそれほど難しくありません。カーネル シンボル テーブルは /proc/kallsyms
で利用可能です にアクセスするための API があります:
#include <linux/kallsyms.h>
const char *kallsyms_lookup(unsigned long addr, unsigned long *symbolsize,
unsigned long *ofset, char **modname, char *namebuf)
void print_symbol(const char *fmt, unsigned long addr)
単純なデバッグ目的では、後者はおそらく必要なことを正確に実行します-アドレスを取得し、フォーマットして、 printk
に送信します 、または printk
を使用できます %pF
で フォーマット指定子。
Linux カーネルでは、"%pF" を直接使用できます。 printk のフォーマット !
void *func = &foo;
printk("func: %pF at address: %p\n", func, func);