10

When debugging, I recently noticed that GDB has the ability to evaluate "complex" expressions while debugging a program, and I am wondering how it does this. For example, with the following code:

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

I am able to compile the program g++ -g myprogram.cpp and debug it in GDB which allows me to type things like print v.at(4); (which prints the correct value after k is dynamically entered) and print v.at(2) == 3 which evaluates to true.

I am wondering how GDB does this. This SO question hints that it is something "compiled in memory" but does not elaborate further, so I am wondering does it use some sort of JIT to make this all work or something else? Are they compiling the code inline as I type it and running it? Do they have a framework to evaluate C++ on the fly in the debugging context? In essence, I want to reproduce this in a debugger I am writing to evaluate expressions at breakpoints which is why I am curious how GDB does it.

llk
  • 2,501
  • 7
  • 36
  • 43
  • 1
    It's unclear to me what kind of answer you hope to get. Gdb is able to analyze C and C++ expressions in the context of the program being debugged, with the help of the debug information contained in the binary, and possibly also with use of the source code when that is available. But you already knew that, and details would be much to lengthy for this venue. – John Bollinger May 31 '17 at 13:45
  • @JohnBollinger I figured I would have to "use the source", but what I am wondering is how they are evaluating the expressions. Are they compiling the code inline as I type it and running it? Do they have a framework to evaluate C++ on the fly in the debugging context? In essence, I want to reproduce this in a debugger I am writing to evaluate expressions at breakpoints which is why I am curious how GDB does it. Thanks! – llk May 31 '17 at 13:50
  • Your question seems to be more C++ focused. I recommend you remove the C tag. – tambre May 31 '17 at 13:57
  • I've investigated a bit into GDB's source. Hope it will help you. – Keyu Gan May 31 '17 at 14:08

2 Answers2

12

Short Answer: It does not compile code.

Long Answer:

  1. You call print command and the procedure occurs in printcmd.c
  2. It calls evaluate_expression, defined in eval.c, which evaluates an expression by reading target memory and calculating it inside gdb for standard operators, otherwise use call_function_by_hand.
  3. call_function_by_hand is defined in infcall.c. When called, the procedure halts target execution (sometimes doesn't, so it is possible to crash a multithreaded program with this feature).
  4. Inject code into the program being debug.
  5. Retrieve the result by reading memory and unpause it if necessary.

You may focus on the code of call_function_by_hand for better understanding.

Note: compile is a different thing from print/call.

Keyu Gan
  • 711
  • 5
  • 17
  • Worth mentioning that GDB also has the `compile code` command, which can compile and inject code at runtime, see e.g.: https://stackoverflow.com/questions/5480868/how-to-call-assembly-in-gdb/31709579#31709579 – Ciro Santilli OurBigBook.com Dec 20 '19 at 17:15
10

which allows me to type things like print v.at(4);

gdb can call functions compiled into the binary. This is exactly what happens here. gdb calls std::vector member function at() and prints the result for you, see documentation.

Also note that this is possible because you are using v.at(0) in your code. If you remove this part of code, v.at() would not get instantiated and will not be available in the resulting binary so that gdb could not call it.

ks1322
  • 33,961
  • 14
  • 109
  • 164
  • So GDB does not compile anything, rather it runs sections of the existing code to evaluate the expressions? Is there a library GDB uses to do this or is it completely coded in a stand-alone manner? – llk May 31 '17 at 14:07
  • 1
    Yes, in the example you posted. But it also can compile and inject code, see https://sourceware.org/gdb/onlinedocs/gdb/Compiling-and-Injecting-Code.html#Compiling-and-Injecting-Code, though I have not used this feature. – ks1322 May 31 '17 at 14:34