[llvm] r221708 - Add Forward Control-Flow Integrity.
Rafael EspĂndola
rafael.espindola at gmail.com
Wed Nov 12 06:23:42 PST 2014
Should be fixed in r221783. Let me know if that looks like the correct fix.
On 11 November 2014 20:36, Rafael EspĂndola <rafael.espindola at gmail.com> wrote:
> This causes tools/gold/option.ll to fail.
>
> Can you take a look? Looks like __llvm_jump_instr_table_* are no
> longer produced for that test.
>
>
> On 11 November 2014 16:08, Tom Roeder <tmroeder at google.com> wrote:
>> Author: tmroeder
>> Date: Tue Nov 11 15:08:02 2014
>> New Revision: 221708
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=221708&view=rev
>> Log:
>> Add Forward Control-Flow Integrity.
>>
>> This commit adds a new pass that can inject checks before indirect calls to
>> make sure that these calls target known locations. It supports three types of
>> checks and, at compile time, it can take the name of a custom function to call
>> when an indirect call check fails. The default failure function ignores the
>> error and continues.
>>
>> This pass incidentally moves the function JumpInstrTables::transformType from
>> private to public and makes it static (with a new argument that specifies the
>> table type to use); this is so that the CFI code can transform function types
>> at call sites to determine which jump-instruction table to use for the check at
>> that site.
>>
>> Also, this removes support for jumptables in ARM, pending further performance
>> analysis and discussion.
>>
>> Review: http://reviews.llvm.org/D4167
>>
>>
>> Added:
>> llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
>> llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp
>> llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll
>> llvm/trunk/test/CodeGen/X86/cfi_invoke.ll
>> llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll
>> llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll
>> llvm/trunk/test/CodeGen/X86/jump_table_align.ll
>> Removed:
>> llvm/trunk/test/CodeGen/ARM/jump_tables.ll
>> Modified:
>> llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h
>> llvm/trunk/include/llvm/CodeGen/CommandFlags.h
>> llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h
>> llvm/trunk/include/llvm/CodeGen/Passes.h
>> llvm/trunk/include/llvm/InitializePasses.h
>> llvm/trunk/include/llvm/Target/TargetInstrInfo.h
>> llvm/trunk/include/llvm/Target/TargetOptions.h
>> llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp
>> llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
>> llvm/trunk/lib/CodeGen/CMakeLists.txt
>> llvm/trunk/lib/CodeGen/JumpInstrTables.cpp
>> llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
>> llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp
>> llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
>> llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
>> llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>> llvm/trunk/lib/Target/X86/X86InstrInfo.h
>> llvm/trunk/test/CodeGen/X86/jump_table_alias.ll
>> llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll
>> llvm/trunk/test/CodeGen/X86/jump_tables.ll
>> llvm/trunk/test/LTO/jump-table-type.ll
>>
>> Modified: llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h (original)
>> +++ llvm/trunk/include/llvm/Analysis/JumpInstrTableInfo.h Tue Nov 11 15:08:02 2014
>> @@ -37,7 +37,9 @@ class JumpInstrTableInfo : public Immuta
>> public:
>> static char ID;
>>
>> - JumpInstrTableInfo();
>> + /// The default byte alignment for jump tables is 16, which is large but
>> + /// usually safe.
>> + JumpInstrTableInfo(uint64_t ByteAlign = 16);
>> virtual ~JumpInstrTableInfo();
>> const char *getPassName() const override {
>> return "Jump-Instruction Table Info";
>> @@ -52,9 +54,19 @@ public:
>> /// Gets the tables.
>> const JumpTables &getTables() const { return Tables; }
>>
>> + /// Gets the alignment in bytes of a jumptable entry.
>> + uint64_t entryByteAlignment() const { return ByteAlignment; }
>> private:
>> JumpTables Tables;
>> +
>> + /// A power-of-two alignment of a jumptable entry.
>> + uint64_t ByteAlignment;
>> };
>> +
>> +/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This
>> +/// bound specifies the maximum number of bytes needed to represent an
>> +/// unconditional jump or a trap instruction in the back end currently in use.
>> +ModulePass *createJumpInstrTableInfoPass(unsigned Bound);
>> }
>>
>> #endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */
>>
>> Modified: llvm/trunk/include/llvm/CodeGen/CommandFlags.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CommandFlags.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/CodeGen/CommandFlags.h (original)
>> +++ llvm/trunk/include/llvm/CodeGen/CommandFlags.h Tue Nov 11 15:08:02 2014
>> @@ -222,6 +222,44 @@ JTableType("jump-table-type",
>> "Create one table per unique function type."),
>> clEnumValEnd));
>>
>> +cl::opt<bool>
>> +FCFI("fcfi",
>> + cl::desc("Apply forward-edge control-flow integrity"),
>> + cl::init(false));
>> +
>> +cl::opt<llvm::CFIntegrity>
>> +CFIType("cfi-type",
>> + cl::desc("Choose the type of Control-Flow Integrity check to add"),
>> + cl::init(CFIntegrity::Sub),
>> + cl::values(
>> + clEnumValN(CFIntegrity::Sub, "sub",
>> + "Subtract the pointer from the table base, then mask."),
>> + clEnumValN(CFIntegrity::Ror, "ror",
>> + "Use rotate to check the offset from a table base."),
>> + clEnumValN(CFIntegrity::Add, "add",
>> + "Mask out the high bits and add to an aligned base."),
>> + clEnumValEnd));
>> +
>> +cl::opt<bool>
>> +CFIEnforcing("cfi-enforcing",
>> + cl::desc("Enforce CFI or pass the violation to a function."),
>> + cl::init(false));
>> +
>> +// Note that this option is linked to the cfi-enforcing option above: if
>> +// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If
>> +// cfi-enforcing is false and no cfi-func-name is set, then a default function
>> +// will be generated that ignores all CFI violations. The expected signature for
>> +// functions called with CFI violations is
>> +//
>> +// void (i8*, i8*)
>> +//
>> +// The first pointer is a C string containing the name of the function in which
>> +// the violation occurs, and the second pointer is the pointer that violated
>> +// CFI.
>> +cl::opt<std::string>
>> +CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"),
>> + cl::init(""));
>> +
>> // Common utility function tightly tied to the options listed here. Initializes
>> // a TargetOptions object with CodeGen flags and returns it.
>> static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
>> @@ -249,6 +287,10 @@ static inline TargetOptions InitTargetOp
>>
>> Options.MCOptions = InitMCTargetOptionsFromFlags();
>> Options.JTType = JTableType;
>> + Options.FCFI = FCFI;
>> + Options.CFIType = CFIType;
>> + Options.CFIEnforcing = CFIEnforcing;
>> + Options.CFIFuncName = CFIFuncName;
>>
>> Options.ThreadModel = TMModel;
>>
>>
>> Added: llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h?rev=221708&view=auto
>> ==============================================================================
>> --- llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h (added)
>> +++ llvm/trunk/include/llvm/CodeGen/ForwardControlFlowIntegrity.h Tue Nov 11 15:08:02 2014
>> @@ -0,0 +1,123 @@
>> +//===-- 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 <string>
>> +
>> +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);
>> + virtual ~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<Instruction *, 64> 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<FunctionType *, CFIConstants> 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
>>
>> Modified: llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h (original)
>> +++ llvm/trunk/include/llvm/CodeGen/JumpInstrTables.h Tue Nov 11 15:08:02 2014
>> @@ -39,13 +39,14 @@ class Module;
>> /// jmp f_orig at PLT
>> /// \endverbatim
>> ///
>> -/// Support for an architecture depends on two functions in TargetInstrInfo:
>> -/// getUnconditionalBranch, and getTrap. 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.
>> +/// 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;
>> @@ -64,6 +65,14 @@ public:
>> /// 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 {
>> @@ -76,14 +85,6 @@ private:
>>
>> typedef DenseMap<FunctionType *, struct TableMeta> JumpMap;
>>
>> - /// 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.
>> - FunctionType *transformType(FunctionType *FunTy);
>> -
>> /// The current state of functions and jump entries in the table(s).
>> JumpMap Metadata;
>>
>>
>> Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
>> +++ llvm/trunk/include/llvm/CodeGen/Passes.h Tue Nov 11 15:08:02 2014
>> @@ -602,6 +602,10 @@ namespace llvm {
>>
>> /// createJumpInstrTables - This pass creates jump-instruction tables.
>> ModulePass *createJumpInstrTablesPass();
>> +
>> + /// createForwardControlFlowIntegrityPass - This pass adds control-flow
>> + /// integrity.
>> + ModulePass *createForwardControlFlowIntegrityPass();
>> } // End llvm namespace
>>
>> /// This initializer registers TargetMachine constructor, so the pass being
>>
>> Modified: llvm/trunk/include/llvm/InitializePasses.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/InitializePasses.h (original)
>> +++ llvm/trunk/include/llvm/InitializePasses.h Tue Nov 11 15:08:02 2014
>> @@ -91,6 +91,7 @@ void initializeCFGOnlyViewerPass(PassReg
>> void initializeCFGPrinterPass(PassRegistry&);
>> void initializeCFGSimplifyPassPass(PassRegistry&);
>> void initializeCFLAliasAnalysisPass(PassRegistry&);
>> +void initializeForwardControlFlowIntegrityPass(PassRegistry&);
>> void initializeFlattenCFGPassPass(PassRegistry&);
>> void initializeStructurizeCFGPass(PassRegistry&);
>> void initializeCFGViewerPass(PassRegistry&);
>>
>> Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original)
>> +++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Tue Nov 11 15:08:02 2014
>> @@ -428,6 +428,26 @@ public:
>> llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!");
>> }
>>
>> + /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold
>> + /// either the instruction returned by getUnconditionalBranch or the
>> + /// instruction returned by getTrap. This only makes sense because
>> + /// getUnconditionalBranch returns a single, specific instruction. This
>> + /// information is needed by the jumptable construction code, since it must
>> + /// decide how many bytes to use for a jumptable entry so it can generate the
>> + /// right mask.
>> + ///
>> + /// Note that if the jumptable instruction requires alignment, then that
>> + /// alignment should be factored into this required bound so that the
>> + /// resulting bound gives the right alignment for the instruction.
>> + virtual unsigned getJumpInstrTableEntryBound() const {
>> + // This method gets called by LLVMTargetMachine always, so it can't fail
>> + // just because there happens to be no implementation for this target.
>> + // Any code that tries to use a jumptable annotation without defining
>> + // getUnconditionalBranch on the appropriate Target will fail anyway, and
>> + // the value returned here won't matter in that case.
>> + return 0;
>> + }
>> +
>> /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic
>> /// block at the specified instruction (i.e. instruction would be the start
>> /// of a new basic block).
>>
>> Modified: llvm/trunk/include/llvm/Target/TargetOptions.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOptions.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Target/TargetOptions.h (original)
>> +++ llvm/trunk/include/llvm/Target/TargetOptions.h Tue Nov 11 15:08:02 2014
>> @@ -57,6 +57,14 @@ namespace llvm {
>> };
>> }
>>
>> + enum class CFIntegrity {
>> + Sub, // Use subtraction-based checks.
>> + Ror, // Use rotation-based checks.
>> + Add // Use addition-based checks. This depends on having
>> + // sufficient alignment in the code and is usually not
>> + // feasible.
>> + };
>> +
>> class TargetOptions {
>> public:
>> TargetOptions()
>> @@ -70,10 +78,11 @@ namespace llvm {
>> EnableFastISel(false), PositionIndependentExecutable(false),
>> UseInitArray(false), DisableIntegratedAS(false),
>> CompressDebugSections(false), FunctionSections(false),
>> - DataSections(false), TrapUnreachable(false), TrapFuncName(""),
>> + DataSections(false), TrapUnreachable(false), TrapFuncName(),
>> FloatABIType(FloatABI::Default),
>> AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
>> - ThreadModel(ThreadModel::POSIX) {}
>> + FCFI(false), ThreadModel(ThreadModel::POSIX),
>> + CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
>>
>> /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
>> /// option is specified on the command line, and should enable debugging
>> @@ -228,10 +237,28 @@ namespace llvm {
>> /// create for functions that have the jumptable attribute.
>> JumpTable::JumpTableType JTType;
>>
>> + /// FCFI - This flags controls whether or not forward-edge control-flow
>> + /// integrity is applied.
>> + bool FCFI;
>> +
>> /// ThreadModel - This flag specifies the type of threading model to assume
>> /// for things like atomics
>> ThreadModel::Model ThreadModel;
>>
>> + /// CFIType - This flag specifies the type of control-flow integrity check
>> + /// to add as a preamble to indirect calls.
>> + CFIntegrity CFIType;
>> +
>> + /// CFIEnforcing - This flags controls whether or not CFI violations cause
>> + /// the program to halt.
>> + bool CFIEnforcing;
>> +
>> + /// getCFIFuncName - If this returns a non-empty string, then this is the
>> + /// name of the function that will be called for each CFI violation in
>> + /// non-enforcing mode.
>> + std::string CFIFuncName;
>> + StringRef getCFIFuncName() const;
>> +
>> /// Machine level options.
>> MCTargetOptions MCOptions;
>> };
>>
>> Modified: llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp (original)
>> +++ llvm/trunk/lib/Analysis/JumpInstrTableInfo.cpp Tue Nov 11 15:08:02 2014
>> @@ -17,6 +17,7 @@
>> #include "llvm/Analysis/Passes.h"
>> #include "llvm/IR/Function.h"
>> #include "llvm/IR/Type.h"
>> +#include "llvm/Support/MathExtras.h"
>>
>> using namespace llvm;
>>
>> @@ -28,7 +29,21 @@ ImmutablePass *llvm::createJumpInstrTabl
>> return new JumpInstrTableInfo();
>> }
>>
>> -JumpInstrTableInfo::JumpInstrTableInfo() : ImmutablePass(ID), Tables() {
>> +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<uint64_t>(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());
>> }
>>
>>
>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Tue Nov 11 15:08:02 2014
>> @@ -879,16 +879,17 @@ bool AsmPrinter::doFinalization(Module &
>> bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb);
>> MCInst TrapInst;
>> TM.getSubtargetImpl()->getInstrInfo()->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());
>> - OutStreamer.EmitSymbolAttribute(FunSym, MCSA_Global);
>> - // FIXME: JumpTableInstrInfo should store information about the required
>> - // alignment of table entries and the size of the padding instruction.
>> - EmitAlignment(3);
>> + EmitAlignment(LogAlignment);
>> if (IsThumb)
>> OutStreamer.EmitThumbFunc(FunSym);
>> if (MAI->hasDotTypeDotSizeDirective())
>> @@ -910,10 +911,9 @@ bool AsmPrinter::doFinalization(Module &
>> }
>>
>> // Emit enough padding instructions to fill up to the next power of two.
>> - // This assumes that the trap instruction takes 8 bytes or fewer.
>> uint64_t Remaining = NextPowerOf2(Count) - Count;
>> for (uint64_t C = 0; C < Remaining; ++C) {
>> - EmitAlignment(3);
>> + EmitAlignment(LogAlignment);
>> OutStreamer.EmitInstruction(TrapInst, getSubtargetInfo());
>> }
>>
>>
>> Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/CodeGen/CMakeLists.txt Tue Nov 11 15:08:02 2014
>> @@ -19,6 +19,7 @@ add_llvm_library(LLVMCodeGen
>> ExecutionDepsFix.cpp
>> ExpandISelPseudos.cpp
>> ExpandPostRAPseudos.cpp
>> + ForwardControlFlowIntegrity.cpp
>> GCMetadata.cpp
>> GCMetadataPrinter.cpp
>> GCStrategy.cpp
>>
>> Added: llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp?rev=221708&view=auto
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp (added)
>> +++ llvm/trunk/lib/CodeGen/ForwardControlFlowIntegrity.cpp Tue Nov 11 15:08:02 2014
>> @@ -0,0 +1,375 @@
>> +//===-- 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/Instructions.h"
>> +#include "llvm/IR/InlineAsm.h"
>> +#include "llvm/IR/IRBuilder.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<ConstantExpr>(V)) {
>> + return !(CE->isCast() && isa<Function>(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";
>> +static const char cfi_func_name_prefix[] = "__llvm_cfi_function_";
>> +
>> +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<JumpInstrTableInfo>();
>> + AU.addRequired<JumpInstrTables>();
>> +}
>> +
>> +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<InlineAsm>(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<PointerType>(VTy);
>> + Type *EltTy = PTy->getElementType();
>> + FunctionType *FunTy = dyn_cast<FunctionType>(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<JumpInstrTableInfo>();
>> + 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<uint64_t>(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<Type *, 2> 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<BasicBlock>(I->getParent());
>> + Function *CurF = cast<Function>(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<uint64_t>(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<Function>(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);
>> +}
>>
>> Modified: llvm/trunk/lib/CodeGen/JumpInstrTables.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/JumpInstrTables.cpp?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/JumpInstrTables.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/JumpInstrTables.cpp Tue Nov 11 15:08:02 2014
>> @@ -163,7 +163,7 @@ void JumpInstrTables::getAnalysisUsage(A
>>
>> Function *JumpInstrTables::insertEntry(Module &M, Function *Target) {
>> FunctionType *OrigFunTy = Target->getFunctionType();
>> - FunctionType *FunTy = transformType(OrigFunTy);
>> + FunctionType *FunTy = transformType(JTType, OrigFunTy);
>>
>> JumpMap::iterator it = Metadata.find(FunTy);
>> if (Metadata.end() == it) {
>> @@ -191,11 +191,12 @@ Function *JumpInstrTables::insertEntry(M
>> }
>>
>> bool JumpInstrTables::hasTable(FunctionType *FunTy) {
>> - FunctionType *TransTy = transformType(FunTy);
>> + FunctionType *TransTy = transformType(JTType, FunTy);
>> return Metadata.end() != Metadata.find(TransTy);
>> }
>>
>> -FunctionType *JumpInstrTables::transformType(FunctionType *FunTy) {
>> +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());
>> @@ -211,7 +212,7 @@ FunctionType *JumpInstrTables::transform
>> Type *Int32Ty = Type::getInt32Ty(FunTy->getContext());
>> FunctionType *VoidFnTy = FunctionType::get(
>> Type::getVoidTy(FunTy->getContext()), EmptyParams, false);
>> - switch (JTType) {
>> + switch (JTT) {
>> case JumpTable::Single:
>>
>> return FunctionType::get(RetTy, EmptyParams, false);
>> @@ -253,10 +254,10 @@ FunctionType *JumpInstrTables::transform
>> bool JumpInstrTables::runOnModule(Module &M) {
>> JITI = &getAnalysis<JumpInstrTableInfo>();
>>
>> - // Get the set of jumptable-annotated functions.
>> + // Get the set of jumptable-annotated functions that have their address taken.
>> DenseMap<Function *, Function *> Functions;
>> for (Function &F : M) {
>> - if (F.hasFnAttribute(Attribute::JumpTable)) {
>> + if (F.hasFnAttribute(Attribute::JumpTable) && F.hasAddressTaken()) {
>> assert(F.hasUnnamedAddr() &&
>> "Attribute 'jumptable' requires 'unnamed_addr'");
>> Functions[&F] = nullptr;
>>
>> Modified: llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp Tue Nov 11 15:08:02 2014
>> @@ -13,8 +13,10 @@
>>
>> #include "llvm/Target/TargetMachine.h"
>>
>> +#include "llvm/Analysis/JumpInstrTableInfo.h"
>> #include "llvm/Analysis/Passes.h"
>> #include "llvm/CodeGen/AsmPrinter.h"
>> +#include "llvm/CodeGen/ForwardControlFlowIntegrity.h"
>> #include "llvm/CodeGen/JumpInstrTables.h"
>> #include "llvm/CodeGen/MachineFunctionAnalysis.h"
>> #include "llvm/CodeGen/MachineModuleInfo.h"
>> @@ -143,8 +145,13 @@ bool LLVMTargetMachine::addPassesToEmitF
>> 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());
>> + 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,
>>
>> Modified: llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/TargetOptionsImpl.cpp Tue Nov 11 15:08:02 2014
>> @@ -51,3 +51,10 @@ bool TargetOptions::HonorSignDependentRo
>> StringRef TargetOptions::getTrapFunctionName() const {
>> return TrapFuncName;
>> }
>> +
>> +/// getCFIFuncName - If this returns a non-empty string, then it is the name of
>> +/// the function that gets called on CFI violations in CFI non-enforcing mode
>> +/// (!TargetOptions::CFIEnforcing).
>> +StringRef TargetOptions::getCFIFuncName() const {
>> + return CFIFuncName;
>> +}
>>
>> Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
>> +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Tue Nov 11 15:08:02 2014
>> @@ -4489,29 +4489,6 @@ breakPartialRegDependency(MachineBasicBl
>> MI->addRegisterKilled(DReg, TRI, true);
>> }
>>
>> -void ARMBaseInstrInfo::getUnconditionalBranch(
>> - MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {
>> - if (Subtarget.isThumb())
>> - Branch.setOpcode(ARM::tB);
>> - else if (Subtarget.isThumb2())
>> - Branch.setOpcode(ARM::t2B);
>> - else
>> - Branch.setOpcode(ARM::Bcc);
>> -
>> - Branch.addOperand(MCOperand::CreateExpr(BranchTarget));
>> - Branch.addOperand(MCOperand::CreateImm(ARMCC::AL));
>> - Branch.addOperand(MCOperand::CreateReg(0));
>> -}
>> -
>> -void ARMBaseInstrInfo::getTrap(MCInst &MI) const {
>> - if (Subtarget.isThumb())
>> - MI.setOpcode(ARM::tTRAP);
>> - else if (Subtarget.useNaClTrap())
>> - MI.setOpcode(ARM::TRAPNaCl);
>> - else
>> - MI.setOpcode(ARM::TRAP);
>> -}
>> -
>> bool ARMBaseInstrInfo::hasNOP() const {
>> return (Subtarget.getFeatureBits() & ARM::HasV6T2Ops) != 0;
>> }
>>
>> Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)
>> +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Tue Nov 11 15:08:02 2014
>> @@ -289,12 +289,6 @@ public:
>> void breakPartialRegDependency(MachineBasicBlock::iterator, unsigned,
>> const TargetRegisterInfo *TRI) const override;
>>
>> - void
>> - getUnconditionalBranch(MCInst &Branch,
>> - const MCSymbolRefExpr *BranchTarget) const override;
>> -
>> - void getTrap(MCInst &MI) const override;
>> -
>> /// Get the number of addresses by LDM or VLDM or zero for unknown.
>> unsigned getNumLDMAddresses(const MachineInstr *MI) const;
>>
>>
>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
>> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Nov 11 15:08:02 2014
>> @@ -5477,16 +5477,32 @@ void X86InstrInfo::getNoopForMachoTarget
>> NopInst.setOpcode(X86::NOOP);
>> }
>>
>> +// This code must remain in sync with getJumpInstrTableEntryBound in this class!
>> +// In particular, getJumpInstrTableEntryBound must always return an upper bound
>> +// on the encoding lengths of the instructions generated by
>> +// getUnconditionalBranch and getTrap.
>> void X86InstrInfo::getUnconditionalBranch(
>> MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {
>> Branch.setOpcode(X86::JMP_4);
>> Branch.addOperand(MCOperand::CreateExpr(BranchTarget));
>> }
>>
>> +// This code must remain in sync with getJumpInstrTableEntryBound in this class!
>> +// In particular, getJumpInstrTableEntryBound must always return an upper bound
>> +// on the encoding lengths of the instructions generated by
>> +// getUnconditionalBranch and getTrap.
>> void X86InstrInfo::getTrap(MCInst &MI) const {
>> MI.setOpcode(X86::TRAP);
>> }
>>
>> +// See getTrap and getUnconditionalBranch for conditions on the value returned
>> +// by this function.
>> +unsigned X86InstrInfo::getJumpInstrTableEntryBound() const {
>> + // 5 bytes suffice: JMP_4 Symbol at PLT is uses 1 byte (E9) for the JMP_4 and 4
>> + // bytes for the symbol offset. And TRAP is ud2, which is two bytes (0F 0B).
>> + return 5;
>> +}
>> +
>> bool X86InstrInfo::isHighLatencyDef(int opc) const {
>> switch (opc) {
>> default: return false;
>>
>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)
>> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Tue Nov 11 15:08:02 2014
>> @@ -413,6 +413,8 @@ public:
>>
>> void getTrap(MCInst &MI) const override;
>>
>> + unsigned getJumpInstrTableEntryBound() const override;
>> +
>> bool isHighLatencyDef(int opc) const override;
>>
>> bool hasHighOperandLatency(const InstrItineraryData *ItinData,
>>
>> Removed: llvm/trunk/test/CodeGen/ARM/jump_tables.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/jump_tables.ll?rev=221707&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM/jump_tables.ll (original)
>> +++ llvm/trunk/test/CodeGen/ARM/jump_tables.ll (removed)
>> @@ -1,32 +0,0 @@
>> -; RUN: llc <%s -mtriple=arm-unknown-linux-gnueabi -jump-table-type=single | FileCheck --check-prefix=ARM %s
>> -; RUN: llc <%s -mtriple=thumb-unknown-linux-gnueabi -jump-table-type=single | FileCheck --check-prefix=THUMB %s
>> -
>> -define void @indirect_fun() unnamed_addr jumptable {
>> - ret void
>> -}
>> -define void ()* @get_fun() {
>> - ret void ()* @indirect_fun
>> -
>> -; ARM: ldr r0, [[LABEL:.*]]
>> -; ARM: mov pc, lr
>> -; ARM: [[LABEL]]:
>> -; ARM: .long __llvm_jump_instr_table_0_1
>> -
>> -; THUMB: ldr r0, [[LABEL:.*]]
>> -; THUMB: bx lr
>> -; THUMB: [[LABEL]]:
>> -; THUMB: .long __llvm_jump_instr_table_0_1
>> -}
>> -
>> -; ARM: .globl __llvm_jump_instr_table_0_1
>> -; ARM: .align 3
>> -; ARM: .type __llvm_jump_instr_table_0_1,%function
>> -; ARM: __llvm_jump_instr_table_0_1:
>> -; ARM: b indirect_fun(PLT)
>> -
>> -; THUMB: .globl __llvm_jump_instr_table_0_1
>> -; THUMB: .align 3
>> -; THUMB: .thumb_func
>> -; THUMB: .type __llvm_jump_instr_table_0_1,%function
>> -; THUMB: __llvm_jump_instr_table_0_1:
>> -; THUMB: b indirect_fun(PLT)
>>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll?rev=221708&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll (added)
>> +++ llvm/trunk/test/CodeGen/X86/cfi_enforcing.ll Tue Nov 11 15:08:02 2014
>> @@ -0,0 +1,34 @@
>> +; 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 at PLT
>>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_invoke.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_invoke.ll?rev=221708&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/cfi_invoke.ll (added)
>> +++ llvm/trunk/test/CodeGen/X86/cfi_invoke.ll Tue Nov 11 15:08:02 2014
>> @@ -0,0 +1,35 @@
>> +; 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(...)
>> +
>> + at _ZTIPKc = external constant i8*
>> + at _ZTIi = external constant i8*
>> +
>> +define void @f() unnamed_addr jumptable {
>> + ret void
>> +}
>> +
>> + at 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
>> +}
>> +
>>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll?rev=221708&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll (added)
>> +++ llvm/trunk/test/CodeGen/X86/cfi_non_default_function.ll Tue Nov 11 15:08:02 2014
>> @@ -0,0 +1,27 @@
>> +; 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 at PLT
>>
>> Added: llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll?rev=221708&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll (added)
>> +++ llvm/trunk/test/CodeGen/X86/cfi_simple_indirect_call.ll Tue Nov 11 15:08:02 2014
>> @@ -0,0 +1,43 @@
>> +; 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, at function
>> +; SUB-LABEL:__llvm_jump_instr_table_0_1:
>> +; SUB-LABEL: jmp indirect_fun at PLT
>>
>> Modified: llvm/trunk/test/CodeGen/X86/jump_table_alias.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_alias.ll?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/jump_table_alias.ll (original)
>> +++ llvm/trunk/test/CodeGen/X86/jump_table_alias.ll Tue Nov 11 15:08:02 2014
>> @@ -25,7 +25,6 @@ define i32 @main(i32 %argc, i8** %argv)
>> ; There should only be one table, even though there are two GlobalAliases,
>> ; because they both alias the same value.
>>
>> -; CHECK: .globl __llvm_jump_instr_table_0_1
>> ; CHECK: .align 8, 0x90
>> ; CHECK: .type __llvm_jump_instr_table_0_1, at function
>> ; CHECK: __llvm_jump_instr_table_0_1:
>>
>> Added: llvm/trunk/test/CodeGen/X86/jump_table_align.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_align.ll?rev=221708&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/jump_table_align.ll (added)
>> +++ llvm/trunk/test/CodeGen/X86/jump_table_align.ll Tue Nov 11 15:08:02 2014
>> @@ -0,0 +1,29 @@
>> +; 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)
>>
>> Modified: llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll (original)
>> +++ llvm/trunk/test/CodeGen/X86/jump_table_bitcast.ll Tue Nov 11 15:08:02 2014
>> @@ -15,12 +15,12 @@ define void @h(void ()* %func) unnamed_a
>> 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]], (%rsp)
>> -; CHECK: movl $__llvm_jump_instr_table_0_[[ENTRY]], %ecx
>> +; 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}}, %edi
>> +; 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)
>> @@ -28,17 +28,14 @@ define i32 @main() {
>> ret i32 %a
>> }
>>
>> -; CHECK: .globl __llvm_jump_instr_table_0_1
>> ; CHECK: .align 8, 0x90
>> ; CHECK: .type __llvm_jump_instr_table_0_1, at function
>> ; CHECK: __llvm_jump_instr_table_0_1:
>> ; CHECK: jmp {{f|g|h}}@PLT
>> -; CHECK: .globl __llvm_jump_instr_table_0_2
>> ; CHECK: .align 8, 0x90
>> ; CHECK: .type __llvm_jump_instr_table_0_2, at function
>> ; CHECK: __llvm_jump_instr_table_0_2:
>> ; CHECK: jmp {{f|g|h}}@PLT
>> -; CHECK: .globl __llvm_jump_instr_table_0_3
>> ; CHECK: .align 8, 0x90
>> ; CHECK: .type __llvm_jump_instr_table_0_3, at function
>> ; CHECK: __llvm_jump_instr_table_0_3:
>>
>> Modified: llvm/trunk/test/CodeGen/X86/jump_tables.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/jump_tables.ll?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/jump_tables.ll (original)
>> +++ llvm/trunk/test/CodeGen/X86/jump_tables.ll Tue Nov 11 15:08:02 2014
>> @@ -7,6 +7,20 @@ target triple = "x86_64-unknown-linux-gn
>>
>> %struct.fun_struct = type { i32 (...)* }
>>
>> + at 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
>> }
>> @@ -74,62 +88,50 @@ define i32 @main(i32 %argc, i8** %argv)
>> ret i32 %a
>> }
>>
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_1
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_1, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_1:
>> ; SINGLE-DAG: jmp indirect_fun_array at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_2
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_2, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_2:
>> ; SINGLE-DAG: jmp indirect_fun_i32_2 at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_3
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_3, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_3:
>> ; SINGLE-DAG: jmp indirect_fun_vec_2 at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_4
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_4, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_4:
>> ; SINGLE-DAG: jmp indirect_fun_i32S_2 at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_5
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_5, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_5:
>> ; SINGLE-DAG: jmp indirect_fun_struct at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_6
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_6, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_6:
>> ; SINGLE-DAG: jmp indirect_fun_i32_1 at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_7
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_7, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_7:
>> ; SINGLE-DAG: jmp indirect_fun_i32 at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_8
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_8, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_8:
>> ; SINGLE-DAG: jmp indirect_fun_fun at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_9
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_9, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_9:
>> ; SINGLE-DAG: jmp indirect_fun_fun_ret at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_10
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_10, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_10:
>> ; SINGLE-DAG: jmp indirect_fun at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_11
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_11, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_11:
>> ; SINGLE-DAG: jmp indirect_fun_match at PLT
>> -; SINGLE-DAG: .globl __llvm_jump_instr_table_0_12
>> ; SINGLE-DAG: .align 8, 0x90
>> ; SINGLE-DAG: .type __llvm_jump_instr_table_0_12, at function
>> ; SINGLE-DAG: __llvm_jump_instr_table_0_12:
>> @@ -144,82 +146,69 @@ define i32 @main(i32 %argc, i8** %argv)
>> ; SINGLE-DAG: ud2
>>
>>
>> -; ARITY-DAG: .globl __llvm_jump_instr_table_2_1
>> ; ARITY-DAG: .align 8, 0x90
>> ; ARITY-DAG: .type __llvm_jump_instr_table_2_1, at 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: .globl __llvm_jump_instr_table_0_1
>> ; ARITY-DAG: .align 8, 0x90
>> ; ARITY-DAG: .type __llvm_jump_instr_table_0_1, at function
>> ; ARITY-DAG: __llvm_jump_instr_table_0_1:
>> ; ARITY-DAG: jmp indirect_fun{{.*}}@PLT
>> -; ARITY-DAG: .globl __llvm_jump_instr_table_1_1
>> ; ARITY-DAG: .align 8, 0x90
>> ; ARITY-DAG: .type __llvm_jump_instr_table_1_1, at function
>> ; ARITY-DAG: __llvm_jump_instr_table_1_1:
>> ; ARITY-DAG: jmp indirect_fun{{.*}}@PLT
>>
>> -; SIMPL-DAG: .globl __llvm_jump_instr_table_2_1
>> ; SIMPL-DAG: .align 8, 0x90
>> ; SIMPL-DAG: .type __llvm_jump_instr_table_2_1, at 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: .globl __llvm_jump_instr_table_0_1
>> ; SIMPL-DAG: .align 8, 0x90
>> ; SIMPL-DAG: .type __llvm_jump_instr_table_0_1, at function
>> ; SIMPL-DAG: __llvm_jump_instr_table_0_1:
>> ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
>> -; SIMPL-DAG: .globl __llvm_jump_instr_table_1_1
>> ; SIMPL-DAG: .align 8, 0x90
>> ; SIMPL-DAG: .type __llvm_jump_instr_table_1_1, at function
>> ; SIMPL-DAG: __llvm_jump_instr_table_1_1:
>> ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
>> -; SIMPL-DAG: .globl __llvm_jump_instr_table_3_1
>> ; SIMPL-DAG: .align 8, 0x90
>> ; SIMPL-DAG: .type __llvm_jump_instr_table_3_1, at function
>> ; SIMPL-DAG: __llvm_jump_instr_table_3_1:
>> ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
>> -; SIMPL-DAG: .globl __llvm_jump_instr_table_4_1
>> ; SIMPL-DAG: .align 8, 0x90
>> ; SIMPL-DAG: .type __llvm_jump_instr_table_4_1, at function
>> ; SIMPL-DAG: __llvm_jump_instr_table_4_1:
>> ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
>>
>>
>> -; FULL-DAG: .globl __llvm_jump_instr_table_10_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_10_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_10_1:
>> ; FULL-DAG: jmp indirect_fun_i32_1 at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_9_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_9_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_9_1:
>> ; FULL-DAG: jmp indirect_fun_i32_2 at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_7_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_7_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_7_1:
>> ; FULL-DAG: jmp indirect_fun_i32S_2 at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_3_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_3_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_3_1:
>> ; FULL-DAG: jmp indirect_fun_vec_2 at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_2_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_2_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_2_1:
>> @@ -228,42 +217,36 @@ define i32 @main(i32 %argc, i8** %argv)
>> ; FULL-DAG: ud2
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_8_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_8_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_8_1:
>> ; FULL-DAG: jmp indirect_fun_i32 at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_1_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_1_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_1_1:
>> ; FULL-DAG: jmp indirect_fun_array at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_0_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_0_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_0_1:
>> ; FULL-DAG: jmp indirect_fun_vec at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_6_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_6_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_6_1:
>> ; FULL-DAG: jmp indirect_fun_struct at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_5_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_5_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_5_1:
>> ; FULL-DAG: jmp indirect_fun_fun at PLT
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: ud2
>> -; FULL-DAG: .globl __llvm_jump_instr_table_4_1
>> ; FULL-DAG: .align 8, 0x90
>> ; FULL-DAG: .type __llvm_jump_instr_table_4_1, at function
>> ; FULL-DAG:__llvm_jump_instr_table_4_1:
>>
>> Modified: llvm/trunk/test/LTO/jump-table-type.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/jump-table-type.ll?rev=221708&r1=221707&r2=221708&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/LTO/jump-table-type.ll (original)
>> +++ llvm/trunk/test/LTO/jump-table-type.ll Tue Nov 11 15:08:02 2014
>> @@ -2,8 +2,8 @@
>> ; 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
>> +; CHECK: t __llvm_jump_instr_table_0_1
>> +; CHECK: t __llvm_jump_instr_table_1_1
>>
>> target triple = "x86_64-unknown-linux-gnu"
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list