0
votes

Comment obtenir l'adresse de retour d'une fonction en C?

J'ai une fonction appelée:

doSomething()

La façon dont je comprends cela est la suivante: Dans l'assemblage, cela sautera à l'emplacement de la fonction et stockera l'adresse de retour de la fonction dans un registre afin qu'une fois la fonction terminée, le compteur de programme puisse revenir au programme principal.

Comment obtenir l'adresse de retour de cette fonction et la mettre dans une variable afin de pouvoir l'utiliser?

__builtin_return_address ne semble pas fonctionner. Quand je le traduis en assemblage, il ne sait pas quoi faire. Je crois que je ne peux pas utiliser GCC. Je n'utilise même pas printf car il ne fait pas partie de la bibliothèque C standard.

Actuellement, j'essaie de deviner quelle est son adresse de retour en mettant divers nombres dans cette variable.

c

7 commentaires

Le langage C ne définit pas les détails d'implémentation, tels que les adresses de retour, les piles et autres. Ce qu'il définit, c'est la sémantique (comportement) des constructions de langage. Je crains que vous ne puissiez pas obtenir l'adresse de retour sans utiliser l'assembly ou des éléments intrinsèques de bas niveau (et spécifiques au compilateur). À quoi souhaitez-vous utiliser l'adresse de retour? Peut-être existe-t-il une fonctionnalité C qui pourrait être utilisée pour obtenir ce que vous voulez.


"stocker l'adresse de retour de la fonction dans un registre" La plupart des implémentations vont stocker (pousser) l'adresse de retour dans la pile. L'instruction RET obtient alors (saute) l'adresse et y saute.


Que voulez-vous faire avec cette adresse? Notez qu'il n'existe que lorsque doSomething est en cours d'exécution, c'est-à-dire que si vous pouvez obtenir l'adresse de retour d'une fonction, vous ne pouvez l'obtenir que dans la fonction elle-même.


Vous voudrez peut-être regarder setjump() et longjump() dans '#include <setjump.h> `ce sont les moyens portables de revenir à autre chose que la fonction d'appel direct.


Il n'y a pas de solution C portable pour obtenir l'adresse de retour d'une fonction.


@solidwaterslayer: Vous avez raison: "Dans l'assemblage, cela passera à l'emplacement de la fonction". Et vous POUVEZ (effectivement) "mettre cette [adresse] dans une variable pour que je puisse l'utiliser". Il existe plusieurs façons d'y parvenir, notamment l' assemblage en ligne . J'ai suggéré des "pointeurs de fonction" ci-dessous pour paramétrer l'adresse de l'appelé. Utilisez setjmp pour paramétrer l'adresse de l' appelant . Q: Cela aide-t-il à répondre à votre question?


Je veux l'adresse de retour de doSomething () car plus tard je voudrais revenir à la même adresse de retour. Un peu comme, remonter le temps.


3 Réponses :


-2
votes

Pointeurs de fonction de support C et C ++:

C Exemple:

int sum (int num1, int num2) {
  return num1 + num2;
}

int (*f2p) (int, int);

int main (int argc, char (argv[]) {
    f2p = sum;
    printf ("sum=%d\n", f2p(10, 13));
    return 0;
}

En C ++, vous utiliseriez std :: function .

Voici un bon tutoriel:

https://www.learncpp.com/cpp-tutorial/78-function-pointers/

Vous n'avez PAS besoin de vous soucier de l'adresse mémoire binaire de la fonction pour utiliser les pointeurs de fonction. Si, pour une raison quelconque, vous vouliez ; il suffit de convertir l'adresse (par exemple "fp2" ci-dessus) en un nombre.


Je suggère des "pointeurs de fonction" pour paramétrer l'adresse de l'appelé.

Comme Persixty l'a suggéré, vous pouvez utiliser setjmp () / longjmp () pour paramétrer l'adresse de l' appelant .

Bien sûr, vous pouvez également utiliser l' assemblage en ligne pour accomplir l'un ou l'autre.

Q: Cela aide-t-il à répondre à votre question?


1 commentaires

Cela ne répond pas à la question.



5
votes

Avec gcc vous pouvez utiliser __builtin_return_address , voir https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html


0 commentaires

3
votes

Un autre utilisateur ici a posté sur l'utilisation de gcc avec lequel je suis d'accord, mais le stocker en tant que variable consiste simplement à utiliser un type de données void, un peu comme ceci:

void *addr = __builtin_extract_return_addr (__builtin_return_address (0));


0 commentaires