Description
On Xbox/Windows, our crash daemon uses StackWalk64 and SymFromAddrW to walk the crashed thread and symbolicate each frame. When there is no PDB, DbgHelp still returns a symbol for the nearest PE export and we write that directly into function and symbol_addr without checking whether it came from PDB-backed debug info.
[ Observation ]
On an Xbox UE5 DevKit crash, the RIP is the same in both the minidump and signalhandler stacks (unwinding is correct), but the signalhandler frames are named with export symbols (e.g. ProxyCommandData::CommandData::CommandData, mu::operator<<, Network::Term). The Sentry issue is titled mu::operator<<, but a local debugger with PDBs shows a different function at that same address.
Root cause: walk_stack_with_dbghelp stores any successful SymFromAddrW result unconditionally (sentry_crash_daemon.c ~2565–2570), then copies to JSON as function (~905–909). No distinction between PDB resolution and export-table fallback.
Looks related to #1595 (which added client-side SymFromAddrW naming in the crash daemon) and #1811 (which partially addressed Windows via module search paths): on Xbox DevKit and local builds, PDBs are still not accessible, so DbgHelp’s export-fallback names continue to be written to the function. On macOS (#1856), we already follow the rule that an unresolved frame is preferred over a potentially incorrect name.
When does the problem happen
Environment
| Key |
Value |
| OS |
Xbox Series X DevKit (Xbox 10.0.26100) / Windows (native backend) |
| SDK |
sentry-native 0.16.x (sentry.native.xbox.unreal) |
| Consumer |
Unreal Sentry plugin 1.18.x, default NativeStackwalkingWithMinidump |
| Build |
local Development build, PDB not uploaded to Sentry |
| Complier |
MSVC / Xbox GDK toolchain, SENTRY_BACKEND=native (out-of-process crash daemon) |
[ Expected ]
When PDBs are unavailable, frames should remain unnamed (or explicitly marked as low-trust), rather than being assigned incorrect names.
Log output from JSON
"debug_status": "missing",
"unwind_status": "missing",
"code_file": "G:\\OD\\Binaries\\XSX\\OD.exe",
"debug_file": "D:\\od\\UE5\\Proj\\OD\\Binaries\\XSX\\OD.pdb"
"function": "mu::operator<<",
"instruction_addr": "0x7ff66454b896",
"symbolicator_status": "missing"
#215475749303296 for Reference
Description
On Xbox/Windows, our crash daemon uses StackWalk64 and SymFromAddrW to walk the crashed thread and symbolicate each frame. When there is no PDB, DbgHelp still returns a symbol for the nearest PE export and we write that directly into
functionandsymbol_addrwithout checking whether it came from PDB-backed debug info.[ Observation ]
On an Xbox UE5 DevKit crash, the RIP is the same in both the minidump and
signalhandlerstacks (unwinding is correct), but the signalhandlerframes are named with export symbols (e.g. ProxyCommandData::CommandData::CommandData, mu::operator<<, Network::Term). The Sentry issue is titled mu::operator<<, but a local debugger with PDBs shows a different function at that same address.Root cause: walk_stack_with_dbghelp stores any successful SymFromAddrW result unconditionally (sentry_crash_daemon.c ~2565–2570), then copies to JSON as function (~905–909). No distinction between PDB resolution and export-table fallback.
Looks related to #1595 (which added client-side SymFromAddrW naming in the crash daemon) and #1811 (which partially addressed Windows via module search paths): on Xbox DevKit and local builds, PDBs are still not accessible, so DbgHelp’s export-fallback names continue to be written to the function. On macOS (#1856), we already follow the rule that an unresolved frame is preferred over a potentially incorrect name.
When does the problem happen
Environment
[ Expected ]
When PDBs are unavailable, frames should remain unnamed (or explicitly marked as low-trust), rather than being assigned incorrect names.
Log output from JSON
#215475749303296 for Reference