123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- //===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
- //
- // The LLVM Linker
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- ///
- /// \file Converts from in-memory normalized mach-o to in-memory Atoms.
- ///
- /// +------------+
- /// | normalized |
- /// +------------+
- /// |
- /// |
- /// v
- /// +-------+
- /// | Atoms |
- /// +-------+
- #include "MachONormalizedFile.h"
- #include "MachONormalizedFileBinaryUtils.h"
- #include "File.h"
- #include "Atoms.h"
- #include "ReferenceKinds.h"
- #include "lld/Core/Error.h"
- #include "lld/Core/LLVM.h"
- #include "llvm/Support/MachO.h"
- #include "llvm/Support/Format.h"
- using namespace llvm::MachO;
- using namespace lld::mach_o::normalized;
- namespace lld {
- namespace mach_o {
- namespace { // anonymous
- #define ENTRY(seg, sect, type, atomType) \
- {seg, sect, type, DefinedAtom::atomType }
- struct MachORelocatableSectionToAtomType {
- StringRef segmentName;
- StringRef sectionName;
- SectionType sectionType;
- DefinedAtom::ContentType atomType;
- };
- const MachORelocatableSectionToAtomType sectsToAtomType[] = {
- ENTRY("__TEXT", "__text", S_REGULAR, typeCode),
- ENTRY("__TEXT", "__text", S_REGULAR, typeResolver),
- ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString),
- ENTRY("", "", S_CSTRING_LITERALS, typeCString),
- ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String),
- ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
- ENTRY("__TEXT", "__const_coal", S_COALESCED, typeConstant),
- ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI),
- ENTRY("__TEXT", "__literal4", S_4BYTE_LITERALS, typeLiteral4),
- ENTRY("__TEXT", "__literal8", S_8BYTE_LITERALS, typeLiteral8),
- ENTRY("__TEXT", "__literal16", S_16BYTE_LITERALS, typeLiteral16),
- ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA),
- ENTRY("__DATA", "__data", S_REGULAR, typeData),
- ENTRY("__DATA", "__datacoal_nt", S_COALESCED, typeData),
- ENTRY("__DATA", "__const", S_REGULAR, typeConstData),
- ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString),
- ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS,
- typeInitializerPtr),
- ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS,
- typeTerminatorPtr),
- ENTRY("__DATA", "___got", S_NON_LAZY_SYMBOL_POINTERS,
- typeGOT),
- ENTRY("__DATA", "___bss", S_ZEROFILL, typeZeroFill),
- ENTRY("", "", S_NON_LAZY_SYMBOL_POINTERS,
- typeGOT),
- ENTRY("__LD", "__compact_unwind", S_REGULAR,
- typeCompactUnwindInfo),
- ENTRY("", "", S_REGULAR, typeUnknown)
- };
- #undef ENTRY
- /// Figures out ContentType of a mach-o section.
- DefinedAtom::ContentType atomTypeFromSection(const Section §ion) {
- // First look for match of name and type. Empty names in table are wildcards.
- for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
- p->atomType != DefinedAtom::typeUnknown; ++p) {
- if (p->sectionType != section.type)
- continue;
- if (!p->segmentName.equals(section.segmentName) && !p->segmentName.empty())
- continue;
- if (!p->sectionName.equals(section.sectionName) && !p->sectionName.empty())
- continue;
- return p->atomType;
- }
- // Look for code denoted by section attributes
- if (section.attributes & S_ATTR_PURE_INSTRUCTIONS)
- return DefinedAtom::typeCode;
- return DefinedAtom::typeUnknown;
- }
- enum AtomizeModel {
- atomizeAtSymbols,
- atomizeFixedSize,
- atomizePointerSize,
- atomizeUTF8,
- atomizeUTF16,
- atomizeCFI,
- atomizeCU,
- atomizeCFString
- };
- /// Returns info on how to atomize a section of the specified ContentType.
- void sectionParseInfo(DefinedAtom::ContentType atomType,
- unsigned int &sizeMultiple,
- DefinedAtom::Scope &scope,
- DefinedAtom::Merge &merge,
- AtomizeModel &atomizeModel) {
- struct ParseInfo {
- DefinedAtom::ContentType atomType;
- unsigned int sizeMultiple;
- DefinedAtom::Scope scope;
- DefinedAtom::Merge merge;
- AtomizeModel atomizeModel;
- };
- #define ENTRY(type, size, scope, merge, model) \
- {DefinedAtom::type, size, DefinedAtom::scope, DefinedAtom::merge, model }
- static const ParseInfo parseInfo[] = {
- ENTRY(typeCode, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeData, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeConstData, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeZeroFill, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeConstant, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeCString, 1, scopeLinkageUnit, mergeByContent,
- atomizeUTF8),
- ENTRY(typeUTF16String, 1, scopeLinkageUnit, mergeByContent,
- atomizeUTF16),
- ENTRY(typeCFI, 1, scopeTranslationUnit, mergeNo,
- atomizeCFI),
- ENTRY(typeLiteral4, 4, scopeLinkageUnit, mergeByContent,
- atomizeFixedSize),
- ENTRY(typeLiteral8, 8, scopeLinkageUnit, mergeByContent,
- atomizeFixedSize),
- ENTRY(typeLiteral16, 16, scopeLinkageUnit, mergeByContent,
- atomizeFixedSize),
- ENTRY(typeCFString, 4, scopeLinkageUnit, mergeByContent,
- atomizeCFString),
- ENTRY(typeInitializerPtr, 4, scopeTranslationUnit, mergeNo,
- atomizePointerSize),
- ENTRY(typeTerminatorPtr, 4, scopeTranslationUnit, mergeNo,
- atomizePointerSize),
- ENTRY(typeCompactUnwindInfo, 4, scopeTranslationUnit, mergeNo,
- atomizeCU),
- ENTRY(typeCFI, 4, scopeTranslationUnit, mergeNo,
- atomizeFixedSize),
- ENTRY(typeGOT, 4, scopeLinkageUnit, mergeByContent,
- atomizePointerSize),
- ENTRY(typeUnknown, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols)
- };
- #undef ENTRY
- const int tableLen = sizeof(parseInfo) / sizeof(ParseInfo);
- for (int i=0; i < tableLen; ++i) {
- if (parseInfo[i].atomType == atomType) {
- sizeMultiple = parseInfo[i].sizeMultiple;
- scope = parseInfo[i].scope;
- merge = parseInfo[i].merge;
- atomizeModel = parseInfo[i].atomizeModel;
- return;
- }
- }
- // Unknown type is atomized by symbols.
- sizeMultiple = 1;
- scope = DefinedAtom::scopeGlobal;
- merge = DefinedAtom::mergeNo;
- atomizeModel = atomizeAtSymbols;
- }
- Atom::Scope atomScope(uint8_t scope) {
- switch (scope) {
- case N_EXT:
- return Atom::scopeGlobal;
- case N_PEXT:
- case N_PEXT | N_EXT:
- return Atom::scopeLinkageUnit;
- case 0:
- return Atom::scopeTranslationUnit;
- }
- llvm_unreachable("unknown scope value!");
- }
- void appendSymbolsInSection(const std::vector<Symbol> &inSymbols,
- uint32_t sectionIndex,
- SmallVector<const Symbol *, 64> &outSyms) {
- for (const Symbol &sym : inSymbols) {
- // Only look at definition symbols.
- if ((sym.type & N_TYPE) != N_SECT)
- continue;
- if (sym.sect != sectionIndex)
- continue;
- outSyms.push_back(&sym);
- }
- }
- void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion,
- MachOFile &file, uint64_t symbolAddr, StringRef symbolName,
- uint16_t symbolDescFlags, Atom::Scope symbolScope,
- uint64_t nextSymbolAddr, bool copyRefs) {
- // Mach-O symbol table does have size in it. Instead the size is the
- // difference between this and the next symbol.
- uint64_t size = nextSymbolAddr - symbolAddr;
- uint64_t offset = symbolAddr - section.address;
- if (section.type == llvm::MachO::S_ZEROFILL) {
- file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size, copyRefs,
- §ion);
- } else {
- DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
- ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo;
- bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF);
- if (atomType == DefinedAtom::typeUnknown) {
- // Mach-O needs a segment and section name. Concatentate those two
- // with a / seperator (e.g. "seg/sect") to fit into the lld model
- // of just a section name.
- std::string segSectName = section.segmentName.str()
- + "/" + section.sectionName.str();
- file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
- merge, thumb,offset, size, segSectName,
- true, §ion);
- } else {
- if ((atomType == lld::DefinedAtom::typeCode) &&
- (symbolDescFlags & N_SYMBOL_RESOLVER)) {
- atomType = lld::DefinedAtom::typeResolver;
- }
- file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
- offset, size, thumb, copyRefs, §ion);
- }
- }
- }
- std::error_code processSymboledSection(DefinedAtom::ContentType atomType,
- const Section §ion,
- const NormalizedFile &normalizedFile,
- MachOFile &file, bool copyRefs) {
- // Find section's index.
- uint32_t sectIndex = 1;
- for (auto § : normalizedFile.sections) {
- if (§ == §ion)
- break;
- ++sectIndex;
- }
- // Find all symbols in this section.
- SmallVector<const Symbol *, 64> symbols;
- appendSymbolsInSection(normalizedFile.globalSymbols, sectIndex, symbols);
- appendSymbolsInSection(normalizedFile.localSymbols, sectIndex, symbols);
- // Sort symbols.
- std::sort(symbols.begin(), symbols.end(),
- [](const Symbol *lhs, const Symbol *rhs) -> bool {
- if (lhs == rhs)
- return false;
- // First by address.
- uint64_t lhsAddr = lhs->value;
- uint64_t rhsAddr = rhs->value;
- if (lhsAddr != rhsAddr)
- return lhsAddr < rhsAddr;
- // If same address, one is an alias so sort by scope.
- Atom::Scope lScope = atomScope(lhs->scope);
- Atom::Scope rScope = atomScope(rhs->scope);
- if (lScope != rScope)
- return lScope < rScope;
- // If same address and scope, sort by name.
- return lhs->name < rhs->name;
- });
- // Debug logging of symbols.
- //for (const Symbol *sym : symbols)
- // llvm::errs() << " sym: "
- // << llvm::format("0x%08llx ", (uint64_t)sym->value)
- // << ", " << sym->name << "\n";
- // If section has no symbols and no content, there are no atoms.
- if (symbols.empty() && section.content.empty())
- return std::error_code();
- if (symbols.empty()) {
- // Section has no symbols, put all content in one anoymous atom.
- atomFromSymbol(atomType, section, file, section.address, StringRef(),
- 0, Atom::scopeTranslationUnit,
- section.address + section.content.size(), copyRefs);
- }
- else if (symbols.front()->value != section.address) {
- // Section has anonymous content before first symbol.
- atomFromSymbol(atomType, section, file, section.address, StringRef(),
- 0, Atom::scopeTranslationUnit, symbols.front()->value,
- copyRefs);
- }
- const Symbol *lastSym = nullptr;
- for (const Symbol *sym : symbols) {
- if (lastSym != nullptr) {
- atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
- lastSym->desc, atomScope(lastSym->scope), sym->value, copyRefs);
- }
- lastSym = sym;
- }
- if (lastSym != nullptr) {
- atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
- lastSym->desc, atomScope(lastSym->scope),
- section.address + section.content.size(), copyRefs);
- }
- return std::error_code();
- }
- std::error_code processSection(DefinedAtom::ContentType atomType,
- const Section §ion,
- const NormalizedFile &normalizedFile,
- MachOFile &file, bool copyRefs) {
- const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
- const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch);
- // Get info on how to atomize section.
- unsigned int sizeMultiple;
- DefinedAtom::Scope scope;
- DefinedAtom::Merge merge;
- AtomizeModel atomizeModel;
- sectionParseInfo(atomType, sizeMultiple, scope, merge, atomizeModel);
- // Validate section size.
- if ((section.content.size() % sizeMultiple) != 0)
- return make_dynamic_error_code(Twine("Section ") + section.segmentName
- + "/" + section.sectionName
- + " has size ("
- + Twine(section.content.size())
- + ") which is not a multiple of "
- + Twine(sizeMultiple) );
- if (atomizeModel == atomizeAtSymbols) {
- // Break section up into atoms each with a fixed size.
- return processSymboledSection(atomType, section, normalizedFile, file,
- copyRefs);
- } else {
- const uint32_t *cfi;
- unsigned int size;
- for (unsigned int offset = 0, e = section.content.size(); offset != e;) {
- switch (atomizeModel) {
- case atomizeFixedSize:
- // Break section up into atoms each with a fixed size.
- size = sizeMultiple;
- break;
- case atomizePointerSize:
- // Break section up into atoms each the size of a pointer.
- size = is64 ? 8 : 4;
- break;
- case atomizeUTF8:
- // Break section up into zero terminated c-strings.
- size = 0;
- for (unsigned int i = offset; i < e; ++i) {
- if (section.content[i] == 0) {
- size = i + 1 - offset;
- break;
- }
- }
- break;
- case atomizeUTF16:
- // Break section up into zero terminated UTF16 strings.
- size = 0;
- for (unsigned int i = offset; i < e; i += 2) {
- if ((section.content[i] == 0) && (section.content[i + 1] == 0)) {
- size = i + 2 - offset;
- break;
- }
- }
- break;
- case atomizeCFI:
- // Break section up into dwarf unwind CFIs (FDE or CIE).
- cfi = reinterpret_cast<const uint32_t *>(§ion.content[offset]);
- size = read32(swap, *cfi) + 4;
- if (offset+size > section.content.size()) {
- return make_dynamic_error_code(Twine(Twine("Section ")
- + section.segmentName
- + "/" + section.sectionName
- + " is malformed. Size of CFI "
- "starting at offset ("
- + Twine(offset)
- + ") is past end of section."));
- }
- break;
- case atomizeCU:
- // Break section up into compact unwind entries.
- size = is64 ? 32 : 20;
- break;
- case atomizeCFString:
- // Break section up into NS/CFString objects.
- size = is64 ? 32 : 16;
- break;
- case atomizeAtSymbols:
- break;
- }
- if (size == 0) {
- return make_dynamic_error_code(Twine("Section ") + section.segmentName
- + "/" + section.sectionName
- + " is malformed. The last atom is "
- "not zero terminated.");
- }
- file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
- false, copyRefs, §ion);
- offset += size;
- }
- }
- return std::error_code();
- }
- // Walks all relocations for a section in a normalized .o file and
- // creates corresponding lld::Reference objects.
- std::error_code convertRelocs(const Section §ion,
- const NormalizedFile &normalizedFile,
- MachOFile &file,
- KindHandler &handler) {
- // Utility function for KindHandler to find atom by its address.
- auto atomByAddr = [&] (uint32_t sectIndex, uint64_t addr,
- const lld::Atom **atom, Reference::Addend *addend)
- -> std::error_code {
- if (sectIndex > normalizedFile.sections.size())
- return make_dynamic_error_code(Twine("out of range section "
- "index (") + Twine(sectIndex) + ")");
- const Section *sect = nullptr;
- if (sectIndex == 0) {
- for (const Section &s : normalizedFile.sections) {
- uint64_t sAddr = s.address;
- if ((sAddr <= addr) && (addr < sAddr+s.content.size())) {
- sect = &s;
- break;
- }
- }
- if (!sect) {
- return make_dynamic_error_code(Twine("address (" + Twine(addr)
- + ") is not in any section"));
- }
- } else {
- sect = &normalizedFile.sections[sectIndex-1];
- }
- uint32_t offsetInTarget;
- uint64_t offsetInSect = addr - sect->address;
- *atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
- *addend = offsetInTarget;
- return std::error_code();
- };
- // Utility function for KindHandler to find atom by its symbol index.
- auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
- -> std::error_code {
- // Find symbol from index.
- const Symbol *sym = nullptr;
- uint32_t numLocal = normalizedFile.localSymbols.size();
- uint32_t numGlobal = normalizedFile.globalSymbols.size();
- uint32_t numUndef = normalizedFile.undefinedSymbols.size();
- if (symbolIndex < numLocal) {
- sym = &normalizedFile.localSymbols[symbolIndex];
- } else if (symbolIndex < numLocal+numGlobal) {
- sym = &normalizedFile.globalSymbols[symbolIndex-numLocal];
- } else if (symbolIndex < numLocal+numGlobal+numUndef) {
- sym = &normalizedFile.undefinedSymbols[symbolIndex-numLocal-numGlobal];
- } else {
- return make_dynamic_error_code(Twine("symbol index (")
- + Twine(symbolIndex) + ") out of range");
- }
- // Find atom from symbol.
- if ((sym->type & N_TYPE) == N_SECT) {
- if (sym->sect > normalizedFile.sections.size())
- return make_dynamic_error_code(Twine("symbol section index (")
- + Twine(sym->sect) + ") out of range ");
- const Section &symSection = normalizedFile.sections[sym->sect-1];
- uint64_t targetOffsetInSect = sym->value - symSection.address;
- MachODefinedAtom *target = file.findAtomCoveringAddress(symSection,
- targetOffsetInSect);
- if (target) {
- *result = target;
- return std::error_code();
- }
- return make_dynamic_error_code(Twine("no atom found for defined symbol"));
- } else if ((sym->type & N_TYPE) == N_UNDF) {
- const lld::Atom *target = file.findUndefAtom(sym->name);
- if (target) {
- *result = target;
- return std::error_code();
- }
- return make_dynamic_error_code(Twine("no undefined atom found for sym"));
- } else {
- // Search undefs
- return make_dynamic_error_code(Twine("no atom found for symbol"));
- }
- };
- const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch);
- // Use old-school iterator so that paired relocations can be grouped.
- for (auto it=section.relocations.begin(), e=section.relocations.end();
- it != e; ++it) {
- const Relocation &reloc = *it;
- // Find atom this relocation is in.
- if (reloc.offset > section.content.size())
- return make_dynamic_error_code(Twine("r_address (") + Twine(reloc.offset)
- + ") is larger than section size ("
- + Twine(section.content.size()) + ")");
- uint32_t offsetInAtom;
- MachODefinedAtom *inAtom = file.findAtomCoveringAddress(section,
- reloc.offset,
- &offsetInAtom);
- assert(inAtom && "r_address in range, should have found atom");
- uint64_t fixupAddress = section.address + reloc.offset;
- const lld::Atom *target = nullptr;
- Reference::Addend addend = 0;
- Reference::KindValue kind;
- std::error_code relocErr;
- if (handler.isPairedReloc(reloc)) {
- // Handle paired relocations together.
- relocErr = handler.getPairReferenceInfo(reloc, *++it, inAtom,
- offsetInAtom, fixupAddress, swap,
- atomByAddr, atomBySymbol, &kind,
- &target, &addend);
- }
- else {
- // Use KindHandler to convert relocation record into information
- // needed to instantiate an lld::Reference object.
- relocErr = handler.getReferenceInfo(reloc, inAtom, offsetInAtom,
- fixupAddress,swap, atomByAddr,
- atomBySymbol, &kind, &target, &addend);
- }
- if (relocErr) {
- return make_dynamic_error_code(
- Twine("bad relocation (") + relocErr.message()
- + ") in section "
- + section.segmentName + "/" + section.sectionName
- + " (r_address=" + Twine::utohexstr(reloc.offset)
- + ", r_type=" + Twine(reloc.type)
- + ", r_extern=" + Twine(reloc.isExtern)
- + ", r_length=" + Twine((int)reloc.length)
- + ", r_pcrel=" + Twine(reloc.pcRel)
- + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
- : (Twine(", r_scattered=1, r_value=")
- + Twine(reloc.value)))
- + ")" );
- } else {
- // Instantiate an lld::Reference object and add to its atom.
- Reference::KindArch arch = Reference::KindArch::all;
- switch (normalizedFile.arch ) {
- case lld::MachOLinkingContext::arch_x86_64:
- arch = Reference::KindArch::x86_64;
- break;
- case lld::MachOLinkingContext::arch_x86:
- arch = Reference::KindArch::x86;
- break;
- case lld::MachOLinkingContext::arch_ppc:
- arch = Reference::KindArch::PowerPC;
- break;
- case lld::MachOLinkingContext::arch_armv6:
- case lld::MachOLinkingContext::arch_armv7:
- case lld::MachOLinkingContext::arch_armv7s:
- arch = Reference::KindArch::ARM;
- break;
- case lld::MachOLinkingContext::arch_unknown:
- return make_dynamic_error_code(Twine("unknown architecture"));
- }
-
- inAtom->addReference(offsetInAtom, kind, target, addend, arch);
- }
- }
- return std::error_code();
- }
- bool isDebugInfoSection(const Section §ion) {
- if ((section.attributes & S_ATTR_DEBUG) == 0)
- return false;
- return section.segmentName.equals("__DWARF");
- }
- /// Converts normalized mach-o file into an lld::File and lld::Atoms.
- ErrorOr<std::unique_ptr<lld::File>>
- normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs) {
- std::unique_ptr<MachOFile> file(new MachOFile(path));
- // Create atoms from each section.
- for (auto § : normalizedFile.sections) {
- if (isDebugInfoSection(sect))
- continue;
- DefinedAtom::ContentType atomType = atomTypeFromSection(sect);
- if (std::error_code ec =
- processSection(atomType, sect, normalizedFile, *file, copyRefs))
- return ec;
- }
- // Create atoms from undefined symbols.
- for (auto &sym : normalizedFile.undefinedSymbols) {
- // Undefinded symbols with n_value != 0 are actually tentative definitions.
- if (sym.value == Hex64(0)) {
- file->addUndefinedAtom(sym.name, copyRefs);
- } else {
- file->addTentativeDefAtom(sym.name, atomScope(sym.scope), sym.value,
- DefinedAtom::Alignment(sym.desc >> 8), copyRefs);
- }
- }
- // Convert mach-o relocations to References
- std::unique_ptr<mach_o::KindHandler> handler
- = KindHandler::create(normalizedFile.arch);
- for (auto § : normalizedFile.sections) {
- if (isDebugInfoSection(sect))
- continue;
- if (std::error_code ec = convertRelocs(sect, normalizedFile, *file, *handler))
- return ec;
- }
- // Sort references in each atom to their canonical order.
- for (const DefinedAtom* defAtom : file->defined()) {
- reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
- }
- return std::unique_ptr<File>(std::move(file));
- }
- ErrorOr<std::unique_ptr<lld::File>>
- normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs) {
- std::unique_ptr<MachODylibFile> file(
- new MachODylibFile(normalizedFile.installName));
- for (auto &sym : normalizedFile.globalSymbols) {
- assert((sym.scope & N_EXT) && "only expect external symbols here");
- file->addSharedLibraryAtom(sym.name, copyRefs);
- }
- return std::unique_ptr<File>(std::move(file));
- }
- } // anonymous namespace
- namespace normalized {
- void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
- StringRef &segmentName,
- StringRef §ionName,
- SectionType §ionType,
- SectionAttr §ionAttrs) {
- for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
- p->atomType != DefinedAtom::typeUnknown; ++p) {
- if (p->atomType != atomType)
- continue;
- // Wild carded entries are ignored for reverse lookups.
- if (p->segmentName.empty() || p->sectionName.empty())
- continue;
- segmentName = p->segmentName;
- sectionName = p->sectionName;
- sectionType = p->sectionType;
- sectionAttrs = 0;
- if (atomType == DefinedAtom::typeCode)
- sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
- return;
- }
- llvm_unreachable("content type not yet supported");
- }
- ErrorOr<std::unique_ptr<lld::File>>
- normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs) {
- switch (normalizedFile.fileType) {
- case MH_DYLIB:
- return normalizedDylibToAtoms(normalizedFile, path, copyRefs);
- case MH_OBJECT:
- return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
- default:
- llvm_unreachable("unhandled MachO file type!");
- }
- }
- } // namespace normalized
- } // namespace mach_o
- } // namespace lld
|