@@ -42,6 +42,9 @@ pub struct GlobalStateInner {
42
42
/// they do not have an `AllocExtra`.
43
43
/// This is the inverse of `int_to_ptr_map`.
44
44
base_addr : FxHashMap < AllocId , u64 > ,
45
+ /// An optional alias for the allocation, where features such as TBI have been used to modify
46
+ /// unused bits in a pointer.
47
+ alias_addr : FxHashMap < AllocId , u64 > ,
45
48
/// A pool of addresses we can reuse for future allocations.
46
49
reuse : ReusePool ,
47
50
/// Whether an allocation has been exposed or not. This cannot be put
@@ -59,6 +62,7 @@ impl VisitProvenance for GlobalStateInner {
59
62
let GlobalStateInner {
60
63
int_to_ptr_map : _,
61
64
base_addr : _,
65
+ alias_addr : _,
62
66
reuse : _,
63
67
exposed : _,
64
68
next_base_addr : _,
@@ -78,6 +82,7 @@ impl GlobalStateInner {
78
82
GlobalStateInner {
79
83
int_to_ptr_map : Vec :: default ( ) ,
80
84
base_addr : FxHashMap :: default ( ) ,
85
+ alias_addr : FxHashMap :: default ( ) ,
81
86
reuse : ReusePool :: new ( config) ,
82
87
exposed : FxHashSet :: default ( ) ,
83
88
next_base_addr : stack_addr,
@@ -339,10 +344,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
339
344
// This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
340
345
// must have been called in the past, so we can just look up the address in the map.
341
346
let base_addr = * ecx. machine . alloc_addresses . borrow ( ) . base_addr . get ( & alloc_id) . unwrap ( ) ;
342
-
343
347
// Wrapping "addr - base_addr"
344
- let rel_offset = ecx. truncate_to_target_usize ( addr. bytes ( ) . wrapping_sub ( base_addr) ) ;
345
- Some ( ( alloc_id, Size :: from_bytes ( rel_offset) ) )
348
+ let base_offset = ecx. truncate_to_target_usize ( addr. bytes ( ) . wrapping_sub ( base_addr) ) ;
349
+
350
+ // If there's an alias, then `offset` should be the offset from the closest out of `base_addr` or the
351
+ // alias' address. Generally, any interaction in user code should use the alias (if one's been set), but
352
+ // cleaning up the stack frame may still use the base address.
353
+ let offset =
354
+ if let Some ( alias) = ecx. machine . alloc_addresses . borrow ( ) . alias_addr . get ( & alloc_id) {
355
+ let alias_offset = ecx. truncate_to_target_usize ( addr. bytes ( ) . wrapping_sub ( * alias) ) ;
356
+ base_offset. min ( alias_offset)
357
+ } else {
358
+ base_offset
359
+ } ;
360
+
361
+ Some ( ( alloc_id, Size :: from_bytes ( offset) ) )
346
362
}
347
363
}
348
364
@@ -368,6 +384,13 @@ impl<'tcx> MiriMachine<'tcx> {
368
384
global_state. int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) . unwrap ( ) ;
369
385
let removed = global_state. int_to_ptr_map . remove ( pos) ;
370
386
assert_eq ! ( removed, ( addr, dead_id) ) ; // double-check that we removed the right thing
387
+ // Remove the alias for this allocation, if there is one.
388
+ if let Some ( alias) = global_state. alias_addr . get ( & dead_id) {
389
+ let pos =
390
+ global_state. int_to_ptr_map . binary_search_by_key ( alias, |( addr, _) | * addr) . unwrap ( ) ;
391
+ let removed = global_state. int_to_ptr_map . remove ( pos) ;
392
+ assert_eq ! ( removed, ( * alias, dead_id) ) ;
393
+ }
371
394
// We can also remove it from `exposed`, since this allocation can anyway not be returned by
372
395
// `alloc_id_from_addr` any more.
373
396
global_state. exposed . remove ( & dead_id) ;
@@ -381,6 +404,25 @@ impl<'tcx> MiriMachine<'tcx> {
381
404
}
382
405
} )
383
406
}
407
+
408
+ /// Set the active alias for the allocation. Note that any dereference of a pointer to this allocation *must* use this alias,
409
+ /// and the alias *must* be valid at the architectural level (eg, TBI on AArch64). Any prior aliases will be invalidated, though
410
+ /// the original `base_addr` will remain valid for cleaning up allocations later.
411
+ pub fn set_alloc_alias ( & mut self , id : AllocId , new : u64 ) {
412
+ let global_state = self . alloc_addresses . get_mut ( ) ;
413
+ if let Some ( alias) = global_state. alias_addr . insert ( id, new) {
414
+ // Remove the old alias' int->ptr mapping.
415
+ let pos = global_state
416
+ . int_to_ptr_map
417
+ . binary_search_by_key ( & alias, |( addr, _) | * addr)
418
+ . unwrap ( ) ;
419
+ let removed = global_state. int_to_ptr_map . remove ( pos) ;
420
+ assert_eq ! ( removed, ( alias, id) ) ;
421
+ }
422
+ let new_pos =
423
+ global_state. int_to_ptr_map . binary_search_by_key ( & new, |( addr, _) | * addr) . unwrap_err ( ) ;
424
+ global_state. int_to_ptr_map . insert ( new_pos, ( new, id) ) ;
425
+ }
384
426
}
385
427
386
428
#[ cfg( test) ]
0 commit comments