[clang] [llvm] [X86] Extend kCFI with a 3-bit arity indicator (PR #121070)

Scott Constable via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 26 11:24:18 PST 2024


================
@@ -181,8 +181,26 @@ void X86AsmPrinter::emitKCFITypeId(const MachineFunction &MF) {
   // Embed the type hash in the X86::MOV32ri instruction to avoid special
   // casing object file parsers.
   EmitKCFITypePadding(MF);
+
+  Register MovReg = X86::EAX;
+  const auto &Triple = MF.getTarget().getTargetTriple();
+  if (Triple.isArch64Bit() && Triple.isOSLinux()) {
+    // Determine the function's arity (i.e., the number of arguments) at the ABI
+    // level by counting the number of parameters that are passed
+    // as registers, such as pointers and 64-bit (or smaller) integers. The
+    // Linux x86-64 ABI allows up to 6 parameters to be passed in GPRs.
+    // Additional parameters or parameters larger than 64 bits may be passed on
+    // the stack, in which case the arity is denoted as 7.
+    const unsigned ArityToRegMap[8] = {X86::EAX, X86::ECX, X86::EDX, X86::EBX,
+                                       X86::ESP, X86::EBP, X86::ESI, X86::EDI};
----------------
scottconstable wrote:

Hi @phoebewang, based on my understanding of kCFI, the `MOVri` instruction emitted by the compiler in each function header will never be executed. The purpose of this instruction is simply to insert the function's kCFI type ID into the header so that it can be verified at the call site before making the call. For example, this is how a kCFI-enforced indirect call looks when the kernel is configured with kCFI:
```
0000000000000010 <foo>:    # foo loads the target address into rax
  ...
  25:   mov    $0x70e5d6ba,%r10d     # 0x70e5d6ba is the kCFI type ID that must be matched at the target
  2b:   add    -0x4(%rax),%r10d         # -0x4(%rax) refers to the immediate operand in the `MOVri` instruction, which holds the kCFI type ID
  2f:   je     33 <foo+0x23>    # If the two type IDs match, then jump to the call; otherwise #UD
  31:   ud2
  33:   call   *%rax      # Note that this will jump directly to the target function, and will not execute the `MOVri`
```
Does this address your concern?

https://github.com/llvm/llvm-project/pull/121070


More information about the llvm-commits mailing list