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
22
if flags != 0 {
24
- throw_unsup_format ! ( "unknown `miri_get_backtrace ` flags {}" , flags) ;
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,60 @@ 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: u64 = 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_layout = 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 & [ _flags] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
83
+
84
+ let alloc = this. allocate ( array_layout, 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 & [ _flags, ref buf] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
101
+
102
+ let buf_place = this. deref_operand ( buf) ?;
103
+
104
+ let ptr_layout = this. layout_of ( ptr_ty) ?;
105
+
106
+ for ( i, ptr) in ptrs. into_iter ( ) . enumerate ( ) {
107
+ let offset = ptr_layout. size * i. try_into ( ) . unwrap ( ) ;
108
+
109
+ let op_place =
110
+ buf_place. offset ( offset, MemPlaceMeta :: None , ptr_layout, this) ?;
111
+
112
+ this. write_pointer ( ptr, & op_place. into ( ) ) ?;
113
+ }
114
+ }
115
+ _ => throw_unsup_format ! ( "unknown `miri_get_backtrace` flags {}" , flags) ,
116
+ } ;
65
117
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
118
Ok ( ( ) )
75
119
}
76
120
77
- fn handle_miri_resolve_frame (
121
+ fn resolve_frame_pointer (
78
122
& mut self ,
79
- abi : Abi ,
80
- link_name : Symbol ,
81
- args : & [ OpTy < ' tcx , Tag > ] ,
82
- dest : & PlaceTy < ' tcx , Tag > ,
83
- ) -> InterpResult < ' tcx > {
123
+ ptr : & OpTy < ' tcx , Tag > ,
124
+ ) -> InterpResult < ' tcx , ( Instance < ' tcx > , Loc , String , String ) > {
84
125
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
126
93
127
let ptr = this. read_pointer ( ptr) ?;
94
128
// Take apart the pointer, we need its pieces.
@@ -101,6 +135,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
101
135
throw_ub_format ! ( "expected function pointer, found {:?}" , ptr) ;
102
136
} ;
103
137
138
+ let lo =
139
+ this. tcx . sess . source_map ( ) . lookup_char_pos ( BytePos ( offset. bytes ( ) . try_into ( ) . unwrap ( ) ) ) ;
140
+
141
+ let name = fn_instance. to_string ( ) ;
142
+ let filename = lo. file . name . prefer_remapped ( ) . to_string ( ) ;
143
+
144
+ Ok ( ( fn_instance, lo, name, filename) )
145
+ }
146
+
147
+ fn handle_miri_resolve_frame (
148
+ & mut self ,
149
+ abi : Abi ,
150
+ link_name : Symbol ,
151
+ args : & [ OpTy < ' tcx , Tag > ] ,
152
+ dest : & PlaceTy < ' tcx , Tag > ,
153
+ ) -> InterpResult < ' tcx > {
154
+ let this = self . eval_context_mut ( ) ;
155
+ let & [ ref ptr, ref flags] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
156
+
157
+ let flags = this. read_scalar ( flags) ?. to_u64 ( ) ?;
158
+
159
+ let ( fn_instance, lo, name, filename) = this. resolve_frame_pointer ( ptr) ?;
160
+
104
161
// Reconstruct the original function pointer,
105
162
// which we pass to user code.
106
163
let fn_ptr = this. memory . create_fn_alloc ( FnVal :: Instance ( fn_instance) ) ;
@@ -115,23 +172,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
115
172
) ;
116
173
}
117
174
118
- let pos = BytePos ( offset. bytes ( ) . try_into ( ) . unwrap ( ) ) ;
119
- let name = fn_instance. to_string ( ) ;
120
-
121
- let lo = tcx. sess . source_map ( ) . lookup_char_pos ( pos) ;
122
-
123
- let filename = lo. file . name . prefer_remapped ( ) . to_string ( ) ;
124
175
let lineno: u32 = lo. line as u32 ;
125
176
// `lo.col` is 0-based - add 1 to make it 1-based for the caller.
126
177
let colno: u32 = lo. col . 0 as u32 + 1 ;
127
178
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
179
let dest = this. force_allocation ( dest) ?;
136
180
if let ty:: Adt ( adt, _) = dest. layout . ty . kind ( ) {
137
181
if !adt. repr ( ) . c ( ) {
@@ -141,10 +185,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
141
185
}
142
186
}
143
187
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 ( ) ) ?;
188
+ match flags {
189
+ 0 => {
190
+ // These are "mutable" allocations as we consider them to be owned by the callee.
191
+ let name_alloc =
192
+ this. allocate_str ( & name, MiriMemoryKind :: Rust . into ( ) , Mutability :: Mut ) ;
193
+ let filename_alloc =
194
+ this. allocate_str ( & filename, MiriMemoryKind :: Rust . into ( ) , Mutability :: Mut ) ;
195
+
196
+ this. write_immediate (
197
+ name_alloc. to_ref ( this) ,
198
+ & this. mplace_field ( & dest, 0 ) ?. into ( ) ,
199
+ ) ?;
200
+ this. write_immediate (
201
+ filename_alloc. to_ref ( this) ,
202
+ & this. mplace_field ( & dest, 1 ) ?. into ( ) ,
203
+ ) ?;
204
+ }
205
+ 1 => {
206
+ this. write_scalar (
207
+ Scalar :: from_machine_usize ( name. len ( ) . try_into ( ) . unwrap ( ) , this) ,
208
+ & this. mplace_field ( & dest, 0 ) ?. into ( ) ,
209
+ ) ?;
210
+ this. write_scalar (
211
+ Scalar :: from_machine_usize ( filename. len ( ) . try_into ( ) . unwrap ( ) , this) ,
212
+ & this. mplace_field ( & dest, 1 ) ?. into ( ) ,
213
+ ) ?;
214
+ }
215
+ _ => throw_unsup_format ! ( "unknown `miri_resolve_frame` flags {}" , flags) ,
216
+ }
217
+
218
+ this. write_scalar ( Scalar :: from_u32 ( lineno) , & this. mplace_field ( & dest, 2 ) ?. into ( ) ) ?;
219
+ this. write_scalar ( Scalar :: from_u32 ( colno) , & this. mplace_field ( & dest, 3 ) ?. into ( ) ) ?;
148
220
149
221
// Support a 4-field struct for now - this is deprecated
150
222
// and slated for removal.
@@ -154,4 +226,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
154
226
155
227
Ok ( ( ) )
156
228
}
229
+
230
+ fn handle_miri_resolve_frame_names (
231
+ & mut self ,
232
+ abi : Abi ,
233
+ link_name : Symbol ,
234
+ args : & [ OpTy < ' tcx , Tag > ] ,
235
+ ) -> InterpResult < ' tcx > {
236
+ let this = self . eval_context_mut ( ) ;
237
+
238
+ let & [ ref ptr, ref flags, ref name_ptr, ref filename_ptr] =
239
+ this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
240
+
241
+ let flags = this. read_scalar ( flags) ?. to_u64 ( ) ?;
242
+ if flags != 0 {
243
+ throw_unsup_format ! ( "unknown `miri_resolve_frame_names` flags {}" , flags) ;
244
+ }
245
+
246
+ let ( _, _, name, filename) = this. resolve_frame_pointer ( ptr) ?;
247
+
248
+ this. memory . write_bytes ( this. read_pointer ( name_ptr) ?, name. bytes ( ) ) ?;
249
+ this. memory . write_bytes ( this. read_pointer ( filename_ptr) ?, filename. bytes ( ) ) ?;
250
+
251
+ Ok ( ( ) )
252
+ }
157
253
}
0 commit comments