Documentation (Status: v0.11 beta)

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]
-cliSelects the CLI to use. Available CLIs are "gdb" and "ddbg" (default)
-cmdexecute 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

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