diff options
Diffstat (limited to 'lld/MachO/InputFiles.cpp')
-rw-r--r-- | lld/MachO/InputFiles.cpp | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index c53874133a78..fda6900edabe 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -347,7 +347,7 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) { section.subsections.push_back({0, isec}); } else if (auto recordSize = getRecordSize(segname, name)) { splitRecords(*recordSize); - } else if (config->parseEhFrames && name == section_names::ehFrame && + } else if (name == section_names::ehFrame && segname == segment_names::text) { splitEhFrames(data, *sections.back()); } else if (segname == segment_names::llvm) { @@ -1117,7 +1117,7 @@ template <class LP> void ObjFile::parse() { } if (compactUnwindSection) registerCompactUnwind(*compactUnwindSection); - if (config->parseEhFrames && ehFrameSection) + if (ehFrameSection) registerEhFrames(*ehFrameSection); } @@ -1687,7 +1687,6 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella, umbrella = this; this->umbrella = umbrella; - auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart()); auto *hdr = reinterpret_cast<const mach_header *>(mb.getBufferStart()); // Initialize installName. @@ -1722,39 +1721,53 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella, // Initialize symbols. exportingFile = isImplicitlyLinked(installName) ? this : this->umbrella; - if (const load_command *cmd = findCommand(hdr, LC_DYLD_INFO_ONLY)) { - auto *c = reinterpret_cast<const dyld_info_command *>(cmd); - struct TrieEntry { - StringRef name; - uint64_t flags; - }; - std::vector<TrieEntry> entries; - // Find all the $ld$* symbols to process first. - parseTrie(buf + c->export_off, c->export_size, - [&](const Twine &name, uint64_t flags) { - StringRef savedName = saver().save(name); - if (handleLDSymbol(savedName)) - return; - entries.push_back({savedName, flags}); - }); - - // Process the "normal" symbols. - for (TrieEntry &entry : entries) { - if (exportingFile->hiddenSymbols.contains( - CachedHashStringRef(entry.name))) - continue; + const auto *dyldInfo = findCommand<dyld_info_command>(hdr, LC_DYLD_INFO_ONLY); + const auto *exportsTrie = + findCommand<linkedit_data_command>(hdr, LC_DYLD_EXPORTS_TRIE); + if (dyldInfo && exportsTrie) { + // It's unclear what should happen in this case. Maybe we should only error + // out if the two load commands refer to different data? + error("dylib " + toString(this) + + " has both LC_DYLD_INFO_ONLY and LC_DYLD_EXPORTS_TRIE"); + return; + } else if (dyldInfo) { + parseExportedSymbols(dyldInfo->export_off, dyldInfo->export_size); + } else if (exportsTrie) { + parseExportedSymbols(exportsTrie->dataoff, exportsTrie->datasize); + } else { + error("No LC_DYLD_INFO_ONLY or LC_DYLD_EXPORTS_TRIE found in " + + toString(this)); + return; + } +} - bool isWeakDef = entry.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; - bool isTlv = entry.flags & EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL; +void DylibFile::parseExportedSymbols(uint32_t offset, uint32_t size) { + struct TrieEntry { + StringRef name; + uint64_t flags; + }; - symbols.push_back( - symtab->addDylib(entry.name, exportingFile, isWeakDef, isTlv)); - } + auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart()); + std::vector<TrieEntry> entries; + // Find all the $ld$* symbols to process first. + parseTrie(buf + offset, size, [&](const Twine &name, uint64_t flags) { + StringRef savedName = saver().save(name); + if (handleLDSymbol(savedName)) + return; + entries.push_back({savedName, flags}); + }); - } else { - error("LC_DYLD_INFO_ONLY not found in " + toString(this)); - return; + // Process the "normal" symbols. + for (TrieEntry &entry : entries) { + if (exportingFile->hiddenSymbols.contains(CachedHashStringRef(entry.name))) + continue; + + bool isWeakDef = entry.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; + bool isTlv = entry.flags & EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL; + + symbols.push_back( + symtab->addDylib(entry.name, exportingFile, isWeakDef, isTlv)); } } |