static unsigned getCOFFSectionFlags(SectionKind K) { unsigned Flags = 0; if (K.isMetadata()) Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE; else if (K.isText()) Flags |= COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_CNT_CODE; else if (K.isBSS ()) Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; else if (K.isReadOnly()) Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ; else if (K.isWriteable()) Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; return Flags; }
/// IsGlobalInSmallSection - Return true if this global address should be /// placed into small data/bss section. bool MipsTargetObjectFile:: IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, SectionKind Kind) const { // Only use small section for non linux targets. const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); if (Subtarget.isLinux()) return false; // Only global variables, not functions. const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV); if (!GVA) return false; // We can only do this for datarel or BSS objects for now. if (!Kind.isBSS() && !Kind.isDataRel()) return false; // If this is a internal constant string, there is a special // section for it, but not in small data/bss. if (Kind.isMergeable1ByteCString()) return false; const Type *Ty = GV->getType()->getElementType(); return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty)); }
// .section name [, "flags"] [, identifier [ identifier ], identifier] // // Supported flags: // a: Ignored. // b: BSS section (uninitialized data) // d: data section (initialized data) // n: Discardable section // r: Readable section // s: Shared section // w: Writable section // x: Executable section // y: Not-readable section (clears 'r') // // Subsections are not supported. bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { StringRef SectionName; if (ParseSectionName(SectionName)) return TokError("expected identifier in directive"); unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; if (getLexer().is(AsmToken::Comma)) { Lex(); if (getLexer().isNot(AsmToken::String)) return TokError("expected string in directive"); StringRef FlagsStr = getTok().getStringContents(); Lex(); if (ParseSectionFlags(FlagsStr, &Flags)) return true; } COFF::COMDATType Type = (COFF::COMDATType)0; StringRef COMDATSymName; if (getLexer().is(AsmToken::Comma)) { Type = COFF::IMAGE_COMDAT_SELECT_ANY; Lex(); Flags |= COFF::IMAGE_SCN_LNK_COMDAT; if (!getLexer().is(AsmToken::Identifier)) return TokError("expected comdat type such as 'discard' or 'largest' " "after protection bits"); if (parseCOMDATType(Type)) return true; if (getLexer().isNot(AsmToken::Comma)) return TokError("expected comma in directive"); Lex(); if (getParser().parseIdentifier(COMDATSymName)) return TokError("expected identifier in directive"); } if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); SectionKind Kind = computeSectionKind(Flags); if (Kind.isText()) { const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) Flags |= COFF::IMAGE_SCN_MEM_16BIT; } ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type); return false; }
static unsigned getELFSectionFlags(SectionKind K) { unsigned Flags = 0; if (!K.isMetadata()) Flags |= ELF::SHF_ALLOC; if (K.isText()) Flags |= ELF::SHF_EXECINSTR; if (K.isWriteable()) Flags |= ELF::SHF_WRITE; if (K.isThreadLocal()) Flags |= ELF::SHF_TLS; // K.isMergeableConst() is left out to honour PR4650 if (K.isMergeableCString() || K.isMergeableConst4() || K.isMergeableConst8() || K.isMergeableConst16()) Flags |= ELF::SHF_MERGE; if (K.isMergeableCString()) Flags |= ELF::SHF_STRINGS; return Flags; }
static unsigned getELFSectionFlags(SectionKind K) { unsigned Flags = 0; if (!K.isMetadata()) Flags |= ELF::SHF_ALLOC; if (K.isText()) Flags |= ELF::SHF_EXECINSTR; if (K.isExecuteOnly()) Flags |= ELF::SHF_ARM_PURECODE; if (K.isWriteable()) Flags |= ELF::SHF_WRITE; if (K.isThreadLocal()) Flags |= ELF::SHF_TLS; if (K.isMergeableCString() || K.isMergeableConst()) Flags |= ELF::SHF_MERGE; if (K.isMergeableCString()) Flags |= ELF::SHF_STRINGS; return Flags; }
static unsigned getXCoreSectionFlags(SectionKind K, bool IsCPRel) { unsigned Flags = 0; if (!K.isMetadata()) Flags |= ELF::SHF_ALLOC; if (K.isText()) Flags |= ELF::SHF_EXECINSTR; else if (IsCPRel) Flags |= ELF::XCORE_SHF_CP_SECTION; else Flags |= ELF::XCORE_SHF_DP_SECTION; if (K.isWriteable()) Flags |= ELF::SHF_WRITE; if (K.isMergeableCString() || K.isMergeableConst4() || K.isMergeableConst8() || K.isMergeableConst16()) Flags |= ELF::SHF_MERGE; if (K.isMergeableCString()) Flags |= ELF::SHF_STRINGS; return Flags; }
/// IsGlobalInSmallSection - Return true if this global value should be /// placed into small data/bss section. bool HexagonTargetObjectFile:: IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, SectionKind Kind) const { // Only global variables, not functions. const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV); if (!GVA) return false; if (Kind.isBSS() || Kind.isDataNoRel() || Kind.isCommon()) { Type *Ty = GV->getType()->getElementType(); return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty)); } return false; }
static unsigned getELFSectionType(StringRef Name, SectionKind K) { if (Name == ".init_array") return ELF::SHT_INIT_ARRAY; if (Name == ".fini_array") return ELF::SHT_FINI_ARRAY; if (Name == ".preinit_array") return ELF::SHT_PREINIT_ARRAY; if (K.isBSS() || K.isThreadBSS()) return ELF::SHT_NOBITS; return ELF::SHT_PROGBITS; }
static bool isExecuteOnlyFunction(const GlobalObject *GO, SectionKind SK, const TargetMachine &TM) { if (const Function *F = dyn_cast<Function>(GO)) if (TM.getSubtarget<ARMSubtarget>(*F).genExecuteOnly() && SK.isText()) return true; return false; }
/// getSectionPrefixForGlobal - Return the section prefix name used by options /// FunctionsSections and DataSections. static StringRef getSectionPrefixForGlobal(SectionKind Kind) { if (Kind.isText()) return ".text."; if (Kind.isReadOnly()) return ".rodata."; if (Kind.isBSS()) return ".bss."; if (Kind.isThreadData()) return ".tdata."; if (Kind.isThreadBSS()) return ".tbss."; if (Kind.isDataNoRel()) return ".data."; if (Kind.isDataRelLocal()) return ".data.rel.local."; if (Kind.isDataRel()) return ".data.rel."; if (Kind.isReadOnlyWithRelLocal()) return ".data.rel.ro.local."; assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); return ".data.rel.ro."; }
static unsigned getELFSectionFlags(SectionKind K, bool InCOMDAT) { unsigned Flags = 0; if (!K.isMetadata()) Flags |= ELF::SHF_ALLOC; if (K.isText()) Flags |= ELF::SHF_EXECINSTR; if (K.isWriteable()) Flags |= ELF::SHF_WRITE; if (K.isThreadLocal()) Flags |= ELF::SHF_TLS; // FIXME: There is nothing in ELF preventing an SHF_MERGE from being // in a comdat. We just avoid it for now because we don't print // those .sections correctly. if (!InCOMDAT && (K.isMergeableCString() || K.isMergeableConst())) Flags |= ELF::SHF_MERGE; if (K.isMergeableCString()) Flags |= ELF::SHF_STRINGS; return Flags; }
static SectionKind getWasmKindForNamedSection(StringRef Name, SectionKind K) { // If we're told we have function data, then use that. if (K.isText()) return SectionKind::getText(); // Otherwise, ignore whatever section type the generic impl detected and use // a plain data section. return SectionKind::getData(); }
static unsigned getELFSectionType(StringRef Name, SectionKind K) { // Use SHT_NOTE for section whose name starts with ".note" to allow // emitting ELF notes from C variable declaration. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77609 if (Name.startswith(".note")) return ELF::SHT_NOTE; if (Name == ".init_array") return ELF::SHT_INIT_ARRAY; if (Name == ".fini_array") return ELF::SHT_FINI_ARRAY; if (Name == ".preinit_array") return ELF::SHT_PREINIT_ARRAY; if (K.isBSS() || K.isThreadBSS()) return ELF::SHT_NOBITS; return ELF::SHT_PROGBITS; }
SVMProgramSection SVMMemoryLayout::getSectionKind(const MCSectionData *SD) const { /* * Categorize a MCSection as one of the several predefined * SVMProgramSection types. This determines which program section * we'll lump it in with, or whether it'll be included as debug-only. * * This value can be specifically overridden with setSectionKind(). * If we have no override, we calculate the proper section kind * using the section's name, size, type, and other data. */ SectionKindOverrides_t::const_iterator it = SectionKindOverrides.find(SD); if (it != SectionKindOverrides.end()) return it->second; const MCSection *S = &SD->getSection(); SectionKind k = S->getKind(); const MCSectionELF *SE = dyn_cast<MCSectionELF>(S); assert(SE); StringRef Name = SE->getSectionName(); if (Name == ".metadata") return SPS_META; if (Name.startswith(".debug_")) return SPS_DEBUG; if (k.isBSS()) return SPS_BSS; if (SE->getType() == ELF::SHT_PROGBITS) { if (k.isReadOnly() || k.isText()) return SPS_RO; if (k.isGlobalWriteableData()) return SPS_RW_PLAIN; } return SPS_DEBUG; }
unsigned MCSectionELF::DetermineEntrySize(SectionKind Kind) { if (Kind.isMergeable1ByteCString()) return 1; if (Kind.isMergeable2ByteCString()) return 2; if (Kind.isMergeable4ByteCString()) return 4; if (Kind.isMergeableConst4()) return 4; if (Kind.isMergeableConst8()) return 8; if (Kind.isMergeableConst16()) return 16; return 0; }
static unsigned getCOFFSectionFlags(SectionKind K, const TargetMachine &TM) { unsigned Flags = 0; bool isThumb = TM.getTargetTriple().getArch() == Triple::thumb; if (K.isMetadata()) Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE; else if (K.isText()) Flags |= COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_CNT_CODE | (isThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0); else if (K.isBSS()) Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; else if (K.isThreadLocal()) Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; else if (K.isReadOnly() || K.isReadOnlyWithRel()) Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ; else if (K.isWriteable()) Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; return Flags; }
// EmitGlobal - Choose the right section for global and emit it void ELFWriter::EmitGlobal(const GlobalValue *GV) { // Check if the referenced symbol is already emitted if (GblSymLookup.find(GV) != GblSymLookup.end()) return; // Handle ELF Bind, Visibility and Type for the current symbol unsigned SymBind = getGlobalELFBinding(GV); unsigned SymType = getGlobalELFType(GV); bool IsUndefSym = IsELFUndefSym(GV); ELFSym *GblSym = IsUndefSym ? ELFSym::getUndefGV(GV, SymBind) : ELFSym::getGV(GV, SymBind, SymType, getGlobalELFVisibility(GV)); if (!IsUndefSym) { assert(isa<GlobalVariable>(GV) && "GV not a global variable!"); const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); // Handle special llvm globals if (EmitSpecialLLVMGlobal(GVar)) return; // Get the ELF section where this global belongs from TLOF const MCSectionELF *S = (const MCSectionELF *)TLOF.SectionForGlobal(GV, Mang, TM); ELFSection &ES = getSection(S->getSectionName(), S->getType(), S->getFlags()); SectionKind Kind = S->getKind(); // The symbol align should update the section alignment if needed const TargetData *TD = TM.getTargetData(); unsigned Align = TD->getPreferredAlignment(GVar); unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType()); GblSym->Size = Size; if (HasCommonSymbols(*S)) { // Symbol must go to a common section GblSym->SectionIdx = ELF::SHN_COMMON; // A new linkonce section is created for each global in the // common section, the default alignment is 1 and the symbol // value contains its alignment. ES.Align = 1; GblSym->Value = Align; } else if (Kind.isBSS() || Kind.isThreadBSS()) { // Symbol goes to BSS. GblSym->SectionIdx = ES.SectionIdx; // Update the size with alignment and the next object can // start in the right offset in the section if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1); ES.Align = std::max(ES.Align, Align); // GblSym->Value should contain the virtual offset inside the section. // Virtual because the BSS space is not allocated on ELF objects GblSym->Value = ES.Size; ES.Size += Size; } else { // The symbol must go to some kind of data section GblSym->SectionIdx = ES.SectionIdx; // GblSym->Value should contain the symbol offset inside the section, // and all symbols should start on their required alignment boundary ES.Align = std::max(ES.Align, Align); ES.emitAlignment(Align); GblSym->Value = ES.size(); // Emit the global to the data section 'ES' EmitGlobalConstant(GVar->getInitializer(), ES); } } AddToSymbolList(GblSym); }
static unsigned getXCoreSectionType(SectionKind K) { if (K.isBSS()) return ELF::SHT_NOBITS; return ELF::SHT_PROGBITS; }
// Return true if this global address should be placed into small data/bss // section. bool LanaiTargetObjectFile::isGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, SectionKind Kind) const { return (isGlobalInSmallSectionImpl(GV, TM) && (Kind.isData() || Kind.isBSS() || Kind.isCommon())); }
/// Return the section prefix name used by options FunctionsSections and /// DataSections. static StringRef getSectionPrefixForGlobal(SectionKind Kind) { if (Kind.isTexTramp()) return ".tramp."; if (Kind.isText()) return ".text"; if (Kind.isReadOnly()) return ".rodata"; if (Kind.isBSS()) return ".bss"; if (Kind.isThreadData()) return ".tdata"; if (Kind.isThreadBSS()) return ".tbss"; if (Kind.isData()) return ".data"; if (Kind.isTexTrap()) return ".textrap."; if (Kind.isTexTrapText()) return ".textrap."; if (Kind.isTexTramp()) return ".text.xvtable."; assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); return ".data.rel.ro"; }
/// IsGlobalInSmallSection - Return true if this global address should be /// placed into small data/bss section. bool TriCoreTargetObjectFile:: IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, SectionKind Kind) const { return (IsGlobalInSmallSectionImpl(GV, TM) && (Kind.isDataRel() || Kind.isBSS() || Kind.isCommon())); }