-
Notifications
You must be signed in to change notification settings - Fork 8
Debugging & Troubleshooting
This page explains how to use Brovan's debugging commands to investigate emulator bugs, missing features, and sample-specific failures.
The goal is to make it easier to answer questions like:
- What code path is the sample taking?
- Which module or function is being accessed?
- Where does execution stop or diverge?
- Is the problem a bug in Brovan, or an unimplemented feature?
When something fails, start with a focused run that captures the smallest useful amount of information.
A common pattern is:
Brovan.exe -c "showinstrs [relevant-code-range-here];debug;start;exit" sample.exe > logs.txtThis gives you:
- instruction output for the area you care about
- debugger and scheduler logs
- a saved log file you can attach to an issue
If the relevant code range is not known yet, start with debug first, then narrow the range once you see where execution goes.
The debug command is the main way to inspect emulator activity.
It shows:
- functions being accessed across modules
- thread scheduler logs
- useful execution context for tracking emulator behavior
This is usually the first command to use when a sample hangs, crashes, or behaves differently than expected.
Use debug when you want to:
- follow module/function activity
- understand scheduler behavior
- see where execution stalls
- confirm whether a code path is being reached
- identify the last successful action before a failure
showinstrs prints instructions from a specific range.
This is useful when you want to inspect the exact code around a crash, an exception, or an unimplemented feature.
You can specify an address range:
showinstrs 0x1000-0x2000You can also specify a symbol-based range:
showinstrs ntdll.dll!NtCreateFile-ntdll.dll!NtCreateFile+0x10Use showinstrs when you want to:
- inspect the instructions leading to a failure
- understand what code path the sample is executing
- verify whether a hook or syscall path is correct
- find the exact instruction sequence that triggers a bug
These commands help you understand how execution reached the current point.
Use calltrace when you want to follow the history of calls that led to a bug or unexpected behavior.
It is especially useful for:
- tracing a failure back to its origin
- checking which function chain was executed
- seeing how control moved through the emulator
Use callstack when you want the current stack context. is is a useful extension of calltrace.
It is especially useful for:
- identifying where execution is right now
- checking stack depth
- comparing expected and actual call flow
- debugging crashes and bad returns
Sometimes a sample fails because Brovan does not yet implement something it needs.
The debugging commands above can help reveal:
- a missing syscall or API behavior
- incomplete memory handling
- scheduler issues
- instruction-level behavior that differs from real execution
- unsupported edge cases in a specific module
When that happens, the logs usually point to the exact feature or code path that needs work.
When opening an issue, it is usually best to include the exact command you used and the log output it produced.
A good starting point is:
Brovan.exe -c "showinstrs [relevant-code-range-here];debug;start;exit" sample.exe > logs.txtThen include:
- what you were trying to run
- what happened
- what you expected to happen
- the sample name or repro steps
- the relevant log excerpt
- whether the problem seems to be a bug or a missing feature
If you already know the problem area, mention it directly. For example:
- scheduler loop
- syscall emulation
- module/function resolution
- instruction handling
- memory protection behavior
A few small habits make debugging much easier:
- keep the repro as small as possible
- capture only the logs needed for the issue
- save the exact command line you used
- note whether the problem is deterministic
- include the first error, not only the final crash
If a sample fails in the middle of execution, logs from the first failure point are usually more useful than the end of the run.
- Run the sample with
debugenabled. - Find the function, module, or scheduler event where execution starts to go wrong.
- Use
showinstrson the surrounding code range. - Check
calltraceandcallstackto understand how you reached that point. - Open an issue with the command line, logs, and the suspected missing feature or bug.
If you are fixing a bug, try to include:
- the smallest repro possible
- the exact command used
- the expected behavior
- the observed behavior
- any relevant module names or function names
This makes it much easier to verify the fix and avoid regressions.
Debugging is much easier when the issue report includes enough context to reproduce the problem quickly.