Debugging in both native and scripting layer - bdsx/bdsx GitHub Wiki
This tutorial will lead you to debug with both VSCode and debuggers compatible with WinDbg server. This tutorial takes Ghidra as an example.
This tutorial is not useful to you if you do not care about what happened in native layer.
In general, debugging with VSCode and attaching the debugger to the process is the simplest way. However, attaching a process must be done by hand. This solution is more convenient than it and will automatically load the corresponding PDB file when called as well.
Prerequisites
- WinDbg (Install the Windows debugger)
- Ghidra (Homepage)
Add a new configuration to launch.json
{
"runtimeExecutable": "WinDbgX",
"cwd": "${workspaceFolder}/bedrock_server",
"type": "legacy-node",
"request": "launch",
"name": "Launch BDSX in WinDbg",
"runtimeArgs": [
"-server",
"tcp:port=5005,server=localhost",
"-g",
"${workspaceFolder}/bedrock_server/bedrock_server.exe"
],
"args": [
"${workspaceFolder}"
],
"skipFiles": [
"<node_internals>/**"
],
"console": "integratedTerminal",
"preLaunchTask": "${defaultBuildTask}"
}
You can change port 5005 to any other you like if ocuppied.
If you need bedrock server to pause at the begining, you can remove "-g"
from runtimeArgs
and set timeout
to a large number. NOTICE: Closing WinDbg before VSCode Debugger attached WILL NOT terminate the debug session until timeout is reached.
Configure Ghidra
- Start debugging (press F5) using the configuration below in VSCode. This will launch WinDbg.
- Break execution (press Ctrl + Break) in WinDbg. Otherwise, debuggee may not respond to Ghidra.
- Open the bedrock server executable with Debugger Tool in Ghidra.
- Select Debugger Menu -> Debug <Project File Name> -> in dbgeng locally via GADP.
- Set DebugConnect options (.server) to
tcp:Port=5005,Server=localhost
, leave other options to their defaults:- DebugConnect options:
tcp:Port=5005,Server=localhost
- Remote process server options:
none
- Agent interface address:
localhost
- Agent TCP port:
0
- Open agent's JDWP port:
-1
- Suspend for JDWP: unchecked
- DebugConnect options:
- See ghidra/issue#3965 if failed to connect.
- Cancel the Cmd dialog. It's unnecessary to launch another instance.
Set breakpoints via Ghidra
- Break the execution.
- Open Objects Window in Ghidra Debugger.
- Expand Sessions -> [0] -> Processes -> [0] -> Threads -> First Node -> Stack. This will notify Ghidra to load stack data of main thread.
- Use Symbol Tree or other window to locate the function you want to break in.
- Right click in Listing or Decompile, click Set breakpoint -> SW_EXECUTE.
- You will find breakpoint is available in WinDbg.
You can expand Debug -> Breakpoints in Objects window to notify Ghidra Debugger sync breakpoint states. Sometimes refreshing the process node (Select process node and click Refresh Node button) is required.
Set breakpoints via WinDbg
- Break the execution.
- Click Breakpoints -> New.
- Enter
bedrock_server!<demangled name>
, such asbedrock_server!ListCommand::execute
. - Press OK and wait for a while.
View stack
You may find stack full of Chakra.
You can create a Model Query:
(@$curstack.Frames).Where(p => !p.ToDisplayString().StartsWith("Chakra") && !p.ToDisplayString().StartsWith("0x"))
Or just execute the following command:
dx (@$curstack.Frames).Where(p => !p.ToDisplayString().StartsWith("Chakra") && !p.ToDisplayString().StartsWith("0x"))