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.

CheriLoopPointerDecanonicalize

Cheri128FailHardPass

CheriAddressingModeFolderPass

CHERICapFoldIntrinsicsPass

CHERICapDirectCallsPass

CheriBoundAllocas

Add bound information to alloca instructions.

Tracking by commit: 2bda57cca54edb8e928de715bfcb6638ea3e1210

llvm/lib/CodeGen/CheriBoundAllocas.cpp: class CheriBoundAllocas:

a module pass:

  • get data layout; get address space for the data layout;
  • check the capability in data layout & address space: if (!DL.isFatPointer(AllocaAS));
  • get I8CapTy and SizeTy using context(M->getContext()), data layout and address space;
  • For every function F in the module M:
    • get optimization attribute: IsOptNone;
    • get TargetMachine and TargetLowering from TargetPassConfig;
    • get set of allocas in the function: Allocas.clear(); visit(F);
    • choose proper intrinsic ID, BoundedStackCap, according to UseRematerilizableIntrinsic;
    • Get the intrinsic function BoundedStackFn according to the intrinsic ID: Intrinsic::getDeclaration(M, BoundedStackCap, SizeTy);
    • IRBuilder<> B©; // C is LLVMContext;
    • For every AllocaInst *AI in Allocas:
      • get total uses: AI->getNumUses();
      • set insert point: B.setInsertPoint(…);
      • get alloca type: PointerType *AllocaTy = AI->getType(); // AllocaTy is here a CheriCap
      • get Type *AllocationTy = AllocaTy -> getElementType();
      • get Value *ArraySize = AI->getArraySize();
      • create a new AS 0 alloca
        • set alignment
        • find uses of allocas that needs to be bounded: (all or only escaped): BoundsChecker.findUsesThatNeedBounds() : now all or nothing
        • for each use that needs bounds: get instruction of the user; find a proper insert point (PHI or not); insert intrinsics:
          code

llvm/lib/CodeGen/CodeGen.cpp: call initializeCheriBoundAllocasPass(Registry); in llvm::initializeCodeGen(...)

llvm/include/llvm/initializePasses.h: void initializeCheriBoundAllocasPass(PassRegistry &);

llvm/include/llvm/Passes.h:

code

FoldCapIntrinsics

file: llvm/lib/Transforms/CHERICap/FoldCapIntrinsics.cpp

Fold Capability Intrinsics.

  • depends on TargetLibraryInfoWrapperPass

runOnModule:

code: CHERICapFoldIntrinsics.runOnModule

PureCapABICalls

file: llvm/lib/Transforms/CHERICap/PureCapABICalls.cpp

The pass that transform PCC-relative calls into direct calls (so that they can be inlined) and then back again (so that we generate the correct code).

class: CheriCapDirectCalls

code: CheriCapDirectCalls.runOnFunction

CheriLogSetBoundPass

A util Function pass; every instruction:

  • only applies to call instruction or invoke instruction
  • first get the CalledFunc and attribute list AL for this instruction.
  • get the attribute from CalledFunc.
  • logging the allocation size from the attribute using a $\lambda$ func: LogAllocSize: a)

The function of LogAllocSize:

  • Input: std::pair<unsigned Optional<unsigned>> AllocSize;
  • Output: by side effects of cheri::CSetBoundsStats->add(Alignment, KnownSize, "function with alloc_size", cheri::SetBoundsPointerSource::Heap, "call to " + (CalledFunc ? CalledFunc->getName() : "function pointer"), cheri::inferSourceLocation(&I), SizeMultipleOf)

Pointer Type Impl.

file: llvm/lib/IR/Type.cpp

  • PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace)
code

All Passes

llvm/include/llvm/initializePasses.h:

passes

llvm/include/llvm/Passes.h:

passes

llvm/lib/Target/Mips/MipsTargetMachine.cpp:

  initializeCHERICapDirectCallsPass(*PR);
  initializeCHERICapFoldIntrinsicsPass(*PR);
  initializeCheriAddressingModeFolderPass(*PR);
  initializeCheriRangeCheckerPass(*PR);

  void addPostRegAlloc() override {
    if (getMipsSubtarget().isCheri())
      addPass(createCheriInvalidatePass());
  }

void MipsPassConfig::addIRPasses() {
  ...
  if (getMipsSubtarget().isCheri()) {
    if (getOptLevel() != CodeGenOpt::Level::None) {
      addPass(createCHERICapFoldIntrinsicsPass());
    }
    addPass(createCheriLoopPointerDecanonicalize());
    addPass(createAggressiveDCEPass());
    addPass(createCheriRangeChecker());
    addPass(createCheriBoundAllocasPass());
  }
}

void MipsPassConfig::addPreRegAlloc() {
  if (getMipsSubtarget().isCheri()) {
    addPass(createCheriAddressingModeFolder());
    // The CheriAddressingModeFolder can sometimes produce new dead instructions
    // be sure to clean them up:
    if (getOptLevel() != CodeGenOpt::Level::None)
      addPass(&DeadMachineInstructionElimID);
    addPass(createCheri128FailHardPass());
  }
}
complete passes init/invoke

Reference 1

  • Bound Allocas
  • References: llvm/lib/CodeGen/CheriBoundAllocas.cpp Overview A Module pass with instruction visitor: class CheriBoundAllocas : public ModulePass, public InstVisitor<CheriBoundAllocas> Initialization: initializeCheriBoundAllocaPass() declared in llvm/include/llvm/InitializePasses.h impl in llvm/lib/CodeGen/CheriBoundAllocas.cpp: INITIALIZE_PASS(…) called in: llvm/lib/CodeGen/CheriBoundAllocas.cpp: CheriBoundAllocas() llvm/lib/CodeGen/CodeGen.cpp: initializeCodeGen() llvm/tools/opt/opt.cpp: main() Pass Creation: createCheriBoundAllocasPass() declared in llvm/include/llvm/CodeGen/Passes.h called in Mips: llvm/lib/Target/Mips/MipsTargetMachine.cpp: MipsPassConfig::addIRPasses() RISCV: llvm/lib/Target/RISCV/RISCVTargetMachine.cpp: RISCVPassConfig::addIRPasses() Adding bound instruction: Get intrinsic: Intrinsic::getDeclaration(M, Intrinsic::cheri_cap_bounds_set, SizeTy); // llvm/lib/CodeGen/CheriBoundAllocas.cpp // Intrinsic handle as function Function *SetBoundsIntrin = Intrinsic::getDeclaration(M, Intrinsic::cheri_cap_bounds_set, SizeTy); Intrinsic::ID BoundedStackCap = UseRematerializableIntrinsic ?

  • CheriRangeChecker Pass
  • References: llvm/lib/Target/Mips/CheriRangeChecker.cpp Add LLVM pass to the pipeline Overview Only in Mips, not in RISCV. A function pass with instruction visitor: class CheriRangeChecker : public FunctionPass, public InstVisitor<CheriRangeChecker>; Pass is initialized at void initializeCheriRangeCheckerPass(PassRegistry &); in llvm/lib/Target/Mips/Mips.h (LLM: this init func’s implementation will be automatically generated by LLVM using macro INITIALIZE_PASS_BEGIN). <– llvm/lib/Target/Mips/MipsTargetMachine.cpp: LLVMInitializeMipsTarget(): initializeCheriRangeCheckerPass(*PR); Pass is invoked at llvm/lib/Target/Mips/MipsTargetMachine.cpp: void MipsPassConfig::addIRPasses(): addPass(createCheriRangeChecker()); Functions/Steps: runOnFunction(): visit(F): collect pairs of range info and correspondign cast instruction in vectors: <AllocaOperands, xxxCastInst> in Casts and <AllocaOperands, ConstantCast> in ConstantCasts: visitAddrSpaceCast(): get ValueSource of the cast operand: auto Src = getValueSource(ASC.


  1. reference ↩
Created Oct 25, 2019 // Last Updated May 18, 2021

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

... what would you change?