From 9133f8c76d27c350bfc625319558f2f9cd2f8c03 Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Tue, 21 Oct 2014 23:45:37 +0000 Subject: [mach-o] Support missing MH_SUBSECTIONS_VIA_SYMBOLS All compiler generated mach-o object files are marked with MH_SUBSECTIONS_VIA_SYMBOLS. But hand written assembly files need to opt-in if they are written correctly. The flag means the linker can break up a sections at symbol addresses and dead strip or re-order functions. This change recognizes object files without the flag and marks its atoms as not dead strippable and adds a layout-after chain of references so that the atoms cannot be re-ordered. llvm-svn: 220348 --- .../MachO/MachONormalizedFileToAtoms.cpp | 51 ++++++++++++++++------ 1 file changed, 37 insertions(+), 14 deletions(-) (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp') diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 3875c6263b1..ba8a08b862d 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -220,12 +220,12 @@ void appendSymbolsInSection(const std::vector &inSymbols, 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) { + uint64_t nextSymbolAddr, bool scatterable, 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; - bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP); + bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || !scatterable; if (section.type == llvm::MachO::S_ZEROFILL) { file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size, noDeadStrip, copyRefs, §ion); @@ -256,7 +256,8 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion, std::error_code processSymboledSection(DefinedAtom::ContentType atomType, const Section §ion, const NormalizedFile &normalizedFile, - MachOFile &file, bool copyRefs) { + MachOFile &file, bool scatterable, + bool copyRefs) { // Find section's index. uint32_t sectIndex = 1; for (auto § : normalizedFile.sections) { @@ -309,13 +310,14 @@ std::error_code processSymboledSection(DefinedAtom::ContentType atomType, // 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); + section.address + section.content.size(), + scatterable, 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); + scatterable, copyRefs); } const Symbol *lastSym = nullptr; @@ -328,7 +330,7 @@ std::error_code processSymboledSection(DefinedAtom::ContentType atomType, || !lastSym->name.startswith("ltmp")) { atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name, lastSym->desc, atomScope(lastSym->scope), sym->value, - copyRefs); + scatterable, copyRefs); } } lastSym = sym; @@ -336,8 +338,23 @@ std::error_code processSymboledSection(DefinedAtom::ContentType atomType, if (lastSym != nullptr) { atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name, lastSym->desc, atomScope(lastSym->scope), - section.address + section.content.size(), copyRefs); + section.address + section.content.size(), + scatterable, copyRefs); } + + // If object built without .subsections_via_symbols, add reference chain. + if (!scatterable) { + MachODefinedAtom *prevAtom = nullptr; + file.eachAtomInSection(section, + [&](MachODefinedAtom *atom, uint64_t offset)->void { + if (prevAtom) + prevAtom->addReference(0, Reference::kindLayoutAfter, atom, 0, + Reference::KindArch::all, + Reference::KindNamespace::all); + prevAtom = atom; + }); + } + return std::error_code(); } @@ -345,7 +362,8 @@ std::error_code processSection(DefinedAtom::ContentType atomType, const Section §ion, bool customSectionName, const NormalizedFile &normalizedFile, - MachOFile &file, bool copyRefs) { + MachOFile &file, bool scatterable, + bool copyRefs) { const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch); const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch); @@ -368,7 +386,7 @@ std::error_code processSection(DefinedAtom::ContentType atomType, if (atomizeModel == atomizeAtSymbols) { // Break section up into atoms each with a fixed size. return processSymboledSection(atomType, section, normalizedFile, file, - copyRefs); + scatterable, copyRefs); } else { const uint32_t *cfi; unsigned int size; @@ -483,6 +501,7 @@ findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file, // creates corresponding lld::Reference objects. std::error_code convertRelocs(const Section §ion, const NormalizedFile &normalizedFile, + bool scatterable, MachOFile &file, ArchHandler &handler) { // Utility function for ArchHandler to find atom by its address. @@ -577,9 +596,10 @@ std::error_code convertRelocs(const Section §ion, if (handler.isPairedReloc(reloc)) { // Handle paired relocations together. relocErr = handler.getPairReferenceInfo(reloc, *++it, inAtom, - offsetInAtom, fixupAddress, swap, - atomByAddr, atomBySymbol, &kind, - &target, &addend); + offsetInAtom, fixupAddress, swap, + scatterable, atomByAddr, + atomBySymbol, &kind, + &target, &addend); } else { // Use ArchHandler to convert relocation record into information @@ -697,6 +717,8 @@ ErrorOr> normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, bool copyRefs) { std::unique_ptr file(new MachOFile(path)); + bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0); + // Create atoms from each section. for (auto § : normalizedFile.sections) { if (isDebugInfoSection(sect)) @@ -706,7 +728,7 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, customSectionName); if (std::error_code ec = processSection(atomType, sect, customSectionName, normalizedFile, - *file, copyRefs)) + *file, scatterable, copyRefs)) return ec; } // Create atoms from undefined symbols. @@ -726,7 +748,8 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, for (auto § : normalizedFile.sections) { if (isDebugInfoSection(sect)) continue; - if (std::error_code ec = convertRelocs(sect, normalizedFile, *file, *handler)) + if (std::error_code ec = convertRelocs(sect, normalizedFile, scatterable, + *file, *handler)) return ec; } -- cgit v1.2.3