[Linux] [C / C ++] Comment obtenir la valeur d'adresse de retour d'une fonction et le nom de fonction de l'appelant

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.

Exemple d'implémentation

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

Relation

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

référence

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

[Linux] [C / C ++] Comment obtenir la valeur d'adresse de retour d'une fonction et le nom de fonction de l'appelant
Comment trouver l'adresse mémoire de la valeur de la trame de données Pandas
Récupérer l'appelant d'une fonction en Python
[Langage C] [Linux] Récupère la valeur de la variable d'environnement
Comment obtenir le "nom" d'un champ dont la valeur est limitée par l'attribut choice dans le modèle Django
[Linux] [C / C ++] Résumé de la façon d'obtenir pid, ppid, tid
Comment obtenir la dernière (dernière) valeur d'une liste en Python
La valeur de retour (générateur) d'une fonction qui combine finally et yield ne doit pas être passée directement à next
[C / C ++] Passez la valeur calculée en C / C ++ à une fonction python pour exécuter le processus et utilisez cette valeur en C / C ++.
Une histoire sur le portage du code de "Essayez de comprendre comment fonctionne Linux" sur Rust
Je veux obtenir le nom de la fonction / méthode en cours d'exécution
Comment obtenir et définir le nom du serveur NTP par DHCP
[Python] Comment obtenir le premier et le dernier jour du mois
Comment afficher le résultat de sortie de la commande man Linux dans un fichier
Comment obtenir les coordonnées de sommet d'une entité dans ArcPy
Créez une fonction pour obtenir le contenu de la base de données dans Go
Comment obtenir la valeur en pixels du point à partir de l'image satellite en spécifiant la latitude et la longitude
Comment diviser et traiter une trame de données à l'aide de la fonction groupby
Comment obtenir un nom de colonne et un nom d'index spécifiques avec Pandas DataFrame
[Linux] Une commande pour obtenir une liste des commandes exécutées dans le passé
Comment créer un wrapper qui préserve la signature de la fonction à envelopper
[Langage C] Comment utiliser la fonction crypt sous Linux [Hachage de mot de passe]
Comment calculer la volatilité d'une marque
[Circuit x Python] Comment trouver la fonction de transfert d'un circuit en utilisant Lcapy
[NNabla] Comment obtenir la sortie (variable) de la couche intermédiaire du réseau construit
Comment compter le nombre d'éléments dans Django et sortir dans le modèle
[Python] J'ai essayé d'obtenir le nom du type sous forme de chaîne de caractères à partir de la fonction type
Je veux obtenir le nom du fichier, le numéro de ligne et le nom de la fonction dans Python 3.4
Sous Linux (Ubuntu), réglez le Trackpad et réglez la fonction sur un balayage à trois doigts
Outil pour insérer le nom du pays et le code du pays dans une partie de l'adresse IP
Comment obtenir une liste de fichiers dans le même répertoire avec python
[Introduction à Python] Comment obtenir l'index des données avec l'instruction for
Comment obtenir le nom de la variable lui-même en python
Obtenez le nom de la variable sous forme de chaîne de caractères.
Comment obtenir le nombre de chiffres en Python
[Python of Hikari-] Chapitre 06-02 Fonction (argument et valeur de retour 1)
Comment frapper le document de Magic Function (Line Magic)
[Django 2.2] Trier et obtenir la valeur de la destination de la relation
[Python] Comment appeler une fonction de c depuis python (édition ctypes)
Comment afficher la date de modification d'un fichier en langage C jusqu'à nanosecondes
[Blender] Comment obtenir l'ordre de sélection des sommets, des côtés et des faces d'un objet
Comment stocker une fonction Python dans la valeur d'un dictionnaire (dict) et appeler la fonction en fonction de la clé
Comment limiter la publication de l'API dans la bibliothèque partagée en langage C de Linux
linux / c> lien> Obtenir le résultat de l'exécution de la commande shell dans le programme C> On m'a appris à utiliser popen ()
[Ubuntu] Comment supprimer tout le contenu du répertoire
Essayez d'obtenir la liste des fonctions du paquet Python> os
La valeur de meta lors de la spécification d'une fonction sans valeur de retour avec Dask dataframe s'applique
Comment appeler une fonction
Obtenir la valeur d'une clé spécifique jusqu'à l'index spécifié de la liste de dictionnaires en Python
[OCI] Script Python pour obtenir l'adresse IP d'une instance de calcul dans Cloud Shell
J'ai fait une fonction pour vérifier le modèle de DCGAN
Comment exécuter automatiquement la fonction d'exportation de GCP Datastore
Comment obtenir toutes les clés et valeurs du dictionnaire
Comment obtenir une liste d'exceptions intégrées pour python
Un résumé approximatif des différences entre Windows et Linux
Comment trouver le coefficient de mise à l'échelle d'une ondelette bipolaire
Attribuez une adresse locale de lien à Linux et utilisez DNS-SD / SSDP
Comment obtenir une liste de liens à partir d'une page de wikipedia