Argentum debugger v1

Debugger v0 supported breakpoints, call-stack inspection and stepping through the program. Version 1 added object inspection and watch expressions. Also it has special support for strings and limited support for arrays. This version is available in binary distribution.

1. Installation and configuration

Follow the steps in the updated post How to play with Argentum in VSCode

Two key steps to make debugger work are:

  1. Install the CodeLLDB VSCode extension.
  2. Update path in the "lldb.library" parameter in the config file argentum-demo/.vscode/settings.json.
    You need to make it the absolute path to the directory with your argentum demo:
{
    "lldb.displayFormat":       "auto",
    "lldb.showDisassembly":     "auto",
    "lldb.dereferencePointers": true,
    "lldb.consoleMode":         "commands",
    "lldb.library":             "C:/downloads/argentum-demo/bin/liblldb.dll"
}

2. Start the debug session:

Set breakpoints on the code of interest (F9) and hit (F5) to compile the current file in debug mode and run it with debugger.

Then the application stops on a break point, you can:

  1. Inspect variables of the current function.
  2. See the call stack and traverse the stack to inspect source lines and variables of these levels.
  3. Add/remove break points (F9).
  4. Step program by expressions (F10), F(11), (F5).

3. Variable panel structure

Variable names and location:

  • Local variables that are not used in the lambdas are shown as is.
  • If variable is accessed in the inner lambda, it is shown as a field of the current_closure structure.
  • If inside lambda having its own current_closure structure, the locals from the outer scope is visible with a parent field of its current_closure.
  • Otherwise outer scope is visible with closure structure.
  • Inside methods there is a this_ member that points to the current object. Sometimes it's a field of closure or current_closure structures.
  • Inside "?" "&&" operators there is a "_" variable that holds the value of the unwrapped optional operand.

Strings: For each string the debugger shows the leftover of the string that hasn't been read yet. So the first string character is the character to be returned on the next String.getCh() call.

Arrays: For each array debugger shows the real number of elements but the only first 20 elements. If nore elements are needed to inspect, use "Watch" panel.

Pointers: Currently pointers don't show the runtime types of the objects. It takes time and a lot of research to alter the way LLDB understands the runtime dynamic types. So, use cast operator in the "Watch" panel.

4. Try "Watch" panel

Here we can type-in the expressions that will be evaluated in each context. They have C++ syntax, not Argentum. So use

  • "->" instead of "."
  • "(className*) expr" instead of "expr ~ ClassName"

Watch panel supports

  • ,x suffix to make hexadecimal output,
  • ,c to convert numbers to characters

Example:

In this example we set a break point that set inside the lambda in file demo.ag:57:72 this is visible in the name of the current function in the "call_stack" panel.

This lambda uses the closure from its parent method that implements tick of interface gui_Actor for class demo_Flare. This method has local variable sc (it's the result of checkinging/locking the weak field scene in line 56.

Sc is a pointer to a "Scene object, that inherits from gui_Group and sys_Array as shown in the "Variables" panel. Also it shows that currently this scene array contains 1143 objects.

Let's inspect one of its object using "Watch" panel.

  • The expression "closure->parent->sc->items[3]" gives us 3rd scene item.
  • Expression "(ag_cls_demo_Sparkles*)*....." casts it to the required class and allows to inspect the object's fields.

That's it for now, though debugger has many directions for improvement, I'll postpone it for now and focus on implementing the multithreading.

Leave a Reply

Your email address will not be published. Required fields are marked *