Cheri LLVM

Reference1:

Todones

  • Passes to
    • tracking data with attributes, such as privileged;

Address space 200

data layout string

(Programmer’s Guide, 2015)

The data layout string is modified to define the address space for alloca instructions. It is assumed that, within a compilation unit, every alloca returns a pointer in the same address space. By default, this address space is 0, but when targeting the pure-capability ABI, it is set to 200.

In the MIPS back end, a pass will replace each of these alloca (all all their uses) with one in address space 0, followed by calls to two intrinsics. The first intrinsic derives a $c11-relative capability from the integer value. The second sets its length to the size of alloca. (LLM: how does this look like in the code???)

This allows the normal MIPS stack pointer to be used as an offset within $c11.

Compatability with other passes: A lots of optimizations, in particular scalar evolution and the SLP vectorizer, assume that the size of a pointer is the size of an integer that can express its range. As a result, they will attempt to create i256 operands to various pointer arithmetic operations. To avoid this, the DataLayout class now provides a few variants of getPointerBaseSize() methods, which get the size of the base of a fat pointer or capability. For non-capability pointer types, these simply return the size.

(os_bench cheritypes/sandbox_hello/) In Cheri Hybrid compilation mode: Cheri LLVM will generate IR with the following layout specification:

target datalayout = "E-m:e-pf200:128:128:128:64-i8:8:32-i16:16:32-i64:64-n32:64-S128"

LLVM language ref: data layout string.

  • “E”: big-endian target data model;
  • “m:e”: ELF mangling: private symbols get a .L prefix;
  • “pf200:128:128:128:64”:

SelectionDAG types

(Programmer’s Guide, 2015)

Q1: Pointer size in code generator.

In LLVM, one of the early parts of the target-independent code generator replaces all pointers with an integer of the correct size. On CHERI, this would be an i256, which is not a valid type for the target and would cause other problems if the definition allowed the rest of the code generator to assume that 256-bit integers were supported.

To avoid this, we add an MVT::iFATPIR machine value type to the code generator. This can be used for any non-integer pointer and can be pattern matched by any of the tablegen-generated machine code.

We also add ISD::INTTOPTR and ISD::PTRTOINT SelectionDAG nodes. These represent conversions between MVT::iFATPTR and integer types and are generated from any address space cast instructions between address space 0 and 200, as well as inttoptr and ptrtoint IR instructions. In the MIPS back end, these expend to CToPtr and CFromPtr instructions.

Q2: Type violation in pointer arithmetic.

The conventional way of expressing pointer arithmetic in the SelectionDAG is via normal arithmetic nodes. This works because the MVT::iPTR type is lowered to an integer type (typically MVT::i32 or MVT::i64) in the legalization phase. The ADD selectionDAG node has the invariant that the operands must be the same type. This does not work for pointer addition with fat pointers, because one operand is the pointer and the other is the integer value that is being added to the pointer, which will typically be MVT::iFATPTR and MVT::i64 respectively for CHERI.

To address this, we add another new SelectionDAG node: ISD::PTRADD. This is lowered to CIncOffset in MIPS back end, but may later be folded to use a complex addressing mode.

LLVM IR Intrinsics

(Programmer’s Guide, 2015)

MIPS back end exposes a number of intrinsics in LLVM IR.

2015-table-5.1-llvm-intrinsics

clang/test/CodeGen/cheri/cheri128.c

// CHECK128: target datalayout = "E-m:e-pf200:128:128:128:64-i8:8:32-i16:16:32-i64:64-n32:64-S128"
// CHECK256: target datalayout = "E-m:e-pf200:256:256:256:64-i8:8:32-i16:16:32-i64:64-n32:64-S256"

LLVM changes in code

grep cheri

Frontend:

IR level:

  • include/llvm/IR/Cheri.h
  • include/llvm/IR/CallingConv.h
  • include/llvm/Transforms/Utils/CheriSetBounds.h ———-
  • lib/Transforms/Utils/CheriLogSetBoundsPass.cpp ———-
  • lib/Transforms/Utils/CheriSetBounds.cpp ———-
  • lib/Transforms/Utils/SimplifyCFG.cpp
  • lib/Transforms/CHERICap/PureCapABICalls.cpp
  • lib/Transforms/CHERICap/FoldCapIntrinsics.cpp
  • lib/Transforms/InstCombine/InstCombineAddSub.cpp
  • lib/Transforms/InstCombine/InstCombineCalls.cpp
  • lib/IR/Instructions.cpp ———-
  • lib/IR/Function.cpp
  • lib/IR/DataLayout.cpp ———-
  • lib/IR/AsmWriter.cpp
  • lib/IR/Verifier.cpp
  • lib/Analysis/CaptureTracking.cpp
  • lib/Analysis/ValueTracking.cpp
  • lib/Analysis/ConstantFolding.cpp

Backend:

  • include/llvm/MC/MCTargetOptions.h
  • include/llvm/MC/MCAsmMacro.h
  • include/llvm/MC/MCStreamer.h
  • include/llvm/MC/MCDwarf.h
  • include/llvm/BinaryFormat/ELF.h
  • include/llvm/ADT/Triple.h
  • include/llvm/Object/ELFObjectFile.h
  • include/llvm/Object/RelocVisitor.h

  • include/llvm/CodeGen/Passes.h ************

  • lib/CodeGen/LLVMTargetMachine.cpp

  • lib/CodeGen/ValueTypes.cpp

  • lib/CodeGen/TargetLoweringObjectFileImpl.cpp

  • lib/CodeGen/InlineSpiller.cpp

  • lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

  • lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

  • lib/CodeGen/AsmPrinter/AsmPrinter.cpp

  • lib/Target/Mips/Mips.h

  • lib/Target/Mips/MipsFastISel.cpp

  • lib/Target/Mips/MipsAsmPrinter.cpp

  • lib/Target/Mips/MipsTargetMachine.h

  • lib/Target/Mips/MipsTargetMachine.cpp

  • lib/Target/Mips/MipsSubtarget.h

  • lib/Target/Mips/MipsSubtarget.cpp

  • lib/Target/Mips/MipsInstrInfo.cpp

  • lib/Target/Mips/MipsRegisterInfo.cpp

  • lib/Target/Mips/MipsExpandPseudo.cpp

  • lib/Target/Mips/MipsISelLowering.h

  • lib/Target/Mips/MipsISelLowering.cpp

  • lib/Target/Mips/MipsSelectionDAGInfo.cpp ——————–

  • lib/Target/Mips/MipsSEISelLowering.cpp

  • lib/Target/Mips/MipsSEISelDAGToDAG.h

  • lib/Target/Mips/MipsSEISelDAGToDAG.cpp

  • lib/Target/Mips/MipsSEFrameLowering.cpp

  • lib/Target/Mips/MipsSEInstrInfo.cpp

  • lib/Target/Mips/MipsSERegisterInfo.cpp

  • lib/Target/Mips/MipsMachineFunction.cpp

  • lib/Target/Mips/MipsBranchExpansion.cpp

  • lib/Target/Mips/MipsDelaySlotFiller.cpp

  • lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp

  • lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h

  • lib/Target/Mips/MCTargetDesc/MipsABIInfo.h

  • lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp

  • lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h

  • lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp

  • lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h

  • lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp

  • lib/Target/Mips/MCTargetDesc/MipsMCExpr.hlib/AsmParser/LLParser.cpp

  • lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp

  • lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h

  • lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp

  • lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h

  • lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp

  • lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp

  • lib/Target/Mips/AsmParser/MipsAsmParser.cpp

  • lib/Target/Mips/Disassembler/MipsDisassembler.cpp

  • lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp

  • lib/Target/Mips/CheriStackInvalidatePass.cpp

  • lib/Target/Mips/CheriExpandIntrinsicsPass.cpp

  • lib/Target/Mips/CheriRangeChecker.cpp

  • lib/Target/Mips/CheriPureCapABI.cpp

  • lib/Target/Mips/CheriLoopPointerDecanonicalize.cpp

  • lib/Target/Mips/CheriAddressingModeFolder.cpp

  • lib/Target/Mips/Cheri128FailHard.cpp

  • lib/MC/MCStreamer.cpp

  • lib/MC/MCTargetOptions.cpp

  • lib/MC/ELFObjectWriter.cpp

  • lib/MC/MCAsmStreamer.cpp

  • lib/MC/MCObjectFileInfo.cpp

  • lib/MC/MCParser/AsmLexer.cpp

  • lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

  • include/llvm/Support/CheriSetBounds.h

  • include/llvm/Support/MipsABIFlags.h

  • lib/Support/CheriSetBounds.cpp

  • lib/Support/Triple.cpp

  • lib/ObjectYAML/ELFYAML.cpp

  • lib/AsmParser/LLParser.cpp

tools:

  • tools/llvm-readobj/llvm-readobj.cpp
  • tools/llvm-readobj/ObjDumper.h
  • tools/llvm-readobj/ELFDumper.cpp
  • tools/llvm-objdump/llvm-objdump.cpp
  • tools/llc/llc.cpp
  • tools/opt/opt.cpp

EG: BasicAA

BasicAA.

BasicAA: Analysis pass providing a never-invalidated alias analysis result.

  • llvm/include/llvm/IR/DataLayout.h/.cpp

    • getMaxPointerSize();// returns the maximum pointer size over all address space.
  • Builtin
  • Reference 1 From github/clang old repo Feb 2019: clang/include/clang/Basic/Builtins.def: __builtin_cheri_* clang/include/clang/Basic/BuiltinsMips.def: __builtin_mips_cheri_* reference ↩

  • Call Convention
  • Reference 1 calling convention in LLVM lib/Target/Mips/ ./CheriStackInvalidatePass.cpp ./CheriAddressingModeFolder.cpp ./MipsInstrCheri.td ./CheriRangeChecker.cpp ./Cheri128FailHard.cpp ./MipsInstrFormatsCheri.td ./CheriLoopPointerDecanonicalize.cpp ./cheri-compressed-cap ./cheri-compressed-cap/decompress_c128_cap.c ./cheri-compressed-cap/LICENSE ./cheri-compressed-cap/README.md ./cheri-compressed-cap/.editorconfig ./cheri-compressed-cap/.gitignore ./cheri-compressed-cap/cheri_compressed_cap.c ./cheri-compressed-cap/.gitrepo ./cheri-compressed-cap/cheri_compressed_cap.h ./cheri-compressed-cap/test ./cheri-compressed-cap/test/fuzz-decompress.cpp ./cheri-compressed-cap/test/decode_inputs.cpp ./cheri-compressed-cap/test/test_util.h ./cheri-compressed-cap/test/setbounds_test.cpp ./cheri-compressed-cap/test/random_inputs_test.cpp ./cheri-compressed-cap/test/simple_test.cpp ./cheri-compressed-cap/test/FuzzedDataProvider.h ./cheri-compressed-cap/test/catch.hpp ./cheri-compressed-cap/test/setbounds_inputs.cpp ./cheri-compressed-cap/.clang-format ./cheri-compressed-cap/CMakeLists.txt in MipsCallingConv.td CC_Mips -> CC_Mips_VarArg -> CC_MipsCheriPureCap_VarArg -> CC_Mips_ByVal -> CC_Mips_N_VarArg -> CC_Mips_FixedArg -> CC_CHERI_CCall -> CC_MipsN -> CC_Mips_ByVal -> CC_Mips_FastCC -> CC_MIpsN CC_CHERI_CCall CC_CHERI_CCall convention -> CC_MipsN -> CC_MipsCheriCapOnStack: // lib/Target/Mips/MipsCallingConv.td def CC_CHERI_CCall : CallingConv<[ CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCAssignToReg<[C1, C2, C3, C4, C5, C6, C7, C8, C9, C10]>>, CCIfType<[i64], CCAssignToReg<[V0_64]>>, CCDelegateTo<CC_MipsN> ]>; See definition in build/lib/Target/Mips/MipsGenCallingConv.

  • Fatptr
  • Q&A How to distinguish capabilities? How does it parse __capability qualifier? Reference 1 reference ↩

  • Passes
  • llvm/lib/Target/Mips/Mips.h Cheri(Stack)InvalidatePass llvm/lib/Target/Mips/CheriStackInvalidatePass.cpp Pass Invoked at: llvm/lib/Target/Mips/MipsTargetMachine.cpp: void addPostRegAlloc() overide. Machine Function Pass: class CheriInvalidatePass : public MachineFunctionPass. Every function do: nothing; // all function code is disabled by #if 0 If enabled, for every function do: check if a sensitive function with metadata cheri.sensitive.functions; if current function is sensitive: get the set of storeToStackSlot(LLM: what is this mean) and return instructions for this function (by runOnMachineBasicBlock) if store set is empty, return; if have store instructions: enumerate all return instructions, for each return: zero all capability and non-capability spills.


  1. CHERI Programmer’s Guide, 2015. ↩
Created Sep 28, 2019 // Last Updated Nov 1, 2019

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?