2012-07-30 3 views
0

Je compile actuellement une pile de données achetée en C. J'utilise leur propre outil pour le compiler, en utilisant en arrière-plan gcc. Je peux passer des drapeaux et des paramètres à gcc comme bon me semble. Je veux savoir, à partir de quel fichier est le principal() utilisé. C'est-à-dire, dans le projet, quel fichier est le point de départ. Est-il possible de dire à gcc de générer une liste de fichiers, ou similaire, étant donné que je ne sais pas de quel fichier est le fichier main()? Je vous remercie.Rechercher le point de départ, int main()

+0

Il ne doit y avoir qu'un fichier contenant la fonction 'main', sinon vous obtiendrez une erreur de l'éditeur de liens. Où votre outil met cela que nous ne pouvons pas savoir si vous ne nous dites pas de quel outil il s'agit. –

+0

Btw c'est une très mauvaise idée d'essayer de déranger avec des détails non documentés comme celui-ci. –

+0

pourquoi pas: grep -rni "main". ? – JohnTortugo

Répondre

0

Vous compilez le projet avec des symboles de débogage, démarrez gdb avec l'exécutable, et écrire list main, suivi de « break » ou directement break main.

+2

'list main' ne montre même pas le nom de fichier que OP veut réellement. –

+0

Merci pour votre réponse. En effet, cela ne montre pas le fichier exact, mais montre les premières lignes de la main utilisée, avec cela je peux faire une recherche de texte normale sur le code source entier et trouver l'endroit d'insertion. Merci beaucoup pour votre réponse à nouveau. –

+0

Si vous voulez voir le numéro de ligne et le fichier, vous écrivez 'break main', ou vous faites 'break' après' list main', etc. Vous n'avez pas besoin de grep. – alinsoar

1

D'où main() est appelé est mise en œuvre dépendant - en utilisant GCC, il sera très probablement un fichier objet stub dans/usr/lib appelé crt0.o ou crt1.o à partir de laquelle il est appelé. (Ce fichier contient le symbole dépendant du système d'exploitation qui est automatiquement appelé par le noyau lorsque votre application est chargée en mémoire Sous Linux et Mac OS X, cela s'appelle start).

3

Vous pouvez désassembler l'exécutable final pour trouver le point de départ. Bien que vous n'ayez pas fourni d'informations supplémentaires pour vous aider davantage. J'utilise un exemple de code pour illustrer le processus.

#include <stdio.h> 

    int main() { 
      printf("hello world\n"); 
      return 0; 
    } 

maintenant l'objet main.o a ce qui suit ce

[[email protected] sf]# gcc -c main.c 
[[email protected] sf]# nm main.o 
0000000000000000 T main 
       U puts 

Vous pouvez voir principale n'est pas initialisé. Parce que cela va changer dans la phase de liaison. Maintenant, après la liaison:

$gcc main.o 
$nm a.out 
       U [email protected]@GLIBC_2.2.5 
0000000000600874 A _edata 
0000000000600888 A _end 
00000000004005b8 T _fini 
0000000000400390 T _init 
00000000004003e0 T _start 
000000000040040c t call_gmon_start 
0000000000600878 b completed.6347 
0000000000600870 W data_start 
0000000000600880 b dtor_idx.6349 
00000000004004a0 t frame_dummy 
00000000004004c4 T main 

Vous voyez que la principale a une adresse maintenant. Mais ce n'est toujours pas définitif. Parce que ce principal sera appelé par C runtime dynamiquement. vous pouvez voir qui fera la part de U [email protected]@GLIBC_2.2.5:

[[email protected] sf]# ldd a.out 
    linux-vdso.so.1 => (0x00007fff61de1000) /* the linux system call interface */ 
    libc.so.6 => /lib64/libc.so.6 (0x0000003c96000000) /* libc runime , this will invoke your main*/ 
    /lib64/ld-linux-x86-64.so.2 (0x0000003c95c00000) /* dynamic loader */ 

Maintenant, vous pouvez le vérifier en consultant le démontage:

00000000004003e0 <_start>: 
.......... 
4003fd: 48 c7 c7 c4 04 40 00 mov rdi,0x4004c4 /* address of start of main */ 
400404: e8 bf ff ff ff   call 4003c8 <[email protected]> /* this will set up the environment for main, like pushing argc and argv to stack */ 
........... 

Si vous n'avez pas la source avec vous, vous pouvez effectuer une recherche dans l'exécutable pour les références à libc_start_main ou main ou start pour voir comment votre fichier exécutable est initialisé et démarre le main.

Maintenant, tout cela est fait lorsque la liaison est faite avec le script de l'éditeur de liens par défaut. Beaucoup de gros projets utiliseront leur propre script d'éditeur de liens. Si votre projet a un script d'éditeur de liens personnalisé, la recherche du point de départ sera différente en fonction du script d'éditeur de liens utilisé. Il existe des projets qui n'utilisent pas glibc's runtime. Si votre binaire est stripped à partir de symboles, alors vous devez compter sur votre compétence d'assembleur pour trouver où il commence.

J'ai supposé que vous n'aviez pas la source, c'est-à-dire que la pile est distribuée avec quelques bibliothèques et certaines définitions d'en-tête seulement (une pratique courante des vendeurs de logiciels commerciaux). Mais si vous avez une source avec vous, c'est juste trop trivial. juste grep votre chemin à travers elle. Certaines réponses ont déjà souligné cela.

0

Vous pouvez utiliser objdump -t pour lister les symboles des fichiers objets. Donc, vous êtes sur Linux en supposant, et en supposant que les fichiers objets sont toujours là quelque part, vous pouvez le faire:

find -name '*.o' -print0 \ 
| xargs -0 objdump -t \ 
| awk '/\.o:/{f=$1} /\.text\.main/{print f, $6}' 

Cela affichera une liste des fichiers objets et les références à main qu'ils contiennent. Habituellement, il devrait y avoir une simple carte des fichiers objets aux fichiers source. S'il existe plusieurs fichiers objets contenant ce symbole, cela dépend de l'un de ceux qui sont réellement liés au binaire que vous regardez, car il ne peut y avoir plus d'un main par exécutable binaire (sauf peut-être pour un noir vraiment exotique la magie). Après que l'application est liée et que les symboles de débogage sont supprimés, il n'y a généralement aucune indication de quel fichier source une fonction spécifique est venue. L'exception à ceci sont les fichiers qui incluent les noms de fonctions en tant que littéraux de chaîne, par ex. en utilisant la macro __FILE__. Avant de supprimer les symboles de débogage, vous pouvez utiliser le débogueur pour obtenir ces informations. Si les symboles de débogage sont inclus, c'est.

Questions connexes