From 98ccac22f303a7c77c8822a8a4ecd54c9a1cdde3 Mon Sep 17 00:00:00 2001 From: OpenByte Date: Fri, 8 Jul 2022 00:19:59 +0200 Subject: [PATCH] Fix #3 --- src/raw/windows.rs | 36 ++++++++++++------------------------ tests/raw.rs | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/raw/windows.rs b/src/raw/windows.rs index 596bbef..504daa1 100644 --- a/src/raw/windows.rs +++ b/src/raw/windows.rs @@ -2,7 +2,7 @@ use crate::utils; use super::super::err::Error; use super::common::{AddressInfo, OverlappingSymbol}; -use once_cell::sync::Lazy; +use once_cell::sync::{Lazy, OnceCell}; use std::ffi::{CStr, OsStr, OsString}; use std::io::{Error as IoError, ErrorKind}; use std::mem::size_of; @@ -14,9 +14,7 @@ use std::sync::Mutex; use winapi::shared::basetsd::DWORD64; use winapi::shared::minwindef::{DWORD, HMODULE, TRUE}; use winapi::shared::winerror::ERROR_CALL_NOT_IMPLEMENTED; -use winapi::um::dbghelp::{ - SymCleanup, SymFromAddrW, SymGetModuleBase64, SymInitializeW, SYMBOL_INFOW, -}; +use winapi::um::dbghelp::{SymFromAddrW, SymGetModuleBase64, SymInitializeW, SYMBOL_INFOW}; use winapi::um::errhandlingapi::{GetLastError, SetErrorMode, SetThreadErrorMode}; use winapi::um::libloaderapi::{ FreeLibrary, GetModuleFileNameW, GetModuleHandleExW, GetProcAddress, LoadLibraryW, @@ -40,7 +38,7 @@ static SET_ERR_MODE_DATA: Lazy> = Lazy::new(|| { previous: 0, }) }); -static OBTAINERS_COUNT: Lazy> = Lazy::new(|| Mutex::new(0)); +static SYM_MUTEX: OnceCell> = OnceCell::new(); pub type Handle = HMODULE; @@ -57,7 +55,7 @@ process. https://msdn.microsoft.com/pl-pl/library/windows/desktop/dd553630(v=vs.85).aspx */ -const ERROR_MODE: DWORD = 1; //app handles everything +const ERROR_MODE: DWORD = 1; // app handles everything enum ErrorModeGuard { ThreadPreviousValue(DWORD), @@ -172,28 +170,26 @@ pub unsafe fn open_lib(name: &OsStr) -> Result { #[inline] pub unsafe fn addr_info_init() { - //calls to Sym* functions are not thread safe. - let mut lock = OBTAINERS_COUNT.lock().expect("Mutex got poisoned"); - if *lock == 0 { + // calls to Sym* functions are not thread safe. + SYM_MUTEX.get_or_init(|| { let process_handle = GetCurrentProcess(); - let result = SymInitializeW(process_handle, null_mut(), TRUE); - assert_eq!(result, TRUE); - } - *lock += 1; + let _result = SymInitializeW(process_handle, null_mut(), TRUE); + Mutex::new(()) + }); } #[inline] pub unsafe fn addr_info_obtain(addr: *const ()) -> Result { let process_handle = GetCurrentProcess(); - // calls to Sym* functions are not thread safe. let mut buffer = utils::maybe_uninit_uninit_array::(); let mut symbol_buffer = utils::maybe_uninit_uninit_array::< u8, { size_of::() + MAX_SYMBOL_LEN * size_of::() }, >(); let (module_base, path_len, symbol_info, result) = { - let mut _lock = OBTAINERS_COUNT.lock().expect("Mutex got poisoned"); + // calls to Sym* functions are not thread safe. + let mut _lock = SYM_MUTEX.get().unwrap().lock().expect("Mutex got poisoned"); let module_base = SymGetModuleBase64(process_handle, addr as u64); if module_base == 0 { @@ -251,15 +247,7 @@ pub unsafe fn addr_info_obtain(addr: *const ()) -> Result { } #[inline] -pub unsafe fn addr_info_cleanup() { - 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); - } -} +pub unsafe fn addr_info_cleanup() {} #[inline] pub fn close_lib(handle: Handle) -> Handle { diff --git a/tests/raw.rs b/tests/raw.rs index db0d1e5..ca42df7 100644 --- a/tests/raw.rs +++ b/tests/raw.rs @@ -68,3 +68,17 @@ fn example_address_info() { assert_eq!(os.name, "c_fun_add_two"); assert_eq!(os.addr, c_fun_add_two as *const ()) } + +// https://github.com/OpenByteDev/dlopen2/issues/3 +#[test] +#[cfg(windows)] +fn double_sym_init_does_not_panic() { + let lib_path = example_lib_path(); + let library = Library::open(&lib_path).expect("Could not open library"); + let pointer: *const () = unsafe { library.symbol("c_fun_add_two") }.unwrap(); + + let _ = std::panic::catch_unwind(|| panic!()); // this generates a backtrace. Backtrace::capture() probably works too + + // Panics because SymInitializeW returns an error + unsafe { AddressInfoObtainer::new().obtain(pointer) }.unwrap(); +}