[lld] r209704 - [mach-o] Support parsing of non-lazy-pointer sections
Nick Kledzik
kledzik at apple.com
Tue May 27 18:16:36 PDT 2014
Author: kledzik
Date: Tue May 27 20:16:35 2014
New Revision: 209704
URL: http://llvm.org/viewvc/llvm-project?rev=209704&view=rev
Log:
[mach-o] Support parsing of non-lazy-pointer sections
Added:
lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml
Modified:
lld/trunk/lib/Core/SymbolTable.cpp
lld/trunk/lib/ReaderWriter/MachO/Atoms.h
lld/trunk/lib/ReaderWriter/MachO/File.h
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Tue May 27 20:16:35 2014
@@ -49,7 +49,10 @@ bool SymbolTable::add(const DefinedAtom
if (atom.merge() == DefinedAtom::mergeByContent) {
// Named atoms cannot be merged by content.
assert(atom.name().empty());
- return addByContent(atom);
+ // Currently only read-only constants can be merged.
+ if (atom.permissions() == DefinedAtom::permR__)
+ return addByContent(atom);
+ // TODO: support mergeByContent of data atoms by comparing content & fixups.
}
return false;
}
@@ -338,8 +341,6 @@ bool SymbolTable::AtomMappingInfo::isEqu
}
bool SymbolTable::addByContent(const DefinedAtom &newAtom) {
- // Currently only read-only constants can be merged.
- assert(newAtom.permissions() == DefinedAtom::permR__);
AtomContentSet::iterator pos = _contentTable.find(&newAtom);
if (pos == _contentTable.end()) {
_contentTable.insert(&newAtom);
Modified: lld/trunk/lib/ReaderWriter/MachO/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/Atoms.h?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/Atoms.h Tue May 27 20:16:35 2014
@@ -17,16 +17,18 @@ namespace mach_o {
class MachODefinedAtom : public SimpleDefinedAtom {
public:
MachODefinedAtom(const File &f, const StringRef name, Scope scope,
- ContentType type, const ArrayRef<uint8_t> content)
+ ContentType type, Merge merge,
+ const ArrayRef<uint8_t> content)
: SimpleDefinedAtom(f), _name(name), _content(content),
- _contentType(type), _scope(scope) {}
+ _contentType(type), _scope(scope), _merge(merge) {}
// Constructor for zero-fill content
MachODefinedAtom(const File &f, const StringRef name, Scope scope,
uint64_t size)
: SimpleDefinedAtom(f), _name(name),
_content(ArrayRef<uint8_t>(nullptr, size)),
- _contentType(DefinedAtom::typeZeroFill), _scope(scope) {}
+ _contentType(DefinedAtom::typeZeroFill),
+ _scope(scope), _merge(mergeNo) {}
uint64_t size() const override { return _content.size(); }
@@ -36,6 +38,8 @@ public:
Scope scope() const override { return _scope; }
+ Merge merge() const override { return _merge; }
+
DeadStripKind deadStrip() const override {
if (_contentType == DefinedAtom::typeInitializerPtr)
return deadStripNever;
@@ -55,6 +59,7 @@ private:
const ArrayRef<uint8_t> _content;
const ContentType _contentType;
const Scope _scope;
+ const Merge _merge;
};
Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Tue May 27 20:16:35 2014
@@ -22,7 +22,7 @@ public:
MachOFile(StringRef path) : SimpleFile(path) {}
void addDefinedAtom(StringRef name, Atom::Scope scope,
- DefinedAtom::ContentType type,
+ DefinedAtom::ContentType type, DefinedAtom::Merge merge,
ArrayRef<uint8_t> content, bool copyRefs) {
if (copyRefs) {
// Make a copy of the atom's name and content that is owned by this file.
@@ -30,7 +30,8 @@ public:
content = content.copy(_allocator);
}
MachODefinedAtom *atom =
- new (_allocator) MachODefinedAtom(*this, name, scope, type, content);
+ new (_allocator) MachODefinedAtom(*this, name, scope, type, merge,
+ content);
addAtom(*atom);
}
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp Tue May 27 20:16:35 2014
@@ -91,6 +91,24 @@ appendRelocations(Relocations &relocs, S
return error_code::success();
}
+static error_code
+appendIndirectSymbols(IndirectSymbols &isyms, StringRef buffer, bool swap,
+ bool bigEndian, uint32_t istOffset, uint32_t istCount,
+ uint32_t startIndex, uint32_t count) {
+ if ((istOffset + istCount*4) > buffer.size())
+ return llvm::make_error_code(llvm::errc::executable_format_error);
+ if (startIndex+count > istCount)
+ return llvm::make_error_code(llvm::errc::executable_format_error);
+ const uint32_t *indirectSymbolArray =
+ reinterpret_cast<const uint32_t*>(buffer.begin()+istOffset);
+
+ for(uint32_t i=0; i < count; ++i) {
+ isyms.push_back(read32(swap, indirectSymbolArray[startIndex+i]));
+ }
+ return error_code::success();
+}
+
+
template <typename T> static T readBigEndian(T t) {
if (llvm::sys::IsLittleEndianHost)
return SwapByteOrder(t);
@@ -185,9 +203,25 @@ readBinary(std::unique_ptr<MemoryBuffer>
f->flags = smh->flags;
- // Walk load commands looking for segments/sections and the symbol table.
+ // Pre-scan load commands looking for indirect symbol table.
+ uint32_t indirectSymbolTableOffset = 0;
+ uint32_t indirectSymbolTableCount = 0;
error_code ec = forEachLoadCommand(lcRange, lcCount, swap, is64,
[&] (uint32_t cmd, uint32_t size, const char* lc) -> bool {
+ if (cmd == LC_DYSYMTAB) {
+ const dysymtab_command *d = reinterpret_cast<const dysymtab_command*>(lc);
+ indirectSymbolTableOffset = read32(swap, d->indirectsymoff);
+ indirectSymbolTableCount = read32(swap, d->nindirectsyms);
+ return true;
+ }
+ return false;
+ });
+ if (ec)
+ return ec;
+
+ // Walk load commands looking for segments/sections and the symbol table.
+ ec = forEachLoadCommand(lcRange, lcCount, swap, is64,
+ [&] (uint32_t cmd, uint32_t size, const char* lc) -> bool {
if (is64) {
if (cmd == LC_SEGMENT_64) {
const segment_command_64 *seg =
@@ -220,6 +254,13 @@ readBinary(std::unique_ptr<MemoryBuffer>
appendRelocations(section.relocations, mb->getBuffer(),
swap, isBigEndianArch, read32(swap, sect->reloff),
read32(swap, sect->nreloc));
+ if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
+ appendIndirectSymbols(section.indirectSymbols, mb->getBuffer(),
+ swap, isBigEndianArch,
+ indirectSymbolTableOffset,
+ indirectSymbolTableCount,
+ read32(swap, sect->reserved1), contentSize/4);
+ }
f->sections.push_back(section);
}
}
@@ -255,6 +296,13 @@ readBinary(std::unique_ptr<MemoryBuffer>
appendRelocations(section.relocations, mb->getBuffer(),
swap, isBigEndianArch, read32(swap, sect->reloff),
read32(swap, sect->nreloc));
+ if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
+ appendIndirectSymbols(section.indirectSymbols, mb->getBuffer(),
+ swap, isBigEndianArch,
+ indirectSymbolTableOffset,
+ indirectSymbolTableCount,
+ read32(swap, sect->reserved1), contentSize/4);
+ }
f->sections.push_back(section);
}
}
@@ -328,10 +376,7 @@ readBinary(std::unique_ptr<MemoryBuffer>
f->localSymbols.push_back(sout);
}
}
- } else if (cmd == LC_DYSYMTAB) {
- // TODO: indirect symbols
}
-
return false;
});
if (ec)
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Tue May 27 20:16:35 2014
@@ -92,7 +92,8 @@ static void processSymbol(const Normaliz
} else {
ArrayRef<uint8_t> atomContent = section.content.slice(offset, size);
file.addDefinedAtom(sym.name, atomScope(sym.scope),
- atomTypeFromSection(section), atomContent, copyRefs);
+ atomTypeFromSection(section), DefinedAtom::mergeNo,
+ atomContent, copyRefs);
}
}
@@ -125,7 +126,8 @@ static error_code processSection(MachOFi
unsigned size = i - offset + 2;
ArrayRef<uint8_t> utf16Content = section.content.slice(offset, size);
file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeUTF16String, utf16Content,
+ DefinedAtom::typeUTF16String,
+ DefinedAtom::mergeByContent, utf16Content,
copyRefs);
offset = i + 2;
}
@@ -139,9 +141,10 @@ static error_code processSection(MachOFi
"terminated.");
}
}
+ break;
case llvm::MachO::S_COALESCED:
case llvm::MachO::S_ZEROFILL:
- // These sections are broken in to atoms based on symbols.
+ // These sections are broken into atoms based on symbols.
break;
case S_MOD_INIT_FUNC_POINTERS:
if ((section.content.size() % pointerSize) != 0) {
@@ -156,7 +159,8 @@ static error_code processSection(MachOFi
for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
file.addDefinedAtom(StringRef(), DefinedAtom::scopeTranslationUnit,
- DefinedAtom::typeInitializerPtr, bytes, copyRefs);
+ DefinedAtom::typeInitializerPtr, DefinedAtom::mergeNo,
+ bytes, copyRefs);
offset += pointerSize;
}
break;
@@ -173,7 +177,26 @@ static error_code processSection(MachOFi
for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
file.addDefinedAtom(StringRef(), DefinedAtom::scopeTranslationUnit,
- DefinedAtom::typeTerminatorPtr, bytes, copyRefs);
+ DefinedAtom::typeTerminatorPtr, DefinedAtom::mergeNo,
+ bytes, copyRefs);
+ offset += pointerSize;
+ }
+ break;
+ case S_NON_LAZY_SYMBOL_POINTERS:
+ if ((section.content.size() % pointerSize) != 0) {
+ return make_dynamic_error_code(Twine("Section ") + section.segmentName
+ + "/" + section.sectionName
+ + " has type S_NON_LAZY_SYMBOL_POINTERS "
+ "but its size ("
+ + Twine(section.content.size())
+ + ") is not a multiple of "
+ + Twine(pointerSize));
+ }
+ for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
+ ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
+ file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
+ DefinedAtom::typeGOT, DefinedAtom::mergeByContent,
+ bytes, copyRefs);
offset += pointerSize;
}
break;
@@ -183,7 +206,8 @@ static error_code processSection(MachOFi
unsigned size = i - offset + 1;
ArrayRef<uint8_t> strContent = section.content.slice(offset, size);
file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeCString, strContent, copyRefs);
+ DefinedAtom::typeCString,
+ DefinedAtom::mergeByContent, strContent, copyRefs);
offset = i + 1;
}
}
@@ -205,7 +229,8 @@ static error_code processSection(MachOFi
for (size_t i = 0, e = section.content.size(); i != e; i += 4) {
ArrayRef<uint8_t> byteContent = section.content.slice(offset, 4);
file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeLiteral4, byteContent, copyRefs);
+ DefinedAtom::typeLiteral4,
+ DefinedAtom::mergeByContent, byteContent, copyRefs);
offset += 4;
}
break;
@@ -219,7 +244,8 @@ static error_code processSection(MachOFi
for (size_t i = 0, e = section.content.size(); i != e; i += 8) {
ArrayRef<uint8_t> byteContent = section.content.slice(offset, 8);
file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeLiteral8, byteContent, copyRefs);
+ DefinedAtom::typeLiteral8,
+ DefinedAtom::mergeByContent, byteContent, copyRefs);
offset += 8;
}
break;
@@ -233,7 +259,8 @@ static error_code processSection(MachOFi
for (size_t i = 0, e = section.content.size(); i != e; i += 16) {
ArrayRef<uint8_t> byteContent = section.content.slice(offset, 16);
file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeLiteral16, byteContent, copyRefs);
+ DefinedAtom::typeLiteral16,
+ DefinedAtom::mergeByContent, byteContent, copyRefs);
offset += 16;
}
break;
@@ -248,7 +275,7 @@ static 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 global symbols.
for (const Symbol &sym : normalizedFile.globalSymbols) {
processSymbol(normalizedFile, *file, sym, copyRefs);
Added: lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml?rev=209704&view=auto
==============================================================================
--- lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml (added)
+++ lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml Tue May 27 20:16:35 2014
@@ -0,0 +1,89 @@
+# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t | FileCheck %s
+#
+# Test parsing of non-lazy-pointer sections.
+#
+
+--- !mach-o
+arch: x86
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00, 0x00,
+ 0x59, 0x8D, 0x81, 0x14, 0x00, 0x00, 0x00, 0x8D,
+ 0x81, 0x18, 0x00, 0x00, 0x00, 0x5D, 0xC3, 0x55,
+ 0x89, 0xE5, 0x5D, 0xC3 ]
+ relocations:
+ - offset: 0x00000011
+ scattered: true
+ type: GENERIC_RELOC_LOCAL_SECTDIFF
+ length: 2
+ pc-rel: false
+ value: 0x00000020
+ - offset: 0x00000000
+ scattered: true
+ type: GENERIC_RELOC_PAIR
+ length: 2
+ pc-rel: false
+ value: 0x00000008
+ - offset: 0x0000000B
+ scattered: true
+ type: GENERIC_RELOC_LOCAL_SECTDIFF
+ length: 2
+ pc-rel: false
+ value: 0x0000001C
+ - offset: 0x00000000
+ scattered: true
+ type: GENERIC_RELOC_PAIR
+ length: 2
+ pc-rel: false
+ value: 0x00000008
+ - segment: __IMPORT
+ section: __pointers
+ type: S_NON_LAZY_SYMBOL_POINTERS
+ attributes: [ ]
+ address: 0x000000000000001C
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ indirect-syms: [ 2, 2147483648 ]
+local-symbols:
+ - name: _foo
+ type: N_SECT
+ sect: 1
+ value: 0x0000000000000017
+global-symbols:
+ - name: _get
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+undefined-symbols:
+ - name: _bar
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+...
+
+
+# CHECK:defined-atoms:
+# CHECK: - scope: hidden
+# CHECK: type: got
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: merge: by-content
+# CHECK: - scope: hidden
+# CHECK: type: got
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: merge: by-content
+# CHECK: - name: _get
+# CHECK: scope: global
+# CHECK: content: [ 55, 89, E5, E8, 00, 00, 00, 00, 59, 8D, 81, 14,
+# CHECK: 00, 00, 00, 8D, 81, 18, 00, 00, 00, 5D, C3 ]
+# CHECK: - name: _foo
+# CHECK: content: [ 55, 89, E5, 5D, C3 ]
+
+
More information about the llvm-commits
mailing list