2015-08-13 21 views
6

Vorrei passare attraverso alcuni codici IR LLVM che ho generato. Il codice è sintatticamente e tipo valido per quanto riguarda l'LLC e il Lli, ma i risultati non sono quelli che mi aspettavo.Esiste un debugger per LLVM IR?

I blocchi sono abbastanza grandi da non avere avuto successo nella semplice lettura del bug e ho difficoltà a produrre un esempio più piccolo con lo stesso bug.

Ho pensato che avrei potuto usare qualcosa come un debugger, ma per LLVM IR. In altre parole, voglio essere in grado di scorrere il codice llvm, esaminare i registri "infiniti" (dati i nomi nel file IR LLVM) e le posizioni di memoria, impostare i punti di interruzione, fino a trovare il punto in cui il mio codice è andato storto.

Ho esaminato lli e lldb, ma nessuno dei due sembra essere lo strumento che sto cercando. lli eseguirà il mio codice ma non mi consentirà di andare passo dopo passo. lldb sembra presupporre che il codice sia stato generato dai front-end C.

Mi sbaglio su lldb e lli? Qualcuno sa di uno strumento che fa anche il 50% di quello che voglio?

+1

Come indovinare: è possibile eseguire il debug di 'lli' e osservare come interpreta ogni istruzione. Dovresti fare un po 'di hacking per impostare un breakpoint, però. – arrowd

risposta

2

Non sono a conoscenza di una cosa del genere (ho il sospetto che non esista). Sebbene condividerò volentieri i miei punti su llvm ha prodotto il debug del codice.

  1. Eseguire il debug del codice generato stesso (eseguirlo in gdb).
  2. Utilizzare l'intrinseco debugtrap (che genera semplicemente int3 o qualsiasi equivalente nella propria architettura). Puoi fare asserzioni con questa cosa e vedere quale di esse fallisce.
  3. Dare i nomi istruzioni (in modo che non sono %0, %1 ma significativo %names) - appaiono come commenti in llc uscita.
  4. Costruire una CFG (grafo di controllo) per la funzione: opt --dot-cfg 1.ll; dot cfg.funcname.dot -Tpng > 1.png
  5. Non dimenticare di disattivare le ottimizzazioni LLVM (si può avere livello di ottimizzazione backend -O3, ma IR trasformazione passa può rendere più difficile per il debug).

Quindi il flusso di lavoro che sto suggerendo è il seguente. Costruisci un CFG (4.) e un assembly (tramite llc). Passa al codice generato in gdb e passa attraverso di esso (o lascia che si intrappoli su una delle tue asserzioni). Correla il punto in cui ti sei fermato in output da gdb a llc, leggi il commento, corolla al CFG. Grok.

È inoltre possibile creare la rappresentazione CFG dal codice generato. Degli strumenti che conosco IDA Pro (un modo molto costoso per costruire CFG) e Saga offrono tale funzionalità.

P.S .: Inizialmente era un commento, ma è diventato troppo lungo.

1

Sto cercando la stessa cosa, e ho trovato questo: Debugging JIT-ed Code With GDB.

1) compilare con clangore ed emettono bytecode

clang++ -emit-llvm -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DDEBUG -O0 -m64 -fomit-frame-pointer -c a.cpp -g -fno-use-cxa-atexit 
clang++ -emit-llvm -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DDEBUG -O0 -m64 -fomit-frame-pointer -c b.cpp -g -fno-use-cxa-atexit 

2) legame con LLVM-link

llvm-link -o all.bc a.bc b.bc 

3) debug con gdb e lli, utilizzando JIT

gdb --quiet --args lli -jit-kind=mcjit all.bc 


(gdb) b initCloneLookups 
Function "initCloneLookups" not defined. 
Make breakpoint pending on future shared library load? (y or [n]) y 
Breakpoint 1 (initCloneLookups) pending. 

(gdb) r 
Starting program: lli -jit-kind=mcjit all.bc 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 
...... 


Breakpoint 1, initCloneLookups() at a.cpp:66 
66    clone_lookups = new BitBoard64[61]; 

Rispondi 'y' al punto di interruzione impostato.