diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index b33e8c9b42b..6a1f9d705df 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -41,33 +41,6 @@ namespace llvm { raw_ostream &OS) const = 0; }; - - class MCSectionELF : public MCSection { - std::string Name; - - /// IsDirective - This is true if the section name is a directive, not - /// something that should be printed with ".section". - /// - /// FIXME: This is a hack. Switch to a semantic view of the section instead - /// of a syntactic one. - bool IsDirective; - - MCSectionELF(const StringRef &name, bool isDirective, SectionKind K) - : MCSection(K), Name(name), IsDirective(isDirective) { - } - public: - - static MCSectionELF *Create(const StringRef &Name, bool IsDirective, - SectionKind K, MCContext &Ctx); - - const std::string &getName() const { return Name; } - bool isDirective() const { return IsDirective; } - - - virtual void PrintSwitchToSection(const TargetAsmInfo &TAI, - raw_ostream &OS) const; - }; - class MCSectionCOFF : public MCSection { std::string Name; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h new file mode 100644 index 00000000000..00369f7d2f6 --- /dev/null +++ b/include/llvm/MC/MCSectionELF.h @@ -0,0 +1,168 @@ +//===- MCSectionELF.h - ELF Machine Code Sections ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionELF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONELF_H +#define LLVM_MC_MCSECTIONELF_H + +#include "llvm/MC/MCSection.h" + +namespace llvm { + +/// MCSectionELF - This represents a section on linux, lots of unix variants +/// and some bare metal systems. +class MCSectionELF : public MCSection { + std::string SectionName; + + /// Type - This is the sh_type field of a section, drawn from the enums below. + unsigned Type; + + /// Flags - This is the sh_flags field of a section, drawn from the enums. + /// below. + unsigned Flags; + + /// HasCrazyBSS - PPC/Linux doesn't support the .bss directive, it + /// needs .section .bss. TODO: replace this with a TAI method. + bool HasCrazyBSS; + + /// IsExplicit - Indicates that this section comes from globals with an + /// explicit section specfied. + bool IsExplicit; + + MCSectionELF(const StringRef &Section, unsigned T, unsigned F, + SectionKind K, bool hasCrazyBSS, bool isExplicit) + : MCSection(K), SectionName(Section.str()), Type(T), Flags(F), + HasCrazyBSS(hasCrazyBSS), IsExplicit(isExplicit) {} +public: + + static MCSectionELF *Create(const StringRef &Section, unsigned Type, + unsigned Flags, SectionKind K, + bool hasCrazyBSS, bool isExplicit, + MCContext &Ctx); + + /// ShouldOmitSectionDirective - Decides whether a '.section' directive + /// should be printed before the section name + bool ShouldOmitSectionDirective(const char *Name) const; + + /// ShouldPrintSectionType - Only prints the section type if supported + bool ShouldPrintSectionType(unsigned Ty) const; + + /// These are the section type and flags fields. An ELF section can have + /// only one Type, but can have more than one of the flags specified. + /// + /// Valid section types. + enum { + // This value marks the section header as inactive. + SHT_NULL = 0x00U, + + // Holds information defined by the program, with custom format and meaning. + SHT_PROGBITS = 0x01U, + + // This section holds a symbol table. + SHT_SYMTAB = 0x02U, + + // The section holds a string table. + SHT_STRTAB = 0x03U, + + // The section holds relocation entries with explicit addends. + SHT_RELA = 0x04U, + + // The section holds a symbol hash table. + SHT_HASH = 0x05U, + + // Information for dynamic linking. + SHT_DYNAMIC = 0x06U, + + // The section holds information that marks the file in some way. + SHT_NOTE = 0x07U, + + // A section of this type occupies no space in the file. + SHT_NOBITS = 0x08U, + + // The section holds relocation entries without explicit addends. + SHT_REL = 0x09U, + + // This section type is reserved but has unspecified semantics. + SHT_SHLIB = 0x0aU, + + // This section holds a symbol table. + SHT_DYNSYM = 0x0bU, + + // This section contains an array of pointers to initialization functions. + SHT_INIT_ARRAY = 0x0eU, + + // This section contains an array of pointers to termination functions. + SHT_FINI_ARRAY = 0x0fU, + + // This section contains an array of pointers to functions that are invoked + // before all other initialization functions. + SHT_PREINIT_ARRAY = 0x10U, + + // A section group is a set of sections that are related and that must be + // treated specially by the linker. + SHT_GROUP = 0x11U, + + // This section is associated with a section of type SHT_SYMTAB, when the + // referenced symbol table contain the escape value SHN_XINDEX + SHT_SYMTAB_SHNDX = 0x12U, + + LAST_KNOWN_SECTION_TYPE = SHT_SYMTAB_SHNDX + }; + + /// Valid section flags. + enum { + // The section contains data that should be writable. + SHF_WRITE = 0x1U, + + // The section occupies memory during execution. + SHF_ALLOC = 0x2U, + + // The section contains executable machine instructions. + SHF_EXECINSTR = 0x4U, + + // The data in the section may be merged to eliminate duplication. + SHF_MERGE = 0x10U, + + // Elements in the section consist of null-terminated character strings. + SHF_STRINGS = 0x20U, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U + }; + + StringRef getSectionName() const { + return StringRef(SectionName); + } + + unsigned getType() const { return Type; } + unsigned getFlags() const { return Flags; } + + virtual void PrintSwitchToSection(const TargetAsmInfo &TAI, + raw_ostream &OS) const; +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 102928b6598..19bb02c0125 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -204,8 +204,9 @@ protected: const MCSection *MergeableConst16Section; protected: - const MCSection *getELFSection(const char *Name, bool isDirective, - SectionKind Kind) const; + const MCSection *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind, + bool IsExplicit = false) const; public: TargetLoweringObjectFileELF(// FIXME: REMOVE AFTER UNIQUING IS FIXED. bool hasCrazyBSS = false) diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index ff41338ce9f..4ad2f8bd53e 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -43,7 +43,7 @@ #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetELFWriterInfo.h" @@ -178,30 +178,32 @@ void ELFWriter::addExternalSymbol(const char *External) { // getCtorSection - Get the static constructor section ELFSection &ELFWriter::getCtorSection() { - const MCSection *Ctor = TLOF.getStaticCtorSection(); - return getSection(((MCSectionELF*)Ctor)->getName(), ELFSection::SHT_PROGBITS, + const MCSectionELF *Ctor = (const MCSectionELF *)TLOF.getStaticCtorSection(); + return getSection(Ctor->getSectionName(), ELFSection::SHT_PROGBITS, getElfSectionFlags(Ctor->getKind())); } // getDtorSection - Get the static destructor section ELFSection &ELFWriter::getDtorSection() { - const MCSection *Dtor = TLOF.getStaticDtorSection(); - return getSection(((MCSectionELF*)Dtor)->getName(), ELFSection::SHT_PROGBITS, + const MCSectionELF *Dtor = (const MCSectionELF *)TLOF.getStaticDtorSection(); + return getSection(Dtor->getSectionName(), ELFSection::SHT_PROGBITS, getElfSectionFlags(Dtor->getKind())); } // getTextSection - Get the text section for the specified function ELFSection &ELFWriter::getTextSection(Function *F) { - const MCSection *Text = TLOF.SectionForGlobal(F, Mang, TM); - return getSection(((MCSectionELF*)Text)->getName(), ELFSection::SHT_PROGBITS, + const MCSectionELF *Text = + (const MCSectionELF *)TLOF.SectionForGlobal(F, Mang, TM); + return getSection(Text->getSectionName(), ELFSection::SHT_PROGBITS, getElfSectionFlags(Text->getKind())); } // getJumpTableSection - Get a read only section for constants when // emitting jump tables. TODO: add PIC support ELFSection &ELFWriter::getJumpTableSection() { - const MCSection *JT = TLOF.getSectionForConstant(SectionKind::getReadOnly()); - return getSection(((MCSectionELF*)JT)->getName(), + const MCSectionELF *JT = + (const MCSectionELF *)TLOF.getSectionForConstant(SectionKind::getReadOnly()); + return getSection(JT->getSectionName(), ELFSection::SHT_PROGBITS, getElfSectionFlags(JT->getKind()), TM.getTargetData()->getPointerABIAlignment()); @@ -226,8 +228,9 @@ ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) { } } - const MCSection *CPSect = TLOF.getSectionForConstant(Kind); - return getSection(((MCSectionELF*)CPSect)->getName(), + const MCSectionELF *CPSect = + (const MCSectionELF *)TLOF.getSectionForConstant(Kind); + return getSection(CPSect->getSectionName(), ELFSection::SHT_PROGBITS, getElfSectionFlags(Kind), CPE.getAlignment()); @@ -358,8 +361,9 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { return; // Get the ELF section where this global belongs from TLOF - const MCSection *S = TLOF.SectionForGlobal(GV, Mang, TM); - SectionKind Kind = ((MCSectionELF*)S)->getKind(); + const MCSectionELF *S = + (const MCSectionELF *)TLOF.SectionForGlobal(GV, Mang, TM); + SectionKind Kind = S->getKind(); unsigned SectionFlags = getElfSectionFlags(Kind); // The symbol align should update the section alignment if needed @@ -370,7 +374,7 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { if (isELFCommonSym(GVar)) { GblSym->SectionIdx = ELFSection::SHN_COMMON; - getSection(((MCSectionELF*)S)->getName(), + getSection(S->getSectionName(), ELFSection::SHT_NOBITS, SectionFlags, 1); // A new linkonce section is created for each global in the @@ -380,7 +384,7 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { } else if (isELFBssSym(GVar, Kind)) { ELFSection &ES = - getSection(((MCSectionELF*)S)->getName(), ELFSection::SHT_NOBITS, + getSection(S->getSectionName(), ELFSection::SHT_NOBITS, SectionFlags); GblSym->SectionIdx = ES.SectionIdx; @@ -396,7 +400,7 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) { } else { // The symbol must go to some kind of data section ELFSection &ES = - getSection(((MCSectionELF*)S)->getName(), ELFSection::SHT_PROGBITS, + getSection(S->getSectionName(), ELFSection::SHT_PROGBITS, SectionFlags); GblSym->SectionIdx = ES.SectionIdx; diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index e3cc536444e..ec76320ad34 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -4,6 +4,7 @@ add_llvm_library(LLVMMC MCAsmStreamer.cpp MCContext.cpp MCSection.cpp + MCSectionELF.cpp MCSectionMachO.cpp MCStreamer.cpp TargetAsmParser.cpp diff --git a/lib/MC/MCSection.cpp b/lib/MC/MCSection.cpp index 8b7fcd2815c..3e837635f22 100644 --- a/lib/MC/MCSection.cpp +++ b/lib/MC/MCSection.cpp @@ -20,91 +20,6 @@ using namespace llvm; MCSection::~MCSection() { } - -//===----------------------------------------------------------------------===// -// MCSectionELF -//===----------------------------------------------------------------------===// - -MCSectionELF *MCSectionELF:: -Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) { - return new (Ctx) MCSectionELF(Name, IsDirective, K); -} - -void MCSectionELF::PrintSwitchToSection(const TargetAsmInfo &TAI, - raw_ostream &OS) const { - if (isDirective()) { - OS << getName() << '\n'; - return; - } - - OS << "\t.section\t" << getName(); - - // Handle the weird solaris syntax if desired. - if (TAI.usesSunStyleELFSectionSwitchSyntax() && - !getKind().isMergeableConst() && !getKind().isMergeableCString()) { - if (!getKind().isMetadata()) - OS << ",#alloc"; - if (getKind().isText()) - OS << ",#execinstr"; - if (getKind().isWriteable()) - OS << ",#write"; - if (getKind().isThreadLocal()) - OS << ",#tls"; - } else { - OS << ",\""; - - if (!getKind().isMetadata()) - OS << 'a'; - if (getKind().isText()) - OS << 'x'; - if (getKind().isWriteable()) - OS << 'w'; - if (getKind().isMergeable1ByteCString() || - getKind().isMergeable2ByteCString() || - getKind().isMergeable4ByteCString() || - getKind().isMergeableConst4() || - getKind().isMergeableConst8() || - getKind().isMergeableConst16()) - OS << 'M'; - if (getKind().isMergeable1ByteCString() || - getKind().isMergeable2ByteCString() || - getKind().isMergeable4ByteCString()) - OS << 'S'; - if (getKind().isThreadLocal()) - OS << 'T'; - - OS << "\","; - - // If comment string is '@', e.g. as on ARM - use '%' instead - if (TAI.getCommentString()[0] == '@') - OS << '%'; - else - OS << '@'; - - if (getKind().isBSS() || getKind().isThreadBSS()) - OS << "nobits"; - else - OS << "progbits"; - - if (getKind().isMergeable1ByteCString()) { - OS << ",1"; - } else if (getKind().isMergeable2ByteCString()) { - OS << ",2"; - } else if (getKind().isMergeable4ByteCString()) { - OS << ",4"; - } else if (getKind().isMergeableConst4()) { - OS << ",4"; - } else if (getKind().isMergeableConst8()) { - OS << ",8"; - } else if (getKind().isMergeableConst16()) { - OS << ",16"; - } - } - - OS << '\n'; -} - - //===----------------------------------------------------------------------===// // MCSectionCOFF //===----------------------------------------------------------------------===// diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp new file mode 100644 index 00000000000..d172a9c9230 --- /dev/null +++ b/lib/MC/MCSectionELF.cpp @@ -0,0 +1,123 @@ +//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmInfo.h" + +using namespace llvm; + +MCSectionELF *MCSectionELF:: +Create(const StringRef &Section, unsigned Type, unsigned Flags, + SectionKind K, bool hasCrazyBSS, bool isExplicit, MCContext &Ctx) { + return new + (Ctx) MCSectionELF(Section, Type, Flags, K, hasCrazyBSS, isExplicit); +} + +// ShouldOmitSectionDirective - Decides whether a '.section' directive +// should be printed before the section name +bool MCSectionELF::ShouldOmitSectionDirective(const char *Name) const { + + // PPC/Linux doesn't support the .bss directive, it needs .section .bss. + // FIXME: Does .section .bss/.data/.text work everywhere?? + if ((!HasCrazyBSS && strncmp(Name, ".bss", 4) == 0) || + strncmp(Name, ".text", 5) == 0 || + strncmp(Name, ".data", 5) == 0) + return true; + + return false; +} + +// ShouldPrintSectionType - Only prints the section type if supported +bool MCSectionELF::ShouldPrintSectionType(unsigned Ty) const { + + if (IsExplicit && !(Ty == SHT_NOBITS || Ty == SHT_PROGBITS)) + return false; + + return true; +} + +void MCSectionELF::PrintSwitchToSection(const TargetAsmInfo &TAI, + raw_ostream &OS) const { + + if (ShouldOmitSectionDirective(SectionName.c_str())) { + OS << '\t' << getSectionName() << '\n'; + return; + } + + OS << "\t.section\t" << getSectionName(); + + // Handle the weird solaris syntax if desired. + if (TAI.usesSunStyleELFSectionSwitchSyntax() && + !(Flags & MCSectionELF::SHF_MERGE)) { + if (Flags & MCSectionELF::SHF_ALLOC) + OS << ",#alloc"; + if (Flags & MCSectionELF::SHF_EXECINSTR) + OS << ",#execinstr"; + if (Flags & MCSectionELF::SHF_WRITE) + OS << ",#write"; + if (Flags & MCSectionELF::SHF_TLS) + OS << ",#tls"; + } else { + OS << ",\""; + + if (Flags & MCSectionELF::SHF_ALLOC) + OS << 'a'; + if (Flags & MCSectionELF::SHF_EXECINSTR) + OS << 'x'; + if (Flags & MCSectionELF::SHF_WRITE) + OS << 'w'; + if (Flags & MCSectionELF::SHF_MERGE) + OS << 'M'; + if (Flags & MCSectionELF::SHF_STRINGS) + OS << 'S'; + if (Flags & MCSectionELF::SHF_TLS) + OS << 'T'; + + OS << '"'; + + if (ShouldPrintSectionType(Type)) { + OS << ','; + + // If comment string is '@', e.g. as on ARM - use '%' instead + if (TAI.getCommentString()[0] == '@') + OS << '%'; + else + OS << '@'; + + if (Type == MCSectionELF::SHT_INIT_ARRAY) + OS << "init_array"; + else if (Type == MCSectionELF::SHT_FINI_ARRAY) + OS << "fini_array"; + else if (Type == MCSectionELF::SHT_PREINIT_ARRAY) + OS << "preinit_array"; + else if (Type == MCSectionELF::SHT_NOBITS) + OS << "nobits"; + else if (Type == MCSectionELF::SHT_PROGBITS) + OS << "progbits"; + + if (getKind().isMergeable1ByteCString()) { + OS << ",1"; + } else if (getKind().isMergeable2ByteCString()) { + OS << ",2"; + } else if (getKind().isMergeable4ByteCString() || + getKind().isMergeableConst4()) { + OS << ",4"; + } else if (getKind().isMergeableConst8()) { + OS << ",8"; + } else if (getKind().isMergeableConst16()) { + OS << ",16"; + } + } + } + + OS << '\n'; +} + diff --git a/lib/Target/ARM/ARMTargetObjectFile.h b/lib/Target/ARM/ARMTargetObjectFile.h index 13fa7e202a0..9703403db22 100644 --- a/lib/Target/ARM/ARMTargetObjectFile.h +++ b/lib/Target/ARM/ARMTargetObjectFile.h @@ -11,6 +11,7 @@ #define LLVM_TARGET_ARM_TARGETOBJECTFILE_H #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/MC/MCSectionELF.h" namespace llvm { @@ -21,14 +22,14 @@ namespace llvm { void Initialize(MCContext &Ctx, const TargetMachine &TM) { TargetLoweringObjectFileELF::Initialize(Ctx, TM); - // FIXME: Add new attribute/flag to MCSection for init_array/fini_array. - // That will allow not treating these as "directives". if (TM.getSubtarget().isAAPCS_ABI()) { StaticCtorSection = - getELFSection("\t.section .init_array,\"aw\",%init_array", true, + getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, SectionKind::getDataRel()); StaticDtorSection = - getELFSection("\t.section .fini_array,\"aw\",%fini_array", true, + getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, SectionKind::getDataRel()); } } diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 00f4ffe5602..edc9ed3ba43 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -19,7 +19,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionMachO.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -288,64 +288,98 @@ TargetLoweringObjectFileELF::~TargetLoweringObjectFileELF() { } const MCSection *TargetLoweringObjectFileELF:: -getELFSection(const char *Name, bool isDirective, SectionKind Kind) const { - // Create the map if it doesn't already exist. +getELFSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind, bool IsExplicit) const { if (UniquingMap == 0) UniquingMap = new ELFUniqueMapTy(); ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)UniquingMap; // Do the lookup, if we have a hit, return it. - const MCSectionELF *&Entry = Map[Name]; + const MCSectionELF *&Entry = Map[Section]; if (Entry) return Entry; - return Entry = MCSectionELF::Create(Name, isDirective, Kind, getContext()); + return Entry = MCSectionELF::Create(Section, Type, Flags, Kind, HasCrazyBSS, + IsExplicit, getContext()); } void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, const TargetMachine &TM) { TargetLoweringObjectFile::Initialize(Ctx, TM); - if (!HasCrazyBSS) - BSSSection = getELFSection("\t.bss", true, SectionKind::getBSS()); - else - // PPC/Linux doesn't support the .bss directive, it needs .section .bss. - // FIXME: Does .section .bss work everywhere?? - // FIXME2: this should just be handle by the section printer. We should get - // away from syntactic view of the sections and MCSection should just be a - // semantic view. - BSSSection = getELFSection("\t.bss", false, SectionKind::getBSS()); + BSSSection = + getELFSection(".bss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getBSS()); - TextSection = getELFSection("\t.text", true, SectionKind::getText()); - DataSection = getELFSection("\t.data", true, SectionKind::getDataRel()); - ReadOnlySection = - getELFSection("\t.rodata", false, SectionKind::getReadOnly()); - TLSDataSection = - getELFSection("\t.tdata", false, SectionKind::getThreadData()); + TextSection = + getELFSection(".text", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_EXECINSTR | MCSectionELF::SHF_ALLOC, + SectionKind::getText()); + + DataSection = + getELFSection(".data", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + + ReadOnlySection = + getELFSection(".rodata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, + SectionKind::getReadOnly()); + + TLSDataSection = + getELFSection(".tdata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadData()); - TLSBSSSection = getELFSection("\t.tbss", false, - SectionKind::getThreadBSS()); + TLSBSSSection = + getELFSection(".tbss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadBSS()); - DataRelSection = getELFSection("\t.data.rel", false, - SectionKind::getDataRel()); - DataRelLocalSection = getELFSection("\t.data.rel.local", false, - SectionKind::getDataRelLocal()); - DataRelROSection = getELFSection("\t.data.rel.ro", false, - SectionKind::getReadOnlyWithRel()); - DataRelROLocalSection = - getELFSection("\t.data.rel.ro.local", false, - SectionKind::getReadOnlyWithRelLocal()); + DataRelSection = + getELFSection(".data.rel", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + DataRelLocalSection = + getELFSection(".data.rel.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRelLocal()); + + DataRelROSection = + getELFSection(".data.rel.ro", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + + DataRelROLocalSection = + getELFSection(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRelLocal()); - MergeableConst4Section = getELFSection(".rodata.cst4", false, - SectionKind::getMergeableConst4()); - MergeableConst8Section = getELFSection(".rodata.cst8", false, - SectionKind::getMergeableConst8()); - MergeableConst16Section = getELFSection(".rodata.cst16", false, - SectionKind::getMergeableConst16()); + MergeableConst4Section = + getELFSection(".rodata.cst4", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst4()); + + MergeableConst8Section = + getELFSection(".rodata.cst8", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst8()); + + MergeableConst16Section = + getELFSection(".rodata.cst16", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst16()); StaticCtorSection = - getELFSection(".ctors", false, SectionKind::getDataRel()); + getELFSection(".ctors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + StaticDtorSection = - getELFSection(".dtors", false, SectionKind::getDataRel()); + getELFSection(".dtors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); // Exception Handling Sections. @@ -354,33 +388,46 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, // runtime hit for C++ apps. Either the contents of the LSDA need to be // adjusted or this should be a data section. LSDASection = - getELFSection(".gcc_except_table", false, SectionKind::getReadOnly()); + getELFSection(".gcc_except_table", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, SectionKind::getReadOnly()); EHFrameSection = - getELFSection(".eh_frame", false, SectionKind::getDataRel()); + getELFSection(".eh_frame", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, SectionKind::getDataRel()); // Debug Info Sections. DwarfAbbrevSection = - getELFSection(".debug_abbrev", false, SectionKind::getMetadata()); + getELFSection(".debug_abbrev", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfInfoSection = - getELFSection(".debug_info", false, SectionKind::getMetadata()); + getELFSection(".debug_info", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfLineSection = - getELFSection(".debug_line", false, SectionKind::getMetadata()); + getELFSection(".debug_line", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfFrameSection = - getELFSection(".debug_frame", false, SectionKind::getMetadata()); + getELFSection(".debug_frame", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfPubNamesSection = - getELFSection(".debug_pubnames", false, SectionKind::getMetadata()); + getELFSection(".debug_pubnames", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfPubTypesSection = - getELFSection(".debug_pubtypes", false, SectionKind::getMetadata()); + getELFSection(".debug_pubtypes", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfStrSection = - getELFSection(".debug_str", false, SectionKind::getMetadata()); + getELFSection(".debug_str", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfLocSection = - getELFSection(".debug_loc", false, SectionKind::getMetadata()); + getELFSection(".debug_loc", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfARangesSection = - getELFSection(".debug_aranges", false, SectionKind::getMetadata()); + getELFSection(".debug_aranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfRangesSection = - getELFSection(".debug_ranges", false, SectionKind::getMetadata()); + getELFSection(".debug_ranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfMacroInfoSection = - getELFSection(".debug_macinfo", false, SectionKind::getMetadata()); + getELFSection(".debug_macinfo", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); } @@ -410,13 +457,62 @@ getELFKindForNamedSection(const char *Name, SectionKind K) { return K; } + +static unsigned +getELFSectionType(const char *Name, SectionKind K) { + + if (strncmp(Name, ".init_array", 11) == 0) + return MCSectionELF::SHT_INIT_ARRAY; + + if (strncmp(Name, ".fini_array", 11) == 0) + return MCSectionELF::SHT_FINI_ARRAY; + + if (strncmp(Name, ".preinit_array", 14) == 0) + return MCSectionELF::SHT_PREINIT_ARRAY; + + if (K.isBSS() || K.isThreadBSS()) + return MCSectionELF::SHT_NOBITS; + + return MCSectionELF::SHT_PROGBITS; +} + + +static unsigned +getELFSectionFlags(SectionKind K) { + unsigned Flags = 0; + + if (!K.isMetadata()) + Flags |= MCSectionELF::SHF_ALLOC; + + if (K.isWriteable()) + Flags |= MCSectionELF::SHF_WRITE; + + if (K.isThreadLocal()) + Flags |= MCSectionELF::SHF_TLS; + + // K.isMergeableConst() is left out to honour PR4650 + if (K.isMergeableCString() || K.isMergeableConst4() || + K.isMergeableConst8() || K.isMergeableConst16()) + Flags |= MCSectionELF::SHF_MERGE; + + if (K.isMergeableCString()) + Flags |= MCSectionELF::SHF_STRINGS; + + return Flags; +} + + const MCSection *TargetLoweringObjectFileELF:: getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { + const char *SectionName = GV->getSection().c_str(); + // Infer section flags from the section name if we can. - Kind = getELFKindForNamedSection(GV->getSection().c_str(), Kind); + Kind = getELFKindForNamedSection(SectionName, Kind); - return getELFSection(GV->getSection().c_str(), false, Kind); + return getELFSection(SectionName, + getELFSectionType(SectionName, Kind), + getELFSectionFlags(Kind), Kind, true); } static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { @@ -445,7 +541,11 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, if (GV->isWeakForLinker()) { const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); std::string Name = Mang->makeNameProper(GV->getNameStr()); - return getELFSection((Prefix+Name).c_str(), false, Kind); + + return getELFSection((Prefix+Name).c_str(), + getELFSectionType((Prefix+Name).c_str(), Kind), + getELFSectionFlags(Kind), + Kind); } if (Kind.isText()) return TextSection; @@ -470,7 +570,11 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, std::string Name = SizeSpec + utostr(Align); - return getELFSection(Name.c_str(), false, Kind); + return getELFSection(Name.c_str(), MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | + MCSectionELF::SHF_MERGE | + MCSectionELF::SHF_STRINGS, + Kind); } if (Kind.isMergeableConst()) { diff --git a/lib/Target/XCore/XCoreTargetObjectFile.cpp b/lib/Target/XCore/XCoreTargetObjectFile.cpp index 4e2dca1c1ab..9415f5127dc 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.cpp +++ b/lib/Target/XCore/XCoreTargetObjectFile.cpp @@ -9,6 +9,7 @@ #include "XCoreTargetObjectFile.h" #include "XCoreSubtarget.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/Target/TargetMachine.h" using namespace llvm; @@ -16,9 +17,12 @@ using namespace llvm; void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ TargetLoweringObjectFileELF::Initialize(Ctx, TM); - TextSection = getELFSection("\t.text", true, SectionKind::getText()); - DataSection = getELFSection("\t.dp.data", false, SectionKind::getDataRel()); - BSSSection = getELFSection("\t.dp.bss", false, SectionKind::getBSS()); + DataSection = getELFSection(".dp.data", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + BSSSection = getELFSection(".dp.bss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getBSS()); // TLS globals are lowered in the backend to arrays indexed by the current // thread id. After lowering they require no special handling by the linker @@ -28,9 +32,12 @@ void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ if (TM.getSubtarget().isXS1A()) // FIXME: Why is this writable ("datarel")??? - ReadOnlySection = getELFSection("\t.dp.rodata", false, - SectionKind::getDataRel()); + ReadOnlySection = + getELFSection(".dp.rodata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); else - ReadOnlySection = getELFSection("\t.cp.rodata", false, - SectionKind::getReadOnly()); + ReadOnlySection = + getELFSection(".cp.rodata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, SectionKind::getReadOnly()); } diff --git a/test/CodeGen/X86/attribute-sections.ll b/test/CodeGen/X86/attribute-sections.ll new file mode 100644 index 00000000000..0dba6e6ff6d --- /dev/null +++ b/test/CodeGen/X86/attribute-sections.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-unknown-linux-gnu | FileCheck %s -check-prefix=LINUX + +declare i32 @foo() +@G0 = global i32 ()* @foo, section ".init_array" + +; LINUX: .section .init_array,"aw" +; LINUX: .globl G0 + +@G1 = global i32 ()* @foo, section ".fini_array" + +; LINUX: .section .fini_array,"aw" +; LINUX: .globl G1 + +@G2 = global i32 ()* @foo, section ".preinit_array" + +; LINUX: .section .preinit_array,"aw" +; LINUX: .globl G2 +