7
votes

Trouver l'adresse du code du programme au moment de l'exécution?

Lorsque j'utilise GDB pour déboguer un programme écrit en C, la commande Démontage indique les codes et leurs adresses dans la segmentation de la mémoire de code. Est-il possible de connaître ces adresses de mémoire à l'exécution? J'utilise Ubuntu OS. Merci.

[modifier] Pour être plus précis, je vais le démontrer avec l'exemple suivant. P>

#include <stdio.h>

int main(int argc,char *argv[]){
    myfunction();
    exit(0);
}

c

3 commentaires

Vous posez des questions sur un désassembleur de temps d'exécution intégré dans votre programme?


Que voulez-vous vraiment?


Merci à tous. J'ai une bonne compréhension de cette affaire: D


4 Réponses :


5
votes

Pour obtenir une backtrage, utilisez exécufo.h code> comme documenté dans le manuel GNU LIBC .

Par exemple: P>

./a(trace_pom+0xc9)[0x80487fd]
./a(DepositMoney+0x11)[0x8048862]
./a(TransferFunds+0x11)[0x8048885]
./a(DepositMoney+0x21)[0x8048872]
./a(TransferFunds+0x11)[0x8048885]
./a(DepositMoney+0x21)[0x8048872]
./a(TransferFunds+0x11)[0x8048885]
./a(DepositMoney+0x21)[0x8048872]
./a(main+0x1d)[0x80488a4]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7e16775]
./a[0x80486a1]


2 commentaires

Existe-t-il une manière que je puisse extraire l'adresse de la fonction de dépôtMoney uniquement, les significations 0x8048872 devraient être la seule sortie au lieu d'imprimer tout le backtrage?


Ah, désolé, je pensais que tu voulais une arrière-marche complète.



16
votes

La réponse ci-dessus est considérablement surchargée. Si la référence de fonction est statique, comme c'est-à-dire ci-dessus, l'adresse est simplement la valeur du nom de symbole dans le contexte du pointeur: xxx

Si vous saisissez la fonction de manière dynamique d'une bibliothèque partagée, Ensuite, la valeur renvoyée de DLSYM () (POSIX) ou GETProCaddress () (Windows) est également l'adresse de la fonction.

Notez que le code ci-dessus risque de générer un avertissement avec certains compilateurs, comme ISO C techniquement interdit l'affectation entre le code et les pointeurs de données (certaines architectures les placent dans des espaces d'adresse physiquement distincts).

et certains pédants soulignent que l'adresse renvoyée n'est pas vraiment garantie Pour être l'adresse de la mémoire de la fonction, il s'agit simplement d'une valeur unique pouvant être comparée à l'égalité avec d'autres pointeurs et actes de fonction, lorsqu'il est appelé, pour transférer le contrôle de la fonction dont il contient le pointeur. Évidemment, tous les compilateurs connus implémentent cela avec une adresse cible de branche.

et enfin, notez que "l'adresse" d'une fonction est un peu ambiguë. Si la fonction a été chargée de manière dynamique ou est une référence externe à un symbole exporté, ce que vous obtenez vraiment, c'est généralement un pointeur à un code de fixuption dans la "PLT" (un terme UNIX / ELF, bien que le mécanisme PE / COFF sur Windows soit similaire ) qui saute ensuite sur la fonction.


3 commentaires

Merci beaucoup pour votre réponse fantastique. Puis-je poser cette question à l'avance: que diriez-vous d'obtenir l'adresse d'une ligne de code spécifique?


Pas de chance là-bas. Les compilateurs sont libres de réaménager et d'optimiser le code, il n'ya donc pas une seule région de mémoire qui correspond à une ligne ou à une expression donnée. Les debuggers peuvent faire un travail assez raisonnable de reconstruire cela à partir de la table des symboles et de déboguer des informations dans l'exécutable, mais malheureusement, vous entrez dans un vaudou profond que je ne sais pas hors main.


Belle réponse, bien expliquée. Vous pouvez également contourner le fait que la conversion entre le code et les pointeurs de données n'est pas définie, en appliquant cette astuce (comme dans "homme dlsym" dans la direction inverse): vide p; * (void (* ) ()) & p = (void (*) ()) et mysculation; ou en utilisant un syndicat.



8
votes

Si vous connaissez le nom de la fonction avant exécutions du programme, utilisez simplement

#include <bfd.h>
#include <stdio.h>
#include <stdlib.h>
#include <type.h>
#include <string.h>

long find_symbol(char *filename, char *symname)
{
    bfd *ibfd;
    asymbol **symtab;
    long nsize, nsyms, i;
    symbol_info syminfo;
    char **matching;

    bfd_init();
    ibfd = bfd_openr(filename, NULL);

    if (ibfd == NULL) {
        printf("bfd_openr error\n");
    }

    if (!bfd_check_format_matches(ibfd, bfd_object, &matching)) {
        printf("format_matches\n");
    }

    nsize = bfd_get_symtab_upper_bound (ibfd);
    symtab = malloc(nsize);
    nsyms = bfd_canonicalize_symtab(ibfd, symtab);

    for (i = 0; i < nsyms; i++) {
        if (strcmp(symtab[i]->name, symname) == 0) {
            bfd_symbol_info(symtab[i], &syminfo);
            return (long) syminfo.value;
        }
    }

    bfd_close(ibfd);
    printf("cannot find symbol\n");
}


2 commentaires

Merci, c'est ce que je cherchais


Désolé pour la nécromancement; Cependant, j'ai trouvé cela vraiment utile. Connaissez-vous un tutoriel pour vous aider avec BFD?



3
votes

À propos d'un commentaire dans une réponse (obtenir l'adresse d'une instruction), vous pouvez utiliser ce truc très laid xxx

il devrait être env [12] (l'EIP), mais être Attention car il a l'air de la machine dépendante, alors triple vérifie mon mot. Ceci est la sortie xxx

amusez-vous!


0 commentaires