Skip to content

Commit 879000b

Browse files
author
hyd-dev
committed
Detect std by checking if the crate defines #[lang = "start"] rather than string comparison
1 parent 28717a0 commit 879000b

File tree

10 files changed

+92
-25
lines changed

10 files changed

+92
-25
lines changed

src/helpers.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
628628
}
629629
Ok(())
630630
}
631+
632+
fn in_std(&self) -> bool {
633+
let this = self.eval_context_ref();
634+
this.tcx.def_path(this.frame().instance.def_id()).krate
635+
== this.tcx.def_path(this.tcx.lang_items().start_fn().unwrap()).krate
636+
}
631637
}
632638

633639
/// Check that the number of args is what we expect.

src/shims/posix/foreign_items.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
475475
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
476476
// These shims are enabled only when the caller is in the standard library.
477477
"pthread_attr_getguardsize"
478-
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
478+
if this.in_std() => {
479479
this.check_abi(abi, Abi::C { unwind: false })?;
480480
let &[ref _attr, ref guard_size] = check_arg_count(args)?;
481481
let guard_size = this.deref_operand(guard_size)?;
@@ -488,28 +488,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
488488

489489
| "pthread_attr_init"
490490
| "pthread_attr_destroy"
491-
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
491+
if this.in_std() => {
492492
this.check_abi(abi, Abi::C { unwind: false })?;
493493
let &[_] = check_arg_count(args)?;
494494
this.write_null(dest)?;
495495
}
496496
| "pthread_attr_setstacksize"
497-
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
497+
if this.in_std() => {
498498
this.check_abi(abi, Abi::C { unwind: false })?;
499499
let &[_, _] = check_arg_count(args)?;
500500
this.write_null(dest)?;
501501
}
502502

503503
| "signal"
504504
| "sigaltstack"
505-
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
505+
if this.in_std() => {
506506
this.check_abi(abi, Abi::C { unwind: false })?;
507507
let &[_, _] = check_arg_count(args)?;
508508
this.write_null(dest)?;
509509
}
510510
| "sigaction"
511511
| "mprotect"
512-
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
512+
if this.in_std() => {
513513
this.check_abi(abi, Abi::C { unwind: false })?;
514514
let &[_, _, _] = check_arg_count(args)?;
515515
this.write_null(dest)?;

src/shims/posix/linux/foreign_items.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
207207

208208
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
209209
// These shims are enabled only when the caller is in the standard library.
210-
"pthread_getattr_np"
211-
if this.frame().instance.to_string().starts_with("std::sys::unix::") =>
212-
{
210+
"pthread_getattr_np" if this.in_std() => {
213211
this.check_abi(abi, Abi::C { unwind: false })?;
214212
let &[ref _thread, ref _attr] = check_arg_count(args)?;
215213
this.write_null(dest)?;

src/shims/posix/macos/foreign_items.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
149149

150150
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
151151
// These shims are enabled only when the caller is in the standard library.
152-
"mmap" if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
152+
"mmap" if this.in_std() => {
153153
this.check_abi(abi, Abi::C { unwind: false })?;
154154
// This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value.
155155
let &[ref addr, _, _, _, _, _] = check_arg_count(args)?;

src/shims/windows/foreign_items.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -348,35 +348,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
348348

349349
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
350350
// These shims are enabled only when the caller is in the standard library.
351-
"GetProcessHeap"
352-
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
353-
{
351+
"GetProcessHeap" if this.in_std() => {
354352
this.check_abi(abi, Abi::System { unwind: false })?;
355353
let &[] = check_arg_count(args)?;
356354
// Just fake a HANDLE
357355
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
358356
}
359-
"SetConsoleTextAttribute"
360-
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
361-
{
357+
"SetConsoleTextAttribute" if this.in_std() => {
362358
this.check_abi(abi, Abi::System { unwind: false })?;
363359
#[allow(non_snake_case)]
364360
let &[ref _hConsoleOutput, ref _wAttribute] = check_arg_count(args)?;
365361
// Pretend these does not exist / nothing happened, by returning zero.
366362
this.write_null(dest)?;
367363
}
368-
"AddVectoredExceptionHandler"
369-
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
370-
{
364+
"AddVectoredExceptionHandler" if this.in_std() => {
371365
this.check_abi(abi, Abi::System { unwind: false })?;
372366
#[allow(non_snake_case)]
373367
let &[ref _First, ref _Handler] = check_arg_count(args)?;
374368
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
375369
this.write_scalar(Scalar::from_machine_usize(1, this), dest)?;
376370
}
377-
"SetThreadStackGuarantee"
378-
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
379-
{
371+
"SetThreadStackGuarantee" if this.in_std() => {
380372
this.check_abi(abi, Abi::System { unwind: false })?;
381373
#[allow(non_snake_case)]
382374
let &[_StackSizeInBytes] = check_arg_count(args)?;
@@ -387,7 +379,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
387379
| "EnterCriticalSection"
388380
| "LeaveCriticalSection"
389381
| "DeleteCriticalSection"
390-
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
382+
if this.in_std() =>
391383
{
392384
this.check_abi(abi, Abi::System { unwind: false })?;
393385
#[allow(non_snake_case)]
@@ -401,9 +393,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
401393
// (Windows locks are reentrant, and we have only 1 thread,
402394
// so not doing any futher checks here is at least not incorrect.)
403395
}
404-
"TryEnterCriticalSection"
405-
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
406-
{
396+
"TryEnterCriticalSection" if this.in_std() => {
407397
this.check_abi(abi, Abi::System { unwind: false })?;
408398
#[allow(non_snake_case)]
409399
let &[ref _lpCriticalSection] = check_arg_count(args)?;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! `GetProcessHeap()` is special on Windows that it's only supported within libstd.
2+
//! (On Linux and macOS, it's just always unsupported.)
3+
4+
fn main() {
5+
extern "system" {
6+
fn GetProcessHeap() -> *mut std::ffi::c_void;
7+
}
8+
unsafe {
9+
GetProcessHeap();
10+
//~^ ERROR unsupported operation: can't call foreign function: GetProcessHeap
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! `signal()` is special on Linux and macOS that it's only supported within libstd.
2+
// ignore-windows: No libc on Windows
3+
#![feature(rustc_private)]
4+
5+
extern crate libc;
6+
7+
fn main() {
8+
unsafe {
9+
libc::signal(libc::SIGPIPE, libc::SIG_IGN);
10+
//~^ ERROR unsupported operation: can't call foreign function: signal
11+
}
12+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![no_std]
2+
3+
fn main() {
4+
extern crate std;
5+
}

tests/run-pass/rename_std.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![no_std]
2+
3+
extern crate std as foo;
4+
5+
fn main() {}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! Make sure we can call foreign functions that are only allowed within libstd if we are "libstd"
2+
//! (defining the `start` lang item).
3+
#![feature(lang_items, rustc_private, core_intrinsics)]
4+
#![no_std]
5+
6+
use core::{intrinsics, panic::PanicInfo};
7+
8+
#[lang = "eh_personality"]
9+
fn rust_eh_personality() {}
10+
11+
#[panic_handler]
12+
fn panic_handler(_: &PanicInfo<'_>) -> ! {
13+
intrinsics::abort()
14+
}
15+
16+
#[lang = "start"]
17+
fn start(main: fn(), _argc: isize, _argv: *const *const u8) -> isize {
18+
main();
19+
0
20+
}
21+
22+
fn main() {
23+
#[cfg(unix)]
24+
unsafe {
25+
extern crate libc;
26+
assert_eq!(libc::signal(libc::SIGPIPE, libc::SIG_IGN), 0);
27+
}
28+
#[cfg(windows)]
29+
unsafe {
30+
extern "system" {
31+
fn GetProcessHeap() -> *mut core::ffi::c_void;
32+
fn ExitProcess(code: u32) -> !;
33+
}
34+
assert_eq!(GetProcessHeap() as usize, 1);
35+
// Early exit to avoid the requirement of
36+
// `std::sys::windows::thread_local_key::p_thread_callback`.
37+
ExitProcess(0);
38+
}
39+
}

0 commit comments

Comments
 (0)