TL;DR
I want to debug a function called from various places, so I want to get the function name of the caller.
It would be nice to use __builtin_return_address (0)
and dladdr
.
test.c(Get the caller's function name and return address)
#include <stdio.h>
#define __USE_GNU
#include <dlfcn.h>
void hoge() {
Dl_info info;
dladdr(__builtin_return_address(0), &info);
printf("[%s] parent func name => %p [%s]\n",
__func__,
__builtin_return_address(0),
info.dli_sname);
}
void foo() {
hoge();
Dl_info info;
dladdr(__builtin_return_address(0), &info);
printf("[%s] parent func name => %p [%s]\n",
__func__,
__builtin_return_address(0),
info.dli_sname);
}
int main(int argc, char const* argv[])
{
hoge();
foo();
return 0;
}
The result of the execution is as follows. You can get the symbol name from dladdr.
$ gcc test.c -ldl -rdynamic
$ ./a.out
[hoge] parent func name => 0x4008ee [main]
[hoge] parent func name => 0x40089e [foo]
[foo] parent func name => 0x4008f8 [main]
However, this method is limited and you have to build with -rdynamic
.
(-rdynamic
=> Add all symbols to the dynamic symbol table)
If the symbol does not exist in the dynamic symbol table, the name cannot be obtained by dladdr
.
Execution result
$ gcc test.c -ldl
$ ./a.out
[hoge] parent func name => 0x4006de [(null)]
[hoge] parent func name => 0x40068e [(null)]
[foo] parent func name => 0x4006e8 [(null)]
Since the return address is known by __builtin_return_address (0)
, it can be determined by using, for example, ʻobjdump`.
$ objdump -d ./a.out | view -
000000000040067c <foo>: #Caller
40067c: 55 push %rbp
40067d: 48 89 e5 mov %rsp,%rbp
400680: 48 83 ec 20 sub $0x20,%rsp
400684: b8 00 00 00 00 mov $0x0,%eax
400689: e8 af ff ff ff callq 40063d <hoge>
40068e: 48 8b 45 08 mov 0x8(%rbp),%rax #Return here when exiting hoge
400692: 48 8d 55 e0 lea -0x20(%rbp),%rdx
400696: 48 89 d6 mov %rdx,%rsi
400699: 48 89 c7 mov %rax,%rdi
40069c: e8 7f fe ff ff callq 400520 <dladdr@plt>
4006a1: 48 8b 55 f0 mov -0x10(%rbp),%rdx
4006a5: 48 8b 45 08 mov 0x8(%rbp),%rax
4006a9: 48 89 d1 mov %rdx,%rcx
4006ac: 48 89 c2 mov %rax,%rdx
4006af: be 9f 07 40 00 mov $0x40079f,%esi
4006b4: bf 78 07 40 00 mov $0x400778,%edi
4006b9: b8 00 00 00 00 mov $0x0,%eax
4006be: e8 4d fe ff ff callq 400510 <printf@plt>
4006c3: c9 leaveq
4006c4: c3 retq
~Omission~
00000000004006c5 <main>: #Caller
4006c5: 55 push %rbp
4006c6: 48 89 e5 mov %rsp,%rbp
4006c9: 48 83 ec 10 sub $0x10,%rsp
4006cd: 89 7d fc mov %edi,-0x4(%rbp)
4006d0: 48 89 75 f0 mov %rsi,-0x10(%rbp)
4006d4: b8 00 00 00 00 mov $0x0,%eax
4006d9: e8 5f ff ff ff callq 40063d <hoge>
4006de: b8 00 00 00 00 mov $0x0,%eax #Return here when exiting hoge
4006e3: e8 94 ff ff ff callq 40067c <foo>
4006e8: b8 00 00 00 00 mov $0x0,%eax #Return here when exiting foo
4006ed: c9 leaveq
4006ee: c3 retq
4006ef: 90 nop
Debugging seems to improve when combined with the hook in LD_PRELOAD that I investigated earlier.
Replace printf later with LD_PRELOAD --Qiita
How to get the string of the function name in C-Diary of Taisho (miettal) Function caller in linux kernel - Stack Overflow How to get function's name from function's pointer in C? - Stack Overflow Return Address - Using the GNU Compiler Collection (GCC) Function tracer with GCC compile options-diary of torutk About __builtin_return_address --syohex ’s diary
Recommended Posts