@@ -259,20 +259,25 @@ impl ProvenanceExtra {
259
259
260
260
/// Extra per-allocation data
261
261
#[ derive( Debug , Clone ) ]
262
- pub struct AllocExtra {
262
+ pub struct AllocExtra < ' tcx > {
263
263
/// Global state of the borrow tracker, if enabled.
264
264
pub borrow_tracker : Option < borrow_tracker:: AllocState > ,
265
- /// Data race detection via the use of a vector-clock,
266
- /// this is only added if it is enabled.
265
+ /// Data race detection via the use of a vector-clock.
266
+ /// This is only added if it is enabled.
267
267
pub data_race : Option < data_race:: AllocState > ,
268
- /// Weak memory emulation via the use of store buffers,
269
- /// this is only added if it is enabled.
268
+ /// Weak memory emulation via the use of store buffers.
269
+ /// This is only added if it is enabled.
270
270
pub weak_memory : Option < weak_memory:: AllocState > ,
271
+ /// A backtrace to where this allocation was allocated.
272
+ /// As this is recorded for leak reports, it only exists
273
+ /// if this allocation is leakable. The backtrace is not
274
+ /// pruned yet; that should be done before printing it.
275
+ pub backtrace : Option < Vec < FrameInfo < ' tcx > > > ,
271
276
}
272
277
273
- impl VisitTags for AllocExtra {
278
+ impl VisitTags for AllocExtra < ' _ > {
274
279
fn visit_tags ( & self , visit : & mut dyn FnMut ( BorTag ) ) {
275
- let AllocExtra { borrow_tracker, data_race, weak_memory } = self ;
280
+ let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace : _ } = self ;
276
281
277
282
borrow_tracker. visit_tags ( visit) ;
278
283
data_race. visit_tags ( visit) ;
@@ -473,12 +478,17 @@ pub struct MiriMachine<'mir, 'tcx> {
473
478
pub ( crate ) gc_interval : u32 ,
474
479
/// The number of blocks that passed since the last BorTag GC pass.
475
480
pub ( crate ) since_gc : u32 ,
481
+
476
482
/// The number of CPUs to be reported by miri.
477
483
pub ( crate ) num_cpus : u32 ,
484
+
478
485
/// Determines Miri's page size and associated values
479
486
pub ( crate ) page_size : u64 ,
480
487
pub ( crate ) stack_addr : u64 ,
481
488
pub ( crate ) stack_size : u64 ,
489
+
490
+ /// Whether to collect a backtrace when each allocation is created, just in case it leaks.
491
+ pub ( crate ) collect_leak_backtraces : bool ,
482
492
}
483
493
484
494
impl < ' mir , ' tcx > MiriMachine < ' mir , ' tcx > {
@@ -587,6 +597,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
587
597
page_size,
588
598
stack_addr,
589
599
stack_size,
600
+ collect_leak_backtraces : config. collect_leak_backtraces ,
590
601
}
591
602
}
592
603
@@ -734,6 +745,7 @@ impl VisitTags for MiriMachine<'_, '_> {
734
745
page_size : _,
735
746
stack_addr : _,
736
747
stack_size : _,
748
+ collect_leak_backtraces : _,
737
749
} = self ;
738
750
739
751
threads. visit_tags ( visit) ;
@@ -779,7 +791,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
779
791
type ExtraFnVal = Dlsym ;
780
792
781
793
type FrameExtra = FrameExtra < ' tcx > ;
782
- type AllocExtra = AllocExtra ;
794
+ type AllocExtra = AllocExtra < ' tcx > ;
783
795
784
796
type Provenance = Provenance ;
785
797
type ProvenanceExtra = ProvenanceExtra ;
@@ -973,9 +985,24 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
973
985
)
974
986
} ) ;
975
987
let buffer_alloc = ecx. machine . weak_memory . then ( weak_memory:: AllocState :: new_allocation) ;
988
+
989
+ // If an allocation is leaked, we want to report a backtrace to indicate where it was
990
+ // allocated. We don't need to record a backtrace for allocations which are allowed to
991
+ // leak.
992
+ let backtrace = if kind. may_leak ( ) || !ecx. machine . collect_leak_backtraces {
993
+ None
994
+ } else {
995
+ Some ( ecx. generate_stacktrace ( ) )
996
+ } ;
997
+
976
998
let alloc: Allocation < Provenance , Self :: AllocExtra > = alloc. adjust_from_tcx (
977
999
& ecx. tcx ,
978
- AllocExtra { borrow_tracker, data_race : race_alloc, weak_memory : buffer_alloc } ,
1000
+ AllocExtra {
1001
+ borrow_tracker,
1002
+ data_race : race_alloc,
1003
+ weak_memory : buffer_alloc,
1004
+ backtrace,
1005
+ } ,
979
1006
|ptr| ecx. global_base_pointer ( ptr) ,
980
1007
) ?;
981
1008
Ok ( Cow :: Owned ( alloc) )
@@ -1055,7 +1082,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
1055
1082
fn before_memory_read (
1056
1083
_tcx : TyCtxt < ' tcx > ,
1057
1084
machine : & Self ,
1058
- alloc_extra : & AllocExtra ,
1085
+ alloc_extra : & AllocExtra < ' tcx > ,
1059
1086
( alloc_id, prov_extra) : ( AllocId , Self :: ProvenanceExtra ) ,
1060
1087
range : AllocRange ,
1061
1088
) -> InterpResult < ' tcx > {
@@ -1075,7 +1102,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
1075
1102
fn before_memory_write (
1076
1103
_tcx : TyCtxt < ' tcx > ,
1077
1104
machine : & mut Self ,
1078
- alloc_extra : & mut AllocExtra ,
1105
+ alloc_extra : & mut AllocExtra < ' tcx > ,
1079
1106
( alloc_id, prov_extra) : ( AllocId , Self :: ProvenanceExtra ) ,
1080
1107
range : AllocRange ,
1081
1108
) -> InterpResult < ' tcx > {
@@ -1095,7 +1122,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
1095
1122
fn before_memory_deallocation (
1096
1123
_tcx : TyCtxt < ' tcx > ,
1097
1124
machine : & mut Self ,
1098
- alloc_extra : & mut AllocExtra ,
1125
+ alloc_extra : & mut AllocExtra < ' tcx > ,
1099
1126
( alloc_id, prove_extra) : ( AllocId , Self :: ProvenanceExtra ) ,
1100
1127
range : AllocRange ,
1101
1128
) -> InterpResult < ' tcx > {
0 commit comments