From 96aa78c8c5ef1a5f268539c9edc86569b436d573 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 23 Jan 2011 17:55:27 +0000 Subject: [PATCH] Add support for the --noexecstack option. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124077 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCAssembler.h | 4 +++ include/llvm/MC/MCStreamer.h | 2 +- include/llvm/Target/TargetMachine.h | 7 ++++++ include/llvm/Target/TargetRegistry.h | 10 +++++--- lib/CodeGen/LLVMTargetMachine.cpp | 3 ++- lib/MC/ELFObjectWriter.cpp | 30 ++++++++++++++++------- lib/MC/MCAssembler.cpp | 2 +- lib/MC/MCELFStreamer.cpp | 6 +++-- lib/Target/ARM/ARMTargetMachine.cpp | 5 ++-- lib/Target/MBlaze/MBlazeTargetMachine.cpp | 6 +++-- lib/Target/PowerPC/PPCTargetMachine.cpp | 3 ++- lib/Target/X86/X86TargetMachine.cpp | 5 ++-- test/MC/ELF/noexec.s | 24 ++++++++++++++++++ tools/llvm-mc/llvm-mc.cpp | 7 +++++- 14 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 test/MC/ELF/noexec.s diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 79d2c8ea41a..30971c62a97 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -694,6 +694,7 @@ private: SmallPtrSet ThumbFuncs; unsigned RelaxAll : 1; + unsigned NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; private: @@ -808,6 +809,9 @@ public: bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } + bool getNoExecStack() const { return NoExecStack; } + void setNoExecStack(bool Value) { NoExecStack = Value; } + /// @name Section List Access /// @{ diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 7c2de30649f..1be2dc6bb6d 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -469,7 +469,7 @@ namespace llvm { /// ELF format object files. MCStreamer *createELFStreamer(MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + bool RelaxAll, bool NoExecStack); /// createLoggingStreamer - Create a machine code streamer which just logs the /// API calls and then dispatches to another streamer. diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index c3136cd4875..030bf5b89f7 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -104,6 +104,7 @@ protected: // Can only create subclasses. const MCAsmInfo *AsmInfo; unsigned MCRelaxAll : 1; + unsigned MCNoExecStack : 1; unsigned MCUseLoc : 1; public: @@ -170,6 +171,12 @@ public: /// relaxed. void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } + /// hasMCNoExecStack - Check whether an executable stack is not needed. + bool hasMCNoExecStack() const { return MCNoExecStack; } + + /// setMCNoExecStack - Set whether an executabel stack is not needed. + void setMCNoExecStack(bool Value) { MCNoExecStack = Value; } + /// hasMCUseLoc - Check whether we should use dwarf's .loc directive. bool hasMCUseLoc() const { return MCUseLoc; } diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 6cdb68f1348..f851ad0a9bf 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -89,7 +89,8 @@ namespace llvm { TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll); + bool RelaxAll, + bool NoExecStack); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, @@ -308,14 +309,17 @@ namespace llvm { /// \arg _OS - The stream object. /// \arg _Emitter - The target independent assembler object.Takes ownership. /// \arg RelaxAll - Relax all fixups? + /// \arg NoExecStack - Mark file as not needing a executable stack. MCStreamer *createObjectStreamer(const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll) const { + bool RelaxAll, + bool NoExecStack) const { if (!ObjectStreamerCtorFn) return 0; - return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll); + return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll, + NoExecStack); } /// createAsmStreamer - Create a target specific MCStreamer. diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 5cff96db736..80dfc763af6 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -168,7 +168,8 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, AsmStreamer.reset(getTarget().createObjectStreamer(TargetTriple, *Context, *TAB, Out, MCE, - hasMCRelaxAll())); + hasMCRelaxAll(), + hasMCNoExecStack())); AsmStreamer.get()->InitSections(); break; } diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 05dd0c76298..4dbb5387f3d 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -329,8 +329,11 @@ namespace { virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap); - virtual void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout, - GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap); + // Create the sections that show up in the symbol table. Currently + // those are the .note.GNU-stack section and the group sections. + virtual void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap); virtual void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); @@ -1174,10 +1177,19 @@ ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, return &SecA == &SecB; } -void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, - MCAsmLayout &Layout, - GroupMapTy &GroupMap, - RevGroupMapTy &RevGroupMap) { +void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, + MCAsmLayout &Layout, + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap) { + // Create the .note.GNU-stack section if needed. + MCContext &Ctx = Asm.getContext(); + if (Asm.getNoExecStack()) { + const MCSectionELF *GnuStackSection = + Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, + SectionKind::getReadOnly()); + Asm.getOrCreateSectionData(*GnuStackSection); + } + // Build the groups for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { @@ -1190,7 +1202,7 @@ void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, Asm.getOrCreateSymbolData(*SignatureSymbol); const MCSectionELF *&Group = RevGroupMap[SignatureSymbol]; if (!Group) { - Group = Asm.getContext().CreateELFGroupSection(); + Group = Ctx.CreateELFGroupSection(); MCSectionData &Data = Asm.getOrCreateSectionData(*Group); Data.setAlignment(4); MCDataFragment *F = new MCDataFragment(&Data); @@ -1334,8 +1346,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { GroupMapTy GroupMap; RevGroupMapTy RevGroupMap; - CreateGroupSections(Asm, const_cast(Layout), GroupMap, - RevGroupMap); + CreateIndexedSections(Asm, const_cast(Layout), GroupMap, + RevGroupMap); SectionIndexMapTy SectionIndexMap; diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 5b291490f71..587068aee5f 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -172,7 +172,7 @@ MCAssembler::MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, raw_ostream &OS_) : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), - OS(OS_), RelaxAll(false), SubsectionsViaSymbols(false) + OS(OS_), RelaxAll(false), NoExecStack(false), SubsectionsViaSymbols(false) { } diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 6a6c9338abf..ac310570653 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -515,10 +515,12 @@ void MCELFStreamer::Finish() { } MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll) { + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool NoExecStack) { MCELFStreamer *S = new MCELFStreamer(Context, TAB, OS, CE); if (RelaxAll) S->getAssembler().setRelaxAll(true); + if (NoExecStack) + S->getAssembler().setNoExecStack(true); return S; } diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index a68fd4945e4..60df718ad21 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -39,7 +39,8 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll) { + bool RelaxAll, + bool NoExecStack) { switch (Triple(TT).getOS()) { case Triple::Darwin: return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll); @@ -50,7 +51,7 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, llvm_unreachable("ARM does not support Windows COFF format"); return NULL; default: - return createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll); + return createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll, NoExecStack); } } diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp index f53dbb0dd63..f83f70b5e1e 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.cpp +++ b/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -33,7 +33,8 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll) { + bool RelaxAll, + bool NoExecStack) { Triple TheTriple(TT); switch (TheTriple.getOS()) { case Triple::Darwin: @@ -46,7 +47,8 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, llvm_unreachable("MBlaze does not support Windows COFF format"); return NULL; default: - return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); + return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, + NoExecStack); } } diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index ad7c5284e35..212b450e7db 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -35,7 +35,8 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll) { + bool RelaxAll, + bool NoExecStack) { switch (Triple(TT).getOS()) { case Triple::Darwin: return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll); diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 2e4bcde07a3..8de20a366cb 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -43,7 +43,8 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll) { + bool RelaxAll, + bool NoExecStack) { Triple TheTriple(TT); switch (TheTriple.getOS()) { case Triple::Darwin: @@ -54,7 +55,7 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, case Triple::Win32: return createWinCOFFStreamer(Ctx, TAB, *_Emitter, _OS, RelaxAll); default: - return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); + return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, NoExecStack); } } diff --git a/test/MC/ELF/noexec.s b/test/MC/ELF/noexec.s new file mode 100644 index 00000000000..87b6f3aa85b --- /dev/null +++ b/test/MC/ELF/noexec.s @@ -0,0 +1,24 @@ +// RUN: llvm-mc -mc-no-exec-stack -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s + +// CHECK: # Section 0x00000004 +// CHECK-NEXT: (('sh_name', 0x00000012) # '.note.GNU-stack' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000040) +// CHECK-NEXT: ('sh_size', 0x00000000) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000001) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ), + +// CHECK: # Symbol 0x00000004 +// CHECK-NEXT: (('st_name', 0x00000000) # '' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000003) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000004) +// CHECK-NEXT: ('st_value', 0x0000000000000000) +// CHECK-NEXT: ('st_size', 0x0000000000000000) +// CHECK-NEXT: ), diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 87082047eef..2c22bedf1c2 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -68,6 +68,9 @@ OutputAsmVariant("output-asm-variant", static cl::opt RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); +static cl::opt +NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack")); + static cl::opt EnableLogging("enable-api-logging", cl::desc("Enable MC API logging")); @@ -336,6 +339,7 @@ static int AssembleInput(const char *ProgName) { TM->getTargetLowering()->getObjFileLowering(); const_cast(TLOF).Initialize(Ctx, *TM); + // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI); @@ -355,7 +359,8 @@ static int AssembleInput(const char *ProgName) { MCCodeEmitter *CE = TheTarget->createCodeEmitter(*TM, Ctx); TargetAsmBackend *TAB = TheTarget->createAsmBackend(TripleName); Str.reset(TheTarget->createObjectStreamer(TripleName, Ctx, *TAB, - FOS, CE, RelaxAll)); + FOS, CE, RelaxAll, + NoExecStack)); } if (EnableLogging) {