diff options
Diffstat (limited to 'llvm/lib/MC/MCContext.cpp')
-rw-r--r-- | llvm/lib/MC/MCContext.cpp | 205 |
1 files changed, 163 insertions, 42 deletions
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index a6417113fd384..a0f9212f3b142 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -68,8 +68,8 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, SecureLogFile = AsSecureLogFileName; if (SrcMgr && SrcMgr->getNumBuffers()) - MainFileName = - SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier(); + MainFileName = std::string(SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID()) + ->getBufferIdentifier()); } MCContext::~MCContext() { @@ -114,6 +114,9 @@ void MCContext::reset() { WasmUniquingMap.clear(); XCOFFUniquingMap.clear(); + ELFEntrySizeMap.clear(); + ELFSeenGenericMergeableSections.clear(); + NextID.clear(); AllowTemporaryLabels = true; DwarfLocSeen = false; @@ -158,6 +161,16 @@ MCSymbol *MCContext::getOrCreateLSDASymbol(StringRef FuncName) { MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name, bool IsTemporary) { + static_assert(std::is_trivially_destructible<MCSymbolCOFF>(), + "MCSymbol classes must be trivially destructible"); + static_assert(std::is_trivially_destructible<MCSymbolELF>(), + "MCSymbol classes must be trivially destructible"); + static_assert(std::is_trivially_destructible<MCSymbolMachO>(), + "MCSymbol classes must be trivially destructible"); + static_assert(std::is_trivially_destructible<MCSymbolWasm>(), + "MCSymbol classes must be trivially destructible"); + static_assert(std::is_trivially_destructible<MCSymbolXCOFF>(), + "MCSymbol classes must be trivially destructible"); if (MOFI) { switch (MOFI->getObjectFileType()) { case MCObjectFileInfo::IsCOFF: @@ -169,7 +182,7 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name, case MCObjectFileInfo::IsWasm: return new (Name, *this) MCSymbolWasm(Name, IsTemporary); case MCObjectFileInfo::IsXCOFF: - return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary); + return createXCOFFSymbolImpl(Name, IsTemporary); } } return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name, @@ -272,13 +285,68 @@ void MCContext::setSymbolValue(MCStreamer &Streamer, StringRef Sym, uint64_t Val) { auto Symbol = getOrCreateSymbol(Sym); - Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this)); + Streamer.emitAssignment(Symbol, MCConstantExpr::create(Val, *this)); } void MCContext::registerInlineAsmLabel(MCSymbol *Sym) { InlineAsmUsedLabelNames[Sym->getName()] = Sym; } +MCSymbolXCOFF * +MCContext::createXCOFFSymbolImpl(const StringMapEntry<bool> *Name, + bool IsTemporary) { + if (!Name) + return new (nullptr, *this) MCSymbolXCOFF(nullptr, IsTemporary); + + StringRef OriginalName = Name->first(); + if (OriginalName.startswith("._Renamed..") || + OriginalName.startswith("_Renamed..")) + reportError(SMLoc(), "invalid symbol name from source"); + + if (MAI->isValidUnquotedName(OriginalName)) + return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary); + + // Now we have a name that contains invalid character(s) for XCOFF symbol. + // Let's replace with something valid, but save the original name so that + // we could still use the original name in the symbol table. + SmallString<128> InvalidName(OriginalName); + + // If it's an entry point symbol, we will keep the '.' + // in front for the convention purpose. Otherwise, add "_Renamed.." + // as prefix to signal this is an renamed symbol. + const bool IsEntryPoint = !InvalidName.empty() && InvalidName[0] == '.'; + SmallString<128> ValidName = + StringRef(IsEntryPoint ? "._Renamed.." : "_Renamed.."); + + // Append the hex values of '_' and invalid characters with "_Renamed.."; + // at the same time replace invalid characters with '_'. + for (size_t I = 0; I < InvalidName.size(); ++I) { + if (!MAI->isAcceptableChar(InvalidName[I]) || InvalidName[I] == '_') { + raw_svector_ostream(ValidName).write_hex(InvalidName[I]); + InvalidName[I] = '_'; + } + } + + // Skip entry point symbol's '.' as we already have a '.' in front of + // "_Renamed". + if (IsEntryPoint) + ValidName.append(InvalidName.substr(1, InvalidName.size() - 1)); + else + ValidName.append(InvalidName); + + auto NameEntry = UsedNames.insert(std::make_pair(ValidName, true)); + assert((NameEntry.second || !NameEntry.first->second) && + "This name is used somewhere else."); + // Mark the name as used for a non-section symbol. + NameEntry.first->second = true; + // Have the MCSymbol object itself refer to the copy of the string + // that is embedded in the UsedNames entry. + MCSymbolXCOFF *XSym = new (&*NameEntry.first, *this) + MCSymbolXCOFF(&*NameEntry.first, IsTemporary); + XSym->setSymbolTableName(MCSymbolXCOFF::getUnqualifiedName(OriginalName)); + return XSym; +} + //===----------------------------------------------------------------------===// // Section Management //===----------------------------------------------------------------------===// @@ -292,23 +360,25 @@ MCSectionMachO *MCContext::getMachOSection(StringRef Segment, StringRef Section, // diagnosed by the client as an error. // Form the name to look up. - SmallString<64> Name; - Name += Segment; - Name.push_back(','); - Name += Section; + assert(Section.size() <= 16 && "section name is too long"); + assert(!memchr(Section.data(), '\0', Section.size()) && + "section name cannot contain NUL"); // Do the lookup, if we have a hit, return it. - MCSectionMachO *&Entry = MachOUniquingMap[Name]; - if (Entry) - return Entry; + auto R = MachOUniquingMap.try_emplace((Segment + Twine(',') + Section).str()); + if (!R.second) + return R.first->second; MCSymbol *Begin = nullptr; if (BeginSymName) Begin = createTempSymbol(BeginSymName, false); // Otherwise, return a new section. - return Entry = new (MachOAllocator.Allocate()) MCSectionMachO( - Segment, Section, TypeAndAttributes, Reserved2, Kind, Begin); + StringRef Name = R.first->first(); + R.first->second = new (MachOAllocator.Allocate()) + MCSectionMachO(Segment, Name.substr(Name.size() - Section.size()), + TypeAndAttributes, Reserved2, Kind, Begin); + return R.first->second; } void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) { @@ -316,12 +386,14 @@ void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) { if (const MCSymbol *Group = Section->getGroup()) GroupName = Group->getName(); + // This function is only used by .debug*, which should not have the + // SHF_LINK_ORDER flag. unsigned UniqueID = Section->getUniqueID(); ELFUniquingMap.erase( - ELFSectionKey{Section->getSectionName(), GroupName, UniqueID}); - auto I = ELFUniquingMap.insert(std::make_pair( - ELFSectionKey{Name, GroupName, UniqueID}, - Section)) + ELFSectionKey{Section->getName(), GroupName, "", UniqueID}); + auto I = ELFUniquingMap + .insert(std::make_pair( + ELFSectionKey{Name, GroupName, "", UniqueID}, Section)) .first; StringRef CachedName = I->first.SectionName; const_cast<MCSectionELF *>(Section)->setSectionName(CachedName); @@ -332,7 +404,7 @@ MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type, unsigned EntrySize, const MCSymbolELF *Group, unsigned UniqueID, - const MCSymbolELF *Associated) { + const MCSymbolELF *LinkedToSym) { MCSymbolELF *R; MCSymbol *&Sym = Symbols[Section]; // A section symbol can not redefine regular symbols. There may be multiple @@ -352,7 +424,7 @@ MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type, R->setType(ELF::STT_SECTION); auto *Ret = new (ELFAllocator.Allocate()) MCSectionELF( - Section, Type, Flags, K, EntrySize, Group, UniqueID, R, Associated); + Section, Type, Flags, K, EntrySize, Group, UniqueID, R, LinkedToSym); auto *F = new MCDataFragment(); Ret->getFragmentList().insert(Ret->begin(), F); @@ -386,26 +458,29 @@ MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix, MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, const Twine &Group, unsigned UniqueID, - const MCSymbolELF *Associated) { + const MCSymbolELF *LinkedToSym) { MCSymbolELF *GroupSym = nullptr; if (!Group.isTriviallyEmpty() && !Group.str().empty()) GroupSym = cast<MCSymbolELF>(getOrCreateSymbol(Group)); return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID, - Associated); + LinkedToSym); } MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, const MCSymbolELF *GroupSym, unsigned UniqueID, - const MCSymbolELF *Associated) { + const MCSymbolELF *LinkedToSym) { StringRef Group = ""; if (GroupSym) Group = GroupSym->getName(); + assert(!(LinkedToSym && LinkedToSym->getName().empty())); // Do the lookup, if we have a hit, return it. - auto IterBool = ELFUniquingMap.insert( - std::make_pair(ELFSectionKey{Section.str(), Group, UniqueID}, nullptr)); + auto IterBool = ELFUniquingMap.insert(std::make_pair( + ELFSectionKey{Section.str(), Group, + LinkedToSym ? LinkedToSym->getName() : "", UniqueID}, + nullptr)); auto &Entry = *IterBool.first; if (!IterBool.second) return Entry.second; @@ -420,16 +495,55 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, else Kind = SectionKind::getReadOnly(); - MCSectionELF *Result = createELFSectionImpl( - CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, Associated); + MCSectionELF *Result = + createELFSectionImpl(CachedName, Type, Flags, Kind, EntrySize, GroupSym, + UniqueID, LinkedToSym); Entry.second = Result; + + recordELFMergeableSectionInfo(Result->getName(), Result->getFlags(), + Result->getUniqueID(), Result->getEntrySize()); + return Result; } MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group) { return createELFSectionImpl(".group", ELF::SHT_GROUP, 0, - SectionKind::getReadOnly(), 4, Group, ~0, - nullptr); + SectionKind::getReadOnly(), 4, Group, + MCSection::NonUniqueID, nullptr); +} + +void MCContext::recordELFMergeableSectionInfo(StringRef SectionName, + unsigned Flags, unsigned UniqueID, + unsigned EntrySize) { + bool IsMergeable = Flags & ELF::SHF_MERGE; + if (IsMergeable && (UniqueID == GenericSectionID)) + ELFSeenGenericMergeableSections.insert(SectionName); + + // For mergeable sections or non-mergeable sections with a generic mergeable + // section name we enter their Unique ID into the ELFEntrySizeMap so that + // compatible globals can be assigned to the same section. + if (IsMergeable || isELFGenericMergeableSection(SectionName)) { + ELFEntrySizeMap.insert(std::make_pair( + ELFEntrySizeKey{SectionName, Flags, EntrySize}, UniqueID)); + } +} + +bool MCContext::isELFImplicitMergeableSectionNamePrefix(StringRef SectionName) { + return SectionName.startswith(".rodata.str") || + SectionName.startswith(".rodata.cst"); +} + +bool MCContext::isELFGenericMergeableSection(StringRef SectionName) { + return isELFImplicitMergeableSectionNamePrefix(SectionName) || + ELFSeenGenericMergeableSections.count(SectionName); +} + +Optional<unsigned> MCContext::getELFUniqueIDForEntsize(StringRef SectionName, + unsigned Flags, + unsigned EntrySize) { + auto I = ELFEntrySizeMap.find( + MCContext::ELFEntrySizeKey{SectionName, Flags, EntrySize}); + return (I != ELFEntrySizeMap.end()) ? Optional<unsigned>(I->second) : None; } MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, @@ -484,13 +598,13 @@ MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec, unsigned Characteristics = Sec->getCharacteristics(); if (KeySym) { Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; - return getCOFFSection(Sec->getSectionName(), Characteristics, - Sec->getKind(), KeySym->getName(), + return getCOFFSection(Sec->getName(), Characteristics, Sec->getKind(), + KeySym->getName(), COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); } - return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(), - "", 0, UniqueID); + return getCOFFSection(Sec->getName(), Characteristics, Sec->getKind(), "", 0, + UniqueID); } MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K, @@ -551,15 +665,18 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section, // Otherwise, return a new section. StringRef CachedName = Entry.first.SectionName; - MCSymbol *QualName = getOrCreateSymbol( - CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]"); + MCSymbolXCOFF *QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol( + CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]")); MCSymbol *Begin = nullptr; if (BeginSymName) Begin = createTempSymbol(BeginSymName, false); - MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) MCSectionXCOFF( - CachedName, SMC, Type, SC, Kind, cast<MCSymbolXCOFF>(QualName), Begin); + // QualName->getUnqualifiedName() and CachedName are the same except when + // CachedName contains invalid character(s) such as '$' for an XCOFF symbol. + MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) + MCSectionXCOFF(QualName->getUnqualifiedName(), SMC, Type, SC, Kind, + QualName, Begin, CachedName); Entry.second = Result; auto *F = new MCDataFragment(); @@ -583,17 +700,21 @@ void MCContext::addDebugPrefixMapEntry(const std::string &From, void MCContext::RemapDebugPaths() { const auto &DebugPrefixMap = this->DebugPrefixMap; + if (DebugPrefixMap.empty()) + return; + const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) { - for (const auto &Entry : DebugPrefixMap) - if (StringRef(Path).startswith(Entry.first)) { - std::string RemappedPath = - (Twine(Entry.second) + Path.substr(Entry.first.size())).str(); - Path.swap(RemappedPath); + SmallString<256> P(Path); + for (const auto &Entry : DebugPrefixMap) { + if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) { + Path = P.str().str(); + break; } + } }; // Remap compilation directory. - std::string CompDir = CompilationDir.str(); + std::string CompDir = std::string(CompilationDir.str()); RemapDebugPath(CompDir); CompilationDir = CompDir; |