From de2d0196a2af5156c9d63cb6f5370eddababa0e9 Mon Sep 17 00:00:00 2001 From: Adrian McCarthy Date: Tue, 9 Jan 2018 23:49:30 +0000 Subject: [PATCH] Reland "Emit Function IDs table for Control Flow Guard" Adds option /guard:cf to clang-cl and -cfguard to cc1 to emit function IDs of functions that have their address taken into a section named .gfids$y for compatibility with Microsoft's Control Flow Guard feature. The original patch didn't have the lit.local.cfg file that restricts the new test to x86, thus the new test was failing on the non-x86 bots. Differential Revision: https://reviews.llvm.org/D40531 The reverts r322008, which was a revert of r322005. This reverts commit a05b89f9aca70597dc79fe97bc49b50b51f525ba. llvm-svn: 322136 --- include/llvm/MC/MCObjectFileInfo.h | 2 + include/llvm/MC/MCStreamer.h | 3 + include/llvm/MC/MCWinCOFFStreamer.h | 1 + lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 10 ++ lib/CodeGen/AsmPrinter/CMakeLists.txt | 1 + lib/CodeGen/AsmPrinter/WinCFGuard.cpp | 45 +++++++ lib/CodeGen/AsmPrinter/WinCFGuard.h | 54 +++++++++ lib/MC/MCAsmStreamer.cpp | 7 ++ lib/MC/MCObjectFileInfo.cpp | 5 + lib/MC/MCParser/COFFAsmParser.cpp | 19 ++- lib/MC/MCStreamer.cpp | 2 + lib/MC/MCWinCOFFStreamer.cpp | 11 ++ test/CodeGen/WinCFGuard/cfguard.ll | 162 ++++++++++++++++++++++++++ test/CodeGen/WinCFGuard/lit.local.cfg | 2 + test/MC/COFF/symidx.s | 15 +++ 15 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 lib/CodeGen/AsmPrinter/WinCFGuard.cpp create mode 100644 lib/CodeGen/AsmPrinter/WinCFGuard.h create mode 100644 test/CodeGen/WinCFGuard/cfguard.ll create mode 100644 test/CodeGen/WinCFGuard/lit.local.cfg create mode 100644 test/MC/COFF/symidx.s diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 79bf2b97015..8f5ca4dee65 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -196,6 +196,7 @@ protected: MCSection *PDataSection; MCSection *XDataSection; MCSection *SXDataSection; + MCSection *GFIDsSection; public: void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx, @@ -349,6 +350,7 @@ public: MCSection *getPDataSection() const { return PDataSection; } MCSection *getXDataSection() const { return XDataSection; } MCSection *getSXDataSection() const { return SXDataSection; } + MCSection *getGFIDsSection() const { return GFIDsSection; } MCSection *getEHFrameSection() { return EHFrameSection; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 7514be93e09..a4a1b5034a8 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -500,6 +500,9 @@ public: virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol); + /// \brief Emits the symbol table index of a Symbol into the current section. + virtual void EmitCOFFSymbolIndex(MCSymbol const *Symbol); + /// \brief Emits a COFF section index. /// /// \param Symbol - Symbol the section number relocation should point to. diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index a2500c06efa..60c17cac9f2 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -50,6 +50,7 @@ public: void EmitCOFFSymbolType(int Type) override; void EndCOFFSymbolDef() override; void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; + void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override; void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index d7995447592..7ffb5ddc2d6 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -16,6 +16,7 @@ #include "CodeViewDebug.h" #include "DwarfDebug.h" #include "DwarfException.h" +#include "WinCFGuard.h" #include "WinException.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" @@ -130,6 +131,8 @@ static const char *const DbgTimerName = "emit"; static const char *const DbgTimerDescription = "Debug Info Emission"; static const char *const EHTimerName = "write_exception"; static const char *const EHTimerDescription = "DWARF Exception Writer"; +static const char *const CFGuardName = "Control Flow Guard"; +static const char *const CFGuardDescription = "Control Flow Guard Tables"; static const char *const CodeViewLineTablesGroupName = "linetables"; static const char *const CodeViewLineTablesGroupDescription = "CodeView Line Tables"; @@ -354,6 +357,13 @@ bool AsmPrinter::doInitialization(Module &M) { if (ES) Handlers.push_back(HandlerInfo(ES, EHTimerName, EHTimerDescription, DWARFGroupName, DWARFGroupDescription)); + + if (mdconst::extract_or_null( + MMI->getModule()->getModuleFlag("cfguard"))) + Handlers.push_back(HandlerInfo(new WinCFGuard(this), CFGuardName, + CFGuardDescription, DWARFGroupName, + DWARFGroupDescription)); + return false; } diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index 05c6a28bbca..f21810f0b05 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -20,6 +20,7 @@ add_llvm_library(LLVMAsmPrinter EHStreamer.cpp ErlangGCPrinter.cpp OcamlGCPrinter.cpp + WinCFGuard.cpp WinException.cpp CodeViewDebug.cpp diff --git a/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/lib/CodeGen/AsmPrinter/WinCFGuard.cpp new file mode 100644 index 00000000000..18d37caf57e --- /dev/null +++ b/lib/CodeGen/AsmPrinter/WinCFGuard.cpp @@ -0,0 +1,45 @@ +//===-- CodeGen/AsmPrinter/WinCFGuard.cpp - Control Flow Guard Impl ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing Win64 exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "WinCFGuard.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Metadata.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCStreamer.h" + +#include + +using namespace llvm; + +WinCFGuard::WinCFGuard(AsmPrinter *A) : AsmPrinterHandler(), Asm(A) {} + +WinCFGuard::~WinCFGuard() {} + +void WinCFGuard::endModule() { + const Module *M = Asm->MMI->getModule(); + std::vector Functions; + for (const Function &F : *M) + if (F.hasAddressTaken()) + Functions.push_back(&F); + if (Functions.empty()) + return; + auto &OS = *Asm->OutStreamer; + OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection()); + for (const Function *F : Functions) + OS.EmitCOFFSymbolIndex(Asm->getSymbol(F)); +} diff --git a/lib/CodeGen/AsmPrinter/WinCFGuard.h b/lib/CodeGen/AsmPrinter/WinCFGuard.h new file mode 100644 index 00000000000..553b4ae261c --- /dev/null +++ b/lib/CodeGen/AsmPrinter/WinCFGuard.h @@ -0,0 +1,54 @@ +//===-- WinCFGuard.h - Windows Control Flow Guard Handling ----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing windows exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H + +#include "AsmPrinterHandler.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class LLVM_LIBRARY_VISIBILITY WinCFGuard : public AsmPrinterHandler { + /// Target of directive emission. + AsmPrinter *Asm; + +public: + WinCFGuard(AsmPrinter *A); + ~WinCFGuard() override; + + void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {} + + /// \brief Emit the Control Flow Guard function ID table + void endModule() override; + + /// \brief Gather pre-function debug information. + /// Every beginFunction(MF) call should be followed by an endFunction(MF) + /// call. + void beginFunction(const MachineFunction *MF) override {} + + /// \brief Gather post-function debug information. + /// Please note that some AsmPrinter implementations may not call + /// beginFunction at all. + void endFunction(const MachineFunction *MF) override {} + + /// \brief Process beginning of an instruction. + void beginInstruction(const MachineInstr *MI) override {} + + /// \brief Process end of an instruction. + void endInstruction() override {} +}; + +} // namespace llvm + +#endif diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 94af2881af7..9af060b605a 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -151,6 +151,7 @@ public: void EmitCOFFSymbolType(int Type) override; void EndCOFFSymbolDef() override; void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; + void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override; void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; @@ -649,6 +650,12 @@ void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { EmitEOL(); } +void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) { + OS << "\t.symidx\t"; + Symbol->print(OS, MAI); + EmitEOL(); +} + void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { OS << "\t.secidx\t"; Symbol->print(OS, MAI); diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index a6b5c43f1d2..f0f4dee8fc1 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -819,6 +819,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { SXDataSection = Ctx->getCOFFSection(".sxdata", COFF::IMAGE_SCN_LNK_INFO, SectionKind::getMetadata()); + GFIDsSection = Ctx->getCOFFSection(".gfids$y", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + TLSDataSection = Ctx->getCOFFSection( ".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE, diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index 687e0cc1faa..2a754eab05b 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -65,8 +65,9 @@ class COFFAsmParser : public MCAsmParserExtension { addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); // Win64 EH directives. @@ -130,6 +131,7 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseDirectiveSecRel32(StringRef, SMLoc); bool ParseDirectiveSecIdx(StringRef, SMLoc); bool ParseDirectiveSafeSEH(StringRef, SMLoc); + bool ParseDirectiveSymIdx(StringRef, SMLoc); bool parseCOMDATType(COFF::COMDATType &Type); bool ParseDirectiveLinkOnce(StringRef, SMLoc); @@ -520,6 +522,21 @@ bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { return false; } +bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) { + StringRef SymbolID; + if (getParser().parseIdentifier(SymbolID)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); + + Lex(); + getStreamer().EmitCOFFSymbolIndex(Symbol); + return false; +} + /// ::= [ identifier ] bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { StringRef TypeId = getTok().getIdentifier(); diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index a6784273aab..9dcd1e9101c 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -795,6 +795,8 @@ void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) { void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { } +void MCStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {} + void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { } diff --git a/lib/MC/MCWinCOFFStreamer.cpp b/lib/MC/MCWinCOFFStreamer.cpp index 8582d9adafb..efb60b7a03b 100644 --- a/lib/MC/MCWinCOFFStreamer.cpp +++ b/lib/MC/MCWinCOFFStreamer.cpp @@ -193,6 +193,17 @@ void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { << COFF::SCT_COMPLEX_TYPE_SHIFT); } +void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) { + MCSection *Sec = getCurrentSectionOnly(); + getAssembler().registerSection(*Sec); + if (Sec->getAlignment() < 4) + Sec->setAlignment(4); + + new MCSymbolIdFragment(Symbol, getCurrentSectionOnly()); + + getAssembler().registerSymbol(*Symbol); +} + void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) { visitUsedSymbol(*Symbol); MCDataFragment *DF = getOrCreateDataFragment(); diff --git a/test/CodeGen/WinCFGuard/cfguard.ll b/test/CodeGen/WinCFGuard/cfguard.ll new file mode 100644 index 00000000000..128bab15b51 --- /dev/null +++ b/test/CodeGen/WinCFGuard/cfguard.ll @@ -0,0 +1,162 @@ +; RUN: llc < %s | FileCheck %s + +; CHECK: .section .gfids$y +; CHECK: .symidx "?address_taken@@YAXXZ" +; CHECK: .symidx "?virt_method@Derived@@UEBAHXZ" + +; ModuleID = 'cfguard.cpp' +source_filename = "cfguard.cpp" +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +%struct.Derived = type { %struct.Base } +%struct.Base = type { i32 (...)** } +%rtti.CompleteObjectLocator = type { i32, i32, i32, i32, i32, i32 } +%rtti.TypeDescriptor13 = type { i8**, i8*, [14 x i8] } +%rtti.ClassHierarchyDescriptor = type { i32, i32, i32, i32 } +%rtti.BaseClassDescriptor = type { i32, i32, i32, i32, i32, i32, i32 } +%rtti.TypeDescriptor10 = type { i8**, i8*, [11 x i8] } + +$"\01??0Derived@@QEAA@XZ" = comdat any + +$"\01??0Base@@QEAA@XZ" = comdat any + +$"\01?virt_method@Derived@@UEBAHXZ" = comdat any + +$"\01??_7Derived@@6B@" = comdat largest + +$"\01??_R4Derived@@6B@" = comdat any + +$"\01??_R0?AUDerived@@@8" = comdat any + +$"\01??_R3Derived@@8" = comdat any + +$"\01??_R2Derived@@8" = comdat any + +$"\01??_R1A@?0A@EA@Derived@@8" = comdat any + +$"\01??_R1A@?0A@EA@Base@@8" = comdat any + +$"\01??_R0?AUBase@@@8" = comdat any + +$"\01??_R3Base@@8" = comdat any + +$"\01??_R2Base@@8" = comdat any + +$"\01??_7Base@@6B@" = comdat largest + +$"\01??_R4Base@@6B@" = comdat any + +@"\01?D@@3UDerived@@A" = global %struct.Derived zeroinitializer, align 8 +@0 = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4Derived@@6B@" to i8*), i8* bitcast (i32 (%struct.Derived*)* @"\01?virt_method@Derived@@UEBAHXZ" to i8*)] }, comdat($"\01??_7Derived@@6B@") +@"\01??_R4Derived@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor13* @"\01??_R0?AUDerived@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Derived@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Derived@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat +@"\01??_7type_info@@6B@" = external constant i8* +@"\01??_R0?AUDerived@@@8" = linkonce_odr global %rtti.TypeDescriptor13 { i8** @"\01??_7type_info@@6B@", i8* null, [14 x i8] c".?AUDerived@@\00" }, comdat +@__ImageBase = external constant i8 +@"\01??_R3Derived@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2Derived@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat +@"\01??_R2Derived@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Derived@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Base@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat +@"\01??_R1A@?0A@EA@Derived@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor13* @"\01??_R0?AUDerived@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Derived@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat +@"\01??_R1A@?0A@EA@Base@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor10* @"\01??_R0?AUBase@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Base@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat +@"\01??_R0?AUBase@@@8" = linkonce_odr global %rtti.TypeDescriptor10 { i8** @"\01??_7type_info@@6B@", i8* null, [11 x i8] c".?AUBase@@\00" }, comdat +@"\01??_R3Base@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Base@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat +@"\01??_R2Base@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Base@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat +@1 = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4Base@@6B@" to i8*), i8* bitcast (void ()* @_purecall to i8*)] }, comdat($"\01??_7Base@@6B@") +@"\01??_R4Base@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor10* @"\01??_R0?AUBase@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Base@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Base@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_cfguard.cpp, i8* null }] + +@"\01??_7Derived@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @0, i32 0, i32 0, i32 1) +@"\01??_7Base@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @1, i32 0, i32 0, i32 1) + +; Function Attrs: noinline nounwind +define internal void @"\01??__ED@@YAXXZ"() #0 { +entry: + %call = call %struct.Derived* @"\01??0Derived@@QEAA@XZ"(%struct.Derived* @"\01?D@@3UDerived@@A") #2 + ret void +} + +; Function Attrs: noinline nounwind optnone +define linkonce_odr %struct.Derived* @"\01??0Derived@@QEAA@XZ"(%struct.Derived* returned %this) unnamed_addr #1 comdat align 2 { +entry: + %this.addr = alloca %struct.Derived*, align 8 + store %struct.Derived* %this, %struct.Derived** %this.addr, align 8 + %this1 = load %struct.Derived*, %struct.Derived** %this.addr, align 8 + %0 = bitcast %struct.Derived* %this1 to %struct.Base* + %call = call %struct.Base* @"\01??0Base@@QEAA@XZ"(%struct.Base* %0) #2 + %1 = bitcast %struct.Derived* %this1 to i32 (...)*** + store i32 (...)** bitcast (i8** @"\01??_7Derived@@6B@" to i32 (...)**), i32 (...)*** %1, align 8 + ret %struct.Derived* %this1 +} + +; Function Attrs: noinline nounwind optnone +define void @"\01?address_taken@@YAXXZ"() #1 { +entry: + ret void +} + +; Function Attrs: noinline nounwind optnone +define void ()* @"\01?foo@@YAP6AXXZPEAUBase@@@Z"(%struct.Base* %B) #1 { +entry: + %retval = alloca void ()*, align 8 + %B.addr = alloca %struct.Base*, align 8 + store %struct.Base* %B, %struct.Base** %B.addr, align 8 + %0 = load %struct.Base*, %struct.Base** %B.addr, align 8 + %1 = bitcast %struct.Base* %0 to i32 (%struct.Base*)*** + %vtable = load i32 (%struct.Base*)**, i32 (%struct.Base*)*** %1, align 8 + %vfn = getelementptr inbounds i32 (%struct.Base*)*, i32 (%struct.Base*)** %vtable, i64 0 + %2 = load i32 (%struct.Base*)*, i32 (%struct.Base*)** %vfn, align 8 + %call = call i32 %2(%struct.Base* %0) + %tobool = icmp ne i32 %call, 0 + br i1 %tobool, label %if.then, label %if.end + +if.then: ; preds = %entry + store void ()* @"\01?address_taken@@YAXXZ", void ()** %retval, align 8 + br label %return + +if.end: ; preds = %entry + store void ()* null, void ()** %retval, align 8 + br label %return + +return: ; preds = %if.end, %if.then + %3 = load void ()*, void ()** %retval, align 8 + ret void ()* %3 +} + +; Function Attrs: noinline nounwind optnone +define linkonce_odr %struct.Base* @"\01??0Base@@QEAA@XZ"(%struct.Base* returned %this) unnamed_addr #1 comdat align 2 { +entry: + %this.addr = alloca %struct.Base*, align 8 + store %struct.Base* %this, %struct.Base** %this.addr, align 8 + %this1 = load %struct.Base*, %struct.Base** %this.addr, align 8 + %0 = bitcast %struct.Base* %this1 to i32 (...)*** + store i32 (...)** bitcast (i8** @"\01??_7Base@@6B@" to i32 (...)**), i32 (...)*** %0, align 8 + ret %struct.Base* %this1 +} + +; Function Attrs: noinline nounwind optnone +define linkonce_odr i32 @"\01?virt_method@Derived@@UEBAHXZ"(%struct.Derived* %this) unnamed_addr #1 comdat align 2 { +entry: + %this.addr = alloca %struct.Derived*, align 8 + store %struct.Derived* %this, %struct.Derived** %this.addr, align 8 + %this1 = load %struct.Derived*, %struct.Derived** %this.addr, align 8 + ret i32 42 +} + +declare dllimport void @_purecall() unnamed_addr + +; Function Attrs: noinline nounwind +define internal void @_GLOBAL__sub_I_cfguard.cpp() #0 { +entry: + call void @"\01??__ED@@YAXXZ"() + ret void +} + +attributes #0 = { noinline nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind } + +!llvm.module.flags = !{!0, !1} +!llvm.ident = !{!2} + +!0 = !{i32 2, !"cfguard", i32 1} +!1 = !{i32 1, !"wchar_size", i32 2} +!2 = !{!"clang version 6.0.0 "} diff --git a/test/CodeGen/WinCFGuard/lit.local.cfg b/test/CodeGen/WinCFGuard/lit.local.cfg new file mode 100644 index 00000000000..c8625f4d9d2 --- /dev/null +++ b/test/CodeGen/WinCFGuard/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'X86' in config.root.targets: + config.unsupported = True diff --git a/test/MC/COFF/symidx.s b/test/MC/COFF/symidx.s new file mode 100644 index 00000000000..46c00334764 --- /dev/null +++ b/test/MC/COFF/symidx.s @@ -0,0 +1,15 @@ +// RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s | llvm-objdump -s -t - | FileCheck %s +.text +foo: + ret +bar: + ret +.data +.symidx bar +.symidx foo + +// CHECK: Contents of section .data: +// CHECK-NEXT: 0000 0[[BAR:[1-9]]]000000 0[[FOO:[1-9]]]000000 +// CHECK: SYMBOL TABLE: +// CHECK: [ [[FOO]]](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x00000000 foo +// CHECK-NEXT: [ [[BAR]]](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x00000001 bar