#debugging #windows

dbgtools-win

Expensive and intrusive debugging tools (for Windows)

3 unstable releases

0.2.1 May 3, 2021
0.2.0 May 3, 2021
0.1.0 Mar 7, 2021

#67 in #debugging

41 downloads per month
Used in 2 crates

0BSD license

22KB
350 lines

dbgtools-win

A set of platform-specific functions that can be useful when debugging userland Windows applications and libraries.

Usage

This crate is meant to be used in development environments only. Its functions are tightly tied to other development tools, and it may add significant overhead to your code.

The recommended way to use dbgtools is to add it as an optional feature so that it is only compiled into your project when it's needed for debugging:

In Cargo.toml:

[dependencies]
dbgtools-win = { version = "0.2", optional = true }

In code:

// Wait for a debugger to connect and break as soon as it has
#[cfg(feature="dbgtools-win")]
dbgtools_win::debugger::wait_for_then_break();

Build using:

cargo build --features dbgtools-win

See also

  • verboten - A simple Windows service wrapper for msvsmon, the remote debugging server for Visual Studio.

lib.rs:

Expensive debugging utility functions for Windows.

This crate is meant to be used in development versions of applications to assist in debugging, and should normally not be included in release builds used for production.

Bloated example

The following is a little bit of a contrived example usage of dbgtools-win which changes plenty of defaults just to show what options are available.

use std::path::PathBuf;
use dbgtools_win::*;

fn init() {
  let mut wp = WinPicnic::default();

  // If a panic occurs, append its output to a log file.  Can be useful if
  // process does not have a console, like a service.  If a debugger is
  // attached the output can be sent to PanicOutput::Debugger instead.
  let plog = PathBuf::from("C:\\Temp\\panic.log");
  wp.output = PanicOutput::FileAppend(plog);

  // If a panic occurs, and there's a debugger attached to the process,
  // then trigger a debug interrupt.
  wp.brk = true;

  // If a panic occurs, play three short notes.  This can be useful to
  // indicate a problem when running in an environment which doesn't have a
  // console, like a service.
  wp.beep = true;

  // Instruct panic hook to generate minidumps if a panic occurs.
  wp.mdump = Some({
    let mut md = minidump::DumpInfo::default();

    // Generate a full memory dump
    md.mdtype = minidump::DumpType::FullMem;

    // Write dumps to a specific, absolute, directory.  This is useful if
    // you don't know what directory your process will be in, or if the
    // process has write access in it, when the panic handler is run.
    let dumpdir = PathBuf::from("C:\\Temp");
    md.dumpsdir = Some(dumpdir);

    // Set a hardcoded base file name for dumps.
    let basename = PathBuf::from("myapp");
    md.name = Some(basename);

    // Don't overwrite existing dump file; instead attach a sequence
    // number to the base name and skip existing sequence numbers.
    md.seq = true;

    md
  });

  // Set custom panic handler
  set_panic_handler(wp);

  // Wait for a debugger to attach.  Once a debugger attaches, trigger a
  // hard-coded debug breakpoint.  This can be useful when remote
  // debugging services which start early during boot.
  debugger::wait_for_then_break();
}

Live debugging example

There's a special diminutive version of set_panic_handler() in debugger::set_panic_handler() which has fewer options but is especially suited to situations where a program is ~always run with a debugger attached.

use std::path::PathBuf;
use dbgtools_win::*;
use dbgtools_win::debugger::OnPanic;

fn init() {
  // Set up a custom panic hook which will output the panic information and
  // backtrace to the debugger output terminal, and trigger an explicit
  // debug breakpoint
  debugger::set_panic_handler(OnPanic::Break);

  // Wait for a debugger to attach and trigger an explicit code breakpoint
  // when that happens.
  debugger::wait_for_then_break();
}

Dependencies

~188MB
~3.5M SLoC