Ddbg - Win32 D Debugger

Home
Links
Roadmap
Download
Documentation
Issues & Bugs

Last update: 2008-06-29

Survey

What frontend would you like to use for D debugging on windows?

| Code::Blocks | 297
| eclipse: descent | 258
| Poseidon | 193
| Microsoft Visual Studio | 94
| Eclipse (CDT is GDB-compatible) | 61
| a standalone GUI debugger | 59
| entice designer | 29
| vim | 28
| emacs | 26
| d should be a complete product like delphi | 8
| DSciTe | 8
| 7-segment displays | 7
| SciTE (not DSciTe) | 7
| slickedit | 5
| softice | 4
| LEDS | 3
| Netbeans | 3
| skyide | 3
| jEdit | 2
| printf | 2
| Anjuta-D-support | 1
| geany | 1
| Kdevelop | 1
| mine | 1

# Win32 Debugger for the D Programming Language

## Documentation (Status: v0.11 beta)

- Introduction
- Using Ddbg from the command line
- Some hints
- Ddbg expressions
- Post-Mortem Debugging
- OutputDebugString interface
- Integrating Ddbg into Code::Blocks

### Introduction

Ddbg is a command-line tool with two CLIs. The main CLI is described below, the other is a GDB emulation mode. This mode is activated by the "-cli=gdb" command line option. The GDB emulation is only used as a compatibility hack to enable integration into GDB frontends like Code::Blocks.

Ddbg currently works with DMD for Windows only. Executables created with GDC are not supported, yet.

### Using Ddbg from the command line

The syntax to start Ddbg is:
ddbg [-cli=<mode>] [-cmd=<commands>] <exe file> [arguments]

-cli | Selects the CLI to use. Available CLIs are "gdb" and "ddbg" (default)
-cmd | execute a string of Ddbg commands separated by semicolons, e.g. ddbg -cmd="sp src; onex \"wmd ddbg.dmp; r\"; r" debuggee.exe
<exe file> | The name of the debuggee. If no extension is given, ".exe" is assumed.
[arguments] | Optional arguments that are passed to the debuggee.

In order to be able to debug a program it has to be compiled with DMD's "-g" switch.

This section describes the Ddbg CLI that is active by default.

#### Commands

Enter "?", "h" or "help" in Ddbg to get the list of supported commands:

                    Running
    -----------------------------------------------------------------------------
    in                                 step into at source level
    ov                                 step over at source level
    out                                step out at source level
    r                                  run/continue the program
                    Breakpoints
    -----------------------------------------------------------------------------
    bp [<file>:<line>[#<thrd>]] [ind]  set breakpoint #index at given file:line
                                       optionally only for the given thread id
                                       optionally with the given breakpoint index
    dbp [<file>:<line>|#index|*]       delete breakpoint by index, line or all
    lbp                                list breakpoints
    ltbp                               list temporary breakpoints
                    Stack/Memory/Registers
    -----------------------------------------------------------------------------
    dm <start> <length>                dump memory (start in hex, length in dec)
    dr [cpu] [fpu] [mmx] [sse]         dump registers [toggle register groups]
    ds                                 dump stack (last line is top)
    lsv                                list variables in current scope
    mi [free] [rsrv]                   memory information. lists blocks in state
                                       commit and optionally free and reserve
    us                                 unwind stack, prints full stacktrace
                    Expressions
    -----------------------------------------------------------------------------
    = <expr>                           evaluate expression
    ed <depth>                         set max depth of implicit evaluation of
                                       recursive structures
    el <length>                        set max number of array elements to print
    er                                 toggle between ed 0 and previous ed
    f <number>                         select frame for evaluation.
                                       default: current frame = 0
    t <expression>                     type of expression
                    Source
    -----------------------------------------------------------------------------
    jkf                                toggle whether to switch to stack frame of
                                       last known source location on exception
    lsm [substring]                    list source modules
    lsp                                list source search paths
    ps [count]                         print count lines of source before
                                       and after current location
    sp <path>                          add source search path
                    Disassembly
    -----------------------------------------------------------------------------
    da [start]                         disassemble from start
                                       (default = function start) to next ret
    dal [#lines]                       disassemble to/from +/- source lines
                    Threads
    -----------------------------------------------------------------------------
    lt                                 list threads
    st <threadId>                      select thread to be evaluation context
                    Minidumps
    -----------------------------------------------------------------------------
    rmd <file>                         read minidump from file
    wmd <file>                         write minidump to file
                    Miscellaneous
    -----------------------------------------------------------------------------
    arg <args>                         set command line arguments
    ii                                 print image information
    ldll                               list loaded DLLs
    lm [substring]                     list debug modules
    ld [substring]                     list data symbols
    lf [substring]                     list function symbols
    lg [substring]                     list global symbols
    lp [substring]                     list global publics
    ls [substring]                     list all symbols
    nc                                 toggle new console for process
    onex <cmd; cmd; ...>               on exception execute list of commands
    onterm <cmd; cmd; ...>             on termination execute list of commands
    q                                  quit debugger

    return repeats the last command

### Some hints

- Do not use absolute paths to set breakpoints. Use the 'lsm' command instead to list the relative paths of the source files saved in the executable. These paths can be used with 'bp'.
- If you want source lines to be printed (for breakpoints or disassembly) and the working directory is not the base path of the relative paths saved in the executable, you need to add the base path to the source search paths using 'sp'.
- Do not use stepping commands to start the debuggee. You have to use the "r" command or "Start" menu item in Code::Blocks first (will be fixed soon)
- To examine exceptions or asserts, run the program until Ddbg breaks with an Unhandled exception message, then issue the "us" command to show the stacktrace.
  Note that Code::Blocks will ask you whether it should display the stacktrace ("backtrace") in such a case. If you click "yes", the stacktrace window will appear, but it will not show the correct stacktrace. You will have to close and reopen the window to refresh the stacktrace.
- Use the "nc" command before starting the process (i.e. directly after starting Ddbg) to redirect the debuggee's console output to a new window
- If stepping through your code doesn't work, set breakpoints at the locations you want to step to instead (and report the problem)
- To display global variables, use expressions with it's full name (including packages), e.g. "mymodule.global_var"
- You can check
  Settings > Compiler and Debugger > Debugger settings > Display Debugger's log
  to enable the message tab "Debugger (debug)" (not the same as "Debugger") which displays almost all of the communication between Code::Blocks and Ddbg. There you may find more detailed information if you're experiencing any problems.
- "dr" remembers the selected register groups from last time.

### Ddbg expressions

Ddbg supports evaluation of versatile expressions in the debuggee's address space. The syntax is a subset of D's expressions (except for register access) and should be intuitive for every D programmer. Register names are prefixed by a # symbol, to distinguish them from symbol identifiers.

For static and dynamic arrays, Ddbg supports the "ptr" and "length" properties, for associative arrays the "length" property.

Evaluate an expression with the "=" command, print the type of an expression with the "t" command. By default, expressions are evaluated one level deep. That means that if the result of an expression is a non-scalar data structure (struct, class, arrays), the evaluation is stopped and "..." is printed instead. You can change the evaluation depth with the "ed" and "er" commands.
Usually it's fine to use depth 1, though, since that gives you a short listing of all scope variables ("lsv" command) and you can inspect variables deeper by issuing explicit "=" commands for single variables.

Here are some sample expressions:

    ->= somevariable

    ->= myclass.mymember

    ->= mystruct

    ->= args[0][3..12]

    ->= (cast(char[][char[]])assoc_array)["key"]

    ->= assoc_array.length

    ->= array.ptr

    ->= (cast(Vector!(float,3)[])vertices)[2 .. 23]

    ->= *cast(uint*)#eax

    ->= (cast(double[2])#xmm0)[0]

    ->= this.surface.vertices[this.surface.faces[7].a].x

    ->= *cast(Foo*)0x12ffc4

The exact syntax of Ddbg's expressions is:

    Expr        = Deref Cast DotChain
    Deref       = "*" Deref
                | epsilon
    DotChain    = Register
                | "(" Expr ")" RefExpr
                | Ident RefExpr
    RefExpr     = "." Ident RefExpr
                | "[" Args "]" RefExpr
                | epsilon
    Args        = Arg ".." Arg
                | Arg
    Arg         = Lit
                | Expr
    Register    = "#" NoWhiteSpace RegName
    RegName     = regexp("e[abcd]x|e[ds]i|e[bs]p|eip|efl")
                | regexp("[abcd]x|[ds]i|[bs]p|(cdefgs)s")
                | regexp("[abcd][hl]")
                | regexp("st[0-7]")
                | regexp("mm[0-7]")
                | regexp("xmm[0-7]")
    Cast        = "cast" "(" Type ")"
                | epsilon
    Type        = BaseType QuantList
    BaseType    = FQNIdent TplParams
    QuantList   = Quantifier QuantList
                | epsilon
    Quantifier  = "*"
                | "[" "]"
                | "[" Integer "]"
                | "[" Type "]"
    TplParams   = "!" "(" TplParam TplParams2 ")"
                | epsilon
    TplParams2  = "," TplParam TplParams2
                | epsilon
    TplParam    = Type
                | Lit
    Lit         = Sign Integer IntegerSuffix
                | regexp("\"(([^\"\\\\]*(\\\\(['\"\\?\\\\abfnrtv]|(x[0-9a-fA-F]{2})|(u[0-9a-fA-F]{4})|(U[0-9a-fA-F]{8})))?)*)\"")
                | regexp("'(([^'\\\\]|(\\\\(['\"\\?\\\\abfnrtv]|(x[0-9a-fA-F]{2})|(u[0-9a-fA-F]{4})|(U[0-9a-fA-F]{8})))))'")
    Ident       = regexp("[a-zA-Z_][_a-zA-Z0-9]*")
    FQNIdent    = regexp("[a-zA-Z_][_a-zA-Z0-9.]*")
    Integer     = regexp("0[xX][0-9a-fA-F_]+")
                | regexp("0[bB][01_]+")
                | regexp("0[0-7_]+")
                | regexp("0|([1-9][0-9_]*)")
    IntegerSuffix   = regexp("L[uU]|[uU]L")
                | "L"
                | regexp("[uU]")
                | epsilon
    Sign        = "-"
                | epsilon

### Post-mortem debugging

Ddbg supports Minidumps for post-mortem debugging. You can use the wmd command to write a minidump of the current state of the debuggee to a file. Later you can read that minidump with the rmd command. After reading a minidump, Ddbg is in post-mortem mode. In that mode you can browse the data from the minidump, but cannot execute the debuggee. Therefore, some commands are not available in post-mortem mode.

Ddbg uses the DBGHELP API to support minidumps. It is available on every Windows XP Installation. For other Windows versions, the Platform SDK must be installed.

To run a debuggee such that it automatically creates a minidump file when it crashes, use the following command line:

    ddbg -cmd="onex \"wmd ddbg.dmp; q\"; onterm \"q\"; r" debuggee.exe

To browse the minidump, you can start ddbg as usual:

    ddbg debuggee.exe

and issue an rmd command to load the minidump file

    ->rmd ddbg.dmp

If the minidump was saved after an exception occured, you will now recieve the exception's message again. Minidumps can be created at anytime, though. Therefore you can also examine problems that do not necessarily throw an exception.

### OutputDebugString interface

You can issue commands to Ddbg from within your debuggee by calling the OutputDebugString function from the Win32 API. To mark a debug string as a Ddbg command sequence, it has to be prefixed with "Ddbg:".

The following call triggers writing of a minidump and continues the debuggee afterwards:

    import win32.winbase;
    // ...
    OutputDebugStringA(toStringz("Ddbg: wmd problem1.dmp; r"));

### Integrating Ddbg into Code::Blocks

- Get the latest nightly build (2007-03-19 or newer is required)
- make sure ddbg.exe is in your path, so that ddbg_gdb.bat will find it
- In Code::Blocks "Settings > Compiler and debugger > Digital Mars D Compiler" choose "Toolchain executables" and set "Debugger" to the ddbg_gdb.bat
- Make sure compiler and linker get the "-g" flag (see also this thread)