2017-05-31 69 views
6

Podczas debugowania ostatnio zauważyłem, że GDB ma możliwość oceny "złożonych" wyrażeń podczas debugowania programu i zastanawiam się, jak to robi. Na przykład za pomocą następującego kodu:W jaki sposób GDB ocenia wyrażenia C++ w czasie wykonywania

int main() { 
    std::vector<int> v = {1, 2, 3}; 
    int k = 0; 
    std::cin >> k; 
    v.push_back(k); 
    return v.at(0); 
} 

jestem w stanie skompilować program g++ -g myprogram.cpp i debugowanie w GDB, które pozwala mi wpisać takie rzeczy print v.at(4); (wyświetlającą prawidłową wartość po k dynamicznie weszła) i print v.at(2) == 3 co jest prawdziwe.

Zastanawiam się, jak GDB to robi. This SO question podpowiada, że ​​jest to coś "skompilowanego w pamięci", ale nie rozwija się dalej, więc zastanawiam się, czy używa on jakiegoś rodzaju JIT, aby to wszystko działało, czy coś innego? Czy kompilują kod podczas wpisywania go i uruchamiania? Czy mają one framework do oceny C++ w locie w kontekście debugowania? Zasadniczo chcę to powtórzyć w debuggerze, który piszę, aby ocenić wyrażenia w punktach przerwania, dlatego jestem ciekawy, jak GDB to robi.

+1

Nie jest dla mnie jasne, jaką odpowiedź masz nadzieję uzyskać. Gdb potrafi analizować wyrażenia C i C++ w kontekście debugowanego programu, korzystając z informacji debugowania zawartych w pliku binarnym, a także z wykorzystaniem kodu źródłowego, gdy jest on dostępny. Ale już to wiedziałeś, a szczegóły będą zbyt długie dla tego miejsca. –

+0

@JohnBollinger Pomyślałem, że będę musiał "użyć źródła", ale zastanawiam się, jak oceniają wyrażenia. Czy kompilują kod podczas wpisywania go i uruchamiania? Czy mają one framework do oceny C++ w locie w kontekście debugowania? Zasadniczo chcę to powtórzyć w debuggerze, który piszę, aby ocenić wyrażenia w punktach przerwania, dlatego jestem ciekawy, jak GDB to robi. Dzięki! – llk

+0

Twoje pytanie wydaje się być bardziej skoncentrowane na C++. Polecam usunąć tag C. – tambre

Odpowiedz

5

Krótka odpowiedź: Nie kompiluje kodu.

Długi Odpowiedź:

  1. wywołać polecenie print a procedura występuje w printcmd.c
  2. wywołuje ona evaluate_expression, określonym w eval.c, który ocenia wyrażenie przez odczyt pamięci docelowej i jej obliczenia wewnątrz gdb dla standardowych operatorów, w przeciwnym razie użyj call_function_by_hand.
  3. call_function_by_hand jest zdefiniowany w infcall.c. Po wywołaniu procedura zatrzymuje wykonywanie celu (czasami nie, więc możliwe jest awarie programu wielowątkowego z tą funkcją).
  4. Wprowadź kod programu do debugowania.
  5. Odzyskaj wynik, odczytując pamięć i, w razie potrzeby, wznów ją.

Możesz skoncentrować się na kodzie call_function_by_hand dla lepszego zrozumienia.

Uwaga: compile to inna sprawa niż print/call.

Kompletna Odpowiedź:

W kilka dni, może napisać szczegółową analizę jak GDB realizuje tę funkcję, do dalszego czytania.

6

co pozwala mi pisać rzeczy takie jak print v.at (4);

gdb może wywoływać funkcje skompilowane do pliku binarnego. Dokładnie to się dzieje tutaj. gdb dzwoni std::vector funkcja użytkownika at() i wyświetla wynik dla ciebie, patrz documentation.

Należy również pamiętać, że jest to możliwe, ponieważ w kodzie używany jest kod v.at(0). Jeśli usuniesz tę część kodu, v.at() nie zostanie utworzone i nie będzie dostępne w wynikowym pliku binarnym, aby gdb nie mógł go wywołać.

+0

A zatem GDB nie kompiluje niczego, a raczej uruchamia sekcje istniejącego kodu, aby ocenić wyrażenia? Czy istnieje biblioteka GDB do tego celu, czy też jest całkowicie zakodowana w niezależny sposób? – llk

+1

Tak, w podanym przykładzie. Ale może również kompilować i wstrzykiwać kod, zobacz https://sourceware.org/gdb/onlinedocs/gdb/Compiling-and-Injecting-Code.html#Compiling-and-Injecting-Code, chociaż nie korzystałem z tej funkcji. – ks1322