Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions bindings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ Windows.Win32.Foundation.HINSTANCE
Windows.Win32.Foundation.INVALID_HANDLE_VALUE
Windows.Win32.Foundation.TRUE
Windows.Win32.Globalization.CP_UTF8
Windows.Win32.Globalization.CP_ACP
Windows.Win32.Globalization.CP_THREAD_ACP
Windows.Win32.Globalization.lstrlenW
Windows.Win32.Globalization.MultiByteToWideChar
Windows.Win32.Globalization.WideCharToMultiByte
Windows.Win32.System.Diagnostics.Debug.AddrModeFlat
Windows.Win32.System.Diagnostics.Debug.CONTEXT
Expand All @@ -28,24 +31,29 @@ Windows.Win32.System.Diagnostics.Debug.StackWalk64
Windows.Win32.System.Diagnostics.Debug.StackWalkEx
Windows.Win32.System.Diagnostics.Debug.SymAddrIncludeInlineTrace
Windows.Win32.System.Diagnostics.Debug.SYMBOL_INFOW
Windows.Win32.System.Diagnostics.Debug.SymFromAddr
Windows.Win32.System.Diagnostics.Debug.SymFromAddrW
Windows.Win32.System.Diagnostics.Debug.SymFromInlineContextW
Windows.Win32.System.Diagnostics.Debug.SymFunctionTableAccess64
Windows.Win32.System.Diagnostics.Debug.SymGetLineFromAddr64
Windows.Win32.System.Diagnostics.Debug.SymGetLineFromAddrW64
Windows.Win32.System.Diagnostics.Debug.SymGetLineFromInlineContextW
Windows.Win32.System.Diagnostics.Debug.SymGetModuleBase64
Windows.Win32.System.Diagnostics.Debug.SymGetOptions
Windows.Win32.System.Diagnostics.Debug.SymGetSearchPathW
Windows.Win32.System.Diagnostics.Debug.SymInitializeW
Windows.Win32.System.Diagnostics.Debug.SymInitialize
Windows.Win32.System.Diagnostics.Debug.SYMOPT_DEFERRED_LOADS
Windows.Win32.System.Diagnostics.Debug.SymQueryInlineTrace
Windows.Win32.System.Diagnostics.Debug.SymSetOptions
Windows.Win32.System.Diagnostics.Debug.SymSetSearchPathW
Windows.Win32.System.Diagnostics.ToolHelp.CreateToolhelp32Snapshot
Windows.Win32.System.Diagnostics.ToolHelp.Module32First
Windows.Win32.System.Diagnostics.ToolHelp.Module32FirstW
Windows.Win32.System.Diagnostics.ToolHelp.Module32Next
Windows.Win32.System.Diagnostics.ToolHelp.Module32NextW
Windows.Win32.System.Diagnostics.ToolHelp.MODULEENTRY32W
Windows.Win32.System.Diagnostics.ToolHelp.TH32CS_SNAPMODULE
Windows.Win32.System.LibraryLoader.GetModuleHandleA
Windows.Win32.System.LibraryLoader.GetProcAddress
Windows.Win32.System.LibraryLoader.LoadLibraryA
Windows.Win32.System.Memory.CreateFileMappingA
Expand All @@ -60,4 +68,4 @@ Windows.Win32.System.Threading.GetCurrentProcessId
Windows.Win32.System.Threading.GetCurrentThread
Windows.Win32.System.Threading.INFINITE
Windows.Win32.System.Threading.ReleaseMutex
Windows.Win32.System.Threading.WaitForSingleObjectEx
Windows.Win32.System.Threading.WaitForSingleObjectEx
41 changes: 41 additions & 0 deletions src/backtrace/win32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,44 @@ fn init_frame(frame: &mut Frame, ctx: &CONTEXT) -> u16 {
frame.addr_frame_mut().Mode = AddrModeFlat;
IMAGE_FILE_MACHINE_ARMNT
}

#[cfg(all(target_arch = "x86", target_family = "rust9x"))]
#[unsafe(naked)]
unsafe extern "stdcall" fn RtlCaptureContext(context: &mut CONTEXT) {
core::arch::naked_asm!(
"
push ebx
mov ebx, [esp+8]

mov [ebx+0xB0], eax
mov [ebx+0xAC], ecx
mov [ebx+0xA8], edx
mov eax, [esp]
mov [ebx+0xA4], eax
mov [ebx+0xA0], esi
mov [ebx+0x9C], edi

mov [ebx+0xBC], cs
mov [ebx+0x98], ds
mov [ebx+0x94], es
mov [ebx+0x90], fs
mov [ebx+0x8C], gs
mov [ebx+0xC8], ss

pushfd
pop dword ptr [ebx]

mov eax, [ebp+4]
mov [ebx+0xB8], eax

mov eax, [ebp+0]
mov [ebx+0xB4], eax

lea eax, [ebp+8]
mov [ebx+0xC4], eax

pop ebx
ret 4
",
)
}
42 changes: 23 additions & 19 deletions src/dbghelp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@
#![allow(non_snake_case)]

use alloc::vec::Vec;
use core::ffi::c_void;
use core::{mem, ptr, slice};

use super::windows_sys::*;
use core::ffi::c_void;
use core::mem;
use core::ptr;
use core::slice;

// This macro is used to define a `Dbghelp` structure which internally contains
// all the function pointers that we might load.
Expand Down Expand Up @@ -118,9 +116,9 @@ dbghelp! {
extern "system" {
fn SymGetOptions() -> u32;
fn SymSetOptions(options: u32) -> u32;
fn SymInitializeW(
fn SymInitialize(
handle: HANDLE,
path: PCWSTR,
path: PCSTR,
invade: BOOL
) -> BOOL;
fn SymGetSearchPathW(
Expand Down Expand Up @@ -168,6 +166,18 @@ dbghelp! {
pdwDisplacement: *mut u32,
Line: *mut IMAGEHLP_LINEW64
) -> BOOL;
fn SymFromAddr(
hProcess: HANDLE,
Address: u64,
Displacement: *mut u64,
Symbol: *mut SYMBOL_INFO
) -> BOOL;
fn SymGetLineFromAddr64(
hProcess: HANDLE,
dwAddr: u64,
pdwDisplacement: *mut u32,
Line: *mut IMAGEHLP_LINE64
) -> BOOL;
fn StackWalkEx(
MachineType: u32,
hProcess: HANDLE,
Expand Down Expand Up @@ -222,7 +232,8 @@ pub struct Init {
/// synchronization. Also note that it is safe to call this function multiple
/// times recursively.
pub fn init() -> Result<Init, ()> {
use core::sync::atomic::{AtomicPtr, Ordering::SeqCst};
use core::sync::atomic::AtomicPtr;
use core::sync::atomic::Ordering::SeqCst;

// Helper function for generating a name that's unique to the process.
fn mutex_name() -> [u8; 33] {
Expand Down Expand Up @@ -340,7 +351,7 @@ unsafe fn set_optional_options(dbghelp: *mut Dbghelp) -> Option<()> {
// the time, but now that it's using this crate it means that someone will
// get to initialization first and the other will pick up that
// initialization.
(*dbghelp).SymInitializeW()?(GetCurrentProcess(), ptr::null_mut(), TRUE);
(*dbghelp).SymInitialize()?(GetCurrentProcess(), ptr::null_mut(), TRUE);

// The default search path for dbghelp will only look in the current working
// directory and (possibly) `_NT_SYMBOL_PATH` and `_NT_ALT_SYMBOL_PATH`.
Expand Down Expand Up @@ -401,9 +412,7 @@ fn utf16_char(c: char) -> u16 {

impl SearchPath {
fn new(initial_search_path: Vec<u16>) -> Self {
Self {
search_path_utf16: initial_search_path,
}
Self { search_path_utf16: initial_search_path }
}

/// Add a path to the search path if it is not already present.
Expand All @@ -413,11 +422,7 @@ impl SearchPath {
// We could deduplicate in a case-insensitive way, but case-sensitivity
// can be configured by directory on Windows, so let's not do that.
// https://learn.microsoft.com/windows/wsl/case-sensitivity
if !self
.search_path_utf16
.split(|&c| c == sep)
.any(|p| p == path)
{
if !self.search_path_utf16.split(|&c| c == sep).any(|p| p == path) {
if self.search_path_utf16.last() != Some(&sep) {
self.search_path_utf16.push(sep);
}
Expand Down Expand Up @@ -451,9 +456,8 @@ extern "system" fn enum_loaded_modules_callback(
let path_sep = utf16_char('\\');
let alt_path_sep = utf16_char('/');

let Some(end_of_directory) = module_name
.iter()
.rposition(|&c| c == path_sep || c == alt_path_sep)
let Some(end_of_directory) =
module_name.iter().rposition(|&c| c == path_sep || c == alt_path_sep)
else {
// `module_name` being an absolute path, it should always contain at least one
// path separator. If not, there is nothing we can do.
Expand Down
Loading