diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 530faa7b5b9..8d11e8053ac 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -159,10 +159,6 @@ namespace llvm { // FunctionPass *createMemDepPrinter(); - // createJumpInstrTableInfoPass - This creates a pass that stores information - // about the jump tables created by JumpInstrTables - ImmutablePass *createJumpInstrTableInfoPass(); - //===--------------------------------------------------------------------===// // // createMemDerefPrinter - This pass collects memory dereferenceability diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h deleted file mode 100644 index ec8e2ef243b..00000000000 --- a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h +++ /dev/null @@ -1,122 +0,0 @@ -//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass instruments indirect calls with checks to ensure that these calls -// pass through the appropriate jump-instruction table generated by -// JumpInstrTables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H -#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Pass.h" -#include "llvm/Target/TargetOptions.h" -#include - -namespace llvm { - -class AnalysisUsage; -class BasicBlock; -class Constant; -class Function; -class Instruction; -class Module; -class Value; - -/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to -/// prepend checks to indirect calls to make sure that these calls target valid -/// locations. -class ForwardControlFlowIntegrity : public ModulePass { -public: - static char ID; - - ForwardControlFlowIntegrity(); - ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT, - CFIntegrity CFIType, - bool CFIEnforcing, std::string CFIFuncName); - ~ForwardControlFlowIntegrity() override; - - /// Runs the CFI pass on a given module. This works best if the module in - /// question is the result of link-time optimization (see lib/LTO). - bool runOnModule(Module &M) override; - const char *getPassName() const override { - return "Forward Control-Flow Integrity"; - } - void getAnalysisUsage(AnalysisUsage &AU) const override; - -private: - typedef SmallVector CallSet; - - /// A structure that is used to keep track of constant table information. - struct CFIConstants { - Constant *StartValue; - Constant *MaskValue; - Constant *Size; - }; - - /// A map from function type to the base of the table for this type and a mask - /// for the table - typedef DenseMap CFITables; - - CallSet IndirectCalls; - - /// The type of jumptable implementation. - JumpTable::JumpTableType JTType; - - /// The type of CFI check to add before each indirect call. - CFIntegrity CFIType; - - /// A value that controls whether or not CFI violations cause a halt. - bool CFIEnforcing; - - /// The name of the function to call in case of a CFI violation when - /// CFIEnforcing is false. There is a default function that ignores - /// violations. - std::string CFIFuncName; - - /// The alignment of each entry in the table, from JumpInstrTableInfo. The - /// JumpInstrTableInfo class always makes this a power of two. - uint64_t ByteAlignment; - - /// The base-2 logarithm of ByteAlignment, needed for some of the transforms - /// (like CFIntegrity::Ror) - unsigned LogByteAlignment; - - /// Adds checks to each indirect call site to make sure that it is calling a - /// function in our jump table. - void updateIndirectCalls(Module &M, CFITables &CFIT); - - /// Walks the instructions to find all the indirect calls. - void getIndirectCalls(Module &M); - - /// Adds a function that handles violations in non-enforcing mode - /// (!CFIEnforcing). The default warning function simply returns, since the - /// exact details of how to handle CFI violations depend on the application. - void addWarningFunction(Module &M); - - /// Rewrites a function pointer in a call/invoke instruction to force it into - /// a table. - void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr, - Constant *JumpTableStart, Constant *JumpTableMask, - Constant *JumpTableSize); - - /// Inserts a check and a call to a warning function at a given instruction - /// that must be an indirect call. - void insertWarning(Module &M, BasicBlock *Block, Instruction *I, - Value *FunPtr); -}; - -ModulePass * -createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT, - CFIntegrity CFIType, - bool CFIEnforcing, StringRef CFIFuncName); -} - -#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h deleted file mode 100644 index 005bc1eb2b2..00000000000 --- a/include/llvm/CodeGen/JumpInstrTables.h +++ /dev/null @@ -1,105 +0,0 @@ -//===-- JumpInstrTables.h: Jump-Instruction Tables --------------*- C++ -*-===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief An implementation of tables consisting of jump instructions -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_JUMPINSTRTABLES_H -#define LLVM_CODEGEN_JUMPINSTRTABLES_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Pass.h" -#include "llvm/Target/TargetOptions.h" - -namespace llvm { -class Constant; -class Function; -class FunctionType; -class JumpInstrTableInfo; -class Module; - -/// A class to manage a set of jump tables indexed on function type. It looks at -/// each function in the module to find all the functions that have the -/// jumptable attribute set. For each such function, it creates a new -/// jump-instruction-table function and stores the mapping in the ImmutablePass -/// JumpInstrTableInfo. -/// -/// These special functions get lowered in AsmPrinter to assembly of the form: -/// \verbatim -/// .globl f -/// .type f,@function -/// .align 8,0x90 -/// f: -/// jmp f_orig@PLT -/// \endverbatim -/// -/// Support for an architecture depends on three functions in TargetInstrInfo: -/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter -/// uses these to generate the appropriate instructions for the jump statement -/// (an unconditional branch) and for padding to make the table have a size that -/// is a power of two. This padding uses a trap instruction to ensure that calls -/// to this area halt the program. The default implementations of these -/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound, -/// which returns 0 by default. -class JumpInstrTables : public ModulePass { -public: - static char ID; - - JumpInstrTables(); - JumpInstrTables(JumpTable::JumpTableType JTT); - virtual ~JumpInstrTables(); - bool runOnModule(Module &M) override; - const char *getPassName() const override { return "Jump-Instruction Tables"; } - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// Creates a jump-instruction table function for the Target and adds it to - /// the tables. - Function *insertEntry(Module &M, Function *Target); - - /// Checks to see if there is already a table for the given FunctionType. - bool hasTable(FunctionType *FunTy); - - /// Maps the function into a subset of function types, depending on the - /// jump-instruction table style selected from JumpTableTypes in - /// JumpInstrTables.cpp. The choice of mapping determines the number of - /// jump-instruction tables generated by this pass. E.g., the simplest mapping - /// converts every function type into void f(); so, all functions end up in a - /// single table. - static FunctionType *transformType(JumpTable::JumpTableType JTT, - FunctionType *FunTy); -private: - /// The metadata used while a jump table is being built - struct TableMeta { - /// The number of this table - unsigned TableNum; - - /// The current number of jump entries in the table. - unsigned Count; - }; - - typedef DenseMap JumpMap; - - /// The current state of functions and jump entries in the table(s). - JumpMap Metadata; - - /// The ImmutablePass that stores information about the generated tables. - JumpInstrTableInfo *JITI; - - /// The total number of tables. - unsigned TableCount; - - /// The type of tables to build. - JumpTable::JumpTableType JTType; -}; - -/// Creates a JumpInstrTables pass for the given type of jump table. -ModulePass *createJumpInstrTablesPass(JumpTable::JumpTableType JTT); -} - -#endif /* LLVM_CODEGEN_JUMPINSTRTABLES_H */ diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index bcf8cf2e4bc..7329d840b54 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -150,8 +150,6 @@ void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); void initializeInternalizePassPass(PassRegistry&); void initializeIntervalPartitionPass(PassRegistry&); -void initializeJumpInstrTableInfoPass(PassRegistry&); -void initializeJumpInstrTablesPass(PassRegistry&); void initializeJumpThreadingPass(PassRegistry&); void initializeLCSSAPass(PassRegistry&); void initializeLICMPass(PassRegistry&); diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 18343e29fa9..2fc4d9c856b 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -91,8 +91,6 @@ namespace { (void) llvm::createIndVarSimplifyPass(); (void) llvm::createInstructionCombiningPass(); (void) llvm::createInternalizePass(); - (void) llvm::createJumpInstrTableInfoPass(); - (void) llvm::createJumpInstrTablesPass(); (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp index 1bfb06d2c9c..4549c1e969f 100644 --- a/lib/Analysis/Analysis.cpp +++ b/lib/Analysis/Analysis.cpp @@ -49,7 +49,6 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeIVUsersPass(Registry); initializeInstCountPass(Registry); initializeIntervalPartitionPass(Registry); - initializeJumpInstrTableInfoPass(Registry); initializeLazyValueInfoPass(Registry); initializeLibCallAliasAnalysisPass(Registry); initializeLintPass(Registry); diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index d8400375b2a..ae40321eb1c 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -27,7 +27,6 @@ add_llvm_library(LLVMAnalysis InstructionSimplify.cpp Interval.cpp IntervalPartition.cpp - JumpInstrTableInfo.cpp LazyCallGraph.cpp LazyValueInfo.cpp LibCallAliasAnalysis.cpp diff --git a/lib/Analysis/JumpInstrTableInfo.cpp b/lib/Analysis/JumpInstrTableInfo.cpp deleted file mode 100644 index 7aae2a5592e..00000000000 --- a/lib/Analysis/JumpInstrTableInfo.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===-- JumpInstrTableInfo.cpp: Info for Jump-Instruction Tables ----------===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Information about jump-instruction tables that have been created by -/// JumpInstrTables pass. -/// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "jiti" - -#include "llvm/Analysis/JumpInstrTableInfo.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/MathExtras.h" - -using namespace llvm; - -INITIALIZE_PASS(JumpInstrTableInfo, "jump-instr-table-info", - "Jump-Instruction Table Info", true, true) -char JumpInstrTableInfo::ID = 0; - -ImmutablePass *llvm::createJumpInstrTableInfoPass() { - return new JumpInstrTableInfo(); -} - -ModulePass *llvm::createJumpInstrTableInfoPass(unsigned Bound) { - // This cast is always safe, since Bound is always in a subset of uint64_t. - uint64_t B = static_cast(Bound); - return new JumpInstrTableInfo(B); -} - -JumpInstrTableInfo::JumpInstrTableInfo(uint64_t ByteAlign) - : ImmutablePass(ID), Tables(), ByteAlignment(ByteAlign) { - if (!llvm::isPowerOf2_64(ByteAlign)) { - // Note that we don't explicitly handle overflow here, since we handle the 0 - // case explicitly when a caller actually tries to create jumptable entries, - // and this is the return value on overflow. - ByteAlignment = llvm::NextPowerOf2(ByteAlign); - } - - initializeJumpInstrTableInfoPass(*PassRegistry::getPassRegistry()); -} - -JumpInstrTableInfo::~JumpInstrTableInfo() {} - -void JumpInstrTableInfo::insertEntry(FunctionType *TableFunTy, Function *Target, - Function *Jump) { - Tables[TableFunTy].push_back(JumpPair(Target, Jump)); -} diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index b94278fae07..1cb14f0833d 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1018,59 +1018,6 @@ bool AsmPrinter::doFinalization(Module &M) { EmitVisibility(Name, V, false); } - // Get information about jump-instruction tables to print. - JumpInstrTableInfo *JITI = getAnalysisIfAvailable(); - - if (JITI && !JITI->getTables().empty()) { - // Since we're at the module level we can't use a function specific - // MCSubtargetInfo - instead create one with the module defaults. - std::unique_ptr STI(TM.getTarget().createMCSubtargetInfo( - TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); - unsigned Arch = Triple(getTargetTriple()).getArch(); - bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb); - const TargetInstrInfo *TII = TM.getSubtargetImpl()->getInstrInfo(); - MCInst TrapInst; - TII->getTrap(TrapInst); - unsigned LogAlignment = llvm::Log2_64(JITI->entryByteAlignment()); - - // Emit the right section for these functions. - OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); - for (const auto &KV : JITI->getTables()) { - uint64_t Count = 0; - for (const auto &FunPair : KV.second) { - // Emit the function labels to make this be a function entry point. - MCSymbol *FunSym = - OutContext.GetOrCreateSymbol(FunPair.second->getName()); - EmitAlignment(LogAlignment); - if (IsThumb) - OutStreamer.EmitThumbFunc(FunSym); - if (MAI->hasDotTypeDotSizeDirective()) - OutStreamer.EmitSymbolAttribute(FunSym, MCSA_ELF_TypeFunction); - OutStreamer.EmitLabel(FunSym); - - // Emit the jump instruction to transfer control to the original - // function. - MCInst JumpToFun; - MCSymbol *TargetSymbol = - OutContext.GetOrCreateSymbol(FunPair.first->getName()); - const MCSymbolRefExpr *TargetSymRef = - MCSymbolRefExpr::Create(TargetSymbol, MCSymbolRefExpr::VK_PLT, - OutContext); - TII->getUnconditionalBranch(JumpToFun, TargetSymRef); - OutStreamer.EmitInstruction(JumpToFun, *STI); - ++Count; - } - - // Emit enough padding instructions to fill up to the next power of two. - uint64_t Remaining = NextPowerOf2(Count) - Count; - for (uint64_t C = 0; C < Remaining; ++C) { - EmitAlignment(LogAlignment); - OutStreamer.EmitInstruction(TrapInst, *STI); - } - - } - } - // Emit module flags. SmallVector ModuleFlags; M.getModuleFlagsMetadata(ModuleFlags); diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index f21d4d252a5..ef5763855a8 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -19,7 +19,6 @@ add_llvm_library(LLVMCodeGen ExecutionDepsFix.cpp ExpandISelPseudos.cpp ExpandPostRAPseudos.cpp - ForwardControlFlowIntegrity.cpp GCMetadata.cpp GCMetadataPrinter.cpp GCRootLowering.cpp @@ -29,7 +28,6 @@ add_llvm_library(LLVMCodeGen InlineSpiller.cpp InterferenceCache.cpp IntrinsicLowering.cpp - JumpInstrTables.cpp LLVMTargetMachine.cpp LatencyPriorityQueue.cpp LexicalScopes.cpp diff --git a/lib/CodeGen/ForwardControlFlowIntegrity.cpp b/lib/CodeGen/ForwardControlFlowIntegrity.cpp deleted file mode 100644 index 63c3699e13b..00000000000 --- a/lib/CodeGen/ForwardControlFlowIntegrity.cpp +++ /dev/null @@ -1,374 +0,0 @@ -//===-- ForwardControlFlowIntegrity.cpp: Forward-Edge CFI -----------------===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief A pass that instruments code with fast checks for indirect calls and -/// hooks for a function to check violations. -/// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "cfi" - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/JumpInstrTableInfo.h" -#include "llvm/CodeGen/ForwardControlFlowIntegrity.h" -#include "llvm/CodeGen/JumpInstrTables.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -STATISTIC(NumCFIIndirectCalls, - "Number of indirect call sites rewritten by the CFI pass"); - -char ForwardControlFlowIntegrity::ID = 0; -INITIALIZE_PASS_BEGIN(ForwardControlFlowIntegrity, "forward-cfi", - "Control-Flow Integrity", true, true) -INITIALIZE_PASS_DEPENDENCY(JumpInstrTableInfo); -INITIALIZE_PASS_DEPENDENCY(JumpInstrTables); -INITIALIZE_PASS_END(ForwardControlFlowIntegrity, "forward-cfi", - "Control-Flow Integrity", true, true) - -ModulePass *llvm::createForwardControlFlowIntegrityPass() { - return new ForwardControlFlowIntegrity(); -} - -ModulePass *llvm::createForwardControlFlowIntegrityPass( - JumpTable::JumpTableType JTT, CFIntegrity CFIType, bool CFIEnforcing, - StringRef CFIFuncName) { - return new ForwardControlFlowIntegrity(JTT, CFIType, CFIEnforcing, - CFIFuncName); -} - -// Checks to see if a given CallSite is making an indirect call, including -// cases where the indirect call is made through a bitcast. -static bool isIndirectCall(CallSite &CS) { - if (CS.getCalledFunction()) - return false; - - // Check the value to see if it is merely a bitcast of a function. In - // this case, it will translate to a direct function call in the resulting - // assembly, so we won't treat it as an indirect call here. - const Value *V = CS.getCalledValue(); - if (const ConstantExpr *CE = dyn_cast(V)) { - return !(CE->isCast() && isa(CE->getOperand(0))); - } - - // Otherwise, since we know it's a call, it must be an indirect call - return true; -} - -static const char cfi_failure_func_name[] = "__llvm_cfi_pointer_warning"; - -ForwardControlFlowIntegrity::ForwardControlFlowIntegrity() - : ModulePass(ID), IndirectCalls(), JTType(JumpTable::Single), - CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName("") { - initializeForwardControlFlowIntegrityPass(*PassRegistry::getPassRegistry()); -} - -ForwardControlFlowIntegrity::ForwardControlFlowIntegrity( - JumpTable::JumpTableType JTT, CFIntegrity CFIType, bool CFIEnforcing, - std::string CFIFuncName) - : ModulePass(ID), IndirectCalls(), JTType(JTT), CFIType(CFIType), - CFIEnforcing(CFIEnforcing), CFIFuncName(CFIFuncName) { - initializeForwardControlFlowIntegrityPass(*PassRegistry::getPassRegistry()); -} - -ForwardControlFlowIntegrity::~ForwardControlFlowIntegrity() {} - -void ForwardControlFlowIntegrity::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addRequired(); -} - -void ForwardControlFlowIntegrity::getIndirectCalls(Module &M) { - // To get the indirect calls, we iterate over all functions and iterate over - // the list of basic blocks in each. We extract a total list of indirect calls - // before modifying any of them, since our modifications will modify the list - // of basic blocks. - for (Function &F : M) { - for (BasicBlock &BB : F) { - for (Instruction &I : BB) { - CallSite CS(&I); - if (!(CS && isIndirectCall(CS))) - continue; - - Value *CalledValue = CS.getCalledValue(); - - // Don't rewrite this instruction if the indirect call is actually just - // inline assembly, since our transformation will generate an invalid - // module in that case. - if (isa(CalledValue)) - continue; - - IndirectCalls.push_back(&I); - } - } - } -} - -void ForwardControlFlowIntegrity::updateIndirectCalls(Module &M, - CFITables &CFIT) { - Type *Int64Ty = Type::getInt64Ty(M.getContext()); - for (Instruction *I : IndirectCalls) { - CallSite CS(I); - Value *CalledValue = CS.getCalledValue(); - - // Get the function type for this call and look it up in the tables. - Type *VTy = CalledValue->getType(); - PointerType *PTy = dyn_cast(VTy); - Type *EltTy = PTy->getElementType(); - FunctionType *FunTy = dyn_cast(EltTy); - FunctionType *TransformedTy = JumpInstrTables::transformType(JTType, FunTy); - ++NumCFIIndirectCalls; - Constant *JumpTableStart = nullptr; - Constant *JumpTableMask = nullptr; - Constant *JumpTableSize = nullptr; - - // Some call sites have function types that don't correspond to any - // address-taken function in the module. This happens when function pointers - // are passed in from external code. - auto it = CFIT.find(TransformedTy); - if (it == CFIT.end()) { - // In this case, make sure that the function pointer will change by - // setting the mask and the start to be 0 so that the transformed - // function is 0. - JumpTableStart = ConstantInt::get(Int64Ty, 0); - JumpTableMask = ConstantInt::get(Int64Ty, 0); - JumpTableSize = ConstantInt::get(Int64Ty, 0); - } else { - JumpTableStart = it->second.StartValue; - JumpTableMask = it->second.MaskValue; - JumpTableSize = it->second.Size; - } - - rewriteFunctionPointer(M, I, CalledValue, JumpTableStart, JumpTableMask, - JumpTableSize); - } - - return; -} - -bool ForwardControlFlowIntegrity::runOnModule(Module &M) { - JumpInstrTableInfo *JITI = &getAnalysis(); - Type *Int64Ty = Type::getInt64Ty(M.getContext()); - Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext()); - - // JumpInstrTableInfo stores information about the alignment of each entry. - // The alignment returned by JumpInstrTableInfo is alignment in bytes, not - // in the exponent. - ByteAlignment = JITI->entryByteAlignment(); - LogByteAlignment = llvm::Log2_64(ByteAlignment); - - // Set up tables for control-flow integrity based on information about the - // jump-instruction tables. - CFITables CFIT; - for (const auto &KV : JITI->getTables()) { - uint64_t Size = static_cast(KV.second.size()); - uint64_t TableSize = NextPowerOf2(Size); - - int64_t MaskValue = ((TableSize << LogByteAlignment) - 1) & -ByteAlignment; - Constant *JumpTableMaskValue = ConstantInt::get(Int64Ty, MaskValue); - Constant *JumpTableSize = ConstantInt::get(Int64Ty, Size); - - // The base of the table is defined to be the first jumptable function in - // the table. - Function *First = KV.second.begin()->second; - Constant *JumpTableStartValue = ConstantExpr::getBitCast(First, VoidPtrTy); - CFIT[KV.first].StartValue = JumpTableStartValue; - CFIT[KV.first].MaskValue = JumpTableMaskValue; - CFIT[KV.first].Size = JumpTableSize; - } - - if (CFIT.empty()) - return false; - - getIndirectCalls(M); - - if (!CFIEnforcing) { - addWarningFunction(M); - } - - // Update the instructions with the check and the indirect jump through our - // table. - updateIndirectCalls(M, CFIT); - - return true; -} - -void ForwardControlFlowIntegrity::addWarningFunction(Module &M) { - PointerType *CharPtrTy = Type::getInt8PtrTy(M.getContext()); - - // Get the type of the Warning Function: void (i8*, i8*), - // where the first argument is the name of the function in which the violation - // occurs, and the second is the function pointer that violates CFI. - SmallVector WarningFunArgs; - WarningFunArgs.push_back(CharPtrTy); - WarningFunArgs.push_back(CharPtrTy); - FunctionType *WarningFunTy = - FunctionType::get(Type::getVoidTy(M.getContext()), WarningFunArgs, false); - - if (!CFIFuncName.empty()) { - Constant *FailureFun = M.getOrInsertFunction(CFIFuncName, WarningFunTy); - if (!FailureFun) - report_fatal_error("Could not get or insert the function specified by" - " -cfi-func-name"); - } else { - // The default warning function swallows the warning and lets the call - // continue, since there's no generic way for it to print out this - // information. - Function *WarningFun = M.getFunction(cfi_failure_func_name); - if (!WarningFun) { - WarningFun = - Function::Create(WarningFunTy, GlobalValue::LinkOnceAnyLinkage, - cfi_failure_func_name, &M); - } - - BasicBlock *Entry = - BasicBlock::Create(M.getContext(), "entry", WarningFun, 0); - ReturnInst::Create(M.getContext(), Entry); - } -} - -void ForwardControlFlowIntegrity::rewriteFunctionPointer( - Module &M, Instruction *I, Value *FunPtr, Constant *JumpTableStart, - Constant *JumpTableMask, Constant *JumpTableSize) { - IRBuilder<> TempBuilder(I); - - Type *OrigFunType = FunPtr->getType(); - - BasicBlock *CurBB = cast(I->getParent()); - Function *CurF = cast(CurBB->getParent()); - Type *Int64Ty = Type::getInt64Ty(M.getContext()); - - Value *TI = TempBuilder.CreatePtrToInt(FunPtr, Int64Ty); - Value *TStartInt = TempBuilder.CreatePtrToInt(JumpTableStart, Int64Ty); - - Value *NewFunPtr = nullptr; - Value *Check = nullptr; - switch (CFIType) { - case CFIntegrity::Sub: { - // This is the subtract, mask, and add version. - // Subtract from the base. - Value *Sub = TempBuilder.CreateSub(TI, TStartInt); - - // Mask the difference to force this to be a table offset. - Value *And = TempBuilder.CreateAnd(Sub, JumpTableMask); - - // Add it back to the base. - Value *Result = TempBuilder.CreateAdd(And, TStartInt); - - // Convert it back into a function pointer that we can call. - NewFunPtr = TempBuilder.CreateIntToPtr(Result, OrigFunType); - break; - } - case CFIntegrity::Ror: { - // This is the subtract and rotate version. - // Rotate right by the alignment value. The optimizer should recognize - // this sequence as a rotation. - - // This cast is safe, since unsigned is always a subset of uint64_t. - uint64_t LogByteAlignment64 = static_cast(LogByteAlignment); - Constant *RightShift = ConstantInt::get(Int64Ty, LogByteAlignment64); - Constant *LeftShift = ConstantInt::get(Int64Ty, 64 - LogByteAlignment64); - - // Subtract from the base. - Value *Sub = TempBuilder.CreateSub(TI, TStartInt); - - // Create the equivalent of a rotate-right instruction. - Value *Shr = TempBuilder.CreateLShr(Sub, RightShift); - Value *Shl = TempBuilder.CreateShl(Sub, LeftShift); - Value *Or = TempBuilder.CreateOr(Shr, Shl); - - // Perform unsigned comparison to check for inclusion in the table. - Check = TempBuilder.CreateICmpULT(Or, JumpTableSize); - NewFunPtr = FunPtr; - break; - } - case CFIntegrity::Add: { - // This is the mask and add version. - // Mask the function pointer to turn it into an offset into the table. - Value *And = TempBuilder.CreateAnd(TI, JumpTableMask); - - // Then or this offset to the base and get the pointer value. - Value *Result = TempBuilder.CreateAdd(And, TStartInt); - - // Convert it back into a function pointer that we can call. - NewFunPtr = TempBuilder.CreateIntToPtr(Result, OrigFunType); - break; - } - } - - if (!CFIEnforcing) { - // If a check hasn't been added (in the rotation version), then check to see - // if it's the same as the original function. This check determines whether - // or not we call the CFI failure function. - if (!Check) - Check = TempBuilder.CreateICmpEQ(NewFunPtr, FunPtr); - BasicBlock *InvalidPtrBlock = - BasicBlock::Create(M.getContext(), "invalid.ptr", CurF, 0); - BasicBlock *ContinuationBB = CurBB->splitBasicBlock(I); - - // Remove the unconditional branch that connects the two blocks. - TerminatorInst *TermInst = CurBB->getTerminator(); - TermInst->eraseFromParent(); - - // Add a conditional branch that depends on the Check above. - BranchInst::Create(ContinuationBB, InvalidPtrBlock, Check, CurBB); - - // Call the warning function for this pointer, then continue. - Instruction *BI = BranchInst::Create(ContinuationBB, InvalidPtrBlock); - insertWarning(M, InvalidPtrBlock, BI, FunPtr); - } else { - // Modify the instruction to call this value. - CallSite CS(I); - CS.setCalledFunction(NewFunPtr); - } -} - -void ForwardControlFlowIntegrity::insertWarning(Module &M, BasicBlock *Block, - Instruction *I, Value *FunPtr) { - Function *ParentFun = cast(Block->getParent()); - - // Get the function to call right before the instruction. - Function *WarningFun = nullptr; - if (CFIFuncName.empty()) { - WarningFun = M.getFunction(cfi_failure_func_name); - } else { - WarningFun = M.getFunction(CFIFuncName); - } - - assert(WarningFun && "Could not find the CFI failure function"); - - Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext()); - - IRBuilder<> WarningInserter(I); - // Create a mergeable GlobalVariable containing the name of the function. - Value *ParentNameGV = - WarningInserter.CreateGlobalString(ParentFun->getName()); - Value *ParentNamePtr = WarningInserter.CreateBitCast(ParentNameGV, VoidPtrTy); - Value *FunVoidPtr = WarningInserter.CreateBitCast(FunPtr, VoidPtrTy); - WarningInserter.CreateCall2(WarningFun, ParentNamePtr, FunVoidPtr); -} diff --git a/lib/CodeGen/JumpInstrTables.cpp b/lib/CodeGen/JumpInstrTables.cpp deleted file mode 100644 index 75fa2619739..00000000000 --- a/lib/CodeGen/JumpInstrTables.cpp +++ /dev/null @@ -1,296 +0,0 @@ -//===-- JumpInstrTables.cpp: Jump-Instruction Tables ----------------------===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief An implementation of jump-instruction tables. -/// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "jt" - -#include "llvm/CodeGen/JumpInstrTables.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/JumpInstrTableInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include - -using namespace llvm; - -char JumpInstrTables::ID = 0; - -INITIALIZE_PASS_BEGIN(JumpInstrTables, "jump-instr-tables", - "Jump-Instruction Tables", true, true) -INITIALIZE_PASS_DEPENDENCY(JumpInstrTableInfo); -INITIALIZE_PASS_END(JumpInstrTables, "jump-instr-tables", - "Jump-Instruction Tables", true, true) - -STATISTIC(NumJumpTables, "Number of indirect call tables generated"); -STATISTIC(NumFuncsInJumpTables, "Number of functions in the jump tables"); - -ModulePass *llvm::createJumpInstrTablesPass() { - // The default implementation uses a single table for all functions. - return new JumpInstrTables(JumpTable::Single); -} - -ModulePass *llvm::createJumpInstrTablesPass(JumpTable::JumpTableType JTT) { - return new JumpInstrTables(JTT); -} - -namespace { -static const char jump_func_prefix[] = "__llvm_jump_instr_table_"; -static const char jump_section_prefix[] = ".jump.instr.table.text."; - -// Checks to see if a given CallSite is making an indirect call, including -// cases where the indirect call is made through a bitcast. -bool isIndirectCall(CallSite &CS) { - if (CS.getCalledFunction()) - return false; - - // Check the value to see if it is merely a bitcast of a function. In - // this case, it will translate to a direct function call in the resulting - // assembly, so we won't treat it as an indirect call here. - const Value *V = CS.getCalledValue(); - if (const ConstantExpr *CE = dyn_cast(V)) { - return !(CE->isCast() && isa(CE->getOperand(0))); - } - - // Otherwise, since we know it's a call, it must be an indirect call - return true; -} - -// Replaces Functions and GlobalAliases with a different Value. -bool replaceGlobalValueIndirectUse(GlobalValue *GV, Value *V, Use *U) { - User *Us = U->getUser(); - if (!Us) - return false; - if (Instruction *I = dyn_cast(Us)) { - CallSite CS(I); - - // Don't do the replacement if this use is a direct call to this function. - // If the use is not the called value, then replace it. - if (CS && (isIndirectCall(CS) || CS.isCallee(U))) { - return false; - } - - U->set(V); - } else if (Constant *C = dyn_cast(Us)) { - // Don't replace calls to bitcasts of function symbols, since they get - // translated to direct calls. - if (ConstantExpr *CE = dyn_cast(Us)) { - if (CE->getOpcode() == Instruction::BitCast) { - // This bitcast must have exactly one user. - if (CE->user_begin() != CE->user_end()) { - User *ParentUs = *CE->user_begin(); - if (CallInst *CI = dyn_cast(ParentUs)) { - CallSite CS(CI); - Use &CEU = *CE->use_begin(); - if (CS.isCallee(&CEU)) { - return false; - } - } - } - } - } - - // GlobalAlias doesn't support replaceUsesOfWithOnConstant. And the verifier - // requires alias to point to a defined function. So, GlobalAlias is handled - // as a separate case in runOnModule. - if (!isa(C)) - C->replaceUsesOfWithOnConstant(GV, V, U); - } else { - llvm_unreachable("The Use of a Function symbol is neither an instruction " - "nor a constant"); - } - - return true; -} - -// Replaces all replaceable address-taken uses of GV with a pointer to a -// jump-instruction table entry. -void replaceValueWithFunction(GlobalValue *GV, Function *F) { - // Go through all uses of this function and replace the uses of GV with the - // jump-table version of the function. Get the uses as a vector before - // replacing them, since replacing them changes the use list and invalidates - // the iterator otherwise. - for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E;) { - Use &U = *I++; - - // Replacement of constants replaces all instances in the constant. So, some - // uses might have already been handled by the time we reach them here. - if (U.get() == GV) - replaceGlobalValueIndirectUse(GV, F, &U); - } - - return; -} -} // end anonymous namespace - -JumpInstrTables::JumpInstrTables() - : ModulePass(ID), Metadata(), JITI(nullptr), TableCount(0), - JTType(JumpTable::Single) { - initializeJumpInstrTablesPass(*PassRegistry::getPassRegistry()); -} - -JumpInstrTables::JumpInstrTables(JumpTable::JumpTableType JTT) - : ModulePass(ID), Metadata(), JITI(nullptr), TableCount(0), JTType(JTT) { - initializeJumpInstrTablesPass(*PassRegistry::getPassRegistry()); -} - -JumpInstrTables::~JumpInstrTables() {} - -void JumpInstrTables::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); -} - -Function *JumpInstrTables::insertEntry(Module &M, Function *Target) { - FunctionType *OrigFunTy = Target->getFunctionType(); - FunctionType *FunTy = transformType(JTType, OrigFunTy); - - JumpMap::iterator it = Metadata.find(FunTy); - if (Metadata.end() == it) { - struct TableMeta Meta; - Meta.TableNum = TableCount; - Meta.Count = 0; - Metadata[FunTy] = Meta; - it = Metadata.find(FunTy); - ++NumJumpTables; - ++TableCount; - } - - it->second.Count++; - - std::string NewName(jump_func_prefix); - NewName += (Twine(it->second.TableNum) + "_" + Twine(it->second.Count)).str(); - Function *JumpFun = - Function::Create(OrigFunTy, GlobalValue::ExternalLinkage, NewName, &M); - // The section for this table - JumpFun->setSection((jump_section_prefix + Twine(it->second.TableNum)).str()); - JITI->insertEntry(FunTy, Target, JumpFun); - - ++NumFuncsInJumpTables; - return JumpFun; -} - -bool JumpInstrTables::hasTable(FunctionType *FunTy) { - FunctionType *TransTy = transformType(JTType, FunTy); - return Metadata.end() != Metadata.find(TransTy); -} - -FunctionType *JumpInstrTables::transformType(JumpTable::JumpTableType JTT, - FunctionType *FunTy) { - // Returning nullptr forces all types into the same table, since all types map - // to the same type - Type *VoidPtrTy = Type::getInt8PtrTy(FunTy->getContext()); - - // Ignore the return type. - Type *RetTy = VoidPtrTy; - bool IsVarArg = FunTy->isVarArg(); - std::vector ParamTys(FunTy->getNumParams()); - FunctionType::param_iterator PI, PE; - int i = 0; - - std::vector EmptyParams; - Type *Int32Ty = Type::getInt32Ty(FunTy->getContext()); - FunctionType *VoidFnTy = FunctionType::get( - Type::getVoidTy(FunTy->getContext()), EmptyParams, false); - switch (JTT) { - case JumpTable::Single: - - return FunctionType::get(RetTy, EmptyParams, false); - case JumpTable::Arity: - // Transform all types to void* so that all functions with the same arity - // end up in the same table. - for (PI = FunTy->param_begin(), PE = FunTy->param_end(); PI != PE; - PI++, i++) { - ParamTys[i] = VoidPtrTy; - } - - return FunctionType::get(RetTy, ParamTys, IsVarArg); - case JumpTable::Simplified: - // Project all parameters types to one of 3 types: composite, integer, and - // function, matching the three subclasses of Type. - for (PI = FunTy->param_begin(), PE = FunTy->param_end(); PI != PE; - ++PI, ++i) { - assert((isa(*PI) || isa(*PI) || - isa(*PI)) && - "This type is not an Integer or a Composite or a Function"); - if (isa(*PI)) { - ParamTys[i] = VoidPtrTy; - } else if (isa(*PI)) { - ParamTys[i] = VoidFnTy; - } else if (isa(*PI)) { - ParamTys[i] = Int32Ty; - } - } - - return FunctionType::get(RetTy, ParamTys, IsVarArg); - case JumpTable::Full: - // Don't transform this type at all. - return FunTy; - } - - return nullptr; -} - -bool JumpInstrTables::runOnModule(Module &M) { - JITI = &getAnalysis(); - - // Get the set of jumptable-annotated functions that have their address taken. - DenseMap Functions; - for (Function &F : M) { - if (F.hasFnAttribute(Attribute::JumpTable) && F.hasAddressTaken()) { - assert(F.hasUnnamedAddr() && - "Attribute 'jumptable' requires 'unnamed_addr'"); - Functions[&F] = nullptr; - } - } - - // Create the jump-table functions. - for (auto &KV : Functions) { - Function *F = KV.first; - KV.second = insertEntry(M, F); - } - - // GlobalAlias is a special case, because the target of an alias statement - // must be a defined function. So, instead of replacing a given function in - // the alias, we replace all uses of aliases that target jumptable functions. - // Note that there's no need to create these functions, since only aliases - // that target known jumptable functions are replaced, and there's no way to - // put the jumptable annotation on a global alias. - DenseMap Aliases; - for (GlobalAlias &GA : M.aliases()) { - Constant *Aliasee = GA.getAliasee(); - if (Function *F = dyn_cast(Aliasee)) { - auto it = Functions.find(F); - if (it != Functions.end()) { - Aliases[&GA] = it->second; - } - } - } - - // Replace each address taken function with its jump-instruction table entry. - for (auto &KV : Functions) - replaceValueWithFunction(KV.first, KV.second); - - for (auto &KV : Aliases) - replaceValueWithFunction(KV.first, KV.second); - - return !Functions.empty(); -} diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 9c233681666..3818b8412aa 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -12,12 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/TargetMachine.h" -#include "llvm/Analysis/JumpInstrTableInfo.h" #include "llvm/Analysis/Passes.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/BasicTTIImpl.h" -#include "llvm/CodeGen/ForwardControlFlowIntegrity.h" -#include "llvm/CodeGen/JumpInstrTables.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" @@ -145,16 +142,6 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) { - // Passes to handle jumptable function annotations. These can't be handled at - // JIT time, so we don't add them directly to addPassesToGenerateCode. - PM.add(createJumpInstrTableInfoPass( - getSubtargetImpl()->getInstrInfo()->getJumpInstrTableEntryBound())); - PM.add(createJumpInstrTablesPass(Options.JTType)); - if (Options.FCFI) - PM.add(createForwardControlFlowIntegrityPass( - Options.JTType, Options.CFIType, Options.CFIEnforcing, - Options.getCFIFuncName())); - // Add common CodeGen passes. MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, StartAfter, StopAfter); diff --git a/test/CodeGen/Generic/stop-after.ll b/test/CodeGen/Generic/stop-after.ll index 5e0e350bc7f..557e097840a 100644 --- a/test/CodeGen/Generic/stop-after.ll +++ b/test/CodeGen/Generic/stop-after.ll @@ -5,6 +5,6 @@ ; STOP: Loop Strength Reduction ; STOP-NEXT: Machine Function Analysis -; START: -machine-branch-prob -jump-instr-tables -gc-lowering +; START: -machine-branch-prob -gc-lowering ; START: FunctionPass Manager ; START-NEXT: Lower Garbage Collection Instructions diff --git a/test/CodeGen/X86/cfi_enforcing.ll b/test/CodeGen/X86/cfi_enforcing.ll deleted file mode 100644 index bcad8c168f2..00000000000 --- a/test/CodeGen/X86/cfi_enforcing.ll +++ /dev/null @@ -1,34 +0,0 @@ -; RUN: llc -mtriple=i386-unknown-linux-gnu -fcfi -cfi-enforcing <%s | FileCheck --check-prefix=X86 %s -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -fcfi -cfi-enforcing <%s | FileCheck --check-prefix=X86-64 %s - -define void @indirect_fun() unnamed_addr jumptable { - ret void -} - -define i32 @m(void ()* %fun) { - call void ()* %fun() -; CHECK: subl -; X86-64: andq $8, -; X86-64: leaq __llvm_jump_instr_table_0_1({{%[a-z0-9]+}}), [[REG:%[a-z0-9]+]] -; X86-64-NOT: callq __llvm_cfi_pointer_warning -; X86-64: callq *[[REG]] -; X86: andl $8, -; X86: leal __llvm_jump_instr_table_0_1({{%[a-z0-9]+}}), [[REG:%[a-z0-9]+]] -; X86-NOT: calll __llvm_cfi_pointer_warning -; X86: calll *[[REG]] - ret i32 0 -} - -define void ()* @get_fun() { - ret void ()* @indirect_fun -} - -define i32 @main(i32 %argc, i8** %argv) { - %f = call void ()* ()* @get_fun() - %a = call i32 @m(void ()* %f) - ret i32 %a -} - -; CHECK: .align 8 -; CHECK: __llvm_jump_instr_table_0_1: -; CHECK: jmp indirect_fun@PLT diff --git a/test/CodeGen/X86/cfi_invoke.ll b/test/CodeGen/X86/cfi_invoke.ll deleted file mode 100644 index dd0d42a59c3..00000000000 --- a/test/CodeGen/X86/cfi_invoke.ll +++ /dev/null @@ -1,35 +0,0 @@ -; RUN: llc <%s -fcfi -cfi-type=sub | FileCheck %s -; ModuleID = 'test.cc' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -declare i32 @__gxx_personality_v0(...) - -@_ZTIPKc = external constant i8* -@_ZTIi = external constant i8* - -define void @f() unnamed_addr jumptable { - ret void -} - -@a = global void ()* @f - -; Make sure invoke gets targeted as well as regular calls -define void @_Z3foov(void ()* %f) uwtable ssp { -; CHECK-LABEL: _Z3foov: - entry: - invoke void %f() - to label %try.cont unwind label %lpad -; CHECK: callq __llvm_cfi_pointer_warning -; CHECK: callq *%rbx - - lpad: - %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - catch i8* bitcast (i8** @_ZTIi to i8*) - filter [1 x i8*] [i8* bitcast (i8** @_ZTIPKc to i8*)] - ret void - - try.cont: - ret void -} - diff --git a/test/CodeGen/X86/cfi_non_default_function.ll b/test/CodeGen/X86/cfi_non_default_function.ll deleted file mode 100644 index 29774a1d442..00000000000 --- a/test/CodeGen/X86/cfi_non_default_function.ll +++ /dev/null @@ -1,27 +0,0 @@ -; RUN: llc -fcfi -cfi-func-name=cfi_new_failure <%s | FileCheck %s - -target triple = "x86_64-unknown-linux-gnu" -define void @indirect_fun() unnamed_addr jumptable { - ret void -} - -define i32 @m(void ()* %fun) { -; CHECK-LABEL: @m - call void ()* %fun() -; CHECK: callq cfi_new_failure - ret i32 0 -} - -define void ()* @get_fun() { - ret void ()* @indirect_fun -} - -define i32 @main(i32 %argc, i8** %argv) { - %f = call void ()* ()* @get_fun() - %a = call i32 @m(void ()* %f) - ret i32 %a -} - -; CHECK: .align 8 -; CHECK: __llvm_jump_instr_table_0_1: -; CHECK: jmp indirect_fun@PLT diff --git a/test/CodeGen/X86/cfi_simple_indirect_call.ll b/test/CodeGen/X86/cfi_simple_indirect_call.ll deleted file mode 100644 index 0ee118d984e..00000000000 --- a/test/CodeGen/X86/cfi_simple_indirect_call.ll +++ /dev/null @@ -1,43 +0,0 @@ -; RUN: llc -fcfi -cfi-type=sub <%s | FileCheck --check-prefix=SUB %s -; RUN: llc -fcfi -cfi-type=add <%s | FileCheck --check-prefix=ADD %s -; RUN: llc -fcfi -cfi-type=ror <%s | FileCheck --check-prefix=ROR %s - -target triple = "x86_64-unknown-linux-gnu" - -define void @indirect_fun() unnamed_addr jumptable { - ret void -} - -define i32 @m(void ()* %fun) { - call void ()* %fun() -; SUB: subl -; SUB: andq $8 -; SUB-LABEL: leaq __llvm_jump_instr_table_0_1 -; SUB-LABEL: callq __llvm_cfi_pointer_warning - -; ROR: subq -; ROR: rolq $61 -; ROR: testq -; ROR-LABEL: callq __llvm_cfi_pointer_warning - -; ADD: andq $8 -; ADD-LABEL: leaq __llvm_jump_instr_table_0_1 -; ADD: cmpq -; ADD-LABEL: callq __llvm_cfi_pointer_warning -ret i32 0 -} - -define void ()* @get_fun() { - ret void ()* @indirect_fun -} - -define i32 @main(i32 %argc, i8** %argv) { - %f = call void ()* ()* @get_fun() - %a = call i32 @m(void ()* %f) - ret i32 %a -} -; SUB: .text -; SUB: .align 8 -; SUB-LABEL: .type __llvm_jump_instr_table_0_1,@function -; SUB-LABEL:__llvm_jump_instr_table_0_1: -; SUB-LABEL: jmp indirect_fun@PLT diff --git a/test/CodeGen/X86/jump_table_alias.ll b/test/CodeGen/X86/jump_table_alias.ll deleted file mode 100644 index 20622009e37..00000000000 --- a/test/CodeGen/X86/jump_table_alias.ll +++ /dev/null @@ -1,32 +0,0 @@ -; RUN: llc <%s -jump-table-type=single | FileCheck %s -target triple = "x86_64-unknown-linux-gnu" -define i32 @f() unnamed_addr jumptable { -entry: - ret i32 0 -} - -@i = internal alias i32 ()* @f -@j = alias i32 ()* @f - -define i32 @main(i32 %argc, i8** %argv) { - %temp = alloca i32 ()*, align 8 - store i32 ()* @i, i32()** %temp, align 8 -; CHECK: movq $__llvm_jump_instr_table_0_1 - %1 = load i32 ()** %temp, align 8 -; CHECK: movl $__llvm_jump_instr_table_0_1 - %2 = call i32 ()* %1() - %3 = call i32 ()* @i() -; CHECK: callq i - %4 = call i32 ()* @j() -; CHECK: callq j - ret i32 %3 -} - -; There should only be one table, even though there are two GlobalAliases, -; because they both alias the same value. - -; CHECK: .align 8, 0x90 -; CHECK: .type __llvm_jump_instr_table_0_1,@function -; CHECK: __llvm_jump_instr_table_0_1: -; CHECK: jmp f@PLT - diff --git a/test/CodeGen/X86/jump_table_align.ll b/test/CodeGen/X86/jump_table_align.ll deleted file mode 100644 index 6ad48d1f54f..00000000000 --- a/test/CodeGen/X86/jump_table_align.ll +++ /dev/null @@ -1,29 +0,0 @@ -; RUN: llc -filetype=obj <%s -jump-table-type=single -o %t1 -; RUN: llvm-objdump -triple=x86_64-unknown-linux-gnu -d %t1 | FileCheck %s -target triple = "x86_64-unknown-linux-gnu" -define i32 @f() unnamed_addr jumptable { - ret i32 0 -} - -define i32 @g(i8* %a) unnamed_addr jumptable { - ret i32 0 -} - -define void @h(void ()* %func) unnamed_addr jumptable { - ret void -} - -define i32 @main() { - %g = alloca i32 (...)*, align 8 - store i32 (...)* bitcast (i32 ()* @f to i32 (...)*), i32 (...)** %g, align 8 - %1 = load i32 (...)** %g, align 8 - %call = call i32 (...)* %1() - call void (void ()*)* @h(void ()* bitcast (void (void ()*)* @h to void ()*)) - %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null) - ret i32 %a -} - -; Make sure that the padding from getJumpInstrTableEntryBound is right. -; CHECK: __llvm_jump_instr_table_0_1: -; CHECK-NEXT: e9 00 00 00 00 jmp 0 -; CHECK-NEXT: 0f 1f 00 nopl (%rax) diff --git a/test/CodeGen/X86/jump_table_bitcast.ll b/test/CodeGen/X86/jump_table_bitcast.ll deleted file mode 100644 index 749b77a166e..00000000000 --- a/test/CodeGen/X86/jump_table_bitcast.ll +++ /dev/null @@ -1,43 +0,0 @@ -; RUN: llc <%s -jump-table-type=single | FileCheck %s -target triple = "x86_64-unknown-linux-gnu" -define i32 @f() unnamed_addr jumptable { - ret i32 0 -} - -define i32 @g(i8* %a) unnamed_addr jumptable { - ret i32 0 -} - -define void @h(void ()* %func) unnamed_addr jumptable { - ret void -} - -define i32 @main() { - %g = alloca i32 (...)*, align 8 - store i32 (...)* bitcast (i32 ()* @f to i32 (...)*), i32 (...)** %g, align 8 -; CHECK: movq $__llvm_jump_instr_table_0_[[ENTRY:1|2|3]], -; CHECK: movl $__llvm_jump_instr_table_0_[[ENTRY]], - %1 = load i32 (...)** %g, align 8 - %call = call i32 (...)* %1() - call void (void ()*)* @h(void ()* bitcast (void (void ()*)* @h to void ()*)) -; CHECK: movl $__llvm_jump_instr_table_0_{{1|2|3}}, -; CHECK: callq h - - %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null) -; CHECK: callq g - ret i32 %a -} - -; CHECK: .align 8, 0x90 -; CHECK: .type __llvm_jump_instr_table_0_1,@function -; CHECK: __llvm_jump_instr_table_0_1: -; CHECK: jmp {{f|g|h}}@PLT -; CHECK: .align 8, 0x90 -; CHECK: .type __llvm_jump_instr_table_0_2,@function -; CHECK: __llvm_jump_instr_table_0_2: -; CHECK: jmp {{f|g|h}}@PLT -; CHECK: .align 8, 0x90 -; CHECK: .type __llvm_jump_instr_table_0_3,@function -; CHECK: __llvm_jump_instr_table_0_3: -; CHECK: jmp {{f|g|h}}@PLT - diff --git a/test/CodeGen/X86/jump_tables.ll b/test/CodeGen/X86/jump_tables.ll deleted file mode 100644 index 485154eaa2a..00000000000 --- a/test/CodeGen/X86/jump_tables.ll +++ /dev/null @@ -1,255 +0,0 @@ -; RUN: llc <%s -jump-table-type=single | FileCheck --check-prefix=SINGLE %s -; RUN: llc <%s -jump-table-type=arity | FileCheck --check-prefix=ARITY %s -; RUN: llc <%s -jump-table-type=simplified | FileCheck --check-prefix=SIMPL %s -; RUN: llc <%s -jump-table-type=full | FileCheck --check-prefix=FULL %s - -target triple = "x86_64-unknown-linux-gnu" - -%struct.fun_struct = type { i32 (...)* } - -@a = global [12 x i32 () *] [ i32 ()* bitcast (void ()* @indirect_fun to i32 ()*), - i32 ()* bitcast (void ()* @indirect_fun_match to i32 ()*), - i32 ()* bitcast (i32 ()* @indirect_fun_i32 to i32 ()*), - i32 ()* bitcast (i32 (i32)* @indirect_fun_i32_1 to i32 ()*), - i32 ()* bitcast (i32 (i32, i32)* @indirect_fun_i32_2 to i32 ()*), - i32 ()* bitcast (i32* (i32*, i32)* @indirect_fun_i32S_2 to i32 ()*), - i32 ()* bitcast (void (%struct.fun_struct)* @indirect_fun_struct to i32 ()*), - i32 ()* bitcast (void (i32 (...)*, i32)* @indirect_fun_fun to i32 ()*), - i32 ()* bitcast (i32 (i32 (...)*, i32)* @indirect_fun_fun_ret to i32 ()*), - i32 ()* bitcast (void ([19 x i8])* @indirect_fun_array to i32 ()*), - i32 ()* bitcast (void (<3 x i32>)* @indirect_fun_vec to i32 ()*), - i32 ()* bitcast (void (<4 x float>)* @indirect_fun_vec_2 to i32 ()*) - ] - -define void @indirect_fun() unnamed_addr jumptable { - ret void -} - -define void @indirect_fun_match() unnamed_addr jumptable { - ret void -} - -define i32 @indirect_fun_i32() unnamed_addr jumptable { - ret i32 0 -} - -define i32 @indirect_fun_i32_1(i32 %a) unnamed_addr jumptable { - ret i32 %a -} - -define i32 @indirect_fun_i32_2(i32 %a, i32 %b) unnamed_addr jumptable { - ret i32 %a -} - -define i32* @indirect_fun_i32S_2(i32* %a, i32 %b) unnamed_addr jumptable { - ret i32* %a -} - -define void @indirect_fun_struct(%struct.fun_struct %fs) unnamed_addr jumptable { - ret void -} - -define void @indirect_fun_fun(i32 (...)* %fun, i32 %a) unnamed_addr jumptable { - ret void -} - -define i32 @indirect_fun_fun_ret(i32 (...)* %fun, i32 %a) unnamed_addr jumptable { - ret i32 %a -} - -define void @indirect_fun_array([19 x i8] %a) unnamed_addr jumptable { - ret void -} - -define void @indirect_fun_vec(<3 x i32> %a) unnamed_addr jumptable { - ret void -} - -define void @indirect_fun_vec_2(<4 x float> %a) unnamed_addr jumptable { - ret void -} - -define i32 @m(void ()* %fun) { - call void ()* %fun() - ret i32 0 -} - -define void ()* @get_fun() { - ret void ()* @indirect_fun -; SINGLE: movl $__llvm_jump_instr_table_0_ -; ARITY: movl $__llvm_jump_instr_table_ -; SIMPL: movl $__llvm_jump_instr_table_ -; FULL: movl $__llvm_jump_instr_table_ -} - -define i32 @main(i32 %argc, i8** %argv) { - %f = call void ()* ()* @get_fun() - %a = call i32 @m(void ()* %f) - ret i32 %a -} - -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_1,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_1: -; SINGLE-DAG: jmp indirect_fun_array@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_2,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_2: -; SINGLE-DAG: jmp indirect_fun_i32_2@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_3,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_3: -; SINGLE-DAG: jmp indirect_fun_vec_2@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_4,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_4: -; SINGLE-DAG: jmp indirect_fun_i32S_2@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_5,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_5: -; SINGLE-DAG: jmp indirect_fun_struct@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_6,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_6: -; SINGLE-DAG: jmp indirect_fun_i32_1@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_7,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_7: -; SINGLE-DAG: jmp indirect_fun_i32@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_8,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_8: -; SINGLE-DAG: jmp indirect_fun_fun@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_9,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_9: -; SINGLE-DAG: jmp indirect_fun_fun_ret@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_10,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_10: -; SINGLE-DAG: jmp indirect_fun@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_11,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_11: -; SINGLE-DAG: jmp indirect_fun_match@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: .type __llvm_jump_instr_table_0_12,@function -; SINGLE-DAG: __llvm_jump_instr_table_0_12: -; SINGLE-DAG: jmp indirect_fun_vec@PLT -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: ud2 -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: ud2 -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: ud2 -; SINGLE-DAG: .align 8, 0x90 -; SINGLE-DAG: ud2 - - -; ARITY-DAG: .align 8, 0x90 -; ARITY-DAG: .type __llvm_jump_instr_table_2_1,@function -; ARITY-DAG: __llvm_jump_instr_table_2_1: -; ARITY-DAG: jmp indirect_fun{{.*}}@PLT -; ARITY-DAG: .align 8, 0x90 -; ARITY-DAG: ud2 -; ARITY-DAG: .align 8, 0x90 -; ARITY-DAG: .type __llvm_jump_instr_table_0_1,@function -; ARITY-DAG: __llvm_jump_instr_table_0_1: -; ARITY-DAG: jmp indirect_fun{{.*}}@PLT -; ARITY-DAG: .align 8, 0x90 -; ARITY-DAG: .type __llvm_jump_instr_table_1_1,@function -; ARITY-DAG: __llvm_jump_instr_table_1_1: -; ARITY-DAG: jmp indirect_fun{{.*}}@PLT - -; SIMPL-DAG: .align 8, 0x90 -; SIMPL-DAG: .type __llvm_jump_instr_table_2_1,@function -; SIMPL-DAG: __llvm_jump_instr_table_2_1: -; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT -; SIMPL-DAG: .align 8, 0x90 -; SIMPL-DAG: ud2 -; SIMPL-DAG: .align 8, 0x90 -; SIMPL-DAG: .type __llvm_jump_instr_table_0_1,@function -; SIMPL-DAG: __llvm_jump_instr_table_0_1: -; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT -; SIMPL-DAG: .align 8, 0x90 -; SIMPL-DAG: .type __llvm_jump_instr_table_1_1,@function -; SIMPL-DAG: __llvm_jump_instr_table_1_1: -; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT -; SIMPL-DAG: .align 8, 0x90 -; SIMPL-DAG: .type __llvm_jump_instr_table_3_1,@function -; SIMPL-DAG: __llvm_jump_instr_table_3_1: -; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT -; SIMPL-DAG: .align 8, 0x90 -; SIMPL-DAG: .type __llvm_jump_instr_table_4_1,@function -; SIMPL-DAG: __llvm_jump_instr_table_4_1: -; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT - - -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_10_1,@function -; FULL-DAG:__llvm_jump_instr_table_10_1: -; FULL-DAG: jmp indirect_fun_i32_1@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_9_1,@function -; FULL-DAG:__llvm_jump_instr_table_9_1: -; FULL-DAG: jmp indirect_fun_i32_2@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_7_1,@function -; FULL-DAG:__llvm_jump_instr_table_7_1: -; FULL-DAG: jmp indirect_fun_i32S_2@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_3_1,@function -; FULL-DAG:__llvm_jump_instr_table_3_1: -; FULL-DAG: jmp indirect_fun_vec_2@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_2_1,@function -; FULL-DAG:__llvm_jump_instr_table_2_1: -; FULL-DAG: jmp indirect_fun@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_8_1,@function -; FULL-DAG:__llvm_jump_instr_table_8_1: -; FULL-DAG: jmp indirect_fun_i32@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_1_1,@function -; FULL-DAG:__llvm_jump_instr_table_1_1: -; FULL-DAG: jmp indirect_fun_array@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_0_1,@function -; FULL-DAG:__llvm_jump_instr_table_0_1: -; FULL-DAG: jmp indirect_fun_vec@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_6_1,@function -; FULL-DAG:__llvm_jump_instr_table_6_1: -; FULL-DAG: jmp indirect_fun_struct@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_5_1,@function -; FULL-DAG:__llvm_jump_instr_table_5_1: -; FULL-DAG: jmp indirect_fun_fun@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: .type __llvm_jump_instr_table_4_1,@function -; FULL-DAG:__llvm_jump_instr_table_4_1: -; FULL-DAG: jmp indirect_fun_fun_ret@PLT -; FULL-DAG: .align 8, 0x90 -; FULL-DAG: ud2 diff --git a/test/LTO/X86/jump-table-type.ll b/test/LTO/X86/jump-table-type.ll deleted file mode 100644 index a806c303f8c..00000000000 --- a/test/LTO/X86/jump-table-type.ll +++ /dev/null @@ -1,23 +0,0 @@ -; RUN: llvm-as <%s >%t1 -; RUN: llvm-lto -o %t2 %t1 -jump-table-type=arity -; RUN: llvm-nm %t2 | FileCheck %s - -; CHECK: t __llvm_jump_instr_table_0_1 -; CHECK: t __llvm_jump_instr_table_1_1 - -target triple = "x86_64-unknown-linux-gnu" - -define i32 @g(i32 %a) unnamed_addr jumptable { - ret i32 %a -} - -define i32 @f() unnamed_addr jumptable { - ret i32 0 -} - -define i32 @main() { - ret i32 0 -} - -@llvm.used = appending global [2 x i8*] [i8* bitcast (i32(i32)* @g to i8*), - i8* bitcast (i32()* @f to i8*)]