@@ -28,16 +28,6 @@ impl DynSym {
2828 }
2929}
3030
31- /// Returned by `emulate_foreign_item_inner`.
32- pub enum EmulateForeignItemResult {
33- /// The caller is expected to jump to the return block.
34- NeedsJumping ,
35- /// Jumping has already been taken care of.
36- AlreadyJumped ,
37- /// The item is not supported.
38- NotSupported ,
39- }
40-
4131impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
4232pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
4333 /// Emulates calling a foreign item, failing if the item is not supported.
@@ -58,84 +48,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
5848 let this = self . eval_context_mut ( ) ;
5949 let tcx = this. tcx . tcx ;
6050
61- // First: functions that diverge.
62- let ret = match ret {
63- None =>
64- match link_name. as_str ( ) {
65- "miri_start_unwind" => {
66- // `check_shim` happens inside `handle_miri_start_unwind`.
67- this. handle_miri_start_unwind ( abi, link_name, args, unwind) ?;
68- return Ok ( None ) ;
69- }
70- // This matches calls to the foreign item `panic_impl`.
71- // The implementation is provided by the function with the `#[panic_handler]` attribute.
72- "panic_impl" => {
73- // We don't use `check_shim` here because we are just forwarding to the lang
74- // item. Argument count checking will be performed when the returned `Body` is
75- // called.
76- this. check_abi_and_shim_symbol_clash ( abi, Abi :: Rust , link_name) ?;
77- let panic_impl_id = tcx. lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
78- let panic_impl_instance = ty:: Instance :: mono ( tcx, panic_impl_id) ;
79- return Ok ( Some ( (
80- this. load_mir ( panic_impl_instance. def , None ) ?,
81- panic_impl_instance,
82- ) ) ) ;
83- }
84- "__rust_alloc_error_handler" => {
85- // Forward to the right symbol that implements this function.
86- let Some ( handler_kind) = this. tcx . alloc_error_handler_kind ( ( ) ) else {
87- // in real code, this symbol does not exist without an allocator
88- throw_unsup_format ! (
89- "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
90- ) ;
91- } ;
92- let name = alloc_error_handler_name ( handler_kind) ;
93- let handler = this
94- . lookup_exported_symbol ( Symbol :: intern ( name) ) ?
95- . expect ( "missing alloc error handler symbol" ) ;
96- return Ok ( Some ( handler) ) ;
97- }
98- #[ rustfmt:: skip]
99- | "exit"
100- | "ExitProcess"
101- => {
102- let exp_abi = if link_name. as_str ( ) == "exit" {
103- Abi :: C { unwind : false }
104- } else {
105- Abi :: System { unwind : false }
106- } ;
107- let [ code] = this. check_shim ( abi, exp_abi, link_name, args) ?;
108- // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
109- let code = this. read_scalar ( code) ?. to_i32 ( ) ?;
110- throw_machine_stop ! ( TerminationInfo :: Exit { code: code. into( ) , leak_check: false } ) ;
111- }
112- "abort" => {
113- let [ ] = this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
114- throw_machine_stop ! ( TerminationInfo :: Abort (
115- "the program aborted execution" . to_owned( )
116- ) )
117- }
118- _ => {
119- if let Some ( body) = this. lookup_exported_symbol ( link_name) ? {
120- return Ok ( Some ( body) ) ;
121- }
122- this. handle_unsupported ( format ! (
123- "can't call (diverging) foreign function: {link_name}"
124- ) ) ?;
125- return Ok ( None ) ;
126- }
127- } ,
128- Some ( p) => p,
129- } ;
51+ // Some shims forward to other MIR bodies.
52+ match link_name. as_str ( ) {
53+ // This matches calls to the foreign item `panic_impl`.
54+ // The implementation is provided by the function with the `#[panic_handler]` attribute.
55+ "panic_impl" => {
56+ // We don't use `check_shim` here because we are just forwarding to the lang
57+ // item. Argument count checking will be performed when the returned `Body` is
58+ // called.
59+ this. check_abi_and_shim_symbol_clash ( abi, Abi :: Rust , link_name) ?;
60+ let panic_impl_id = tcx. lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
61+ let panic_impl_instance = ty:: Instance :: mono ( tcx, panic_impl_id) ;
62+ return Ok ( Some ( (
63+ this. load_mir ( panic_impl_instance. def , None ) ?,
64+ panic_impl_instance,
65+ ) ) ) ;
66+ }
67+ "__rust_alloc_error_handler" => {
68+ // Forward to the right symbol that implements this function.
69+ let Some ( handler_kind) = this. tcx . alloc_error_handler_kind ( ( ) ) else {
70+ // in real code, this symbol does not exist without an allocator
71+ throw_unsup_format ! (
72+ "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
73+ ) ;
74+ } ;
75+ let name = alloc_error_handler_name ( handler_kind) ;
76+ let handler = this
77+ . lookup_exported_symbol ( Symbol :: intern ( name) ) ?
78+ . expect ( "missing alloc error handler symbol" ) ;
79+ return Ok ( Some ( handler) ) ;
80+ }
81+ _ => { }
82+ }
13083
131- // Second: functions that return immediately .
132- match this. emulate_foreign_item_inner ( link_name, abi, args, dest) ? {
133- EmulateForeignItemResult :: NeedsJumping => {
84+ // The rest either implements the logic, or falls back to `lookup_exported_symbol` .
85+ match this. emulate_foreign_item_inner ( link_name, abi, args, dest, unwind ) ? {
86+ EmulateItemResult :: NeedsJumping => {
13487 trace ! ( "{:?}" , this. dump_place( & dest. clone( ) . into( ) ) ) ;
135- this. go_to_block ( ret) ;
88+ this. return_to_block ( ret) ? ;
13689 }
137- EmulateForeignItemResult :: AlreadyJumped => ( ) ,
138- EmulateForeignItemResult :: NotSupported => {
90+ EmulateItemResult :: AlreadyJumped => ( ) ,
91+ EmulateItemResult :: NotSupported => {
13992 if let Some ( body) = this. lookup_exported_symbol ( link_name) ? {
14093 return Ok ( Some ( body) ) ;
14194 }
@@ -243,7 +196,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
243196 abi : Abi ,
244197 args : & [ OpTy < ' tcx , Provenance > ] ,
245198 dest : & MPlaceTy < ' tcx , Provenance > ,
246- ) -> InterpResult < ' tcx , EmulateForeignItemResult > {
199+ unwind : mir:: UnwindAction ,
200+ ) -> InterpResult < ' tcx , EmulateItemResult > {
247201 let this = self . eval_context_mut ( ) ;
248202
249203 // First deal with any external C functions in linked .so file.
@@ -254,7 +208,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
254208 // by the specified `.so` file; we should continue and check if it corresponds to
255209 // a provided shim.
256210 if this. call_external_c_fct ( link_name, dest, args) ? {
257- return Ok ( EmulateForeignItemResult :: NeedsJumping ) ;
211+ return Ok ( EmulateItemResult :: NeedsJumping ) ;
258212 }
259213 }
260214
@@ -298,6 +252,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
298252 // shim, add it to the corresponding submodule.
299253 match link_name. as_str ( ) {
300254 // Miri-specific extern functions
255+ "miri_start_unwind" => {
256+ // `check_shim` happens inside `handle_miri_start_unwind`.
257+ this. handle_miri_start_unwind ( abi, link_name, args, unwind) ?;
258+ return Ok ( EmulateItemResult :: AlreadyJumped ) ;
259+ }
301260 "miri_run_provenance_gc" => {
302261 let [ ] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
303262 this. run_provenance_gc ( ) ;
@@ -362,29 +321,24 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
362321 // Return value: 0 on success, otherwise the size it would have needed.
363322 this. write_int ( if success { 0 } else { needed_size } , dest) ?;
364323 }
365-
366324 // Obtains the size of a Miri backtrace. See the README for details.
367325 "miri_backtrace_size" => {
368326 this. handle_miri_backtrace_size ( abi, link_name, args, dest) ?;
369327 }
370-
371328 // Obtains a Miri backtrace. See the README for details.
372329 "miri_get_backtrace" => {
373330 // `check_shim` happens inside `handle_miri_get_backtrace`.
374331 this. handle_miri_get_backtrace ( abi, link_name, args, dest) ?;
375332 }
376-
377333 // Resolves a Miri backtrace frame. See the README for details.
378334 "miri_resolve_frame" => {
379335 // `check_shim` happens inside `handle_miri_resolve_frame`.
380336 this. handle_miri_resolve_frame ( abi, link_name, args, dest) ?;
381337 }
382-
383338 // Writes the function and file names of a Miri backtrace frame into a user provided buffer. See the README for details.
384339 "miri_resolve_frame_names" => {
385340 this. handle_miri_resolve_frame_names ( abi, link_name, args) ?;
386341 }
387-
388342 // Writes some bytes to the interpreter's stdout/stderr. See the
389343 // README for details.
390344 "miri_write_to_stdout" | "miri_write_to_stderr" => {
@@ -398,7 +352,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
398352 _ => unreachable ! ( ) ,
399353 } ;
400354 }
401-
402355 // Promises that a pointer has a given symbolic alignment.
403356 "miri_promise_symbolic_alignment" => {
404357 use rustc_target:: abi:: AlignFromBytesError ;
@@ -442,6 +395,25 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
442395 }
443396 }
444397
398+ // Aborting the process.
399+ "exit" | "ExitProcess" => {
400+ let exp_abi = if link_name. as_str ( ) == "exit" {
401+ Abi :: C { unwind : false }
402+ } else {
403+ Abi :: System { unwind : false }
404+ } ;
405+ let [ code] = this. check_shim ( abi, exp_abi, link_name, args) ?;
406+ // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
407+ let code = this. read_scalar ( code) ?. to_i32 ( ) ?;
408+ throw_machine_stop ! ( TerminationInfo :: Exit { code: code. into( ) , leak_check: false } ) ;
409+ }
410+ "abort" => {
411+ let [ ] = this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
412+ throw_machine_stop ! ( TerminationInfo :: Abort (
413+ "the program aborted execution" . to_owned( )
414+ ) )
415+ }
416+
445417 // Standard C allocation
446418 "malloc" => {
447419 let [ size] = this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
@@ -504,7 +476,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
504476 "__rust_alloc" => return this. emulate_allocator ( default) ,
505477 "miri_alloc" => {
506478 default ( this) ?;
507- return Ok ( EmulateForeignItemResult :: NeedsJumping ) ;
479+ return Ok ( EmulateItemResult :: NeedsJumping ) ;
508480 }
509481 _ => unreachable ! ( ) ,
510482 }
@@ -564,7 +536,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
564536 }
565537 "miri_dealloc" => {
566538 default ( this) ?;
567- return Ok ( EmulateForeignItemResult :: NeedsJumping ) ;
539+ return Ok ( EmulateItemResult :: NeedsJumping ) ;
568540 }
569541 _ => unreachable ! ( ) ,
570542 }
@@ -966,11 +938,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
966938 shims:: windows:: foreign_items:: EvalContextExt :: emulate_foreign_item_inner (
967939 this, link_name, abi, args, dest,
968940 ) ,
969- _ => Ok ( EmulateForeignItemResult :: NotSupported ) ,
941+ _ => Ok ( EmulateItemResult :: NotSupported ) ,
970942 } ,
971943 } ;
972944 // We only fall through to here if we did *not* hit the `_` arm above,
973945 // i.e., if we actually emulated the function with one of the shims.
974- Ok ( EmulateForeignItemResult :: NeedsJumping )
946+ Ok ( EmulateItemResult :: NeedsJumping )
975947 }
976948}
0 commit comments