diff options
Diffstat (limited to 'contrib/llvm-project/lld/MachO/InputSection.cpp')
-rw-r--r-- | contrib/llvm-project/lld/MachO/InputSection.cpp | 160 |
1 files changed, 114 insertions, 46 deletions
diff --git a/contrib/llvm-project/lld/MachO/InputSection.cpp b/contrib/llvm-project/lld/MachO/InputSection.cpp index d42085737dbb..25eb878736d9 100644 --- a/contrib/llvm-project/lld/MachO/InputSection.cpp +++ b/contrib/llvm-project/lld/MachO/InputSection.cpp @@ -29,8 +29,8 @@ using namespace lld::macho; // Verify ConcatInputSection's size on 64-bit builds. The size of std::vector // can differ based on STL debug levels (e.g. iterator debugging on MSVC's STL), // so account for that. -static_assert(sizeof(void *) != 8 || - sizeof(ConcatInputSection) == sizeof(std::vector<Reloc>) + 96, +static_assert(sizeof(void *) != 8 || sizeof(ConcatInputSection) == + sizeof(std::vector<Reloc>) + 104, "Try to minimize ConcatInputSection's size, we create many " "instances of it"); @@ -55,46 +55,82 @@ static uint64_t resolveSymbolVA(const Symbol *sym, uint8_t type) { return sym->getVA(); } -// ICF needs to hash any section that might potentially be duplicated so -// that it can match on content rather than identity. -bool ConcatInputSection::isHashableForICF() const { - switch (sectionType(getFlags())) { - case S_REGULAR: - return true; - case S_CSTRING_LITERALS: - case S_4BYTE_LITERALS: - case S_8BYTE_LITERALS: - case S_16BYTE_LITERALS: - case S_LITERAL_POINTERS: - llvm_unreachable("found unexpected literal type in ConcatInputSection"); - case S_ZEROFILL: - case S_GB_ZEROFILL: - case S_NON_LAZY_SYMBOL_POINTERS: - case S_LAZY_SYMBOL_POINTERS: - case S_SYMBOL_STUBS: - case S_MOD_INIT_FUNC_POINTERS: - case S_MOD_TERM_FUNC_POINTERS: - case S_COALESCED: - case S_INTERPOSING: - case S_DTRACE_DOF: - case S_LAZY_DYLIB_SYMBOL_POINTERS: - case S_THREAD_LOCAL_REGULAR: - case S_THREAD_LOCAL_ZEROFILL: - case S_THREAD_LOCAL_VARIABLES: - case S_THREAD_LOCAL_VARIABLE_POINTERS: - case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: - return false; - default: - llvm_unreachable("Section type"); +const Defined *InputSection::getContainingSymbol(uint64_t off) const { + auto *nextSym = llvm::upper_bound( + symbols, off, [](uint64_t a, const Defined *b) { return a < b->value; }); + if (nextSym == symbols.begin()) + return nullptr; + return *std::prev(nextSym); +} + +std::string InputSection::getLocation(uint64_t off) const { + // First, try to find a symbol that's near the offset. Use it as a reference + // point. + if (auto *sym = getContainingSymbol(off)) + return (toString(getFile()) + ":(symbol " + sym->getName() + "+0x" + + Twine::utohexstr(off - sym->value) + ")") + .str(); + + // If that fails, use the section itself as a reference point. + for (const Subsection &subsec : section.subsections) { + if (subsec.isec == this) { + off += subsec.offset; + break; + } } + + return (toString(getFile()) + ":(" + getName() + "+0x" + + Twine::utohexstr(off) + ")") + .str(); } -void ConcatInputSection::hashForICF() { - assert(data.data()); // zeroFill section data has nullptr with non-zero size - assert(icfEqClass[0] == 0); // don't overwrite a unique ID! - // Turn-on the top bit to guarantee that valid hashes have no collisions - // with the small-integer unique IDs for ICF-ineligible sections - icfEqClass[0] = xxHash64(data) | (1ull << 63); +std::string InputSection::getSourceLocation(uint64_t off) const { + auto *obj = dyn_cast_or_null<ObjFile>(getFile()); + if (!obj) + return {}; + + DWARFCache *dwarf = obj->getDwarf(); + if (!dwarf) + return std::string(); + + for (const Subsection &subsec : section.subsections) { + if (subsec.isec == this) { + off += subsec.offset; + break; + } + } + + auto createMsg = [&](StringRef path, unsigned line) { + std::string filename = sys::path::filename(path).str(); + std::string lineStr = (":" + Twine(line)).str(); + if (filename == path) + return filename + lineStr; + return (filename + lineStr + " (" + path + lineStr + ")").str(); + }; + + // First, look up a function for a given offset. + if (Optional<DILineInfo> li = dwarf->getDILineInfo( + section.addr + off, object::SectionedAddress::UndefSection)) + return createMsg(li->FileName, li->Line); + + // If it failed, look up again as a variable. + if (const Defined *sym = getContainingSymbol(off)) { + // Symbols are generally prefixed with an underscore, which is not included + // in the debug information. + StringRef symName = sym->getName(); + if (!symName.empty() && symName[0] == '_') + symName = symName.substr(1); + + if (Optional<std::pair<std::string, unsigned>> fileLine = + dwarf->getVariableLoc(symName)) + return createMsg(fileLine->first, fileLine->second); + } + + // Try to get the source file's name from the DWARF information. + if (obj->compileUnit) + return obj->sourceFile(); + + return {}; } void ConcatInputSection::foldIdentical(ConcatInputSection *copy) { @@ -102,6 +138,8 @@ void ConcatInputSection::foldIdentical(ConcatInputSection *copy) { copy->live = false; copy->wasCoalesced = true; copy->replacement = this; + for (auto ©Sym : copy->symbols) + copySym->wasIdenticalCodeFolded = true; // Merge the sorted vectors of symbols together. auto it = symbols.begin(); @@ -139,6 +177,10 @@ void ConcatInputSection::writeTo(uint8_t *buf) { memcpy(buf, data.data(), data.size()); + std::vector<uint64_t> relocTargets; + if (!optimizationHints.empty()) + relocTargets.reserve(relocs.size()); + for (size_t i = 0; i < relocs.size(); i++) { const Reloc &r = relocs[i]; uint8_t *loc = buf + r.offset; @@ -174,7 +216,25 @@ void ConcatInputSection::writeTo(uint8_t *buf) { referentVA = referentIsec->getVA(r.addend); } target->relocateOne(loc, r, referentVA, getVA() + r.offset); + + if (!optimizationHints.empty()) + relocTargets.push_back(referentVA); } + + if (!optimizationHints.empty()) + target->applyOptimizationHints(buf, this, relocTargets); +} + +ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName, + StringRef sectName, + uint32_t flags, + ArrayRef<uint8_t> data, + uint32_t align) { + Section §ion = + *make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0); + auto isec = make<ConcatInputSection>(section, data, align); + section.subsections.push_back({0, isec}); + return isec; } void CStringInputSection::splitIntoPieces() { @@ -183,7 +243,7 @@ void CStringInputSection::splitIntoPieces() { while (!s.empty()) { size_t end = s.find(0); if (end == StringRef::npos) - fatal(toString(this) + ": string is not null terminated"); + fatal(getLocation(off) + ": string is not null terminated"); size_t size = end + 1; uint32_t hash = config->dedupLiterals ? xxHash64(s.substr(0, size)) : 0; pieces.emplace_back(off, hash); @@ -211,13 +271,11 @@ uint64_t CStringInputSection::getOffset(uint64_t off) const { return piece.outSecOff + addend; } -WordLiteralInputSection::WordLiteralInputSection(StringRef segname, - StringRef name, - InputFile *file, +WordLiteralInputSection::WordLiteralInputSection(const Section §ion, ArrayRef<uint8_t> data, - uint32_t align, uint32_t flags) - : InputSection(WordLiteralKind, segname, name, file, data, align, flags) { - switch (sectionType(flags)) { + uint32_t align) + : InputSection(WordLiteralKind, section, data, align) { + switch (sectionType(getFlags())) { case S_4BYTE_LITERALS: power2LiteralSize = 2; break; @@ -271,6 +329,16 @@ bool macho::isCfStringSection(const InputSection *isec) { isec->getSegName() == segment_names::data; } +bool macho::isClassRefsSection(const InputSection *isec) { + return isec->getName() == section_names::objcClassRefs && + isec->getSegName() == segment_names::data; +} + +bool macho::isEhFrameSection(const InputSection *isec) { + return isec->getName() == section_names::ehFrame && + isec->getSegName() == segment_names::text; +} + std::string lld::toString(const InputSection *isec) { return (toString(isec->getFile()) + ":(" + isec->getName() + ")").str(); } |