Skip to content

WDBG API

Oleg Shilo edited this page Jan 5, 2023 · 12 revisions

Architecture Overview

WDBG is a lightweight stack analyser that delivers a debugging experience with no external dependency. Thus it is not based on true debugging API available on arguably all operating systems, but on the AOP injection technique that modifies the script at runtime by embedding inspection routines in the appropriate places of the script.

This is the script that we want to debug:

using System;

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 3; i++)
        {
            Console.WriteLine($"Hello World! ({i})"); 
        }
    }
}

And this is how this script is modified at runtime by the Debug Info Injector (pseudo-code):

//css_inc C:\ProgramData\chocolatey\lib\cs-script\tools\-wdbg\dbg-runtime.cs
using System;

class Program
{
    static void Main(string[] args)
    { dbg_inspect();
        dbg_inspect();for (int i = 0; i < 3; i++)
        { dbg_inspect();
            dbg_inspect();Console.WriteLine($"Hello World! ({i})");
        dbg_inspect();}
    dbg_inspect();}
}

The dbg_inspect() is defined in dbg-runtime.cs. This routine is nothing else but a conditional wait-loop (pseudo-code):

dbg_inspect()
{
    if (current_line_has_breakpoint)
    {
        REST.send_local_variables_to_debugger_client();
        while (!resume_requested_by_user)
        {
            sleep_one_second();
        }
    }
}

The file dbg-runtime.cs is an implementation of the Debug Agent component. This component interacts with the Debugger Client via REST interface.

There are two distinct phases of debugging: debug preparation and the debugging session as in the diagram below.

image

All this is orchestrated by the -wdbg/-run.cs script. Thus when you execute css -wdbg script.cs the script engine interprets it as css -wdbg/-run.cs script.cs.

If you want to create your own debugger client then you should only provide a custom front-end for Debug Client. You can also reimplement the back end but you may also reuse the existing one. The rest of the architecture should stay unchanged.

Debugging REST interface

The REST server is running by default on localhost at port 5001. The REST API can be explored through swagger (https://localhost:5001/swagger)

GET: /dbg/breakpoints

Description:
Dbg Agent sends this request to Dbg Client to obtain breakpoints defined by the user.

Response:
a multiline text where each line is a single breakpoint info <file>:<line_number>.

Example:

D:\dev\Galos\cs-script\src\out\static_content\-wdbg\test\script.cs:8
D:\dev\Galos\cs-script\src\out\static_content\-wdbg\test\script.cs:10
D:\dev\Galos\cs-script\src\out\static_content\-wdbg\test\script.cs:14

GET: /dbg/userrequest

Description:
Dbg Agent sends this request to Dbg Client to obtain any pending user request for a debugging action.

Response:
Possible responses are:

  • step_over
    The user requested a "step over" action.
  • step_in
    The user requested a "step into" action.
  • resume
    The user requested a "resume execution" action.
  • evaluate:<expression>
    The user requested to evaluate an expression. The expression is either the name of the local variable or a C# code expression that dereferences public properties or fields. IE evaluate:Environment.TickCount, evaluate:this.Name
    When Dbg Agent receives this user request it evaluates the expression and posts the result with /dbg/expressions request.
  • serializeObject:<expression>
    The user requested to serialize an expression. It is similar to the expression evaluation in Immediate Window of Visual Studio.
    The expression format is the same as for evaluate:<expression> user request.
    When Dbg Agent receives this user request it evaluates the expression and posts the result with /dbg/object request.

POST: /dbg/break

Description:
Dbg Agent posts this request to Dbg Client in when it pauses on break point. The payload is defined in the format "{sourceFilePath}|{sourceLineNumber - 1}|{variables.ToJson()}"

<source_file_path>|<line_number>|<variables>. Where 'variables 'is a single-line JSON serialization of the list of values of anonymous type:

{
   string Name,  // 'expression' from `evaluate:<expression>` request
   string Value, // display value of the expression evaluation result
   string Type   // type of the value of the expression evaluation result
}

Example: D:\dev\Galos\cs-script\src\out\static_content\-wdbg\test\script.cs|8|[{"Name":"this","Value":"null","Type":"string"}] Response: not in use.

POST: /dbg/object

Description:
Dbg Agent posts this request to Dbg Client in response to the user request serializeObject:<expression>. The payload is defined in the format <expression>:<serialized_object_stringt>. The serialization technique is similar to the one that is used in Immediate Window of Visual Studio. Response: not in use.

POST: /dbg/expressions

Description:
Dbg Agent posts this request to Dbg Client in response to the user request evaluate:<expression>. The payload is a JSON serialized list of values of anonymous type:

{
   string Name,  // 'expression' from `evaluate:<expression>` request
   string Value, // display value of the expression evaluation result
   string Type   // type of the value of the expression evaluation result
}

Example:

[
   {
      "Name":"Environment.TickCount",
      "Value":"null",
      "Type":"string"
   },
   {
      "Name":"this",
      "Value":"null",
      "Type":"string"
   }
]

Response: not in use.