Luaexts¶
Overview¶
Luaexts is an extension for Windbg (and the other dbgeng-based debuggers) that provides access to the dbgeng COM API from Lua. It also implements a lightweight framework for writing extensions in Lua.
Project source: | https://bitbucket.org/kbhutchinson/luaexts/ |
Project documentation: | https://luaexts.readthedocs.io/ |
Getting started¶
Download luaexts-x86.zip and/or luaexts-x64.zip, depending on your debugger’s bitness, and unpack into your .extpath.
Within Windbg, run the following command:
.load luaexts
To verify that the extension loaded correctly, run the following command:
!lua say('success')
The growing list of supported dbgeng API functions can be accessed through the global table dbgeng. The table is split up into sub-tables matching the organization of the dbgeng API itself. So the functions from the IDebugSymbols interface (as well as IDebugSymbols2, etc) can be found in the dbgeng.symbols table.
As an example, here’s how to call the IDebugSymbols::GetSymbolTypeId function, use the return values to call the IDebugSymbols::GetTypeName function, and then print the type name of a variable named foo that exists in the current scope:
!lua local module, typeid = dbgeng.symbols.get_symbol_type_id( 'foo' ) say( dbgeng.symbols.get_type_name( module, typeid ) )
or without the temporary variables:
!lua say( dbgeng.symbols.get_type_name( dbgeng.symbols.get_symbol_type_id( 'foo' ) ) )
Small side note: A global function called say()
is available that takes the place of Lua’s normal print()
function: it prints whatever is given to it and appends a newline. The print()
function has been overridden to output without a newline.
Building¶
The dbgeng headers and libs, required to build luaexts, are not included in this repository because I’m unsure of their redistribution license. So to build luaexts, you’ll need to do the following:
Clone the luaexts repository.
Retrieve the dbgeng headers and libs.
- Once you have Windbg installed, the headers can be found in
<install-dir>\Debuggers\inc
and the libs in<install-dir>\Debuggers\lib
. Copy the headers toluaexts\inc
and the libs to the appropriate platform directory underluaexts\lib
.
- Once you have Windbg installed, the headers can be found in
Build
luaexts.sln
with Visual Studio.Binaries will be placed in directories under
luaexts\bin
.
Remember that after building locally, in addition to luaexts.dll, you also need the contents of luaexts\src\luaexts\lua copied to your Windbg extension path, next to the DLL or in a luaexts
directory next to the DLL.
General usage¶
Using the facilities provided by luaexts is usually done at the debugger’s command prompt by entering extension commands, or by writing Lua scripts and running them. This section will discuss the commands that drive these interactions.
The !lua
command¶
The primary interface point for using luaexts is the !lua
command, which consumes the rest of
the command line as a chunk of Lua code, and simply runs it. Quotation marks surrounding the Lua
code are not required, as the dbgeng command parser will automatically consume all text until the
next semicolon, which is the debugger’s command-separation marker. If a semicolon is needed within
the Lua code itself, then enclosing quotation marks are required, to prevent the dbgeng command
parser from interpreting the chunk as multiple dbgeng commands. Fortunately, semicolons as
statement-termination markers are optional in Lua syntax, so they are needed very rarely.
Each !lua
command runs as a separate Lua chunk. This means that variables declared as local
will be in scope only during the execution of one command. Variables assigned to, but not declared
as local
, will become global variables, available across all subsequent chunks run by luaexts.
This can be useful, but care must be taken, because the memory being used by data structures that
are pointed to by global variables cannot be freed by the Lua garbage collector as long as they are
alive. Assigning nil
to a global variable will remove the reference to the data the variable was
pointing to, at which point the data will become a candidate for garbage collection.
Lua’s print()
function, which normally outputs to stdout, has been replaced by a function that
directs output to the debugger command window. Another slight change is that usually Lua’s
print()
will append a newline, but the print()
provided by luaexts does not append a
newline, in order to provide more control over exact text output. Instead a global say()
function exists that automatically appends a newline.
As an example, here’s how to call the IDebugSymbols::GetSymbolTypeId function, use the return values to call the IDebugSymbols::GetTypeName function, and then print the type name of a variable named foo that exists in the current scope:
!lua local module, typeid = dbgeng.symbols.get_symbol_type_id( 'foo' ) say( dbgeng.symbols.get_type_name( module, typeid ) )
Running scripts: dofile()
¶
Although the !lua
command provides the full expressiveness of Lua, it can be tedious to compose
complicated code chunks at the debugger command line. We can take advantage of built-in Lua
functionality to ease the pain. Lua provides a dofile()
function that takes a file path, loads
the file as a Lua code chunk, and runs it. Like the scoping of !lua
chunks, variables declared
as local
within the file will be scoped to the file’s chunk, while variables assigned to but not
declared local
will become global and available to any subsequent chunks run by luaexts.
Developing a script file can then be easily done by opening the file in your favorite text editor,
making changes, and then running !lua dofile('path\to\script.lua')
from the debugger command
line to test each change. (Protip: In Windbg, the previous command can be retrieved from the command
history by pressing the Up arrow key when keyboard focus is in the command line input field.)
Running registered commands: !luacmd
¶
Extensions written for luaexts can expose their functionality in two ways. First, they can simply
provide named functions to call, either globally scoped or within namespace tables. Second,
extensions can register commands that can then be run using the !luacmd
command.
Registered commands are functions that take advantage of the debugger engine’s built-in command line parser to automatically parse and tokenize a user-entered debugger command into arguments for the function.
As an example, imagine that an extension would like to expose a function for adding two numbers and
printing the result with a label. The simplest way to call such a function using the !lua
command would be like so:
!lua add_and_print( 'three', 2, 1 )
With an appropriate registered command, it could be run like this:
!luacmd add_and_print three 2 1
Although at first glance that might not appear very helpful, it has a couple of benefits. One is that the debugger engine’s command line parser has a fair amount of intelligence, and can perform tasks like automatic expression parsing and evaluation, as well as string tokenization for one-word strings so they can be given without requiring quotation marks.
The other main benefit is that registered commands can be used with user-named debugger aliases. Aliases work by replacing aliased text with substitute text. However, aliases cannot take arguments to insert into the substitute text; it is a simple, straightforward replacement. Since most Lua function calls require a closing parenthesis at the end, it would be impossible to define an alias that can be given just the three function arguments and expand into the first code example above. The best that could be done would be:
as !ap !lua add_and_print(
which would need to be called as:
!ap 'three', 2, 1 )
As !luacmd
does not use a closing parenthesis, a suitable alias for an appropriate registered
command could be defined easily like this:
as !ap !luacmd add_and_print
and then called like this:
!ap three 2 1
As with standard dbgeng extensions, luaexts registered commands can be run in unqualified if there is no ambiguity in the command name, or can be run fully qualified leading with the extension name to resolve ambiguity:
!luacmd add_and_print three 2 1
!luacmd some_ext.add_and_print three 2 1
Finding registered commands: !luahelp
¶
luaexts provides a help mechanism similar to the help mechanism for standard dbgeng extensions.
Executing the !luahelp
command with no arguments will list all registered commands along with a
brief description of the command. The !luahelp
command can also be given a registered command
name, either qualified or unqualified, to display more detailed help for the given command.
Resetting luaexts: !reinitialize
¶
The !reinitialize
command will reset the internal Lua virtual machine, wiping out all global
variables and freeing memory allocated by Lua. It will then reinitialize the extension’s
configuration by rereading the configuration files and reloading all designated Lua extensions.
This command can be very helpful while implementing a Lua extension, to reset luaexts to a pristine state, or simply to reload functions to test changes.
API¶
The luaexts API is divided into two categories: 1) the exposed dbgeng COM API; and 2) the additional
API that luaexts provides, sometimes as higher level constructs on top of the dbgeng API like
cppobj
, and sometimes as Lua-extension scaffolding like register_extension().
luaexts¶
Global functions¶
Most of the API provided by luaexts is scoped within an appropriately named global table. However, there are a number of global functions that are accessible without prefixing.
-
print
(anything) → nil¶ Takes any number of arguments of any type, converts them to strings, and outputs those strings to the debugger’s output window with no other formatting.
-
dml_print
(anything) → nil¶ Similar to
print()
, but outputs using debugger markup language (DML).
cppobj¶
cppobj provides a high level interface for working with C++ objects. The goal is to allow intuitive manipulation of those objects through familiar syntax.
For example, here’s how to wrap an object named foo from the current scope, and print the value of its bar data member:
local foo = cppobj.new( 'foo' )
print( foo.bar )
Lua’s metatable feature is used to overload the indexing operation performed by foo.bar
, in
order to return a new cppobj for the bar data member, which is then stringified. Stringification
is overloaded to return a dbgeng “view” of an object, i.e., the same string that the dbgeng COM API
would return when asked to return an object as text. A native Lua value can be retrieved for
fundamental types by using cppobj.value()
.
Due to this overloading of the indexing operation, and the fact that object methods in Lua are also implemented by overloading indexing, most of the functions that operate on cppobj objects are instead implemented as class functions that simply take the cppobj as a paramater.
Class Functions¶
Class functions are accessible through the global cppobj table. Many of them operate on a cppobj, and return information about the wrapped C++ object.
-
cppobj.
new
(expr) → cppobj¶ Creates a new cppobj, representing a C++ symbol.
Parameters: expr (string) – C++ expression that evaluates to a symbol Returns: New cppobj representing the given symbol
-
cppobj.
is_cppobj
(value) → boolean¶ Checks whether the given Lua value is a cppobj.
Parameters: value – Lua value to check Returns: True if value is a cppobj, otherwise false
-
cppobj.
value
(obj) → Lua value¶ For fundamental types (
cppobj.kind()
returns “base”, “enum”, or “pointer”), returns an object’s value as an appropriately typed Lua value.For array types, (
cppobj.kind()
returns “array), returns the memory offset of the array.For other types, returns
nil
.Parameters: obj (cppobj) – Object whose value to return
-
cppobj.
kind
(obj) → string¶ Returns the “kind” of a C++ object. The kind will be one of the following values:
base
: Fundamental type likebool
,char
,int
,float
, etcenum
: Enum valuepointer
array
class
: Class instancefunction
unknown
: Some other, unrecognized kind
Parameters: obj (cppobj) – Object whose kind to return
-
cppobj.
type
(obj) → string¶ Returns an object’s type.
Parameters: obj (cppobj) – Object whose type to return
-
cppobj.
name
(obj) → string¶ Returns an object’s name, usually the variable or field name.
Parameters: obj (cppobj) – Object whose name to return
-
cppobj.
long_name
(obj) → string¶ Returns an object’s “long” name, which is a fully qualified expression that is valid for the current scope.
Parameters: obj (cppobj) – Object whose long name to return
-
cppobj.
offset
(obj) → integer¶ Returns an object’s memory offset in the debugging target’s memory.
Parameters: obj (cppobj) – Object whose offset to return
-
cppobj.
size
(obj) → integer¶ Returns an object’s size.
Parameters: obj (cppobj) – Object whose size to return
-
cppobj.
type_id
(obj) → integer¶ Returns an object’s type id. This id is used in various dbgeng COM API functions.
Parameters: obj (cppobj) – Object whose type id to return
-
cppobj.
type_module
(obj) → integer¶ Returns the base memory offset of the module that the object’s type is from. This is effectively an id for the module, and is used in various dbgeng COM API functions.
Parameters: obj (cppobj) – Object whose module to return
-
cppobj.
address_of
(obj) → cppobj¶ Returns a new cppobj representing a pointer to obj.
Parameters: obj (cppobj) – Object to create a pointer to
-
cppobj.
dereference
(obj) → cppobj¶ Given a cppobj representing a pointer, returns a new cppobj representing the pointee.
Parameters: obj (cppobj) – Object to dereference
Overloaded Operators¶
Overloaded operators comprise the remainder of the interactions with and between cppobj objects.
-
cppobj.
__index
(name) → cppobj¶ The indexing operator (
.
or[]
) is overloaded to return a new cppobj representing a data member of the cppobj being indexed.Assuming foo is a formerly created cppobj, the following retrieves its bar data member as a cppobj:
local bar = foo.bar -- equivalent: local bar = foo[ 'bar' ]
-
cppobj.
__eq
(cppobj) → boolean¶ The equality operator (
==
) is overloaded to test C++ objects for equality, according to the following rules:- arrays are treated as pointers
- pointers, base, and enum types are compared as numbers
- class types are considered equal if two objects represent the same type at the same memory offset
If the first operand is a cppobj, any other equality result will be false.
-
cppobj.
__sub
(cppobj) → number¶
-
cppobj.
__sub
(number) → cppobj or number The subtraction operator (
-
) is overloaded to perform subtraction with C++ objects, according to the following rules:- if the 1st operand is a cppobj pointer or array, and the 2nd operand is:
- cppobj pointer or array of the same type
- result is the scaled distance between the two memory locations, scaled by the object size
- cppobj base integral type
- result is a new pointer, offset by the given scaled distance
- Lua integer
- result is a new pointer, offset by the given scaled distance
- cppobj pointer or array of the same type
- if the 1st operand is a cppobj base type or enum, and the 2nd operand is:
- cppobj base type or enum or Lua number; result is the difference of the two operands
- if the 1st operand is a Lua value, and the 2nd operand is:
- cppobj base type or enum or Lua number; result is the difference of the two operands
- otherwise, the result is
nil
- if the 1st operand is a cppobj pointer or array, and the 2nd operand is:
dbgeng¶
The dbgeng COM API is divided into several categories of COM objects, each relating to a specific set of functionality. The provided Lua functions are intended to be a thin facade over the actual COM functions, and so are patterned very closely after them.
Global data¶
-
dbgeng.
ANY_ID
¶ Used with functions that take an id number to let the engine choose the id.
-
dbgeng.
hr
¶ Table containing HRESULT codes, with string names as keys and their corresponding numeric values. Contains at least the following keys:
S_OK
S_FALSE
E_FAIL
E_INVALIDARG
E_NOINTERFACE
E_OUTOFMEMORY
E_UNEXPECTED
E_NOTIMPL
ERROR_ACCESS_DENIED
: numeric value is the evaluation ofHRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)
The dbgeng COM API is painstakingly implemented as functions that return HRESULT values, using out parameters to return values that are not suited to a simple HRESULT. The Lua functions that wrap the COM functions try to return sensible Lua values when they can, but when the underlying COM function returns an HRESULT that is not considered a success value, they almost always fall back to returning three values:
nil
- a string value matching one of the HRESULT keys above
- the corresponding numeric HRESULT value
Those return values should make it easy to determine which specific HRESULT was returned by comparing the strings directly or by comparing with the value of that key in the table.
For example, when calling
dbgeng.symbolgroup.expand_symbol()
, if the symbol cannot be expanded because it is already at the maximum expansion depth, the function will returnnil
,'E_INVALIDARG'
, and theE_INVALIDARG
numeric value. So complete error handling can be done as follows:local expanded, hrstr, hrnum = sg:expand_symbol( index, true ) if expanded then -- success elseif expanded == false then -- no children elseif hrstr == 'E_INVALIDARG' then -- already at max expansion elseif hrnum == dbgeng.hr.E_INVALIDARG then -- same as above elseif clause elseif hrnum == dbgeng.hr.E_OUTOFMEMORY then -- memory allocation failed ... -- etc, more error handling end
See HRESULT Values for common HRESULT return values and their usual meanings.
-
dbgeng.
outctl
¶ Table containing values that are used to control output. The values should be combined into a bitfield.
The lower bits of the bitfield must be exactly one of the following values:
THIS_CLIENT
: Output generated by methods called by this client will be sent only to this client’s output callbacks.ALL_CLIENTS
: Output will be sent to all clients.ALL_OTHER_CLIENTS
: Output will be sent to all clients (except to the client that generated the output).IGNORE
: Output will be discarded immediately and will not be logged or sent to callbacks.LOG_ONLY
: Output will be logged but not sent to callbacks.
The higher bits of the bitfield may contain a combination of zero or more of the following values:
NOT_LOGGED
: Do not put output from this client in the global log file.OVERRIDE_MASK
: Sends output to clients regardless of whether the client’s output mask allows it.DML
: For output that supports Debugger Markup Language (DML), sends the output in DML format.
As an alternative to creating a custom output control bitfield value, you can use one of the following values:
AMBIENT_DML
: Sets the new output control to the same value as the current output control and specifies that the output will be in DML format.AMBIENT_TEXT
: Sets the new output control to the same value as the current output control and specifies that the output will be in text format.AMBIENT
: Same asAMBIENT_TEXT
.
See DEBUG_OUTCTL_XXX.
dbgeng.control¶
The control functions are all accessible from the global dbgeng.control table, and represent the functions from the IDebugControl interfaces of the dbgeng COM API.
Functions¶
-
dbgeng.control.
add_assembly_options
(options) → boolean¶ Turns on some of the assembly and disassembly options. The given options will be added to the existing options. See AddAssemblyOptions.
Parameters: options (integer) – bitfield, combining values from the asmopt
tableReturns: true if successful
-
dbgeng.control.
add_breakpoint
(type, id) → dbgeng.breakpoint¶ Adds a breakpoint. type can be one of the values from the
dbgeng.breakpoint.type
table. See AddBreakpoint.Parameters: - type (dbgeng.breakpoint.type) – breakpoint type, from the
dbgeng.breakpoint.type
table - id (integer) – breakpoint id to use; use
dbgeng.ANY_ID
to have the engine assign the id
Return type: - type (dbgeng.breakpoint.type) – breakpoint type, from the
-
dbgeng.control.
add_engine_options
(options) → boolean¶ Turns on some of the debugger engine’s options, by combining the given bitfield with the existing options using bitwise OR. Possible bitflag values can be found in the
engopt
table. See AddEngineOptions.Parameters: options (integer) – bitfield, combining values from the engopt
tableReturns: true if successful
-
dbgeng.control.
add_extension
(path) → integer¶ Loads an extension library into the debugger engine. If the extension library is already loaded, simply returns the handle, the library will not be loaded again. See AddExtension.
Parameters: path (string) – fully qualified path to the extension library to load Returns: handle to the loaded library
-
dbgeng.control.
call_extension
(handle, function, argstr) → boolean¶ Calls an extension library function. See CallExtension.
Parameters: - handle (integer) – handle to the extension library, returned by
add_extension()
; if set to 0, the engine will walk the extension library chain search for the function - function (string) – name of the extension function to call
- argstr (string) – parsed into arguments by the extension as if typed at the command prompt
Returns: true if called successfully
- handle (integer) – handle to the extension library, returned by
-
dbgeng.control.
disassemble
(offset, flags) → string, integer¶ Disassembles a processor instruction in the target’s memory. See Disassemble.
Parameters: - offset (integer) – location in the target’s memory of the instruction to disassemble
- flags (integer) – bitfield of flags that affect the behavior of the function; currently the
only flag that can be set is
dbgeng.control.disasm_flag.EFFECTIVE_ADDRESS
, which will instruct the engine to computer and display the effective address from the current register information
Returns: two values, the first being the disassembled instruction as a string, and the second being the memory location of the following instruction
-
dbgeng.control.
execute
(outctl, command, flags) → boolean¶ Executes the specified debugger commands, as if typed at the command prompt. See Execute.
Parameters: - outctl (integer) – bitfield, combining values from the
dbgeng.outctl
table - command (string) – command string to execute, may contain multiple commands
- flags (integer) – bitfield, combining values from the
execute_flag
table
- outctl (integer) – bitfield, combining values from the
-
dbgeng.control.
get_assembly_options
() → integer¶ Returns the assembly and disassembly options that affect how the debugger engine assembles and disassembles processor instructions for the target. See GetAssemblyOptions.
Returns: bitfield containing a combination of values from the asmopt
table
-
dbgeng.control.
get_breakpoint_by_id
(id) → breakpoint¶ Returns the
dbgeng.breakpoint
with the specified breakpoint id. See GetBreakpointById.If a breakpoint with the given id is not found, belongs to another process, or is private, returns
nil
.Parameters: id (integer) – id of the breakpoint to return Return type: dbgeng.breakpoint
-
dbgeng.control.
get_breakpoint_by_index
(index) → breakpoint¶ Returns the breakpoint at the specified index. See GetBreakpointByIndex.
If a breakpoint with the given index is not found or is private, returns
nil
.Parameters: index (integer) – zero-based index of the breakpoint to return, ranging from 0 to the number of defined breakpoints; this is specific to the current process Return type: dbgeng.breakpoint
-
dbgeng.control.
get_code_level
() → integer¶ Returns the current code level and is mainly used when stepping through code. See GetCodeLevel.
Returns: one of the values from the level
table
-
dbgeng.control.
get_engine_options
() → integer¶ Returns the current engine options. See GetEngineOptions.
Returns: bitfield containing the engine options, which is a combination of the values in the engopt
table
-
dbgeng.control.
get_expression_syntax
() → integer¶ Returns the current syntax that the engine is using for evaluating expressions. See GetExpressionSyntax.
Returns: one of the values from the expr
table
-
dbgeng.control.
get_expression_syntax_names
(index) → string, string¶ Returns the full and abbreviated names of an expression syntax. See GetExpressionSyntaxNames.
Parameters: index (integer) – index of the expression syntax, which should be between zero and the number returned by get_number_expression_syntaxes()
minus one.Returns: two values, the first being the abbreviated name of the expression syntax, and the second being the full name
-
dbgeng.control.
get_interrupt
() → boolean¶ Checks whether a user interrupt was issued. If a user interrupt was issued, it’s cleared when this function is called. Examples of user interrupts include pressing Ctrl+C or pressing the Stop button in a debugger. Calling :func:
.set_interrupt
also causes a user interrupt. See GetInterrupt.Returns: true if an interrupt has been requested, otherwise false
-
dbgeng.control.
get_number_expression_syntaxes
() → integer¶ Returns the number of expression syntaxes that are supported by the engine. See GetNumberExpressionSyntaxes.
Returns: number of supported syntaxes
-
dbgeng.control.
get_stack_trace
(frmoff, stkoff, instoff, numframes) → array of stack frame data¶ Returns the frames at the top of the specified call stack. See GetStackTrace.
Parameters: - frmoff (integer) – memory offset of the stack frame at the top of the stack; if zero, the current frame pointer is used
- stkoff (integer) – memory offset of the current stack; if zero, the current stack pointer is used
- instoff (integer) – memory offset of the instruction of interest for the function at the top of the stack; if zero, the current instruction pointer is used
- numframes (integer) – number of frames to retrieve
Returns: array of tables representing the requested stack frames, each of which contains the following fields:
instruction_offset
: memory offset of the related instruction for the stack frame; typically, the return address for the next stack frame, or the current instruction pointer if the frame is at the top of the stackreturn_offset
: memory offset of the return address for the stack frame; typically, the related instruction for the previous stack frameframe_offset
: memory offset of the stack frame, if knownstack_offset
: memory offset of the processor stackfunc_table_entry
: memory offset of the function entry point for this frame, if availableparams
: array containing the first four stack slots passed to the function, if availablevirtual
: boolean, set to true if this stack frame was generated by the debugger during unwinding; set to false if it was formed from a thread’s current contextframe_number
: index of the frame from the top of the stack, which has index 0
-
dbgeng.control.
is_pointer_64bit
() → boolean¶ See IsPointer64Bit.
Returns: true if the effective processor uses 64-bit pointers, otherwise false
-
dbgeng.control.
output_disassembly_lines
(outctl, previous_lines, total_lines, offset, flags) → table of memory location data¶ Disassembles several processor instructions and sends the resulting assembly instructions to the output callbacks. See OutputDisassemblyLines.
Parameters: - outctl (integer) – combination of flags from
dbgeng.outctl
that control output - previous_lines (integer) – number of lines of instructions before offset to include in the output
- total_lines (integer) – number of lines of instructions to include in the output
- offset (integer) – memory location to disassemble, along with surrounding instructions depending on other arguments
- flags (integer) – bitfield, combining values from the
disasm_flag
table
Returns: table containing the following fields:
offset_line
: line number in the output that contains the instruction at offsetstart_offset
: memory location of the first instruction included in the outputend_offset
: memory location of the instruction after the last disassembled instructionline_offsets
: array that contains the memory location of each instruction included in the output; if the output for an instruction spans multiple lines, the array element corresponding to the first line of output will contain the address of the instruction
New in version 1.1.0.
- outctl (integer) – combination of flags from
-
dbgeng.control.
remove_assembly_options
(options) → boolean¶ Turns off some of the assembly and disassembly options. The given options will be removed from the existing options. See RemoveAssemblyOptions.
Parameters: options (integer) – bitfield, combining values from the asmopt
tableReturns: true if successful
-
dbgeng.control.
remove_breakpoint
(bp) → boolean¶ Removes the given breakpoint. See RemoveBreakpoint.
Parameters: bp (breakpoint) – breakpoint to remove Returns: true if breakpoint was successfully removed
-
dbgeng.control.
remove_engine_options
(options) → boolean¶ Turns off some of the debugger engine’s options, by combining the complement of the given bitfield with the existing options using bitwise AND. Possible bitflag values can be found in the
engopt
table. See RemoveEngineOptions.Parameters: options (integer) – bitfield, combining values from the engopt
tableReturns: true if successful
-
dbgeng.control.
remove_extension
(handle) → boolean¶ Unloads an extension library. See RemoveExtension.
Parameters: handle (integer) – handle of the extension to unload, returned from add_extension()
Returns: true if successful
-
dbgeng.control.
set_assembly_options
(options) → boolean¶ Changes the assembly and disassembly options. The given options will completely replace the existing options. See SetAssemblyOptions.
Parameters: options (integer) – bitfield, combining values from the asmopt
tableReturns: true if successful
-
dbgeng.control.
set_code_level
(level) → boolean¶ Sets the current code level and is mainly used when stepping through code. See SetCodeLevel.
Parameters: level (integer) – one of the values from the level
tableReturns: true if successful
-
dbgeng.control.
set_engine_options
(options) → boolean¶ Changes the debugger engine’s options, completely replacing the existing options. Possible bitflag values can be found in the
engopt
table. See SetEngineOptions.Parameters: options (integer) – bitfield, combining values from the engopt
tableReturns: true if successful
-
dbgeng.control.
set_expression_syntax
(syntax) → boolean¶ Sets the syntax that the engine will use to evaluate expressions. See SetExpressionSyntax.
Parameters: syntax (integer) – one of the values from the expr
tableReturns: true if successful
-
dbgeng.control.
set_expression_syntax_by_name
(syntax) → boolean¶ Sets the syntax that the engine will use to evaluate expressions, by syntax name. See SetExpressionSyntaxByName.
Parameters: syntax (string) – one of the following values:
"MASM"
: expressions will be evaluated according to MASM syntax"CPLUSPLUS"
: expressions will be evaluated according to C++ syntax
Returns: true if successful
-
dbgeng.control.
set_interrupt
(flags) → boolean¶ Registers a user interrupt or breaks into the debugger. See SetInterrupt.
Parameters: flags (integer) – one of the values from the interrupt
tableReturns: true if successful
Other¶
-
dbgeng.control.
asmopt
¶ Table containing assembly and disassembly options that affect how the debugger engine assembles and disassembles processor instructions for the target. Contains the following values, which are intended to be combined in a bitfield:
VERBOSE
: When set, additional information is included in the disassemblyNO_CODE_BYTES
: When set, the raw bytes for an instruction are not included in the disassemblyIGNORE_OUTPUT_WIDTH
: When set, the debugger ignores the width of the output display when formatting instructions during dissameblySOURCE_LINE_NUMBER
: When set, each line of dissembly output is prefixed with the line number of the source code provided by symbol information
See DEBUG_ASMOPT_XXX.
-
dbgeng.control.
disasm_flag
¶ Table containing options controlled some disassembly functions. Contains the following values, which are intended to be combined in a bitfield:
EFFECTIVE_ADDRESS
: Compute the effective address from the current register information.MATCHING_SYMBOLS
: If the address of the instruction has an exact symbol match, output the symbol.SOURCE_LINE_NUMBER
: Include the source line number of the instruction in the output.SOURCE_FILE_NAME
: Include the source file name in the output.
See the table in the documentation for OutputDisassembly.
-
dbgeng.control.
engopt
¶ Table containing global options that affect the behavior of the debugger engine. Contains the following values, which are intended to be combined in a bitfield:
IGNORE_DBGHELP_VERSION
: The debugger engine generates a warning instead of an error if the version of the DbgHelp DLL does not match the version of the debugger engine.IGNORE_EXTENSION_VERSIONS
: Disable version checking for extensions.ALLOW_NETWORK_PATHS
: Network shares can be used for loading symbols and extensions. This option cannot be set if DISALLOW_NETWORK_PATHS is set.DISALLOW_NETWORK_PATHS
: Network shares cannot be used for loading symbols and extensions. This option cannot be set if ALLOW_NETWORK_PATHS is set.NETWORK_PATHS
: Bitwise OR of ALLOW_NETWORK_PATHS and DISALLOW_NETWORK_PATHS.IGNORE_LOADER_EXCEPTIONS
: Ignore expected first-chance exceptions that are generated by the loader in certain versions of Windows.INITIAL_BREAK
: Break into the debugger at the target’s initial event.INITIAL_MODULE_BREAK
: Break into the debugger when the target loads its first module.FINAL_BREAK
: Break into the debugger at the target’s final event. In a live user-mode target, this is when the process exits. It has no effect in kernel mode.NO_EXECUTE_REPEAT
: When given an empty command, the debugger engine does not repeat the last command.FAIL_INCOMPLETE_INFORMATION
: Prevent the debugger from loading modules whose images cannot be mapped.ALLOW_READ_ONLY_BREAKPOINTS
: Allow the debugger engine to manipulate page protections on the target to allow for setting software breakpoints in a read-only section of memory.SYNCHRONIZE_BREAKPOINTS
: In live user-mode debugging, the engine performs extra work when inserting and removing breakpoints to ensure that all threads in the target have a consistent breakpoint state at all times.DISALLOW_SHELL_COMMANDS
: Disallow executing shell commands through the debugger. After this option has been set, it cannot be unset.KD_QUIET_MODE
: Turn on quiet mode. For more info see the documentation for thesq
command.DISABLE_MANAGED_SUPPORT
: Disables debugger engine support for managed code. If support for managed code is already in use, this option has no effect.DISABLE_MODULE_SYMBOL_LOAD
: The debugger does not load symbols for modules that are loaded while this flag is set.DISABLE_EXECUTION_COMMANDS
: Prevents any commands that would cause the target to begin executing.DISALLOW_IMAGE_FILE_MAPPING
: Disallows mapping of image files from disk.PREFER_DML
: The debugger runs DML-enhanced versions of commands and operations by default.DISABLESQM
: Disables upload of Software Quality Metrics (SQM) data.DISABLE_STEPLINES_OPTIONS
See DEBUG_ENGOPT_XXX.
-
dbgeng.control.
execute_flag
¶ Table containing options that control the operation of
execute()
. Contains the following values:ECHO
: The command string is sent to the output.NOT_LOGGED
: The command string is not logged. This is overridden byECHO
.NO_REPEAT
: If command is an empty string, do not repeat the last command, and do not save the current command string for repeat execution later.
See the table in the documentation for Execute.
-
dbgeng.control.
expr
¶ Table containing values that represent possible expression evaluation syntaxes. Contains the following values:
MASM
: Expressions will be evaluated according to MASM syntax.CPLUSPLUS
: Expressions will be evaluated according to C++ syntax.
See the table in the documentation for GetExpressionSyntax.
-
dbgeng.control.
interrupt
¶ Table containing values that control the operation of
set_interrupt()
. Contains the following values:ACTIVE
: If the target is running, the engine will request a break into the debugger. This request might time out. Otherwise, when the target is suspended, the engine will register a user interrupt.PASSIVE
: The engine will register a user interrupt.EXIT
: See documentation on MSDN.
See table in the documentation for SetInterrupt.
-
dbgeng.control.
level
¶ Table containing values that represent possible code stepping levels. Contains the following values:
SOURCE
: When stepping through code on the target, the size of a single step will be a line of source code.ASSEMBLY
: When stepping through code on the target, the size of a single step will be a single processor instruction.
See the table in the documentation for GetCodeLevel.
dbgeng.symbols¶
The symbols functions are accessible from the global dbgeng.symbols table, and represent the functions from the IDebugSymbols interfaces of the dbgeng COM API.
Functions¶
-
dbgeng.symbols.
create_symbol_group
() → dbgeng.symbolgroup¶ Creates a new symbol group. See CreateSymbolGroup2.
Return type: dbgeng.symbolgroup
-
dbgeng.symbols.
get_module_name_string
(which, index, base) → string¶ Returns the name of the specified module. See GetModuleNameString.
Parameters: - which (integer) – which of the module’s names to return; should be a value from the
modname
table - index (integer) – index of the module; if set to
dbgeng.ANY_ID
, the base parameter is used instead - base (integer) – if the index paramate is
dbgeng.ANY_ID
, specifies the module base address; otherwise, it’s ignored
Returns: name of the specified module
- which (integer) – which of the module’s names to return; should be a value from the
-
dbgeng.symbols.
get_symbol_type_id
(symbol) → integer, integer¶ Returns the module and type id for a symbol. See GetSymbolTypeId.
Parameters: symbol (string) – expression of the symbol whose type id is requested Returns: two values, the first being the module base address containing the symbol; the second being the type id for the given expression
-
dbgeng.symbols.
get_type_id
(module, name) → integer¶ Returns the type id for a type given its module and name. See GetTypeId.
Parameters: - module (integer) – module base address of the module to which the type belongs
- name (string) – type name or symbol expression whose type id is requested
Returns: type id of the symbol
-
dbgeng.symbols.
get_type_name
(module, typeid) → string¶ Returns the name of a type specified by its module and type id. See GetTypeName.
Parameters: - module (integer) – module base address of the module to which the type belongs
- typeid (integer) – specifies the type id of the type
Returns: name of the type
-
dbgeng.symbols.
get_type_size
(module, typeid) → integer¶ Returns the size of a type specified by its module and type id. See GetTypeSize.
Parameters: - module (integer) – module base address of the module to which the type belongs
- typeid (integer) – specifies the type id of the type
Returns: number of bytes of memory an instance of the specified type requires
Other¶
-
dbgeng.symbols.
modname
¶ Table containing values that control the operation of
get_module_name_string()
. Contains the following values:IMAGE
: image name; this is the name of the executable file, including the extensionMODULE
: module name; this is usually just the file name without the extensionLOADED_IMAGE
: loaded image name; unless Microsoft CodeView symbols are present, this is the same as the image nameSYMBOL_FILE
: symbol file name; the path and name of the symbol file; if no symbols have been loaded, this is the name of the executable file insteadMAPPED_IMAGE
: mapped image name; in most cases, this is NULL; if the debugger is mapping an image file (for example, during minidump debugging), this is the name of the mapped image
See table in the documentation for GetModuleNameString.
dbgeng.symbolgroup¶
The symbol group functions are accessible from the global dbgeng.symbolgroup table, and represent the functions from the IDebugSymbolGroup interfaces of the dbgeng COM API.
Symbol group objects are created from the create_symbol_group()
function in dbgeng.symbols
.
Symbol groups are disposed automatically by garbage collection when the object is no longer referenced by any variables.
All of the symbolgroup methods are object methods, which means they can be called using Lua object method syntax. Assuming a variable sg containing a symbol group object, this call would return the number of symbols contained in the symbol group:
local numsyms = sg:get_number_symbols()
This is really just syntatic sugar for the more verbose:
local numsyms = dbgeng.symbolgroup.get_number_symbols( sg )
Object methods¶
-
dbgeng.symbolgroup.
add_symbol
(symexpr, index) → integer¶ Adds a symbol to the symbol group. See AddSymbol.
Parameters: - symexpr (string) – C++ expression representing the symbol to add, which can include pointer, array, and structure dereferencing
- index (integre) – desired index within the symbol group for the added symbol; pass
dbgeng.ANY_ID
to append the symbol to the end
Returns: index of the newly added symbol
-
dbgeng.symbolgroup.
expand_symbol
(index, expand) → boolean¶ Adds or removes the children of a symbol within the symbol group. See ExpandSymbol.
Parameters: - index (integer) – index of the symbol to expand or collapse
- expand (boolean) –
true
to expand,false
to collapse
Returns: indication of success of the operation
true
if the operation succeededfalse
if the symbol had no children to add- if the symbol is already at the maximum expansion depth, so that its children could not be
added, returns the three values:
nil
,'E_INVALIDARG'
, anddbgeng.hr.E_INVALIDARG
-
dbgeng.symbolgroup.
get_number_symbols
() → integer¶ Returns the number of symbols in the symbol group. See GetNumberSymbols.
-
dbgeng.symbolgroup.
get_symbol_entry_information
(index) → table of symbol information¶ Returns information about a symbol in a symbol group. See GetSymbolEntryInformation.
Parameters: index (integer) – index of the symbol whose information to retrieve Returns: table containing the following fields: module
: module base addressoffset
: memory location of the symbolid
: id of the symbol; if not known, will be equal todbgeng.INVALID_OFFSET
arg64
: interpretation depends on the type of the symbol; if not known, will be 0size
: size of the symbol’s value, in bytestype_id
: type id of the symbolname_size
: size of the symbol’s name, in characterstoken
: managed token of the symbol; if not known or has none, will be 0tag
: symbol tag of the symbol; will equal one of the values in thedbgeng.symtag
tablearg32
: interpretation depends on the type of the symbol; currently, equals the register that holds the value or pointer to the value of the symbol; if the symbol is not held in a register or the register is not known, will be 0
-
dbgeng.symbolgroup.
get_symbol_name
(index) → string¶ Returns the name of a symbol in the symbol group. See GetSymbolName.
Parameters: index (integer) – index of the symbol whose information to retrieve
-
dbgeng.symbolgroup.
get_symbol_offset
(index) → integer¶ Returns the memory location in the target’s memory of a symbol in the symbol group, if the symbol has an absolute address. See GetSymbolOffset.
Parameters: index (integer) – index of the symbol whose information to retrieve
-
dbgeng.symbolgroup.
get_symbol_parameters
(start, count) → array of symbol parameter information¶ Returns symbol parameters that describe the specified symbols from the symbol group. See GetSymbolParameters.
Parameters: - start (integer) – index of the first symbol for which to retrieve parameters
- count (integer) – number of symbols for which to retrieve parameters
Returns: array of tables, each of which contains the following fields:
module
: module base addresstype_id
: type id of the symbolparent_symbol
: index within the symbol group of the symbol’s parentsub_elements
: number of children of the symbolflags
: bitfield combination of the values in thesymbol_flag
tableexpansion_depth
: expansion depth of the symbol within the symbol group; the depth of a child symbol is always one more than the depth of its parent
-
dbgeng.symbolgroup.
get_symbol_register
(index) → integer¶ Returns the index of the register that contains the value or a pointer to the value of a symbol in the symbol group. See GetSymbolRegister.
Parameters: index (integer) – index of the symbol whose information to retrieve
-
dbgeng.symbolgroup.
get_symbol_size
(index) → integer¶ Returns the size of a symbol’s value, in bytes. See GetSymbolSize.
Parameters: index (integer) – index of the symbol whose information to retrieve
-
dbgeng.symbolgroup.
get_symbol_type_name
(index) → string¶ Returns the name of a symbol’s type. See GetSymbolTypeName.
Parameters: index (integer) – index of the symbol whose information to retrieve
-
dbgeng.symbolgroup.
get_symbol_value_text
(index) → string¶ Returns a string representation of a symbol’s value. See GetSymbolValueText.
Parameters: index (integer) – index of the symbol whose information to retrieve
-
dbgeng.symbolgroup.
remove_symbol_by_index
(index) → boolean¶ Removes the specified symbol from the symbol group. Child symbols cannot be removed using this method; the parent symbol must be removed, which will remove the children as well. See RemoveSymbolByIndex.
Parameters: index (integer) – index of the symbol to remove Returns: true
if the operation succeeded, otherwisenil
-
dbgeng.symbolgroup.
remove_symbol_by_name
(name) → boolean¶ Removes the specified symbol from the symbol group. Child symbols cannot be removed using this method; the parent symbol must be removed, which will remove the children as well. See RemoveSymbolByName.
Parameters: name (string) – name of the symbol to remove Returns: true
if the operation succeeded, otherwisenil
-
dbgeng.symbolgroup.
write_symbol
(index, value) → boolean¶ Sets the value of a symbol in the symbol group. See WriteSymbol.
Parameters: - index (integer) – index of the symbol to set
- value (string) – C++ expression that is evaluated to determine the symbol’s new value
Returns: true
if the operation is successful, otherwisenil
Other¶
-
dbgeng.symbolgroup.
symbol_flag
¶ EXPANDED
: The children of the symbol are part of the symbol group.READ_ONLY
: The symbol represents a read-only variable.IS_ARRAY
: The symbol represents an array variable.IS_FLOAT
: The symbol represents a floating-point variable.IS_ARGUMENT
: The symbol represents an argument passed to a function.IS_LOCAL
: The symbol represents a local variable in a scope.
See DEBUG_SYMBOL_XXX.
dbgeng.breakpoint¶
The breakpoint functions are accessible from the global dbgeng.breakpoint table, and represent the functions from the IDebugBreakpoint interfaces of the dbgeng COM API.
Breakpoints objects are generated from functions in dbgeng.control
:
add_breakpoint()
to create a new breakpoint, and get_breakpoint_by_id()
or
get_breakpoint_by_index()
to retrieve an existing breakpoint.
Breakpoints are removed by calling dbgeng.control.remove_breakpoint()
and passing a breakpoint
object. They are not removed when the Lua variable goes out of scope or is collected by garbage
collection.
All of the breakpoint methods are object methods, which means they can be called using Lua object method syntax. Assuming a variable bp containing a breakpoint object, this call would return the command to be executed when the breakpoint is hit:
local cmd = bp:get_command()
This is really just syntatic sugar for the more verbose:
local cmd = dbgeng.breakpoint.get_command( bp )
Object methods¶
-
dbgeng.breakpoint.
add_flags
(flags) → nil¶ Adds flags to the breakpoint by combining the given bitfield with existing flags using bitwise OR. Possible flag values can be found in the
flag
table. See AddFlags.Parameters: flags (integer) – bitfield, combining values from flag
-
dbgeng.breakpoint.
get_command
() → string¶ Returns the command string that is executed when a breakpoint is triggered. See GetCommand.
-
dbgeng.breakpoint.
get_current_pass_count
() → integer¶ Returns the remaining number of times that the target must reach the breakpoint location before the breakpoint is triggered. See GetCurrentPassCount.
-
dbgeng.breakpoint.
get_data_parameters
() → integer, integer¶ Returns two values:
- The first is the size in bytes of the memory block whose access triggers the breakpoint.
- The second is the access type, which will equal one of the values from the
access
table.
See GetDataParameters.
-
dbgeng.breakpoint.
get_flags
() → integer¶ Returns the flags for a breakpoint, as a bitfield, combining values from the
flag
table. See GetFlags.
-
dbgeng.breakpoint.
get_match_thread_id
() → integer or nil¶ If a thread has been set for the breakpoint, the breakpoint can be triggered only if that thread hits the breakpoint. If a thread has not been set, any thread can trigger the breakpoint.
Returns the engine thread id that can trigger the breakpoint, or
nil
if a thread has not been set. See GetMatchThreadId.
-
dbgeng.breakpoint.
get_offset
() → integer¶ Returns the location that triggers the breakpoint. See GetOffset.
-
dbgeng.breakpoint.
get_offset_expression
() → string¶ Returns the expression that evaluates to the location that triggers the breakpoint. See GetOffsetExpression.
-
dbgeng.breakpoint.
get_parameters
() → table¶ Returns most parameter information for a breakpoint in one call, rather than using separate calls for each piece. See GetParameters.
Returns: table with the following named fields: offset
: location in the target’s memory that will trigger the breakpointid
: breakpoint idbreak_type
: one of the values from thetype
tableproc_type
: type of processor the breakpoint is set forflags
: breakpoint flagsdata_size
: for a data breakpoint, the size in bytes of the memory location that will trigger the breakpoint; otherwise, zerodata_access_type
: for a data breakpoint, one of the values from theaccess
table; otherwise, zeropass_count
: number of times the target will hit the breakpoint before it triggerscurrent_pass_count
: remaining number of times the target will hit the breakpoint before it triggersmatch_thread
: engine thread id of the thread that can trigger the breakpoint; if any thread can trigger it,dbgeng.ANY_ID
-
dbgeng.breakpoint.
get_pass_count
() → integer¶ Returns the number of times that the target was originally required to reach the breakpoint location before the breakpoint is triggered. See GetPassCount.
-
dbgeng.breakpoint.
get_type
() → integer, integer¶ Returns two values:
- type of breakpoint, which can be one of the values in the
type
table - type of processor the breakpoint is set for
See GetType.
- type of breakpoint, which can be one of the values in the
-
dbgeng.breakpoint.
remove_flags
(flags) → nil¶ Removes flags from a breakpoint, by combining the complement of the given bitfield with the existing flags, using bitwise AND. Possible flag values can be found in the
flag
table. See RemoveFlags.Parameters: flags (integer) – bitfield, combining values from flag
-
dbgeng.breakpoint.
set_command
(command) → nil¶ Sets the command string that is executed when a breakpoint is triggered. See SetCommand.
Parameters: command (string) – command string to execute
-
dbgeng.breakpoint.
set_data_parameters
(size, access_type) → nil¶ Sets parameters for a processor breakpoint. See SetDataParameters.
Parameters: - size (integer) – size in bytes of the memory location whose access will trigger the breakpoint
- access_type (integer) – one of the values from the
access
table
-
dbgeng.breakpoint.
set_flags
(flags) → nil¶ Sets the flags for a breakpoint. See SetFlags.
Parameters: flags (integer) – bitfield, combining values from the flag
table
-
dbgeng.breakpoint.
set_match_thread_id
(id) → nil¶ Sets the engine thread id that can trigger the breakpoint. If a thread has been set, the setting can be removed by passing
dbgeng.ANY_ID
for the id. See SetMatchThreadId.Parameters: id (integer) – id of the thread that can trigger the breakpoint
-
dbgeng.breakpoint.
set_offset
(offset) → nil¶ Sets the memory location in the target that triggers the breakpoint. See SetOffset.
Parameters: offset (integer) – location in the target’s memory
-
dbgeng.breakpoint.
set_offset_expression
(expression) → nil¶ Sets the expression string that evaluates to the location that triggers the breakpoint. See SetOffsetExpression.
Parameters: expression (string) – expression that evaluates to a location in the target’s memory
-
dbgeng.breakpoint.
set_pass_count
(passes) → nil¶ Sets the number of times that the target must reach the breakpoint location before the breakpoint is triggered. See SetPassCount.
Parameters: passes (integer) – number of passes to trigger the breakpoint
Other¶
-
dbgeng.breakpoint.
access
¶ Table containing the access types that processor breakpoints can be defined with.
READ
: Triggered when the CPU reads or writes memory in the breakpoint’s block.WRITE
: Triggered when the CPU writes memory in the breakpoint’s block.EXECUTE
: Triggered when the CPU fetches the instruction in the breakpoint’s block.IO
: Triggered when the I/O port in the breakpoint’s block is accessed.
-
dbgeng.breakpoint.
flag
¶ Table containing bit-flags that affect breakpoint operation.
ENABLED
: When set, the breakpoint is enabled. When not set, the breakpoint is disabled.ADDER_ONLY
: When set, the breakpoint is a private breakpoint, only visible to the client that added it. Other clients will not be able to query for it, and events will not be sent to other clients. Callbacks related to the breakpoint will only be sent to this client.GO_ONLY
: When set, the breakpoint will only be triggered if the target is in unrestricted execution. It will not be triggered when stepping through instructions.ONE_SHOT
: When set, the breakpoint will automatically be removed the first time it triggers.DEFERRED
: When set, the breakpoint is deferred. The engine sets this flag when a breakpoint is defined using a symbolic expression, and the engine can’t evaluate the expression. Every time a module is loaded or unloaded in the target, the engine will attempt to reevaluate the expression. This flag cannot be modified by any client.
-
dbgeng.breakpoint.
type
¶ Table containing types of breakpoints that can be created.
CODE
: software breakpointDATA
: processor breakpoint