Skip to content

Commit 185882e

Browse files
committed
compiler: builds for Windows again
The stack-limit extern block is unsafe, as the edition requires, and process_symbol asks each loaded module in turn where there is no default dlsym handle.
1 parent c0f601e commit 185882e

2 files changed

Lines changed: 38 additions & 3 deletions

File tree

‎crates/compiler/src/collector.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ fn query_stack_top() -> usize {
883883
#[cfg(windows)]
884884
fn query_stack_top() -> usize {
885885
#[link(name = "kernel32")]
886-
extern "system" {
886+
unsafe extern "system" {
887887
fn GetCurrentThreadStackLimits(low: *mut usize, high: *mut usize);
888888
}
889889
let (mut low, mut high) = (0usize, 0usize);

‎crates/compiler/src/hir_interp.rs‎

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub fn trace_enabled() -> bool {
112112

113113
/// The address of `name` in the running process, if the dynamic linker
114114
/// knows it.
115-
#[cfg(not(target_arch = "wasm32"))]
115+
#[cfg(all(unix, not(target_arch = "wasm32")))]
116116
fn process_symbol(name: &str) -> Option<*const u8> {
117117
let c = std::ffi::CString::new(name).ok()?;
118118
// SAFETY: `dlsym` with the default handle reads the process's own
@@ -121,7 +121,42 @@ fn process_symbol(name: &str) -> Option<*const u8> {
121121
(!p.is_null()).then_some(p as *const u8)
122122
}
123123

124-
#[cfg(target_arch = "wasm32")]
124+
/// Windows has no default handle: every loaded module is asked in turn.
125+
#[cfg(windows)]
126+
fn process_symbol(name: &str) -> Option<*const u8> {
127+
use std::ffi::{c_char, c_void};
128+
#[link(name = "kernel32")]
129+
unsafe extern "system" {
130+
fn GetCurrentProcess() -> *mut c_void;
131+
fn K32EnumProcessModules(
132+
process: *mut c_void,
133+
modules: *mut *mut c_void,
134+
size: u32,
135+
needed: *mut u32,
136+
) -> i32;
137+
fn GetProcAddress(module: *mut c_void, name: *const c_char) -> *const c_void;
138+
}
139+
let c = std::ffi::CString::new(name).ok()?;
140+
let mut modules = [std::ptr::null_mut::<c_void>(); 512];
141+
let mut needed = 0u32;
142+
// SAFETY: the buffer is passed with its own byte size, and only the
143+
// handles written into it are read; `c` outlives the lookups.
144+
unsafe {
145+
let size = size_of_val(&modules) as u32;
146+
if K32EnumProcessModules(GetCurrentProcess(), modules.as_mut_ptr(), size, &mut needed) == 0
147+
{
148+
return None;
149+
}
150+
let n = (needed as usize / size_of::<*mut c_void>()).min(modules.len());
151+
modules[..n]
152+
.iter()
153+
.map(|&m| GetProcAddress(m, c.as_ptr()))
154+
.find(|p| !p.is_null())
155+
.map(|p| p as *const u8)
156+
}
157+
}
158+
159+
#[cfg(not(any(all(unix, not(target_arch = "wasm32")), windows)))]
125160
fn process_symbol(_name: &str) -> Option<*const u8> {
126161
None
127162
}

0 commit comments

Comments
 (0)