TL;DR
Je veux déboguer une fonction appelée à partir de divers endroits, donc je veux obtenir le nom de fonction de l'appelant.
Ce serait bien d'utiliser __builtin_return_address (0)
et dladdr
.
test.c(Obtenez le nom de la fonction de l'appelant et l'adresse de retour)
#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;
}
Le résultat de l'exécution est le suivant. Vous pouvez obtenir le nom du symbole à partir de 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]
Cependant, cette méthode est limitée et vous devez construire avec -rdynamic
.
(-rdynamic
=> Ajouter tous les symboles à la table de symboles dynamiques)
Si le symbole n'existe pas dans la table des symboles dynamiques, le nom ne peut pas être obtenu par dladdr
.
Résultat d'exécution
$ gcc test.c -ldl
$ ./a.out
[hoge] parent func name => 0x4006de [(null)]
[hoge] parent func name => 0x40068e [(null)]
[foo] parent func name => 0x4006e8 [(null)]
Puisque l'adresse de retour est connue par __builtin_return_address (0)
, elle peut être déterminée en utilisant, par exemple, ʻobjdump`.
$ objdump -d ./a.out | view -
000000000040067c <foo>: #Votre interlocuteur
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 #Revenir ici en sortant de 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>: #Votre interlocuteur
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 #Revenir ici en sortant de Hoge
4006e3: e8 94 ff ff ff callq 40067c <foo>
4006e8: b8 00 00 00 00 mov $0x0,%eax #Revenir ici en quittant foo
4006ed: c9 leaveq
4006ee: c3 retq
4006ef: 90 nop
Si vous le combinez avec le hook dans LD_PRELOAD que vous avez examiné auparavant, le débogage semble s'améliorer.
Remplacez printf plus tard par LD_PRELOAD --Qiita
Comment obtenir la chaîne de caractères du nom de la fonction en langage C-Journal de 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) Fonction traceur avec GCC compile les options-journal de torutk À propos de __builtin_return_address - journal de syohex
Recommended Posts