diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h index 7733b2a95463..d6e0cf1658f7 100644 --- a/lld/lib/ReaderWriter/MachO/Atoms.h +++ b/lld/lib/ReaderWriter/MachO/Atoms.h @@ -18,8 +18,8 @@ class MachODefinedAtom : public SimpleDefinedAtom { public: // FIXME: This constructor should also take the ContentType. MachODefinedAtom(const File &f, const StringRef name, - const ArrayRef content) - : SimpleDefinedAtom(f), _name(name), _content(content) {} + const ArrayRef content, Scope scope) + : SimpleDefinedAtom(f), _name(name), _content(content), _scope(scope) {} virtual uint64_t size() const { return rawContent().size(); } @@ -27,13 +27,14 @@ public: virtual StringRef name() const { return _name; } - virtual Scope scope() const { return scopeGlobal; } + virtual Scope scope() const { return _scope; } virtual ArrayRef rawContent() const { return _content; } private: const StringRef _name; const ArrayRef _content; + const Scope _scope; }; } // mach_o } // lld diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index dad5462c098e..697c2e4d1447 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -21,8 +21,9 @@ class MachOFile : public SimpleFile { public: MachOFile(StringRef path) : SimpleFile(path) {} - void addDefinedAtom(StringRef name, ArrayRef content, bool cpyRefs) { - if (cpyRefs) { + void addDefinedAtom(StringRef name, ArrayRef content, + Atom::Scope scope, bool copyRefs) { + if (copyRefs) { // Make a copy of the atom's name and content that is owned by this file. char *s = _allocator.Allocate(name.size()); memcpy(s, name.data(), name.size()); @@ -32,7 +33,7 @@ public: content = llvm::makeArrayRef(bytes, content.size()); } MachODefinedAtom *atom = - new (_allocator) MachODefinedAtom(*this, name, content); + new (_allocator) MachODefinedAtom(*this, name, content, scope); addAtom(*atom); } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index b53d0de55e6f..b91e3a812992 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -50,9 +50,30 @@ static uint64_t nextSymbolAddress(const NormalizedFile &normalizedFile, if (sValue < closestAddr) closestAddr = s.value; } + for (const Symbol &s : normalizedFile.localSymbols) { + if (s.sect != symbolSectionIndex) + continue; + uint64_t sValue = s.value; + if (sValue <= symbolAddr) + continue; + if (sValue < closestAddr) + closestAddr = s.value; + } return closestAddr; } +static Atom::Scope atomScope(uint8_t scope) { + switch (scope) { + case N_EXT: + return Atom::scopeGlobal; + case N_PEXT | N_EXT: + return Atom::scopeLinkageUnit; + case 0: + return Atom::scopeTranslationUnit; + } + llvm_unreachable("unknown scope value!"); +} + static void processSymbol(const NormalizedFile &normalizedFile, MachOFile &file, const Symbol &sym, bool copyRefs) { // Mach-O symbol table does have size in it, so need to scan ahead @@ -61,7 +82,7 @@ static void processSymbol(const NormalizedFile &normalizedFile, MachOFile &file, uint64_t offset = sym.value - section.address; uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value; ArrayRef atomContent = section.content.slice(offset, size); - file.addDefinedAtom(sym.name, atomContent, copyRefs); + file.addDefinedAtom(sym.name, atomContent, atomScope(sym.scope), copyRefs); } static ErrorOr> @@ -73,8 +94,10 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, processSymbol(normalizedFile, *file, sym, copyRefs); } - assert(normalizedFile.localSymbols.empty() && - "local symbols not supported yet!"); + for (const Symbol &sym : normalizedFile.localSymbols) { + processSymbol(normalizedFile, *file, sym, copyRefs); + } + assert(normalizedFile.undefinedSymbols.empty() && "undefined symbols not supported yet!"); diff --git a/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp b/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp index 2a46e36e8c0a..66642deaef2c 100644 --- a/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp +++ b/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp @@ -33,38 +33,56 @@ TEST(ToAtomsTest, basic_obj_x86_64) { NormalizedFile f; f.arch = lld::MachOLinkingContext::arch_x86_64; Section textSection; - static const uint8_t contentBytes[] = { 0x90, 0xC3, 0xC3 }; + static const uint8_t contentBytes[] = { 0x90, 0xC3, 0xC3, 0xC4 }; const unsigned contentSize = sizeof(contentBytes) / sizeof(contentBytes[0]); textSection.content = llvm::makeArrayRef(contentBytes, contentSize); f.sections.push_back(textSection); Symbol fooSymbol; fooSymbol.name = "_foo"; fooSymbol.type = N_SECT; + fooSymbol.scope = N_EXT; fooSymbol.sect = 1; fooSymbol.value = 0; f.globalSymbols.push_back(fooSymbol); Symbol barSymbol; barSymbol.name = "_bar"; barSymbol.type = N_SECT; + barSymbol.scope = N_EXT; barSymbol.sect = 1; barSymbol.value = 2; f.globalSymbols.push_back(barSymbol); + Symbol bazSymbol; + bazSymbol.name = "_baz"; + bazSymbol.type = N_SECT; + bazSymbol.scope = N_EXT | N_PEXT; + bazSymbol.sect = 1; + bazSymbol.value = 3; + f.localSymbols.push_back(bazSymbol); ErrorOr> atom_f = normalizedToAtoms(f, "", false); EXPECT_FALSE(!atom_f); const lld::File &file = **atom_f; - EXPECT_EQ(2U, file.defined().size()); + EXPECT_EQ(3U, file.defined().size()); lld::File::defined_iterator it = file.defined().begin(); const lld::DefinedAtom *atom1 = *it; ++it; const lld::DefinedAtom *atom2 = *it; + ++it; + const lld::DefinedAtom *atom3 = *it; EXPECT_TRUE(atom1->name().equals("_foo")); EXPECT_EQ(2U, atom1->rawContent().size()); EXPECT_EQ(0x90, atom1->rawContent()[0]); EXPECT_EQ(0xC3, atom1->rawContent()[1]); + EXPECT_EQ(lld::Atom::scopeGlobal, atom1->scope()); EXPECT_TRUE(atom2->name().equals("_bar")); EXPECT_EQ(1U, atom2->rawContent().size()); EXPECT_EQ(0xC3, atom2->rawContent()[0]); + EXPECT_EQ(lld::Atom::scopeGlobal, atom2->scope()); + + EXPECT_TRUE(atom3->name().equals("_baz")); + EXPECT_EQ(1U, atom3->rawContent().size()); + EXPECT_EQ(0xC4, atom3->rawContent()[0]); + EXPECT_EQ(lld::Atom::scopeLinkageUnit, atom3->scope()); }