@@ -31,6 +31,28 @@ pub struct Instance<'tcx> {
3131 pub args : GenericArgsRef < ' tcx > ,
3232}
3333
34+ /// Describes why a `ReifyShim` was created. This is needed to distingish a ReifyShim created to
35+ /// adjust for things like `#[track_caller]` in a vtable from a `ReifyShim` created to produce a
36+ /// function pointer from a vtable entry.
37+ /// Currently, this is only used when KCFI is enabled, as only KCFI needs to treat those two
38+ /// `ReifyShim`s differently.
39+ #[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
40+ #[ derive( TyEncodable , TyDecodable , HashStable ) ]
41+ pub enum ReifyReason {
42+ /// The `ReifyShim` was created to produce a function pointer. This happens when:
43+ /// * A vtable entry is directly converted to a function call (e.g. creating a fn ptr from a
44+ /// method on a `dyn` object).
45+ /// * A function with `#[track_caller]` is converted to a function pointer
46+ /// * If KCFI is enabled, creating a function pointer from a method on an object-safe trait.
47+ /// This includes the case of converting `::call`-like methods on closure-likes to function
48+ /// pointers.
49+ FnPtr ,
50+ /// This `ReifyShim` was created to populate a vtable. Currently, this happens when a
51+ /// `#[track_caller]` mismatch occurs between the implementation of a method and the method.
52+ /// This includes the case of `::call`-like methods in closure-likes' vtables.
53+ Vtable ,
54+ }
55+
3456#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
3557#[ derive( TyEncodable , TyDecodable , HashStable , TypeFoldable , TypeVisitable , Lift ) ]
3658pub enum InstanceDef < ' tcx > {
@@ -67,7 +89,13 @@ pub enum InstanceDef<'tcx> {
6789 /// Because this is a required part of the function's ABI but can't be tracked
6890 /// as a property of the function pointer, we use a single "caller location"
6991 /// (the definition of the function itself).
70- ReifyShim ( DefId ) ,
92+ ///
93+ /// The second field encodes *why* this shim was created. This allows distinguishing between
94+ /// a `ReifyShim` that appears in a vtable vs one that appears as a function pointer.
95+ ///
96+ /// This field will only be populated if we are compiling in a mode that needs these shims
97+ /// to be separable, currently only when KCFI is enabled.
98+ ReifyShim ( DefId , Option < ReifyReason > ) ,
7199
72100 /// `<fn() as FnTrait>::call_*` (generated `FnTrait` implementation for `fn()` pointers).
73101 ///
@@ -194,7 +222,7 @@ impl<'tcx> InstanceDef<'tcx> {
194222 match self {
195223 InstanceDef :: Item ( def_id)
196224 | InstanceDef :: VTableShim ( def_id)
197- | InstanceDef :: ReifyShim ( def_id)
225+ | InstanceDef :: ReifyShim ( def_id, _ )
198226 | InstanceDef :: FnPtrShim ( def_id, _)
199227 | InstanceDef :: Virtual ( def_id, _)
200228 | InstanceDef :: Intrinsic ( def_id)
@@ -354,7 +382,9 @@ fn fmt_instance(
354382 match instance. def {
355383 InstanceDef :: Item ( _) => Ok ( ( ) ) ,
356384 InstanceDef :: VTableShim ( _) => write ! ( f, " - shim(vtable)" ) ,
357- InstanceDef :: ReifyShim ( _) => write ! ( f, " - shim(reify)" ) ,
385+ InstanceDef :: ReifyShim ( _, None ) => write ! ( f, " - shim(reify)" ) ,
386+ InstanceDef :: ReifyShim ( _, Some ( ReifyReason :: FnPtr ) ) => write ! ( f, " - shim(reify-fnptr)" ) ,
387+ InstanceDef :: ReifyShim ( _, Some ( ReifyReason :: Vtable ) ) => write ! ( f, " - shim(reify-vtable)" ) ,
358388 InstanceDef :: ThreadLocalShim ( _) => write ! ( f, " - shim(tls)" ) ,
359389 InstanceDef :: Intrinsic ( _) => write ! ( f, " - intrinsic" ) ,
360390 InstanceDef :: Virtual ( _, num) => write ! ( f, " - virtual#{num}" ) ,
@@ -476,15 +506,16 @@ impl<'tcx> Instance<'tcx> {
476506 debug ! ( "resolve(def_id={:?}, args={:?})" , def_id, args) ;
477507 // Use either `resolve_closure` or `resolve_for_vtable`
478508 assert ! ( !tcx. is_closure_like( def_id) , "Called `resolve_for_fn_ptr` on closure: {def_id:?}" ) ;
509+ let reason = tcx. sess . is_sanitizer_kcfi_enabled ( ) . then_some ( ReifyReason :: FnPtr ) ;
479510 Instance :: resolve ( tcx, param_env, def_id, args) . ok ( ) . flatten ( ) . map ( |mut resolved| {
480511 match resolved. def {
481512 InstanceDef :: Item ( def) if resolved. def . requires_caller_location ( tcx) => {
482513 debug ! ( " => fn pointer created for function with #[track_caller]" ) ;
483- resolved. def = InstanceDef :: ReifyShim ( def) ;
514+ resolved. def = InstanceDef :: ReifyShim ( def, reason ) ;
484515 }
485516 InstanceDef :: Virtual ( def_id, _) => {
486517 debug ! ( " => fn pointer created for virtual call" ) ;
487- resolved. def = InstanceDef :: ReifyShim ( def_id) ;
518+ resolved. def = InstanceDef :: ReifyShim ( def_id, reason ) ;
488519 }
489520 _ => { }
490521 }
@@ -508,6 +539,7 @@ impl<'tcx> Instance<'tcx> {
508539 debug ! ( " => associated item with unsizeable self: Self" ) ;
509540 Some ( Instance { def : InstanceDef :: VTableShim ( def_id) , args } )
510541 } else {
542+ let reason = tcx. sess . is_sanitizer_kcfi_enabled ( ) . then_some ( ReifyReason :: Vtable ) ;
511543 Instance :: resolve ( tcx, param_env, def_id, args) . ok ( ) . flatten ( ) . map ( |mut resolved| {
512544 match resolved. def {
513545 InstanceDef :: Item ( def) => {
@@ -544,18 +576,18 @@ impl<'tcx> Instance<'tcx> {
544576 // Create a shim for the `FnOnce/FnMut/Fn` method we are calling
545577 // - unlike functions, invoking a closure always goes through a
546578 // trait.
547- resolved = Instance { def : InstanceDef :: ReifyShim ( def_id) , args } ;
579+ resolved = Instance { def : InstanceDef :: ReifyShim ( def_id, reason ) , args } ;
548580 } else {
549581 debug ! (
550582 " => vtable fn pointer created for function with #[track_caller]: {:?}" , def
551583 ) ;
552- resolved. def = InstanceDef :: ReifyShim ( def) ;
584+ resolved. def = InstanceDef :: ReifyShim ( def, reason ) ;
553585 }
554586 }
555587 }
556588 InstanceDef :: Virtual ( def_id, _) => {
557589 debug ! ( " => vtable fn pointer created for virtual call" ) ;
558- resolved. def = InstanceDef :: ReifyShim ( def_id) ;
590+ resolved. def = InstanceDef :: ReifyShim ( def_id, reason )
559591 }
560592 _ => { }
561593 }
0 commit comments