1
1
use crate :: * ;
2
2
use rustc_ast:: ast:: Mutability ;
3
3
use rustc_middle:: ty:: layout:: LayoutOf as _;
4
- use rustc_middle:: ty:: { self , TypeAndMut } ;
5
- use rustc_span:: { BytePos , Symbol } ;
4
+ use rustc_middle:: ty:: { self , Instance , TypeAndMut } ;
5
+ use rustc_span:: { BytePos , Loc , Symbol } ;
6
6
use rustc_target:: { abi:: Size , spec:: abi:: Abi } ;
7
7
use std:: convert:: TryInto as _;
8
8
9
9
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
10
10
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
11
- fn handle_miri_get_backtrace (
11
+ fn handle_miri_backtrace_size (
12
12
& mut self ,
13
13
abi : Abi ,
14
14
link_name : Symbol ,
15
15
args : & [ OpTy < ' tcx , Tag > ] ,
16
16
dest : & PlaceTy < ' tcx , Tag > ,
17
17
) -> InterpResult < ' tcx > {
18
18
let this = self . eval_context_mut ( ) ;
19
- let tcx = this. tcx ;
20
19
let & [ ref flags] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
21
20
22
21
let flags = this. read_scalar ( flags) ?. to_u64 ( ) ?;
23
- if flags != 0 {
24
- throw_unsup_format ! ( "unknown `miri_get_backtrace ` flags {}" , flags) ;
22
+ if flags != 1 {
23
+ throw_unsup_format ! ( "unknown `miri_backtrace_size ` flags {}" , flags) ;
25
24
}
26
25
26
+ let frame_count = this. active_thread_stack ( ) . len ( ) ;
27
+
28
+ this. write_scalar ( Scalar :: from_machine_usize ( frame_count. try_into ( ) . unwrap ( ) , this) , dest)
29
+ }
30
+
31
+ fn handle_miri_get_backtrace (
32
+ & mut self ,
33
+ abi : Abi ,
34
+ link_name : Symbol ,
35
+ args : & [ OpTy < ' tcx , Tag > ] ,
36
+ dest : & PlaceTy < ' tcx , Tag > ,
37
+ ) -> InterpResult < ' tcx > {
38
+ let this = self . eval_context_mut ( ) ;
39
+ let tcx = this. tcx ;
40
+
41
+ let flags = if let Some ( flags_op) = args. get ( 0 ) {
42
+ this. read_scalar ( flags_op) ?. to_u64 ( ) ?
43
+ } else {
44
+ throw_ub_format ! ( "expected at least 1 argument" )
45
+ } ;
46
+
27
47
let mut data = Vec :: new ( ) ;
28
48
for frame in this. active_thread_stack ( ) . iter ( ) . rev ( ) {
29
49
let mut span = frame. current_span ( ) ;
@@ -49,46 +69,69 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
49
69
} )
50
70
. collect ( ) ;
51
71
52
- let len = ptrs. len ( ) ;
72
+ let len = ptrs. len ( ) . try_into ( ) . unwrap ( ) ;
53
73
54
74
let ptr_ty = tcx. mk_ptr ( TypeAndMut { ty : tcx. types . unit , mutbl : Mutability :: Mut } ) ;
55
75
56
- let array_ty = tcx. mk_array ( ptr_ty, ptrs . len ( ) . try_into ( ) . unwrap ( ) ) ;
76
+ let array_ty = this . layout_of ( tcx. mk_array ( ptr_ty, len) ) . unwrap ( ) ;
57
77
58
- // Write pointers into array
59
- let alloc =
60
- this. allocate ( this. layout_of ( array_ty) . unwrap ( ) , MiriMemoryKind :: Rust . into ( ) ) ?;
61
- for ( i, ptr) in ptrs. into_iter ( ) . enumerate ( ) {
62
- let place = this. mplace_index ( & alloc, i as u64 ) ?;
63
- this. write_pointer ( ptr, & place. into ( ) ) ?;
64
- }
78
+ match flags {
79
+ // storage for pointers is allocated by miri
80
+ // deallocating the slice is undefined behavior with a custom global allocator
81
+ 0 => {
82
+ let & [ _] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
83
+
84
+ let alloc = this. allocate ( array_ty, MiriMemoryKind :: Rust . into ( ) ) ?;
85
+
86
+ // Write pointers into array
87
+ for ( i, ptr) in ptrs. into_iter ( ) . enumerate ( ) {
88
+ let place = this. mplace_index ( & alloc, i as u64 ) ?;
89
+
90
+ this. write_pointer ( ptr, & place. into ( ) ) ?;
91
+ }
92
+
93
+ this. write_immediate (
94
+ Immediate :: new_slice ( Scalar :: from_maybe_pointer ( alloc. ptr , this) , len, this) ,
95
+ dest,
96
+ ) ?;
97
+ }
98
+ // storage for pointers is allocated by the caller
99
+ 1 => {
100
+ let & [ _, ref buf] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
101
+
102
+ this. memory . check_ptr_access_align (
103
+ this. read_pointer ( buf) ?,
104
+ array_ty. size ,
105
+ array_ty. align . abi ,
106
+ CheckInAllocMsg :: MemoryAccessTest ,
107
+ ) ?;
108
+
109
+ let ptr_layout = this. layout_of ( ptr_ty) ?;
110
+
111
+ for ( i, ptr) in ptrs. into_iter ( ) . enumerate ( ) {
112
+ let offset = ptr_layout. size * i. try_into ( ) . unwrap ( ) ;
113
+
114
+ let op_place = this. deref_operand ( buf) ?. offset (
115
+ offset,
116
+ MemPlaceMeta :: None ,
117
+ ptr_layout,
118
+ this,
119
+ ) ?;
120
+
121
+ this. write_pointer ( ptr, & op_place. into ( ) ) ?;
122
+ }
123
+ }
124
+ _ => throw_unsup_format ! ( "unknown `miri_get_backtrace` flags {}" , flags) ,
125
+ } ;
65
126
66
- this. write_immediate (
67
- Immediate :: new_slice (
68
- Scalar :: from_maybe_pointer ( alloc. ptr , this) ,
69
- len. try_into ( ) . unwrap ( ) ,
70
- this,
71
- ) ,
72
- dest,
73
- ) ?;
74
127
Ok ( ( ) )
75
128
}
76
129
77
- fn handle_miri_resolve_frame (
130
+ fn resolve_frame_pointer (
78
131
& mut self ,
79
- abi : Abi ,
80
- link_name : Symbol ,
81
- args : & [ OpTy < ' tcx , Tag > ] ,
82
- dest : & PlaceTy < ' tcx , Tag > ,
83
- ) -> InterpResult < ' tcx > {
132
+ ptr : & OpTy < ' tcx , Tag > ,
133
+ ) -> InterpResult < ' tcx , ( Instance < ' tcx > , Loc ) > {
84
134
let this = self . eval_context_mut ( ) ;
85
- let tcx = this. tcx ;
86
- let & [ ref ptr, ref flags] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
87
-
88
- let flags = this. read_scalar ( flags) ?. to_u64 ( ) ?;
89
- if flags != 0 {
90
- throw_unsup_format ! ( "unknown `miri_resolve_frame` flags {}" , flags) ;
91
- }
92
135
93
136
let ptr = this. read_pointer ( ptr) ?;
94
137
// Take apart the pointer, we need its pieces.
@@ -101,6 +144,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
101
144
throw_ub_format ! ( "expected function pointer, found {:?}" , ptr) ;
102
145
} ;
103
146
147
+ let lo =
148
+ this. tcx . sess . source_map ( ) . lookup_char_pos ( BytePos ( offset. bytes ( ) . try_into ( ) . unwrap ( ) ) ) ;
149
+
150
+ Ok ( ( fn_instance, lo) )
151
+ }
152
+
153
+ fn handle_miri_resolve_frame (
154
+ & mut self ,
155
+ abi : Abi ,
156
+ link_name : Symbol ,
157
+ args : & [ OpTy < ' tcx , Tag > ] ,
158
+ dest : & PlaceTy < ' tcx , Tag > ,
159
+ ) -> InterpResult < ' tcx > {
160
+ let this = self . eval_context_mut ( ) ;
161
+ let & [ ref ptr, ref flags] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
162
+
163
+ let flags = this. read_scalar ( flags) ?. to_u64 ( ) ?;
164
+
165
+ let ( fn_instance, lo) = this. resolve_frame_pointer ( ptr) ?;
166
+
104
167
// Reconstruct the original function pointer,
105
168
// which we pass to user code.
106
169
let fn_ptr = this. memory . create_fn_alloc ( FnVal :: Instance ( fn_instance) ) ;
@@ -115,23 +178,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
115
178
) ;
116
179
}
117
180
118
- let pos = BytePos ( offset. bytes ( ) . try_into ( ) . unwrap ( ) ) ;
119
181
let name = fn_instance. to_string ( ) ;
120
182
121
- let lo = tcx. sess . source_map ( ) . lookup_char_pos ( pos) ;
122
-
123
183
let filename = lo. file . name . prefer_remapped ( ) . to_string ( ) ;
124
184
let lineno: u32 = lo. line as u32 ;
125
185
// `lo.col` is 0-based - add 1 to make it 1-based for the caller.
126
186
let colno: u32 = lo. col . 0 as u32 + 1 ;
127
187
128
- // These are "mutable" allocations as we consider them to be owned by the callee.
129
- let name_alloc = this. allocate_str ( & name, MiriMemoryKind :: Rust . into ( ) , Mutability :: Mut ) ;
130
- let filename_alloc =
131
- this. allocate_str ( & filename, MiriMemoryKind :: Rust . into ( ) , Mutability :: Mut ) ;
132
- let lineno_alloc = Scalar :: from_u32 ( lineno) ;
133
- let colno_alloc = Scalar :: from_u32 ( colno) ;
134
-
135
188
let dest = this. force_allocation ( dest) ?;
136
189
if let ty:: Adt ( adt, _) = dest. layout . ty . kind ( ) {
137
190
if !adt. repr . c ( ) {
@@ -141,10 +194,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
141
194
}
142
195
}
143
196
144
- this. write_immediate ( name_alloc. to_ref ( this) , & this. mplace_field ( & dest, 0 ) ?. into ( ) ) ?;
145
- this. write_immediate ( filename_alloc. to_ref ( this) , & this. mplace_field ( & dest, 1 ) ?. into ( ) ) ?;
146
- this. write_scalar ( lineno_alloc, & this. mplace_field ( & dest, 2 ) ?. into ( ) ) ?;
147
- this. write_scalar ( colno_alloc, & this. mplace_field ( & dest, 3 ) ?. into ( ) ) ?;
197
+ match flags {
198
+ 0 => {
199
+ // These are "mutable" allocations as we consider them to be owned by the callee.
200
+ let name_alloc =
201
+ this. allocate_str ( & name, MiriMemoryKind :: Rust . into ( ) , Mutability :: Mut ) ;
202
+ let filename_alloc =
203
+ this. allocate_str ( & filename, MiriMemoryKind :: Rust . into ( ) , Mutability :: Mut ) ;
204
+
205
+ this. write_immediate (
206
+ name_alloc. to_ref ( this) ,
207
+ & this. mplace_field ( & dest, 0 ) ?. into ( ) ,
208
+ ) ?;
209
+ this. write_immediate (
210
+ filename_alloc. to_ref ( this) ,
211
+ & this. mplace_field ( & dest, 1 ) ?. into ( ) ,
212
+ ) ?;
213
+ }
214
+ 1 => {
215
+ this. write_scalar (
216
+ Scalar :: from_machine_usize ( name. len ( ) . try_into ( ) . unwrap ( ) , this) ,
217
+ & this. mplace_field ( & dest, 0 ) ?. into ( ) ,
218
+ ) ?;
219
+ this. write_scalar (
220
+ Scalar :: from_machine_usize ( filename. len ( ) . try_into ( ) . unwrap ( ) , this) ,
221
+ & this. mplace_field ( & dest, 1 ) ?. into ( ) ,
222
+ ) ?;
223
+ }
224
+ _ => throw_unsup_format ! ( "unknown `miri_resolve_frame` flags {}" , flags) ,
225
+ }
226
+
227
+ this. write_scalar ( Scalar :: from_u32 ( lineno) , & this. mplace_field ( & dest, 2 ) ?. into ( ) ) ?;
228
+ this. write_scalar ( Scalar :: from_u32 ( colno) , & this. mplace_field ( & dest, 3 ) ?. into ( ) ) ?;
148
229
149
230
// Support a 4-field struct for now - this is deprecated
150
231
// and slated for removal.
@@ -154,4 +235,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
154
235
155
236
Ok ( ( ) )
156
237
}
238
+
239
+ fn handle_miri_resolve_frame_names (
240
+ & mut self ,
241
+ abi : Abi ,
242
+ link_name : Symbol ,
243
+ args : & [ OpTy < ' tcx , Tag > ] ,
244
+ dest : & PlaceTy < ' tcx , Tag > ,
245
+ ) -> InterpResult < ' tcx > {
246
+ let this = self . eval_context_mut ( ) ;
247
+
248
+ let & [ ref ptr, ref flags, ref name_ptr, ref filename_ptr] =
249
+ this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
250
+
251
+ let flags = this. read_scalar ( flags) ?. to_u64 ( ) ?;
252
+ if flags != 1 {
253
+ throw_unsup_format ! ( "unknown `miri_backtrace_size` flags {}" , flags) ;
254
+ }
255
+
256
+ let ( fn_instance, lo) = this. resolve_frame_pointer ( ptr) ?;
257
+
258
+ let name = fn_instance. to_string ( ) ;
259
+ let filename = lo. file . name . prefer_remapped ( ) . to_string ( ) ;
260
+
261
+ this. memory . write_bytes ( this. read_pointer ( name_ptr) ?, name. bytes ( ) ) ?;
262
+ this. memory . write_bytes ( this. read_pointer ( filename_ptr) ?, filename. bytes ( ) ) ?;
263
+
264
+ Ok ( ( ) )
265
+ }
157
266
}
0 commit comments