An implementation overview By Aldo Núñez
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
Run/Attach Control Inspect Why? Find out the cause of a problem (bug)
Kick off a process Attach to an already running process
Breakpoints Stepping Changing instruction pointer Suspend and resume threads
Callstack Loaded modules Threads Memory Registers Variables Expressions
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
A process that runs, controls, and inspects another process Special relationship between debugger and debuggee System notifies debugger of events taking place in debuggee
OS Debug events Break/Run mode Change state HW Single Step Breakpoints Registers
Loop event ← WaitForDebugEvent( timeout ) if got event ContinueDebugEvent( event.pid,event.tid, DISCARD_EXCEPTION ) Until event.code = EXIT_PROCESS
Start Process Exit Process Start Thread Exit Thread Load Module Unload Module Exception Message
Debug Events WaitForDebugEvent ContinueDebugEvent Launch CreateProcess TerminateProcess Attach DebugActiveProcess DebugActiveProcessStop Registers GetThreadContext SetThreadContext Memory ReadProcessMemory WriteProcessMemory Threads SuspendThread ResumeThread
Enable SS GetThreadContext context.Eflags or 0x100 SetThreadContext ContinueDebugEvent SS Event event ← WaitForEvent event.code = EXCEPTION event.exception.code = EXCEPTION_SINGLE_STEP
Enable BP ReadProcessMemory WriteProcessMemory data = 0xCC (int 3) FlushInstructionCache ContinueDebugEvent BP Event event ← WaitForEvent event.code = EXCEPTION event.exception.code = EXCEPTION_BREAKPOINT Except. address = original EIP = original + 1
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
A debugger for D programs A set of independent libraries A Visual Studio plug-in
Interest in debuggers since 2005 Started September 2009 Source code released August 2010 Integrated into Visual D September 2010
Benefits to making separate components Targeted testing Mix and match for different purposes Use with any shell program Benefits to making VS plug-in Well tested shell program already written High level debug programming model
Debug EngineExecExprSyms
Exec Control debuggee Read and change state Expr Evaluate D Expressions Formatting Syms Read debug info DE Combine other components Expose AD7 interface
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
Abstracts run, control, and inspection services Built first to make it as solid as possible Many APIs are locked to thread that started debuggee Because of underlying Windows API
WaitForEvent, Continue from event Launch, Terminate Attach, Detach Read, Write Memory Set, Remove Breakpoint Step, Cancel Step Async Break
Software breakpoint abstraction Hardware breakpoint abstraction Breakpoint sharing Resuming from breakpoint
Stepping over a single instruction Can easily step over most instructions with native single step (SS) Others require setting a BP after the instruction REP string instructions
State machines for complex stepping In, Over, Out, Go/Resume Instruction, Statement Control low-level SS and BP Receive notification of SS and BP events Can be canceled
Instruction steppers handle 18 scenarios 3x Instruction type: (simple, call, REP) 2x At a BP 3x Movement: (Go, Step In, Step Over) Range stepper uses instruction steppers over an address range Step Out stepper runs to a BP at return address
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
Evaluates D expressions Input is textual expression Output is a result value record Declarations, symbols, and input values come from outside IValueBinder, IDeclaration Handles formatting values Enumerates children of values Based on DMD front end
MakeTypeEnv( &typeEnv ); MakeNameTable( &nameTable ); ParseText( L”a[2] + 3”, typeEnv, nameTable, &expr ); expr->Bind( options, binder ); expr->Evaluate( options, binder, &result );
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
Reads debug info for a program Maps of source files to lines Maps of source code lines to addresses Functions – address and scopes Symbols – name, type, value, storage Types Reads specific formats Currently, CodeView 4.10, output by DMD
CODEVIEW Fixed record fields Numeric constant compression Common type encoding Sorted symbols Nested Lexical blocks DWARF Flexible Attributes: key-value Explicit base type definition Location expressions Compression Flatten tree Abbreviations Byte code for tables
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
A plug-in to the VS Debugger package (vsdebug.dll) Standalone DLL doesn’t depend on any other package Expected to implement AD7 interface Knows how to debug one kind of program DEs are multiplexed during a debug session
A programming model for debugging processes Single-threaded calls from VS Debugger to DE Simplifies design COM interfaces Debug Engine is a COM co-class
IDebugEngine2 IDebugThread2 IDebugBoundBreakpoint2 IDebugExpression2 IDebugStackFrame2 IDebugDisassemblyStream2 IDebugEvent2
What is debugging? What is a debugger? What is Mago? Execution Agent Expression Evaluator Symbol Reader Debug Engine D and the debugger
Rewrite in D eventually Only EE and parts of DE know about D EE Test input generated by D program Expression and expected value Uses compile-time reflection
void main( string[] args ) { writeln( " " ); if ( set == 1 ) UnaryList!(byte, ubyte, short, ushort, int, uint, long, ulong).Operation( op ); else if ( set == 2 ) UnaryList!(float, double, real, ifloat, idouble, ireal, cfloat, cdouble, creal).Operation( op ); writeln( " " ); } template Unary(T) { void Unary( void function( T ) func ) { foreach ( t; Vals!T.vals ) { Id++; writefln( " ", Prefix, Id ); func( t ); writefln( " " ); } template UnaryList(T...) { void Operation( Op op ) { foreach ( t; T ) { switch ( op ) { case Op.Negate: Unary!(t)(&UnOp!(t).Negate); break; case Op.BitNot: static if (__traits( compiles, Unary!(t)( &UnOp!(t).BitNot ))) Unary!(t)( &UnOp!(t).BitNot ); break; } template Vals(T) { static T[] vals; static this() { static if ( !__traits( isFloating, T ) ) // Add values like T.max, cast(T) -1, cast(T) 0 else // Add values like T.nan, -T.infinity, cast(T) 0 }
template UnOp(T) { static if ( __traits( isIntegral, T ) ) void BitNot( T t ) { writeln( " " ); CastTerm( t ); writeln( " " ); PrintType!(typeof( ~t ))(); PrintTerm( ~t ); writeln( " " ); } void PrintType(X)() { static if ( __traits( isArithmetic, X ) ) writefln( " ", typeid( X ) ); else writefln( " ", typeid( X ) ); } void CastTerm(X)( X x ) { writeln( " " ); PrintType!X(); PrintTerm( x ); writeln( " " ); } void PrintTerm(X)( X x ) { static if ( is(X==creal) || is(X==cdouble) || is(X==cfloat) ) { writeln( " " ); writefln( " ", x.re ); writefln( " ", x.im ); writeln( " " ); } else if ( is( X == ireal ) || is( X == idouble ) || is( X == ifloat ) ) { writefln( " ", x ); } else if ( __traits( isFloating, X ) ) { writefln( " ", x ); } else if ( is( X == ulong ) || (is( X == long ) && (x < 0)) ) { writefln( " ", x ); } else writefln( " ", x ); }
Interface for sharing between modules Take DMD front end or mimic it 80-bit floating point in expression eval Disassembling variable length instructions
Mago: D: Visual D IDE by Rainer Schuetze: Visual Studio Debugger Extensibility: us/library/bb aspx us/library/bb aspx x86 and x64 Manuals: DWARF Format: