2013-05-28 13 views
8

Zbudowałem frontend kierujący LLVM, który produkuje niektóre IR. Następnie i całkowicie oczekiwanie, wyjście IR jest nieprawidłowe w niektórych przypadkach (jak w, wydaje się poprawne, ale wynikowy program zawiesza się po uruchomieniu). Jednak nie znalazłem wielu przydatnych narzędzi do radzenia sobie z tym.Debugowanie LLVM IR

Próbowałem używać Lli, ale komunikat wyjściowy komunikatu o błędzie jest nieprzydatny (kiedy można założyć, że tłumacz może podać bardzo precyzyjne szczegóły błędu).

Szukałem konwersji kodu IR na C, a następnie debugowania tego w Visual Studio, ale wygląda na to, że ta funkcjonalność została usunięta z LLVM.

Zajrzałem również do zajmowania się GDB. Jednak format informacji debugowania DWARF jest dość specyficzny dla kilku istniejących języków, jak się wydaje, a ponadto źródło, które tłumaczę z moim frontendem jest poprawne, to wyprodukowane IR jest błędne, więc symbole debugowania dla oryginalnego źródła nie byłyby prawidłowe nie jest zbyt pomocny - na przykład musiałbym zobaczyć wartości szeregu pośrednich wartości rejestru, które nie odpowiadają żadnej zmiennej źródłowej lub punktowi przerwania w funkcjach generowanych przez kompilator.

Jakie narzędzia i techniki istnieją w celu debugowania wyjścia LLVM IR?

Odpowiedz

3

Nie jestem pewien, czy w pełni rozumiem Twój problem. Czy mówisz, że Twój kompilator (od języka X do LLVM IR) generuje niepoprawne wyjście (nieprawidłowe LLVM IR) i nie wiesz, jak to debugować? Innymi słowy, istnieją dwie możliwości:

  1. IR wytworzony przez twój kompilator jest niepoprawny - możesz wskazać na niektóre instrukcje i powiedzieć - nie to miałem zamiar wygenerować.
  2. Wartość IR wydaje się być poprawna, ale nie daje wyników, których oczekiwałam.

Zakładam, że (1) mówisz (bo to właśnie kwestia mówił, zanim go aktualizowany)

To nie byłoby LLVM-specyficzny problem, wtedy. Załóżmy, że piszesz kompilator od języka X do kodu natywnego. Wytworzony kod natywny jest niepoprawny - w jaki sposób debugujesz problem? Cóż, oczywiście debugujesz swój kompilator. Próbujesz znaleźć ostatnie miejsce, w którym rozumienie danych wejściowych przez kompilator było poprawne lub pierwsze miejsce, w którym stało się niepoprawne. Sposób, w jaki to robisz, zależy w dużym stopniu od architektury twojego kompilatora. Jednak bardzo pomocne jest drukowanie reprezentacji innych warstw pośrednich w kompilatorze.

Na przykład Clang (który wytwarza LLVM IR z C, C++ i Celu C) może zrzucić całą swoją AST. Patrząc na AST za niepoprawny kod, można przeciąć kompilator na pół, pomagając określić, czy problem dotyczy front-endu (źródło C -> AST) czy gen kodu (AST -> LLVM IR). Backend LLVM (kompiluje LLVM IR do kodu natywnego) ma również kilka warstw pośrednich (przede wszystkim SelectionDAG i MI), które mogą być badane ze względu na debugowanie. To tylko przykłady innych istniejących kompilatorów, YMMV z twoimi.

+1

Er, w rzeczywistości jest to # 2. Mogę teraz złapać # 1 bez zbytniego problemu. Program jest bardzo mały, wizualnie sprawdziłem większość części IR i wydaje się, że są one całkowicie poprawne, ale program następnie zawiesza się w czasie wykonywania. Sprawdziłem również, że program źródłowy jest poprawny. – Puppy

+0

@DeadMG: musisz zadać inne pytanie. "Oto mały fragment LLVM IR, który nie działa" i sprawdź, czy ktoś może pomóc. Poza tym, zakładam, że to zawiesza się z 'lli'? Czy próbowałeś skompilować go z 'llc' i zobaczyć, co wyjdzie? Czy jest to możliwe dzięki opcji "opt" z weryfikacją modułu? –

+0

'lli' rzeczywiście nie działa (oczywiście z niepomocnym komunikatem o błędzie). Skompilowałem z 'llc' i weryfikuję zarówno funkcje, jak i moduł jako całość. – Puppy

1

Will Diez opisał on realizowany że:
https://groups.google.com/d/msg/llvm-dev/O4Dj9FW1gtM/ovnm6dqoJJsJ

Cześć wszystkim

Dla moich własnych celów, napisałem podanie, że robi dokładnie to, czego wszyscy są opisujące: dodawać metadane debugowania do LLVM IR.

jako przepustkę, trzeba było rozwiązać problem „Ten plik musi istnieć na dysku gdzieś tak gdb można go znaleźć”, które rozwiązać mój dumping go na/tmp/gdzieś. Nie świetne rozwiązanie (kto je usuwa?), Ale działało wystarczająco dobrze.

Inną interesującą kwestią jest to, jak współistnieć z każdym istniejącym debug metadane, które mogą być przydatne do jednoczesnego debugowanie IR przekształcić inline ze źródła C w oprzyrządowaniu stylu przechodzi jak SAFECode, Asan/Tsan.

Krótki przykład:

(gdb) break main 
Breakpoint 1 at 0x4010b1: file 
/home/wdietz2/magic/test/unit/test_loop.c, line 9. 
(gdb) r 
Starting program: 
/home/wdietz2/llvm/32-obj-make/projects/magic/test/Output/test_loop 

Breakpoint 1, main (argc=<value optimized out>, argv=<value optimized 
out>) at /home/wdietz2/magic/test/unit/test_loop.c:9 
9   unsigned k = 0; 
Missing separate debuginfos, use: debuginfo-install 
glibc-2.12-1.80.el6_3.5.x86_64 libgcc-4.4.6-4.el6.x86_64 
libstdc++-4.4.6-4.el6.x86_64 
(gdb) n 
10  source(argc != 0, &k); 
(gdb) n 
14  %and.i.i.i.i104 = and i64 %4, 70368744177660 
(gdb) n 
15  %5 = load i8** @global, align 8 
(gdb) n 
18  store i32 16843009, i32* %6, align 1 
(gdb) n 
19  store i8 1, i8* getelementptr inbounds ([1 x i8]* @array, 
i64 0, i64 0), align 1 
(gdb) n 
20  call coldcc void @runtime_func() nounwind 
(gdb) n 
11  while(i-- > argc) 
(gdb) n 
23  %and.i.i.i.i85 = and i64 %7, 70368744177660 
(gdb) n 
14   while(j++ < i) k += j; 
(gdb) n 
11  while(i-- > argc) 
(gdb) n 
14   while(j++ < i) k += j; 
(gdb) n 
102  %77 = load i8** @global, align 8 
(gdb) n 
105  %79 = load i32* %78, align 4 
(gdb) n 
106  %cmp7.i.i.i = icmp ne i32 %79, 0 
(gdb) n 
108  call void @llvm.memset.p0i8.i64(i8* %add.ptr.i.i.i.i86, i8 
%conv8.i.i.i, i64 4, i32 1, i1 false) nounwind 
(gdb) n 
14   while(j++ < i) k += j; 
(gdb) n 
15   while(j-- > 0) k *= k + j; 
(gdb) n 
95  %69 = load i8** @global, align 8 
(gdb) n 
98  %71 = load i32* %70, align 4 
(gdb) 

Samo przejście jest dość prosta - trudno Problem rozwiązuje to emitujące IR na dysk i wnioskowania o co Instruction * jest jakiej linii, która naprawdę powinnam” t być problem, jeśli zrobione prawidłowo w LLVM. Na życzenie mogę oczywiście udostępnić kod na życzenie.

Krótko mówiąc, wydawało mi się, że działa dobrze dla mnie i że wykonanie tego poprawnie w samo w sobie LLVM byłoby wspaniałe!

Niestety, wygląda na to, że kod jest niedostępny.

Powiązane problemy