Mago Debugger Inner Workings
Download
Report
Transcript Mago Debugger Inner Workings
An implementation overview
By Aldo Núñez
What is debugging?
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 a 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
Continue
Create or Attach
Break
Run
Break Event
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
Launch
Attach
• WaitForDebugEvent
• ContinueDebugEvent
• CreateProcess
• TerminateProcess
• DebugActiveProcess
• DebugActiveProcessStop
Registers
Memory
Threads
• GetThreadContext
• SetThreadContext
• ReadProcessMemory
• WriteProcessMemory
• 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 Mago?
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 Engine
Exec
Expr
Syms
Exec
• Control
debuggee
• Read and
change state
Expr
• Evaluate D
Expressions
• Formatting
Syms
• Read debug
info
DE
• Combine
other
components
• Expose AD7
interface
Execution Agent
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
SS Target
Thread
SS
SS event
A
A
Q
B
B
R
Hardware is set up to single step in this thread only.
When that SS is over,
hardware fires SS event for this thread only.
SS Target
Thread
run
BP event
A
A
Q
B
B
R
Force scoping BP to target thread by suspending all others.
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
Go/Resume
BP
XA IP
IP
SS=1
SS
BP
BP
Step In
BP
XA IP
SS
IP
SS=1
BP
BP
Step Over
BP
XA IP
BP
SS
IP
BP
XA
IP
SS=1
BP
BP
BP
BP
BP
BP
IP
BP
Debugger Thread
Dispatch Event
Debuggee
Main Thread
Command
Events
Run Command
Expression Evaluator
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
Process
Debug Info
Node Tree
chars
Scanner
tokens
Parser
Value Binder
Value
MakeTypeEnv( &typeEnv );
MakeNameTable( &nameTable );
ParseText( L”a[2] + 3”, typeEnv, nameTable,
&expr );
expr->Bind( options, binder );
expr->Evaluate( options, binder, &result );
Symbol Reader
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
DWARF
Fixed record fields
Numeric constant
compression
Common type encoding
Sorted symbols
Nested Lexical blocks
Flexible
Attributes: key-value
Explicit base type definition
Location expressions
Compression
Flatten tree
Abbreviations
Byte code for tables
Size
Spec
Actual
2
record length
12
2
record type
S_GDATA32
4
offset
0x00000310
2
segment
1
2
@type
0x1003
*
name
2
record length
18
2
record type
LF_ARRAY
2
@elemtype
T_INT4 (0x0074)
2
@idxtype
T_UINT4 (0x0075)
*
byte count
0x0010
*
name
1
9
a
IntArray1
Debug Engine
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
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( "<test>" );
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( "</test>" );
}
template Unary(T) {
void Unary( void function( T ) func ) {
foreach ( t; Vals!T.vals ) {
Id++;
writefln( " <verify id=\"%s_%d\">", Prefix, Id );
func( t );
writefln( " </verify>" );
}
}
}
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( " <bitnot>" );
CastTerm( t );
writeln( " </bitnot>" );
writeln( " <typedvalue>" );
PrintType!(typeof( ~t ))();
PrintTerm( ~t );
writeln( " </typedvalue>" );
}
void PrintType(X)() {
static if ( __traits( isArithmetic, X ) )
writefln( " <basictype name=\"%s\"/>", typeid( X ) );
else
writefln( " <reftype name=\"%s\"/>", typeid( X ) );
}
void CastTerm(X)( X x ) {
writeln( " <cast>" );
PrintType!X();
PrintTerm( x );
writeln( " </cast>" );
}
void PrintTerm(X)( X x ) {
static if ( is(X==creal) || is(X==cdouble) || is(X==cfloat) ) {
writeln( " <group>" );
writeln( "
<add>" );
writefln( "
<realvalue value=\"%a\"/>", x.re );
writefln( "
<realvalue value=\"%ai\"/>", x.im );
writeln( "
</add>" );
writeln( " </group>" );
}
else if ( is( X == ireal ) || is( X == idouble ) || is( X == ifloat ) ) {
writefln( " <realvalue value=\"%ai\"/>", x );
}
else if ( __traits( isFloating, X ) ) {
writefln( " <realvalue value=\"%a\"/>", x );
}
else if ( is( X == ulong ) || (is( X == long ) && (x < 0)) ) {
writefln( " <intvalue value=\"%dUL\"/>", x );
}
else
writefln( " <intvalue value=\"%d\"/>", 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: http://dsource.org/projects/mago_debugger
D: http://digitalmars.com/d/
Visual D IDE by Rainer Schuetze:
http://dsource.org/projects/visuald
Visual Studio Debugger Extensibility:
http://msdn.microsoft.com/enus/library/bb161718.aspx
x86 and x64 Manuals:
http://www.intel.com/products/processor/manuals/
DWARF Format: http://www.dwarfstd.org