Skip to content

Commit 5fdde10

Browse files
Fix function pointer checks on Windows
1 parent 5614859 commit 5fdde10

4 files changed

Lines changed: 57 additions & 6 deletions

File tree

ctest/src/runner.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,15 @@ pub fn __compile_test(
141141

142142
// Pass in a different target, linker or flags if set, useful for cross compilation.
143143

144-
let target = env::var("TARGET_PLATFORM").unwrap_or_default();
144+
let target = env::var("TARGET_PLATFORM")
145+
.or_else(|_| env::var("TARGET"))
146+
.unwrap_or_default();
145147
if !target.is_empty() {
146-
cmd.arg("--target").arg(target);
148+
cmd.arg("--target").arg(&target);
149+
}
150+
151+
if target.contains("windows") && target.contains("gnu") {
152+
cmd.arg("-lws2_32");
147153
}
148154

149155
let linker = env::var("LINKER").unwrap_or_default();

ctest/templates/test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ CTEST_EXTERN uint64_t ctest_offset_of__{{ item.id }}__{{ item.field.ident() }}(v
8989
}
9090

9191
CTEST_EXTERN uint64_t ctest_size_of__{{ item.id }}__{{ item.field.ident() }}(void) {
92-
return sizeof((({{ item.c_ty }}){}).{{ item.c_field }});
92+
return sizeof((({{ item.c_ty }} *)0)->{{ item.c_field }});
9393
}
9494
{%- endfor +%}
9595

ctest/templates/test.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,47 @@ mod generated_tests {
3939
}
4040
}
4141

42+
fn check_same_fn_ptr(mut rust: u64, mut c: u64, attr: &str) {
43+
if rust == c {
44+
NTESTS.fetch_add(1, Ordering::Relaxed);
45+
return;
46+
}
47+
48+
#[cfg(target_os = "windows")]
49+
unsafe {
50+
let resolve = |addr: u64| -> u64 {
51+
if addr == 0 {
52+
return 0;
53+
}
54+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
55+
{
56+
let bytes = addr as *const u8;
57+
if *bytes == 0xff && *bytes.add(1) == 0x25 {
58+
if cfg!(target_arch = "x86_64") {
59+
let displacement = (bytes.add(2) as *const i32).read_unaligned();
60+
let address_of_pointer = bytes.add(6).offset(displacement as isize) as *const *const ();
61+
return *address_of_pointer as u64;
62+
} else if cfg!(target_arch = "x86") {
63+
let address_of_pointer = (bytes.add(2) as *const *const *const ()).read_unaligned();
64+
return *address_of_pointer as u64;
65+
}
66+
}
67+
}
68+
addr
69+
};
70+
71+
rust = resolve(rust);
72+
c = resolve(c);
73+
}
74+
75+
if rust != c {
76+
eprintln!("bad {attr}: rust: {rust:?} != c {c:?}");
77+
FAILED.store(true, Ordering::Relaxed);
78+
} else {
79+
NTESTS.fetch_add(1, Ordering::Relaxed);
80+
}
81+
}
82+
4283
fn check_same_bytes(rust: &[u8], c: &[u8], attr: &str) {
4384
if rust == c {
4485
NTESTS.fetch_add(1, Ordering::Relaxed);
@@ -360,7 +401,7 @@ mod generated_tests {
360401
}
361402
let actual = unsafe { ctest_foreign_fn__{{ item.id }}() } as u64;
362403
let expected = {{ item.id }} as *const () as u64;
363-
check_same(actual, expected, "`{{ item.id }}` function pointer");
404+
check_same_fn_ptr(actual, expected, "`{{ item.id }}` function pointer");
364405
}
365406
{%- endfor +%}
366407

libc-test/build.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -847,8 +847,12 @@ fn test_windows(target: &str) {
847847
});
848848

849849
cfg.skip_struct_field(move |s, field| s.ident() == "CONTEXT" && field.ident() == "Fp");
850-
// FIXME(windows): All functions point to the wrong addresses?
851-
cfg.skip_fn_ptrcheck(|_| true);
850+
// FIXME(windows): ctime and difftime are inline functions on the C side,
851+
// so their addresses resolve to local wrappers rather than the DLL exports.
852+
cfg.skip_fn_ptrcheck(|name| match name {
853+
"ctime" | "difftime" => true,
854+
_ => false,
855+
});
852856

853857
cfg.skip_signededness(move |c| {
854858
match c {

0 commit comments

Comments
 (0)