rustc_sanitizers/kcfi/typeid/
mod.rs

1//! Type metadata identifiers for LLVM Kernel Control Flow Integrity (KCFI) and cross-language LLVM
2//! KCFI support for the Rust compiler.
3//!
4//! For more information about LLVM KCFI and cross-language LLVM KCFI support for the Rust compiler,
5//! see the tracking issue #123479.
6
7use std::hash::Hasher;
8
9use rustc_middle::ty::{Instance, InstanceKind, ReifyReason, Ty, TyCtxt};
10use rustc_target::callconv::FnAbi;
11use twox_hash::XxHash64;
12
13pub use crate::cfi::typeid::{TypeIdOptions, itanium_cxx_abi};
14
15/// Returns a KCFI type metadata identifier for the specified FnAbi.
16pub fn typeid_for_fnabi<'tcx>(
17    tcx: TyCtxt<'tcx>,
18    fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
19    options: TypeIdOptions,
20) -> u32 {
21    // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
22    // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
23    let mut hash: XxHash64 = Default::default();
24    hash.write(itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, options).as_bytes());
25    hash.finish() as u32
26}
27
28/// Returns a KCFI type metadata identifier for the specified Instance.
29pub fn typeid_for_instance<'tcx>(
30    tcx: TyCtxt<'tcx>,
31    instance: Instance<'tcx>,
32    mut options: TypeIdOptions,
33) -> u32 {
34    // KCFI support for Rust shares most of its implementation with the CFI support, with some key
35    // differences:
36    //
37    // 1. KCFI performs type tests differently and are implemented as different LLVM passes than CFI
38    //    to not require LTO.
39    // 2. KCFI has the limitation that a function or method may have one type id assigned only.
40    //
41    // Because of the limitation listed above (2), the current KCFI implementation (not CFI) does
42    // reifying of types (i.e., adds shims/trampolines for indirect calls in these cases) for:
43    //
44    // * Supporting casting between function items, closures, and Fn trait objects.
45    // * Supporting methods being cast as function pointers.
46    //
47    // This was implemented for KCFI support in #123106 and #123052 (which introduced the
48    // ReifyReason). The tracking issue for KCFI support for Rust is #123479.
49    if matches!(instance.def, InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr))) {
50        options.insert(TypeIdOptions::USE_CONCRETE_SELF);
51    }
52    // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
53    // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
54    let mut hash: XxHash64 = Default::default();
55    hash.write(itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes());
56    hash.finish() as u32
57}