@@ -42,6 +42,9 @@ pub struct GlobalStateInner {
4242 /// they do not have an `AllocExtra`.
4343 /// This is the inverse of `int_to_ptr_map`.
4444 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 > ,
4548 /// A pool of addresses we can reuse for future allocations.
4649 reuse : ReusePool ,
4750 /// Whether an allocation has been exposed or not. This cannot be put
@@ -59,6 +62,7 @@ impl VisitProvenance for GlobalStateInner {
5962 let GlobalStateInner {
6063 int_to_ptr_map : _,
6164 base_addr : _,
65+ alias_addr : _,
6266 reuse : _,
6367 exposed : _,
6468 next_base_addr : _,
@@ -78,6 +82,7 @@ impl GlobalStateInner {
7882 GlobalStateInner {
7983 int_to_ptr_map : Vec :: default ( ) ,
8084 base_addr : FxHashMap :: default ( ) ,
85+ alias_addr : FxHashMap :: default ( ) ,
8186 reuse : ReusePool :: new ( config) ,
8287 exposed : FxHashSet :: default ( ) ,
8388 next_base_addr : stack_addr,
@@ -339,10 +344,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
339344 // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
340345 // must have been called in the past, so we can just look up the address in the map.
341346 let base_addr = * ecx. machine . alloc_addresses . borrow ( ) . base_addr . get ( & alloc_id) . unwrap ( ) ;
342-
343347 // 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) ) )
346362 }
347363}
348364
@@ -368,6 +384,13 @@ impl<'tcx> MiriMachine<'tcx> {
368384 global_state. int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) . unwrap ( ) ;
369385 let removed = global_state. int_to_ptr_map . remove ( pos) ;
370386 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+ }
371394 // We can also remove it from `exposed`, since this allocation can anyway not be returned by
372395 // `alloc_id_from_addr` any more.
373396 global_state. exposed . remove ( & dead_id) ;
@@ -381,6 +404,25 @@ impl<'tcx> MiriMachine<'tcx> {
381404 }
382405 } )
383406 }
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+ }
384426}
385427
386428#[ cfg( test) ]
0 commit comments