@@ -28,16 +28,6 @@ impl DynSym {
28
28
}
29
29
}
30
30
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
-
41
31
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
42
32
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
43
33
/// 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> {
58
48
let this = self . eval_context_mut ( ) ;
59
49
let tcx = this. tcx . tcx ;
60
50
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
+ }
130
83
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 => {
134
87
trace ! ( "{:?}" , this. dump_place( & dest. clone( ) . into( ) ) ) ;
135
- this. go_to_block ( ret) ;
88
+ this. return_to_block ( ret) ? ;
136
89
}
137
- EmulateForeignItemResult :: AlreadyJumped => ( ) ,
138
- EmulateForeignItemResult :: NotSupported => {
90
+ EmulateItemResult :: AlreadyJumped => ( ) ,
91
+ EmulateItemResult :: NotSupported => {
139
92
if let Some ( body) = this. lookup_exported_symbol ( link_name) ? {
140
93
return Ok ( Some ( body) ) ;
141
94
}
@@ -243,7 +196,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
243
196
abi : Abi ,
244
197
args : & [ OpTy < ' tcx , Provenance > ] ,
245
198
dest : & MPlaceTy < ' tcx , Provenance > ,
246
- ) -> InterpResult < ' tcx , EmulateForeignItemResult > {
199
+ unwind : mir:: UnwindAction ,
200
+ ) -> InterpResult < ' tcx , EmulateItemResult > {
247
201
let this = self . eval_context_mut ( ) ;
248
202
249
203
// First deal with any external C functions in linked .so file.
@@ -254,7 +208,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
254
208
// by the specified `.so` file; we should continue and check if it corresponds to
255
209
// a provided shim.
256
210
if this. call_external_c_fct ( link_name, dest, args) ? {
257
- return Ok ( EmulateForeignItemResult :: NeedsJumping ) ;
211
+ return Ok ( EmulateItemResult :: NeedsJumping ) ;
258
212
}
259
213
}
260
214
@@ -298,6 +252,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
298
252
// shim, add it to the corresponding submodule.
299
253
match link_name. as_str ( ) {
300
254
// 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
+ }
301
260
"miri_run_provenance_gc" => {
302
261
let [ ] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
303
262
this. run_provenance_gc ( ) ;
@@ -362,29 +321,24 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
362
321
// Return value: 0 on success, otherwise the size it would have needed.
363
322
this. write_int ( if success { 0 } else { needed_size } , dest) ?;
364
323
}
365
-
366
324
// Obtains the size of a Miri backtrace. See the README for details.
367
325
"miri_backtrace_size" => {
368
326
this. handle_miri_backtrace_size ( abi, link_name, args, dest) ?;
369
327
}
370
-
371
328
// Obtains a Miri backtrace. See the README for details.
372
329
"miri_get_backtrace" => {
373
330
// `check_shim` happens inside `handle_miri_get_backtrace`.
374
331
this. handle_miri_get_backtrace ( abi, link_name, args, dest) ?;
375
332
}
376
-
377
333
// Resolves a Miri backtrace frame. See the README for details.
378
334
"miri_resolve_frame" => {
379
335
// `check_shim` happens inside `handle_miri_resolve_frame`.
380
336
this. handle_miri_resolve_frame ( abi, link_name, args, dest) ?;
381
337
}
382
-
383
338
// Writes the function and file names of a Miri backtrace frame into a user provided buffer. See the README for details.
384
339
"miri_resolve_frame_names" => {
385
340
this. handle_miri_resolve_frame_names ( abi, link_name, args) ?;
386
341
}
387
-
388
342
// Writes some bytes to the interpreter's stdout/stderr. See the
389
343
// README for details.
390
344
"miri_write_to_stdout" | "miri_write_to_stderr" => {
@@ -398,7 +352,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
398
352
_ => unreachable ! ( ) ,
399
353
} ;
400
354
}
401
-
402
355
// Promises that a pointer has a given symbolic alignment.
403
356
"miri_promise_symbolic_alignment" => {
404
357
use rustc_target:: abi:: AlignFromBytesError ;
@@ -442,6 +395,25 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
442
395
}
443
396
}
444
397
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
+
445
417
// Standard C allocation
446
418
"malloc" => {
447
419
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> {
504
476
"__rust_alloc" => return this. emulate_allocator ( default) ,
505
477
"miri_alloc" => {
506
478
default ( this) ?;
507
- return Ok ( EmulateForeignItemResult :: NeedsJumping ) ;
479
+ return Ok ( EmulateItemResult :: NeedsJumping ) ;
508
480
}
509
481
_ => unreachable ! ( ) ,
510
482
}
@@ -564,7 +536,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
564
536
}
565
537
"miri_dealloc" => {
566
538
default ( this) ?;
567
- return Ok ( EmulateForeignItemResult :: NeedsJumping ) ;
539
+ return Ok ( EmulateItemResult :: NeedsJumping ) ;
568
540
}
569
541
_ => unreachable ! ( ) ,
570
542
}
@@ -966,11 +938,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
966
938
shims:: windows:: foreign_items:: EvalContextExt :: emulate_foreign_item_inner (
967
939
this, link_name, abi, args, dest,
968
940
) ,
969
- _ => Ok ( EmulateForeignItemResult :: NotSupported ) ,
941
+ _ => Ok ( EmulateItemResult :: NotSupported ) ,
970
942
} ,
971
943
} ;
972
944
// We only fall through to here if we did *not* hit the `_` arm above,
973
945
// i.e., if we actually emulated the function with one of the shims.
974
- Ok ( EmulateForeignItemResult :: NeedsJumping )
946
+ Ok ( EmulateItemResult :: NeedsJumping )
975
947
}
976
948
}
0 commit comments