@@ -31,6 +31,13 @@ pub struct Instance<'tcx> {
3131 pub args : GenericArgsRef < ' tcx > ,
3232}
3333
34+ #[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
35+ #[ derive( TyEncodable , TyDecodable , HashStable ) ]
36+ pub enum ReifyReason {
37+ FnPtr ,
38+ Vtable ,
39+ }
40+
3441#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
3542#[ derive( TyEncodable , TyDecodable , HashStable , TypeFoldable , TypeVisitable , Lift ) ]
3643pub enum InstanceDef < ' tcx > {
@@ -67,7 +74,13 @@ pub enum InstanceDef<'tcx> {
6774 /// Because this is a required part of the function's ABI but can't be tracked
6875 /// as a property of the function pointer, we use a single "caller location"
6976 /// (the definition of the function itself).
70- ReifyShim ( DefId ) ,
77+ ///
78+ /// The second field encodes *why* this shim was created. This allows distinguishing between
79+ /// a `ReifyShim` that appears in a vtable vs one that appears as a function pointer.
80+ ///
81+ /// This field will only be populated if we are compiling in a mode that needs these shims
82+ /// to be separable, currently only when KCFI is enabled.
83+ ReifyShim ( DefId , Option < ReifyReason > ) ,
7184
7285 /// `<fn() as FnTrait>::call_*` (generated `FnTrait` implementation for `fn()` pointers).
7386 ///
@@ -194,7 +207,7 @@ impl<'tcx> InstanceDef<'tcx> {
194207 match self {
195208 InstanceDef :: Item ( def_id)
196209 | InstanceDef :: VTableShim ( def_id)
197- | InstanceDef :: ReifyShim ( def_id)
210+ | InstanceDef :: ReifyShim ( def_id, _ )
198211 | InstanceDef :: FnPtrShim ( def_id, _)
199212 | InstanceDef :: Virtual ( def_id, _)
200213 | InstanceDef :: Intrinsic ( def_id)
@@ -354,7 +367,9 @@ fn fmt_instance(
354367 match instance. def {
355368 InstanceDef :: Item ( _) => Ok ( ( ) ) ,
356369 InstanceDef :: VTableShim ( _) => write ! ( f, " - shim(vtable)" ) ,
357- InstanceDef :: ReifyShim ( _) => write ! ( f, " - shim(reify)" ) ,
370+ InstanceDef :: ReifyShim ( _, None ) => write ! ( f, " - shim(reify)" ) ,
371+ InstanceDef :: ReifyShim ( _, Some ( ReifyReason :: FnPtr ) ) => write ! ( f, " - shim(reify-fnptr)" ) ,
372+ InstanceDef :: ReifyShim ( _, Some ( ReifyReason :: Vtable ) ) => write ! ( f, " - shim(reify-vtable)" ) ,
358373 InstanceDef :: ThreadLocalShim ( _) => write ! ( f, " - shim(tls)" ) ,
359374 InstanceDef :: Intrinsic ( _) => write ! ( f, " - intrinsic" ) ,
360375 InstanceDef :: Virtual ( _, num) => write ! ( f, " - virtual#{num}" ) ,
@@ -476,15 +491,16 @@ impl<'tcx> Instance<'tcx> {
476491 debug ! ( "resolve(def_id={:?}, args={:?})" , def_id, args) ;
477492 // Use either `resolve_closure` or `resolve_for_vtable`
478493 assert ! ( !tcx. is_closure_like( def_id) , "Called `resolve_for_fn_ptr` on closure: {def_id:?}" ) ;
494+ let reason = tcx. sess . is_sanitizer_kcfi_enabled ( ) . then_some ( ReifyReason :: FnPtr ) ;
479495 Instance :: resolve ( tcx, param_env, def_id, args) . ok ( ) . flatten ( ) . map ( |mut resolved| {
480496 match resolved. def {
481497 InstanceDef :: Item ( def) if resolved. def . requires_caller_location ( tcx) => {
482498 debug ! ( " => fn pointer created for function with #[track_caller]" ) ;
483- resolved. def = InstanceDef :: ReifyShim ( def) ;
499+ resolved. def = InstanceDef :: ReifyShim ( def, reason ) ;
484500 }
485501 InstanceDef :: Virtual ( def_id, _) => {
486502 debug ! ( " => fn pointer created for virtual call" ) ;
487- resolved. def = InstanceDef :: ReifyShim ( def_id) ;
503+ resolved. def = InstanceDef :: ReifyShim ( def_id, reason ) ;
488504 }
489505 _ => { }
490506 }
@@ -508,6 +524,7 @@ impl<'tcx> Instance<'tcx> {
508524 debug ! ( " => associated item with unsizeable self: Self" ) ;
509525 Some ( Instance { def : InstanceDef :: VTableShim ( def_id) , args } )
510526 } else {
527+ let reason = tcx. sess . is_sanitizer_kcfi_enabled ( ) . then_some ( ReifyReason :: Vtable ) ;
511528 Instance :: resolve ( tcx, param_env, def_id, args) . ok ( ) . flatten ( ) . map ( |mut resolved| {
512529 match resolved. def {
513530 InstanceDef :: Item ( def) => {
@@ -544,18 +561,18 @@ impl<'tcx> Instance<'tcx> {
544561 // Create a shim for the `FnOnce/FnMut/Fn` method we are calling
545562 // - unlike functions, invoking a closure always goes through a
546563 // trait.
547- resolved = Instance { def : InstanceDef :: ReifyShim ( def_id) , args } ;
564+ resolved = Instance { def : InstanceDef :: ReifyShim ( def_id, reason ) , args } ;
548565 } else {
549566 debug ! (
550567 " => vtable fn pointer created for function with #[track_caller]: {:?}" , def
551568 ) ;
552- resolved. def = InstanceDef :: ReifyShim ( def) ;
569+ resolved. def = InstanceDef :: ReifyShim ( def, reason ) ;
553570 }
554571 }
555572 }
556573 InstanceDef :: Virtual ( def_id, _) => {
557574 debug ! ( " => vtable fn pointer created for virtual call" ) ;
558- resolved. def = InstanceDef :: ReifyShim ( def_id) ;
575+ resolved. def = InstanceDef :: ReifyShim ( def_id, reason )
559576 }
560577 _ => { }
561578 }
0 commit comments