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::Blocks333
eclipse: descent281
Poseidon201
Microsoft Visual Studio102
a standalone GUI debugger63
Eclipse (CDT is GDB-compatible)62
entice designer31
emacs28
vim28
D-IDE11
Kdevelop10
d should be a complete product like delphi9
7-segment displays8
DSciTe8
SciTE (not DSciTe)7
slickedit5
Netbeans4
softice4
jEdit3
LEDS3
skyide3
printf2
Anjuta-D-support1
AtWIrFRi1
ebkrhaNz1
fNBLjiDT1
geany1
JqmiWJzO1
mine1

Locations of visitors to this page

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]
-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

  • 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)