diff --git a/src/raw/windows.rs b/src/raw/windows.rs index 6026588..b9f5b6a 100644 --- a/src/raw/windows.rs +++ b/src/raw/windows.rs @@ -34,6 +34,7 @@ lazy_static! { count: 0, previous: 0 }); + static ref OBTAINERS_COUNT : Mutex = Mutex::new(0); } @@ -167,35 +168,45 @@ pub unsafe fn open_lib(name: &OsStr) -> Result { #[inline] pub unsafe fn addr_info_init(){ - let process_handle = GetCurrentProcess(); - let result = SymInitializeW(process_handle, null_mut(), TRUE); - assert_eq!(result, TRUE); + //calls to Sym* functions are not thread safe. + let mut lock = OBTAINERS_COUNT.lock().expect("Mutex got poisoned"); + if *lock == 0 { + let process_handle = GetCurrentProcess(); + let result = SymInitializeW(process_handle, null_mut(), TRUE); + assert_eq!(result, TRUE); + } + *lock += 1; } #[inline] pub unsafe fn addr_info_obtain(addr: * const ()) -> Result{ let process_handle = GetCurrentProcess(); - let module_base = SymGetModuleBase64(process_handle, addr as u64); - - if module_base == 0 { - return Err(Error::AddrNotMatchingDll(get_win_error())); - } - let mut buffer: [WCHAR; PATH_MAX as usize] = uninitialized(); - - let path_len = GetModuleFileNameW(module_base as HMODULE, buffer.as_mut_ptr(), PATH_MAX); - - if path_len == 0 { - return Err(Error::AddrNotMatchingDll(get_win_error())); - } + //calls to Sym* functions are not thread safe. + let mut buffer: [WCHAR; PATH_MAX as usize] = uninitialized(); let mut symbol_buffer: [u8; size_of::() + MAX_SYMBOL_LEN * size_of::()] = uninitialized(); - let symbol_info: * mut SYMBOL_INFOW = symbol_buffer.as_mut_ptr() as * mut SYMBOL_INFOW; + let (module_base, path_len, symbol_info, result) = { + let mut _lock = OBTAINERS_COUNT.lock().expect("Mutex got poisoned"); + let module_base = SymGetModuleBase64(process_handle, addr as u64); + + if module_base == 0 { + return Err(Error::AddrNotMatchingDll(get_win_error())); + } + - (*symbol_info).SizeOfStruct = size_of::() as DWORD; - (*symbol_info).MaxNameLen = MAX_SYMBOL_LEN as DWORD; - let mut displacement:DWORD64 = 0; - let result = SymFromAddrW(process_handle, addr as DWORD64, &mut displacement, symbol_info); + let path_len = GetModuleFileNameW(module_base as HMODULE, buffer.as_mut_ptr(), PATH_MAX); + if path_len == 0 { + return Err(Error::AddrNotMatchingDll(get_win_error())); + } + let symbol_info: * mut SYMBOL_INFOW = symbol_buffer.as_mut_ptr() as * mut SYMBOL_INFOW; + + (*symbol_info).SizeOfStruct = size_of::() as DWORD; + (*symbol_info).MaxNameLen = MAX_SYMBOL_LEN as DWORD; + let mut displacement:DWORD64 = 0; + let result = SymFromAddrW(process_handle, addr as DWORD64, &mut displacement, symbol_info); + (module_base, path_len, symbol_info, result) + }; let os = if result == TRUE { let name_len = (*symbol_info).NameLen as usize; @@ -224,9 +235,13 @@ pub unsafe fn addr_info_obtain(addr: * const ()) -> Result{ #[inline] pub unsafe fn addr_info_cleanup(){ - let process_handle = GetCurrentProcess(); - let result = SymCleanup(process_handle); - assert_eq!(result, TRUE); + let mut lock = OBTAINERS_COUNT.lock().expect("Mutex got poisoned"); + *lock -= 1; + if *lock == 0 { + let process_handle = GetCurrentProcess(); + let result = SymCleanup(process_handle); + assert_eq!(result, TRUE); + } } #[inline]