2012-08-29 10 views
6

Sto costruendo un progetto che costruisce più librerie condivise e file eseguibili. Tutti i file di origine utilizzati per creare questi file binari si trovano in una singola directory/src. Quindi non è ovvio capire quali file sorgente sono stati usati per costruire ciascuno dei binari (c'è una relazione molti-a-molti).Come trovare i file * .c e * .h che sono stati usati per creare un binario?

Il mio obiettivo è scrivere uno script che analizzi un set di file C per ogni file binario e si assicuri che vengano chiamate solo le funzioni giuste.

Un'opzione sembra essere quella di provare a estrarre queste informazioni da Makefile. Ma questo non funziona bene con i file e le intestazioni generati (a causa della dipendenza da Include).

Un'altra opzione potrebbe essere semplicemente sfogliare i grafici delle chiamate, ma ciò si complicherebbe, poiché molte funzioni vengono chiamate utilizzando i puntatori di funzione.

Altre idee?

+1

Solo per curiosità: perché ci provi? – stefan

+0

Il meccanismo del pacchetto di distribuzione conosce tutte le dipendenze ... –

+0

Hai una definizione precisa di cosa significa "le funzioni giuste sono chiamate"? Non è ovvio e non è semplice. –

risposta

6

È possibile innanzitutto compilare il progetto con informazioni di debug (gcc -g) e utilizzare objdump per ottenere quali file di origine sono stati inclusi.

objdump -W <some_compiled_binary> 

Il formato nano dovrebbe contenere le informazioni che stai cercando.

<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) 
    < c> DW_AT_producer : (indirect string, offset: 0x5f): GNU C 4.4.3 
    <10> DW_AT_language : 1 (ANSI C) 
    <11> DW_AT_name  : (indirect string, offset: 0x28): test_3.c  
    <15> DW_AT_comp_dir : (indirect string, offset: 0x36): /home/auselen/trials  
    <19> DW_AT_low_pc  : 0x82f0 
    <1d> DW_AT_high_pc  : 0x8408 
    <21> DW_AT_stmt_list : 0x0 

In questo esempio, ho compilato file oggetto da test_3, e si trovava in ... directory/prove. Quindi, ovviamente, è necessario scrivere degli script attorno a questo per raccogliere i nomi dei file di origine correlati.

2

Ecco un'idea, è necessario perfezionare in base alla build specifica. Crea una build, collegala usando lo script (ad esempio script log.txt make clean all). L'ultimo (o uno degli ultimi) passaggi dovrebbe essere il collegamento di file oggetto. (Suggerimento: cercare cc -o <your_binary_name>). Tale linea deve collegare tutti i file .o che dovrebbero avere i file .c corrispondenti nella struttura. Quindi avviare i file .c per tutti i file di intestazione inclusi.

Se si hanno nomi duplicati nei propri file .c nella struttura, sarà necessario esaminare il percorso completo nella riga del linker o lavorare da Makefile.

Ciò che Mahmood suggerisce di seguito dovrebbe funzionare anche. Se hai un'immagine con simboli, strings <debug_image> | grep <full_path_of_src_directory> dovrebbe darti un elenco di file C.

+0

Buona idea anche. Ma io non ho familiarità con i Makefile per GCC, ma io con VS e VS non mostrerò quel passo in molti dettagli che sarà semplice elencare i file della libreria con i quali stai collegando. –

2

Per prima cosa è necessario separare i simboli di debug dal file binario appena compilato. controlla questa domanda su come farlo: How to generate gcc debug symbol outside the build target?

Quindi puoi provare ad analizzare questo file da solo. So come farlo per Visual Studio ma siccome usi GCC, non sarò in grado di aiutarti ulteriormente.

+0

Anche questo dovrebbe funzionare! – jman

1

È possibile utilizzare lo strumento unix nm. Mostra tutti i simboli definiti nell'oggetto. Quindi è necessario:

  1. Run nm sul binario e afferrare tutti i simboli non definiti
  2. Run ldd sul binario per afferrare elenco di tutte le sue dipendenze dinamiche (file .so il tuo binario è legata a)
  3. eseguire nm su ogni file .so Youf trovato nel passaggio 2.

che vi darà l'elenco completo delle dinamiche simboli che l'utilizzo binario.

Esempio:

nm -C --dynamic /bin/ls 
....skipping..... 
00000000006186d0 A _edata 
0000000000618c70 A _end 
       U _exit 
0000000000410e34 T _fini 
0000000000401d88 T _init 
       U _obstack_begin 
       U _obstack_newchunk 
       U _setjmp 
       U abort 
       U acl_extended_file 
       U bindtextdomain 
       U calloc 
       U clock_gettime 
       U closedir 
       U dcgettext 
       U dirfd 

Tutti questi simboli con capitale "U" sono utilizzati da comando ls.

1

Se il tuo obiettivo è analizzare i file sorgente C, puoi farlo personalizzando il compilatore GCC. Potresti usare MELT per questo scopo (MELT è un linguaggio di dominio di alto livello per estendere GCC) - aggiungere i tuoi pass di analisi codificati in MELT all'interno di GCC-, ma dovresti prima conoscere le rappresentazioni interne di middle-end GCC (Gimple, Tree , ...).

La personalizzazione di GCC richiede diversi giorni di lavoro (principalmente perché gli interni GCC sono piuttosto complessi nei dettagli).

Sentitevi liberi di chiedermi di più su MELT.

Problemi correlati