aboutsummaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/MachO
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/MachO')
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm.cpp20
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm64.cpp34
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86.cpp4
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp21
-rw-r--r--lib/ReaderWriter/MachO/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/MachO/CompactUnwindPass.cpp4
-rw-r--r--lib/ReaderWriter/MachO/DebugInfo.h106
-rw-r--r--lib/ReaderWriter/MachO/File.h18
-rw-r--r--lib/ReaderWriter/MachO/GOTPass.cpp2
-rw-r--r--lib/ReaderWriter/MachO/LayoutPass.cpp2
-rw-r--r--lib/ReaderWriter/MachO/MachOLinkingContext.cpp63
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFile.h3
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp14
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h9
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp163
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp220
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp372
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp2
-rw-r--r--lib/ReaderWriter/MachO/ObjCPass.cpp2
-rw-r--r--lib/ReaderWriter/MachO/ShimPass.cpp4
-rw-r--r--lib/ReaderWriter/MachO/StubsPass.cpp6
-rw-r--r--lib/ReaderWriter/MachO/TLVPass.cpp2
22 files changed, 855 insertions, 218 deletions
diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index 3286fe064535..7d1544854cf1 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -540,7 +540,7 @@ llvm::Error ArchHandler_arm::getReferenceInfo(
// Instruction contains branch to addend.
displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
*addend = fixupAddress + 4 + displacement;
- return llvm::Error();
+ return llvm::Error::success();
case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
// ex: bl _foo (and _foo is defined)
if ((instruction & 0xD000F800) == 0x9000F000)
@@ -563,7 +563,7 @@ llvm::Error ArchHandler_arm::getReferenceInfo(
// reloc.value is target atom's address. Instruction contains branch
// to atom+addend.
*addend += (targetAddress - reloc.value);
- return llvm::Error();
+ return llvm::Error::success();
case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
// ex: bl _foo (and _foo is undefined)
if (((instruction & 0x0F000000) == 0x0A000000)
@@ -576,7 +576,7 @@ llvm::Error ArchHandler_arm::getReferenceInfo(
// Instruction contains branch to addend.
displacement = getDisplacementFromArmBranch(instruction);
*addend = fixupAddress + 8 + displacement;
- return llvm::Error();
+ return llvm::Error::success();
case ARM_RELOC_BR24 | rPcRel | rLength4:
// ex: bl _foo (and _foo is defined)
if (((instruction & 0x0F000000) == 0x0A000000)
@@ -601,32 +601,32 @@ llvm::Error ArchHandler_arm::getReferenceInfo(
// reloc.value is target atom's address. Instruction contains branch
// to atom+addend.
*addend += (targetAddress - reloc.value);
- return llvm::Error();
+ return llvm::Error::success();
case ARM_RELOC_VANILLA | rExtern | rLength4:
// ex: .long _foo (and _foo is undefined)
*kind = pointer32;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = instruction;
- return llvm::Error();
+ return llvm::Error::success();
case ARM_RELOC_VANILLA | rLength4:
// ex: .long _foo (and _foo is defined)
*kind = pointer32;
if (auto ec = atomFromAddress(reloc.symbol, instruction, target, addend))
return ec;
*addend = clearThumbBit((uint32_t) * addend, *target);
- return llvm::Error();
+ return llvm::Error::success();
case ARM_RELOC_VANILLA | rScattered | rLength4:
// ex: .long _foo+a (and _foo is defined)
*kind = pointer32;
if (auto ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
*addend += (clearThumbBit(instruction, *target) - reloc.value);
- return llvm::Error();
+ return llvm::Error::success();
default:
return llvm::make_error<GenericError>("unsupported arm relocation type");
}
- return llvm::Error();
+ return llvm::Error::success();
}
llvm::Error
@@ -847,7 +847,7 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
value = clearThumbBit(value, *target);
int64_t ta = (int64_t) value - (toAddress - fromAddress);
*addend = ta - offsetInFrom;
- return llvm::Error();
+ return llvm::Error::success();
} else {
uint32_t sectIndex;
if (thumbReloc) {
@@ -895,7 +895,7 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
}
}
- return llvm::Error();
+ return llvm::Error::success();
}
void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *loc,
diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
index a61f6aac05e1..392a1be5b3d0 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
@@ -275,8 +275,8 @@ const ArchHandler::StubInfo ArchHandler_arm64::_sStubInfo = {
// GOT pointer to dyld_stub_binder
{ Reference::KindArch::AArch64, pointer64, 0, 0 },
- // arm64 code alignment 2^2
- 2,
+ // arm64 code alignment 2^1
+ 1,
// Stub size and code
12,
@@ -389,56 +389,56 @@ llvm::Error ArchHandler_arm64::getReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4:
// ex: adrp x1, _foo@PAGE
*kind = page21;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_PAGEOFF12 | rExtern | rLength4:
// ex: ldr x0, [x1, _foo@PAGEOFF]
*kind = offset12KindFromInstruction(*(const little32_t *)fixupContent);
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4:
// ex: adrp x1, _foo@GOTPAGE
*kind = gotPage21;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4:
// ex: ldr x0, [x1, _foo@GOTPAGEOFF]
*kind = gotOffset12;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4:
// ex: adrp x1, _foo@TLVPAGE
*kind = tlvPage21;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4:
// ex: ldr x0, [x1, _foo@TLVPAGEOFF]
*kind = tlvOffset12;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_UNSIGNED | rExtern | rLength8:
// ex: .quad _foo + N
*kind = pointer64;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const little64_t *)fixupContent;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_UNSIGNED | rLength8:
// ex: .quad Lfoo + N
*kind = pointer64;
@@ -450,7 +450,7 @@ llvm::Error ArchHandler_arm64::getReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
case ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4:
// ex: .long _foo@GOT - .
@@ -464,7 +464,7 @@ llvm::Error ArchHandler_arm64::getReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return llvm::Error();
+ return llvm::Error::success();
default:
return llvm::make_error<GenericError>("unsupported arm64 relocation type");
}
@@ -485,7 +485,7 @@ llvm::Error ArchHandler_arm64::getPairReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = reloc1.symbol;
- return llvm::Error();
+ return llvm::Error::success();
case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4):
// ex: adrp x1, _foo@PAGE
@@ -493,7 +493,7 @@ llvm::Error ArchHandler_arm64::getPairReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = reloc1.symbol;
- return llvm::Error();
+ return llvm::Error::success();
case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
ARM64_RELOC_PAGEOFF12 | rExtern | rLength4): {
// ex: ldr w0, [x1, _foo@PAGEOFF]
@@ -502,7 +502,7 @@ llvm::Error ArchHandler_arm64::getPairReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = reloc1.symbol;
- return llvm::Error();
+ return llvm::Error::success();
}
case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
ARM64_RELOC_UNSIGNED | rExtern | rLength8):
@@ -522,7 +522,7 @@ llvm::Error ArchHandler_arm64::getPairReferenceInfo(
return llvm::make_error<GenericError>(
"paired relocs must have the same offset");
*addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
- return llvm::Error();
+ return llvm::Error::success();
case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
ARM64_RELOC_UNSIGNED | rExtern | rLength4):
// ex: .quad _foo - .
@@ -530,7 +530,7 @@ llvm::Error ArchHandler_arm64::getPairReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
- return llvm::Error();
+ return llvm::Error::success();
default:
return llvm::make_error<GenericError>("unsupported arm64 relocation pair");
}
diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
index 15f1f793b5d7..c940ea542ee4 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
@@ -345,7 +345,7 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
default:
return llvm::make_error<GenericError>("unsupported i386 relocation type");
}
- return llvm::Error();
+ return llvm::Error::success();
}
llvm::Error
@@ -403,7 +403,7 @@ ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
*addend = fromAddress + value - toAddress;
}
}
- return llvm::Error();
+ return llvm::Error::success();
break;
default:
return llvm::make_error<GenericError>("unsupported i386 relocation type");
diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
index c36982a77b13..d687ca5de5b4 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
@@ -382,22 +382,22 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const little32_t *)fixupContent;
- return llvm::Error();
+ return llvm::Error::success();
case ripRel32Minus1:
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + 1;
- return llvm::Error();
+ return llvm::Error::success();
case ripRel32Minus2:
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + 2;
- return llvm::Error();
+ return llvm::Error::success();
case ripRel32Minus4:
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + 4;
- return llvm::Error();
+ return llvm::Error::success();
case ripRel32Anon:
targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent;
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
@@ -416,7 +416,7 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const little32_t *)fixupContent;
- return llvm::Error();
+ return llvm::Error::success();
case tlvInitSectionOffset:
case pointer64:
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
@@ -429,7 +429,7 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
assert(*addend == 0 && "TLV-init has non-zero addend?");
} else
*addend = *(const little64_t *)fixupContent;
- return llvm::Error();
+ return llvm::Error::success();
case pointer64Anon:
targetAddress = *(const little64_t *)fixupContent;
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
@@ -463,7 +463,10 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
return ec;
uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent;
if (inAtom == fromTarget) {
- *kind = delta64;
+ if (inAtom->contentType() == DefinedAtom::typeCFI)
+ *kind = unwindFDEToFunction;
+ else
+ *kind = delta64;
*addend = encodedAddend + offsetInAtom;
} else if (inAtom == *target) {
*kind = negDelta64;
@@ -471,7 +474,7 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
*target = fromTarget;
} else
return llvm::make_error<GenericError>("Invalid pointer diff");
- return llvm::Error();
+ return llvm::Error::success();
}
case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
X86_64_RELOC_UNSIGNED | rExtern | rLength4): {
@@ -487,7 +490,7 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
*target = fromTarget;
} else
return llvm::make_error<GenericError>("Invalid pointer diff");
- return llvm::Error();
+ return llvm::Error::success();
}
case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
X86_64_RELOC_UNSIGNED | rLength8):
diff --git a/lib/ReaderWriter/MachO/CMakeLists.txt b/lib/ReaderWriter/MachO/CMakeLists.txt
index 70f451c997b3..6a1064d6dfb5 100644
--- a/lib/ReaderWriter/MachO/CMakeLists.txt
+++ b/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -21,8 +21,10 @@ add_lld_library(lldMachO
LINK_LIBS
lldCore
lldYAML
+ LLVMDebugInfoDWARF
LLVMObject
LLVMSupport
+ LLVMDemangle
${PTHREAD_LIB}
)
diff --git a/lib/ReaderWriter/MachO/CompactUnwindPass.cpp b/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
index 6f5ab83dbda6..49d518456a45 100644
--- a/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
+++ b/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
@@ -298,7 +298,7 @@ private:
// Skip rest of pass if no unwind info.
if (unwindLocs.empty() && dwarfFrames.empty())
- return llvm::Error();
+ return llvm::Error::success();
// FIXME: if there are more than 4 personality functions then we need to
// defer to DWARF info for the ones we don't put in the list. They should
@@ -353,7 +353,7 @@ private:
return atom->contentType() == DefinedAtom::typeCompactUnwindInfo;
});
- return llvm::Error();
+ return llvm::Error::success();
}
void collectCompactUnwindEntries(
diff --git a/lib/ReaderWriter/MachO/DebugInfo.h b/lib/ReaderWriter/MachO/DebugInfo.h
new file mode 100644
index 000000000000..28e41bf4263c
--- /dev/null
+++ b/lib/ReaderWriter/MachO/DebugInfo.h
@@ -0,0 +1,106 @@
+//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_DEBUGINFO_H
+#define LLD_READER_WRITER_MACHO_DEBUGINFO_H
+
+#include "lld/Core/Atom.h"
+#include <vector>
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+
+namespace lld {
+namespace mach_o {
+
+class DebugInfo {
+public:
+ enum class Kind {
+ Dwarf,
+ Stabs
+ };
+
+ Kind kind() const { return _kind; }
+
+ void setAllocator(std::unique_ptr<llvm::BumpPtrAllocator> allocator) {
+ _allocator = std::move(allocator);
+ }
+
+protected:
+ DebugInfo(Kind kind) : _kind(kind) {}
+
+private:
+ std::unique_ptr<llvm::BumpPtrAllocator> _allocator;
+ Kind _kind;
+};
+
+struct TranslationUnitSource {
+ StringRef name;
+ StringRef path;
+};
+
+class DwarfDebugInfo : public DebugInfo {
+public:
+ DwarfDebugInfo(TranslationUnitSource tu)
+ : DebugInfo(Kind::Dwarf), _tu(std::move(tu)) {}
+
+ static inline bool classof(const DebugInfo *di) {
+ return di->kind() == Kind::Dwarf;
+ }
+
+ const TranslationUnitSource &translationUnitSource() const { return _tu; }
+
+private:
+ TranslationUnitSource _tu;
+};
+
+struct Stab {
+ Stab(const Atom* atom, uint8_t type, uint8_t other, uint16_t desc,
+ uint32_t value, StringRef str)
+ : atom(atom), type(type), other(other), desc(desc), value(value),
+ str(str) {}
+
+ const class Atom* atom;
+ uint8_t type;
+ uint8_t other;
+ uint16_t desc;
+ uint32_t value;
+ StringRef str;
+};
+
+inline raw_ostream& operator<<(raw_ostream &os, Stab &s) {
+ os << "Stab -- atom: " << llvm::format("%p", s.atom) << ", type: " << (uint32_t)s.type
+ << ", other: " << (uint32_t)s.other << ", desc: " << s.desc << ", value: " << s.value
+ << ", str: '" << s.str << "'";
+ return os;
+}
+
+class StabsDebugInfo : public DebugInfo {
+public:
+
+ typedef std::vector<Stab> StabsList;
+
+ StabsDebugInfo(StabsList stabs)
+ : DebugInfo(Kind::Stabs), _stabs(std::move(stabs)) {}
+
+ static inline bool classof(const DebugInfo *di) {
+ return di->kind() == Kind::Stabs;
+ }
+
+ const StabsList& stabs() const { return _stabs; }
+
+public:
+ StabsList _stabs;
+};
+
+} // end namespace mach_o
+} // end namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_DEBUGINFO_H
diff --git a/lib/ReaderWriter/MachO/File.h b/lib/ReaderWriter/MachO/File.h
index 64a0fcf82844..2bdd6342b477 100644
--- a/lib/ReaderWriter/MachO/File.h
+++ b/lib/ReaderWriter/MachO/File.h
@@ -11,11 +11,13 @@
#define LLD_READER_WRITER_MACHO_FILE_H
#include "Atoms.h"
+#include "DebugInfo.h"
#include "MachONormalizedFile.h"
#include "lld/Core/SharedLibraryFile.h"
#include "lld/Core/Simple.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Format.h"
#include <unordered_map>
namespace lld {
@@ -25,11 +27,15 @@ using lld::mach_o::normalized::Section;
class MachOFile : public SimpleFile {
public:
+
+ /// Real file constructor - for on-disk files.
MachOFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
: SimpleFile(mb->getBufferIdentifier(), File::kindMachObject),
_mb(std::move(mb)), _ctx(ctx) {}
- MachOFile(StringRef path) : SimpleFile(path, File::kindMachObject) {}
+ /// Dummy file constructor - for virtual files.
+ MachOFile(StringRef path)
+ : SimpleFile(path, File::kindMachObject) {}
void addDefinedAtom(StringRef name, Atom::Scope scope,
DefinedAtom::ContentType type, DefinedAtom::Merge merge,
@@ -225,6 +231,13 @@ public:
return F->kind() == File::kindMachObject;
}
+ void setDebugInfo(std::unique_ptr<DebugInfo> debugInfo) {
+ _debugInfo = std::move(debugInfo);
+ }
+
+ DebugInfo* debugInfo() const { return _debugInfo.get(); }
+ std::unique_ptr<DebugInfo> takeDebugInfo() { return std::move(_debugInfo); }
+
protected:
std::error_code doParse() override {
// Convert binary file to normalized mach-o.
@@ -265,6 +278,7 @@ private:
MachOLinkingContext::objc_unknown;
uint32_t _swiftVersion = 0;
normalized::FileFlags _flags = llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
+ std::unique_ptr<DebugInfo> _debugInfo;
};
class MachODylibFile : public SharedLibraryFile {
@@ -297,7 +311,7 @@ public:
_reExportedDylibs.emplace_back(dylibPath);
}
- StringRef installName() { return _installName; }
+ StringRef installName() const { return _installName; }
uint32_t currentVersion() { return _currentVersion; }
uint32_t compatVersion() { return _compatVersion; }
diff --git a/lib/ReaderWriter/MachO/GOTPass.cpp b/lib/ReaderWriter/MachO/GOTPass.cpp
index 6cdca0a9e055..8458a1c79282 100644
--- a/lib/ReaderWriter/MachO/GOTPass.cpp
+++ b/lib/ReaderWriter/MachO/GOTPass.cpp
@@ -134,7 +134,7 @@ private:
for (const GOTEntryAtom *slot : entries)
mergedFile.addAtom(*slot);
- return llvm::Error();
+ return llvm::Error::success();
}
bool shouldReplaceTargetWithGOTAtom(const Atom *target, bool canBypassGOT) {
diff --git a/lib/ReaderWriter/MachO/LayoutPass.cpp b/lib/ReaderWriter/MachO/LayoutPass.cpp
index dd2ee8567ec9..24dbf79d3e3b 100644
--- a/lib/ReaderWriter/MachO/LayoutPass.cpp
+++ b/lib/ReaderWriter/MachO/LayoutPass.cpp
@@ -474,7 +474,7 @@ llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
});
DEBUG(llvm::dbgs() << "******** Finished laying out atoms\n");
- return llvm::Error();
+ return llvm::Error::success();
}
void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx) {
diff --git a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 05375f145d34..db4a96823e74 100644
--- a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -22,7 +22,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Config/config.h"
+#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Host.h"
@@ -30,10 +30,6 @@
#include "llvm/Support/Path.h"
#include <algorithm>
-#if defined(HAVE_CXXABI_H)
-#include <cxxabi.h>
-#endif
-
using lld::mach_o::ArchHandler;
using lld::mach_o::MachOFile;
using lld::mach_o::MachODylibFile;
@@ -734,7 +730,7 @@ uint32_t MachOLinkingContext::dylibCurrentVersion(StringRef installName) const {
if (pos != _pathToDylibMap.end())
return pos->second->currentVersion();
else
- return 0x1000; // 1.0
+ return 0x10000; // 1.0
}
uint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const {
@@ -742,7 +738,7 @@ uint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const {
if (pos != _pathToDylibMap.end())
return pos->second->compatVersion();
else
- return 0x1000; // 1.0
+ return 0x10000; // 1.0
}
void MachOLinkingContext::createImplicitFiles(
@@ -772,7 +768,10 @@ void MachOLinkingContext::createImplicitFiles(
void MachOLinkingContext::registerDylib(MachODylibFile *dylib,
bool upward) const {
std::lock_guard<std::mutex> lock(_dylibsMutex);
- _allDylibs.insert(dylib);
+
+ if (std::find(_allDylibs.begin(),
+ _allDylibs.end(), dylib) == _allDylibs.end())
+ _allDylibs.push_back(dylib);
_pathToDylibMap[dylib->installName()] = dylib;
// If path is different than install name, register path too.
if (!dylib->path().equals(dylib->installName()))
@@ -873,24 +872,32 @@ std::string MachOLinkingContext::demangle(StringRef symbolName) const {
if (!symbolName.startswith("__Z"))
return symbolName;
-#if defined(HAVE_CXXABI_H)
SmallString<256> symBuff;
StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
// Mach-O has extra leading underscore that needs to be removed.
const char *cstr = nullTermSym.data() + 1;
int status;
- char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
+ char *demangled = llvm::itaniumDemangle(cstr, nullptr, nullptr, &status);
if (demangled) {
std::string result(demangled);
// __cxa_demangle() always uses a malloc'ed buffer to return the result.
free(demangled);
return result;
}
-#endif
return symbolName;
}
+static void addDependencyInfoHelper(llvm::raw_fd_ostream *DepInfo,
+ char Opcode, StringRef Path) {
+ if (!DepInfo)
+ return;
+
+ *DepInfo << Opcode;
+ *DepInfo << Path;
+ *DepInfo << '\0';
+}
+
std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
std::error_code ec;
_dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(new
@@ -900,42 +907,20 @@ std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
return ec;
}
- char linkerVersionOpcode = 0x00;
- *_dependencyInfo << linkerVersionOpcode;
- *_dependencyInfo << "lld"; // FIXME
- *_dependencyInfo << '\0';
-
+ addDependencyInfoHelper(_dependencyInfo.get(), 0x00, "lld" /*FIXME*/);
return std::error_code();
}
void MachOLinkingContext::addInputFileDependency(StringRef path) const {
- if (!_dependencyInfo)
- return;
-
- char inputFileOpcode = 0x10;
- *_dependencyInfo << inputFileOpcode;
- *_dependencyInfo << path;
- *_dependencyInfo << '\0';
+ addDependencyInfoHelper(_dependencyInfo.get(), 0x10, path);
}
void MachOLinkingContext::addInputFileNotFound(StringRef path) const {
- if (!_dependencyInfo)
- return;
-
- char inputFileOpcode = 0x11;
- *_dependencyInfo << inputFileOpcode;
- *_dependencyInfo << path;
- *_dependencyInfo << '\0';
+ addDependencyInfoHelper(_dependencyInfo.get(), 0x11, path);
}
void MachOLinkingContext::addOutputFileDependency(StringRef path) const {
- if (!_dependencyInfo)
- return;
-
- char outputFileOpcode = 0x40;
- *_dependencyInfo << outputFileOpcode;
- *_dependencyInfo << path;
- *_dependencyInfo << '\0';
+ addDependencyInfoHelper(_dependencyInfo.get(), 0x40, path);
}
void MachOLinkingContext::appendOrderedSymbol(StringRef symbol,
@@ -1044,7 +1029,7 @@ void MachOLinkingContext::finalizeInputFiles() {
llvm::Error MachOLinkingContext::handleLoadedFile(File &file) {
auto *machoFile = dyn_cast<MachOFile>(&file);
if (!machoFile)
- return llvm::Error();
+ return llvm::Error::success();
// Check that the arch of the context matches that of the file.
// Also set the arch of the context if it didn't have one.
@@ -1111,7 +1096,7 @@ llvm::Error MachOLinkingContext::handleLoadedFile(File &file) {
return llvm::make_error<GenericError>("different swift versions");
}
- return llvm::Error();
+ return llvm::Error::success();
}
} // end namespace lld
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lib/ReaderWriter/MachO/MachONormalizedFile.h
index 92a21f7ef83d..60d76d4b5c9b 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFile.h
+++ b/lib/ReaderWriter/MachO/MachONormalizedFile.h
@@ -42,6 +42,7 @@
#ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
#define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
+#include "DebugInfo.h"
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
@@ -226,7 +227,6 @@ struct DataInCode {
DataRegionType kind;
};
-
/// A typedef so that YAML I/O can encode/decode mach_header.flags.
LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags)
@@ -242,6 +242,7 @@ struct NormalizedFile {
std::vector<Symbol> localSymbols;
std::vector<Symbol> globalSymbols;
std::vector<Symbol> undefinedSymbols;
+ std::vector<Symbol> stabsSymbols;
// Maps to load commands with no LINKEDIT content (final linked images only).
std::vector<DependentDylib> dependentDylibs;
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
index a17de5be1742..23c7ea17f7e7 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
@@ -70,12 +70,12 @@ static llvm::Error forEachLoadCommand(
return llvm::make_error<GenericError>("Load command exceeds range");
if (func(slc->cmd, slc->cmdsize, p))
- return llvm::Error();
+ return llvm::Error::success();
p += slc->cmdsize;
}
- return llvm::Error();
+ return llvm::Error::success();
}
static std::error_code appendRelocations(Relocations &relocs, StringRef buffer,
@@ -390,12 +390,14 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
if (sin->n_strx > strSize)
return true;
sout.name = &strings[sin->n_strx];
- sout.type = (NListType)(sin->n_type & N_TYPE);
+ sout.type = static_cast<NListType>(sin->n_type & (N_STAB|N_TYPE));
sout.scope = (sin->n_type & (N_PEXT|N_EXT));
sout.sect = sin->n_sect;
sout.desc = sin->n_desc;
sout.value = sin->n_value;
- if (sout.type == N_UNDF)
+ if (sin->n_type & N_STAB)
+ f->stabsSymbols.push_back(sout);
+ else if (sout.type == N_UNDF)
f->undefinedSymbols.push_back(sout);
else if (sin->n_type & N_EXT)
f->globalSymbols.push_back(sout);
@@ -429,6 +431,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
f->undefinedSymbols.push_back(sout);
else if (sout.scope == (SymbolScope)N_EXT)
f->globalSymbols.push_back(sout);
+ else if (sin->n_type & N_STAB)
+ f->stabsSymbols.push_back(sout);
else
f->localSymbols.push_back(sout);
}
@@ -535,7 +539,7 @@ public:
loadFile(std::unique_ptr<MemoryBuffer> mb,
const Registry &registry) const override {
std::unique_ptr<File> ret =
- llvm::make_unique<MachOFile>(std::move(mb), &_ctx);
+ llvm::make_unique<MachOFile>(std::move(mb), &_ctx);
return std::move(ret);
}
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
index 86823efa33c9..d69c5389e9d6 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
@@ -71,22 +71,19 @@ using llvm::sys::getSwappedBytes;
template<typename T>
static inline uint16_t read16(const T *loc, bool isBig) {
- assert((uint64_t)loc % llvm::alignOf<T>() == 0 &&
- "invalid pointer alignment");
+ assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
return isBig ? read16be(loc) : read16le(loc);
}
template<typename T>
static inline uint32_t read32(const T *loc, bool isBig) {
- assert((uint64_t)loc % llvm::alignOf<T>() == 0 &&
- "invalid pointer alignment");
+ assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
return isBig ? read32be(loc) : read32le(loc);
}
template<typename T>
static inline uint64_t read64(const T *loc, bool isBig) {
- assert((uint64_t)loc % llvm::alignOf<T>() == 0 &&
- "invalid pointer alignment");
+ assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
return isBig ? read64be(loc) : read64le(loc);
}
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
index f3e159684e15..e853faf9112e 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
@@ -66,26 +66,9 @@ struct TrieEdge : public llvm::ilist_node<TrieEdge> {
namespace llvm {
- using lld::mach_o::normalized::TrieEdge;
- template <>
- struct ilist_traits<TrieEdge>
- : public ilist_default_traits<TrieEdge> {
- private:
- mutable ilist_half_node<TrieEdge> Sentinel;
- public:
- TrieEdge *createSentinel() const {
- return static_cast<TrieEdge*>(&Sentinel);
- }
- void destroySentinel(TrieEdge *) const {}
-
- TrieEdge *provideInitialHead() const { return createSentinel(); }
- TrieEdge *ensureHead(TrieEdge*) const { return createSentinel(); }
- static void noteHead(TrieEdge*, TrieEdge*) {}
- void deleteNode(TrieEdge *N) {}
-
- private:
- void createNode(const TrieEdge &);
- };
+using lld::mach_o::normalized::TrieEdge;
+template <>
+struct ilist_alloc_traits<TrieEdge> : ilist_noalloc_traits<TrieEdge> {};
} // namespace llvm
@@ -103,6 +86,9 @@ struct TrieNode {
void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
std::vector<TrieNode *> &allNodes);
+
+ void addOrderedNodes(const Export &entry,
+ std::vector<TrieNode *> &allNodes);
bool updateOffset(uint32_t &offset);
void appendToByteBuffer(ByteBuffer &out);
@@ -115,6 +101,7 @@ private:
StringRef _importedName;
uint32_t _trieOffset;
bool _hasExportInfo;
+ bool _ordered = false;
};
/// Utility class for writing a mach-o binary file given an in-memory
@@ -639,7 +626,9 @@ llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
seg->vmsize = _file.sections.back().address
+ _file.sections.back().content.size();
seg->fileoff = _endOfLoadCommands;
- seg->filesize = seg->vmsize;
+ seg->filesize = _sectInfo[&_file.sections.back()].fileOffset +
+ _file.sections.back().content.size() -
+ _sectInfo[&_file.sections.front()].fileOffset;
seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
seg->nsects = _file.sections.size();
@@ -668,7 +657,7 @@ llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
++sout;
}
lc = next;
- return llvm::Error();
+ return llvm::Error::success();
}
template <typename T>
@@ -738,7 +727,7 @@ llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
}
lc = reinterpret_cast<uint8_t*>(next);
}
- return llvm::Error();
+ return llvm::Error::success();
}
static void writeVersionMinLoadCommand(const NormalizedFile &_file,
@@ -789,8 +778,8 @@ llvm::Error MachOFileLayout::writeLoadCommands() {
st->cmd = LC_SYMTAB;
st->cmdsize = sizeof(symtab_command);
st->symoff = _startOfSymbols;
- st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
- + _file.undefinedSymbols.size();
+ st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
+ _file.globalSymbols.size() + _file.undefinedSymbols.size();
st->stroff = _startOfSymbolStrings;
st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
if (_swap)
@@ -876,8 +865,8 @@ llvm::Error MachOFileLayout::writeLoadCommands() {
st->cmd = LC_SYMTAB;
st->cmdsize = sizeof(symtab_command);
st->symoff = _startOfSymbols;
- st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
- + _file.undefinedSymbols.size();
+ st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
+ _file.globalSymbols.size() + _file.undefinedSymbols.size();
st->stroff = _startOfSymbolStrings;
st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
if (_swap)
@@ -890,7 +879,8 @@ llvm::Error MachOFileLayout::writeLoadCommands() {
dst->cmd = LC_DYSYMTAB;
dst->cmdsize = sizeof(dysymtab_command);
dst->ilocalsym = _symbolTableLocalsStartIndex;
- dst->nlocalsym = _file.localSymbols.size();
+ dst->nlocalsym = _file.stabsSymbols.size() +
+ _file.localSymbols.size();
dst->iextdefsym = _symbolTableGlobalsStartIndex;
dst->nextdefsym = _file.globalSymbols.size();
dst->iundefsym = _symbolTableUndefinesStartIndex;
@@ -1017,7 +1007,7 @@ llvm::Error MachOFileLayout::writeLoadCommands() {
lc += sizeof(linkedit_data_command);
}
}
- return llvm::Error();
+ return llvm::Error::success();
}
void MachOFileLayout::writeSectionContent() {
@@ -1101,7 +1091,10 @@ void MachOFileLayout::writeSymbolTable() {
// Write symbol table and symbol strings in parallel.
uint32_t symOffset = _startOfSymbols;
uint32_t strOffset = _startOfSymbolStrings;
- _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
+ // Reserve n_strx offset of zero to mean no name.
+ _buffer[strOffset++] = ' ';
+ _buffer[strOffset++] = '\0';
+ appendSymbols(_file.stabsSymbols, symOffset, strOffset);
appendSymbols(_file.localSymbols, symOffset, strOffset);
appendSymbols(_file.globalSymbols, symOffset, strOffset);
appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
@@ -1182,19 +1175,44 @@ void MachOFileLayout::buildRebaseInfo() {
void MachOFileLayout::buildBindInfo() {
// TODO: compress bind info.
uint64_t lastAddend = 0;
+ int lastOrdinal = 0x80000000;
+ StringRef lastSymbolName;
+ BindType lastType = (BindType)0;
+ Hex32 lastSegOffset = ~0U;
+ uint8_t lastSegIndex = (uint8_t)~0U;
for (const BindLocation& entry : _file.bindingInfo) {
- _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
- _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
- | entry.segIndex);
- _bindingInfo.append_uleb128(entry.segOffset);
- if (entry.ordinal > 0)
- _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
- (entry.ordinal & 0xF));
- else
- _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
- (entry.ordinal & 0xF));
- _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
- _bindingInfo.append_string(entry.symbolName);
+ if (entry.ordinal != lastOrdinal) {
+ if (entry.ordinal <= 0)
+ _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
+ (entry.ordinal & BIND_IMMEDIATE_MASK));
+ else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
+ _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
+ entry.ordinal);
+ else {
+ _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
+ _bindingInfo.append_uleb128(entry.ordinal);
+ }
+ lastOrdinal = entry.ordinal;
+ }
+
+ if (lastSymbolName != entry.symbolName) {
+ _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
+ _bindingInfo.append_string(entry.symbolName);
+ lastSymbolName = entry.symbolName;
+ }
+
+ if (lastType != entry.kind) {
+ _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
+ lastType = entry.kind;
+ }
+
+ if (lastSegIndex != entry.segIndex || lastSegOffset != entry.segOffset) {
+ _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+ | entry.segIndex);
+ _bindingInfo.append_uleb128(entry.segOffset);
+ lastSegIndex = entry.segIndex;
+ lastSegOffset = entry.segOffset;
+ }
if (entry.addend != lastAddend) {
_bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
_bindingInfo.append_sleb128(entry.addend);
@@ -1208,22 +1226,25 @@ void MachOFileLayout::buildBindInfo() {
void MachOFileLayout::buildLazyBindInfo() {
for (const BindLocation& entry : _file.lazyBindingInfo) {
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
| entry.segIndex);
- _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
- if (entry.ordinal > 0)
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
- (entry.ordinal & 0xF));
- else
+ _lazyBindingInfo.append_uleb128(entry.segOffset);
+ if (entry.ordinal <= 0)
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
- (entry.ordinal & 0xF));
+ (entry.ordinal & BIND_IMMEDIATE_MASK));
+ else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
+ _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
+ entry.ordinal);
+ else {
+ _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
+ _lazyBindingInfo.append_uleb128(entry.ordinal);
+ }
+ // FIXME: We need to | the opcode here with flags.
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
_lazyBindingInfo.append_string(entry.symbolName);
_lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
_lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
}
- _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
_lazyBindingInfo.align(_is64 ? 8 : 4);
}
@@ -1287,6 +1308,24 @@ void TrieNode::addSymbol(const Export& entry,
allNodes.push_back(newNode);
}
+void TrieNode::addOrderedNodes(const Export& entry,
+ std::vector<TrieNode*> &orderedNodes) {
+ if (!_ordered) {
+ orderedNodes.push_back(this);
+ _ordered = true;
+ }
+
+ StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
+ for (TrieEdge &edge : _children) {
+ StringRef edgeStr = edge._subString;
+ if (partialStr.startswith(edgeStr)) {
+ // Already have matching edge, go down that path.
+ edge._child->addOrderedNodes(entry, orderedNodes);
+ return;
+ }
+ }
+}
+
bool TrieNode::updateOffset(uint32_t& offset) {
uint32_t nodeSize = 1; // Length when no export info
if (_hasExportInfo) {
@@ -1392,20 +1431,26 @@ void MachOFileLayout::buildExportTrie() {
rootNode->addSymbol(entry, allocator, allNodes);
}
+ std::vector<TrieNode*> orderedNodes;
+ orderedNodes.reserve(allNodes.size());
+
+ for (const Export& entry : _file.exportInfo)
+ rootNode->addOrderedNodes(entry, orderedNodes);
+
// Assign each node in the vector an offset in the trie stream, iterating
// until all uleb128 sizes have stabilized.
bool more;
do {
uint32_t offset = 0;
more = false;
- for (TrieNode* node : allNodes) {
+ for (TrieNode* node : orderedNodes) {
if (node->updateOffset(offset))
more = true;
}
} while (more);
// Serialize trie to ByteBuffer.
- for (TrieNode* node : allNodes) {
+ for (TrieNode* node : orderedNodes) {
node->appendToByteBuffer(_exportTrie);
}
_exportTrie.align(_is64 ? 8 : 4);
@@ -1414,10 +1459,15 @@ void MachOFileLayout::buildExportTrie() {
void MachOFileLayout::computeSymbolTableSizes() {
// MachO symbol tables have three ranges: locals, globals, and undefines
const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
- _symbolTableSize = nlistSize * (_file.localSymbols.size()
+ _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
+ + _file.localSymbols.size()
+ _file.globalSymbols.size()
+ _file.undefinedSymbols.size());
- _symbolStringPoolSize = 1; // Always reserve 1-byte for the empty string.
+ // Always reserve 1-byte for the empty string and 1-byte for its terminator.
+ _symbolStringPoolSize = 2;
+ for (const Symbol &sym : _file.stabsSymbols) {
+ _symbolStringPoolSize += (sym.name.size()+1);
+ }
for (const Symbol &sym : _file.localSymbols) {
_symbolStringPoolSize += (sym.name.size()+1);
}
@@ -1428,7 +1478,8 @@ void MachOFileLayout::computeSymbolTableSizes() {
_symbolStringPoolSize += (sym.name.size()+1);
}
_symbolTableLocalsStartIndex = 0;
- _symbolTableGlobalsStartIndex = _file.localSymbols.size();
+ _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
+ _file.localSymbols.size();
_symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
+ _file.globalSymbols.size();
@@ -1486,7 +1537,7 @@ llvm::Error MachOFileLayout::writeBinary(StringRef path) {
writeLinkEditContent();
fob->commit();
- return llvm::Error();
+ return llvm::Error::success();
}
/// Takes in-memory normalized view and writes a mach-o object file.
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 4775c75f7211..ddd3259842e2 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -22,6 +22,7 @@
#include "MachONormalizedFile.h"
#include "ArchHandler.h"
+#include "DebugInfo.h"
#include "MachONormalizedFileBinaryUtils.h"
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
@@ -34,6 +35,7 @@
#include "llvm/Support/MachO.h"
#include <map>
#include <system_error>
+#include <unordered_set>
using llvm::StringRef;
using llvm::isa;
@@ -120,6 +122,7 @@ public:
void copySectionInfo(NormalizedFile &file);
void updateSectionInfo(NormalizedFile &file);
void buildAtomToAddressMap();
+ llvm::Error synthesizeDebugNotes(NormalizedFile &file);
llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file);
void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
@@ -201,6 +204,7 @@ private:
bool _allSourceFilesHaveMinVersions = true;
LoadCommandType _minVersionCommandType = (LoadCommandType)0;
uint32_t _minVersion = 0;
+ std::vector<lld::mach_o::Stab> _stabs;
};
Util::~Util() {
@@ -785,6 +789,158 @@ void Util::buildAtomToAddressMap() {
}
}
+llvm::Error Util::synthesizeDebugNotes(NormalizedFile &file) {
+
+ // Bail out early if we don't need to generate a debug map.
+ if (_ctx.debugInfoMode() == MachOLinkingContext::DebugInfoMode::noDebugMap)
+ return llvm::Error::success();
+
+ std::vector<const DefinedAtom*> atomsNeedingDebugNotes;
+ std::set<const mach_o::MachOFile*> filesWithStabs;
+ bool objFileHasDwarf = false;
+ const File *objFile = nullptr;
+
+ for (SectionInfo *sect : _sectionInfos) {
+ for (const AtomInfo &info : sect->atomsAndOffsets) {
+ if (const DefinedAtom *atom = dyn_cast<DefinedAtom>(info.atom)) {
+
+ // FIXME: No stabs/debug-notes for symbols that wouldn't be in the
+ // symbol table.
+ // FIXME: No stabs/debug-notes for kernel dtrace probes.
+
+ if (atom->contentType() == DefinedAtom::typeCFI ||
+ atom->contentType() == DefinedAtom::typeCString)
+ continue;
+
+ // Whenever we encounter a new file, update the 'objfileHasDwarf' flag.
+ if (&info.atom->file() != objFile) {
+ objFileHasDwarf = false;
+ if (const mach_o::MachOFile *atomFile =
+ dyn_cast<mach_o::MachOFile>(&info.atom->file())) {
+ if (atomFile->debugInfo()) {
+ if (isa<mach_o::DwarfDebugInfo>(atomFile->debugInfo()))
+ objFileHasDwarf = true;
+ else if (isa<mach_o::StabsDebugInfo>(atomFile->debugInfo()))
+ filesWithStabs.insert(atomFile);
+ }
+ }
+ }
+
+ // If this atom is from a file that needs dwarf, add it to the list.
+ if (objFileHasDwarf)
+ atomsNeedingDebugNotes.push_back(info.atom);
+ }
+ }
+ }
+
+ // Sort atoms needing debug notes by file ordinal, then atom ordinal.
+ std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(),
+ [](const DefinedAtom *lhs, const DefinedAtom *rhs) {
+ if (lhs->file().ordinal() != rhs->file().ordinal())
+ return (lhs->file().ordinal() < rhs->file().ordinal());
+ return (lhs->ordinal() < rhs->ordinal());
+ });
+
+ // FIXME: Handle <rdar://problem/17689030>: Add -add_ast_path option to \
+ // linker which add N_AST stab entry to output
+ // See OutputFile::synthesizeDebugNotes in ObjectFile.cpp in ld64.
+
+ StringRef oldFileName = "";
+ StringRef oldDirPath = "";
+ bool wroteStartSO = false;
+ std::unordered_set<std::string> seenFiles;
+ for (const DefinedAtom *atom : atomsNeedingDebugNotes) {
+ const auto &atomFile = cast<mach_o::MachOFile>(atom->file());
+ assert(dyn_cast_or_null<lld::mach_o::DwarfDebugInfo>(atomFile.debugInfo())
+ && "file for atom needing debug notes does not contain dwarf");
+ auto &dwarf = cast<lld::mach_o::DwarfDebugInfo>(*atomFile.debugInfo());
+
+ auto &tu = dwarf.translationUnitSource();
+ StringRef newFileName = tu.name;
+ StringRef newDirPath = tu.path;
+
+ // Add an SO whenever the TU source file changes.
+ if (newFileName != oldFileName || newDirPath != oldDirPath) {
+ // Translation unit change, emit ending SO
+ if (oldFileName != "")
+ _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
+
+ oldFileName = newFileName;
+ oldDirPath = newDirPath;
+
+ // If newDirPath doesn't end with a '/' we need to add one:
+ if (newDirPath.back() != '/') {
+ char *p =
+ file.ownedAllocations.Allocate<char>(newDirPath.size() + 2);
+ memcpy(p, newDirPath.data(), newDirPath.size());
+ p[newDirPath.size()] = '/';
+ p[newDirPath.size() + 1] = '\0';
+ newDirPath = p;
+ }
+
+ // New translation unit, emit start SOs:
+ _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newDirPath));
+ _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newFileName));
+
+ // Synthesize OSO for start of file.
+ char *fullPath = nullptr;
+ {
+ SmallString<1024> pathBuf(atomFile.path());
+ if (auto EC = llvm::sys::fs::make_absolute(pathBuf))
+ return llvm::errorCodeToError(EC);
+ fullPath = file.ownedAllocations.Allocate<char>(pathBuf.size() + 1);
+ memcpy(fullPath, pathBuf.c_str(), pathBuf.size() + 1);
+ }
+
+ // Get mod time.
+ uint32_t modTime = 0;
+ llvm::sys::fs::file_status stat;
+ if (!llvm::sys::fs::status(fullPath, stat))
+ if (llvm::sys::fs::exists(stat))
+ modTime = llvm::sys::toTimeT(stat.getLastModificationTime());
+
+ _stabs.push_back(mach_o::Stab(nullptr, N_OSO, _ctx.getCPUSubType(), 1,
+ modTime, fullPath));
+ // <rdar://problem/6337329> linker should put cpusubtype in n_sect field
+ // of nlist entry for N_OSO debug note entries.
+ wroteStartSO = true;
+ }
+
+ if (atom->contentType() == DefinedAtom::typeCode) {
+ // Synthesize BNSYM and start FUN stabs.
+ _stabs.push_back(mach_o::Stab(atom, N_BNSYM, 1, 0, 0, ""));
+ _stabs.push_back(mach_o::Stab(atom, N_FUN, 1, 0, 0, atom->name()));
+ // Synthesize any SOL stabs needed
+ // FIXME: add SOL stabs.
+ _stabs.push_back(mach_o::Stab(nullptr, N_FUN, 0, 0,
+ atom->rawContent().size(), ""));
+ _stabs.push_back(mach_o::Stab(nullptr, N_ENSYM, 1, 0,
+ atom->rawContent().size(), ""));
+ } else {
+ if (atom->scope() == Atom::scopeTranslationUnit)
+ _stabs.push_back(mach_o::Stab(atom, N_STSYM, 1, 0, 0, atom->name()));
+ else
+ _stabs.push_back(mach_o::Stab(nullptr, N_GSYM, 1, 0, 0, atom->name()));
+ }
+ }
+
+ // Emit ending SO if necessary.
+ if (wroteStartSO)
+ _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
+
+ // Copy any stabs from .o file.
+ for (const auto *objFile : filesWithStabs) {
+ const auto &stabsList =
+ cast<mach_o::StabsDebugInfo>(objFile->debugInfo())->stabs();
+ for (auto &stab : stabsList) {
+ // FIXME: Drop stabs whose atoms have been dead-stripped.
+ _stabs.push_back(stab);
+ }
+ }
+
+ return llvm::Error::success();
+}
+
uint16_t Util::descBits(const DefinedAtom* atom) {
uint16_t desc = 0;
switch (atom->merge()) {
@@ -807,7 +963,8 @@ uint16_t Util::descBits(const DefinedAtom* atom) {
desc |= REFERENCED_DYNAMICALLY;
if (_archHandler.isThumbFunction(*atom))
desc |= N_ARM_THUMB_DEF;
- if (atom->deadStrip() == DefinedAtom::deadStripNever) {
+ if (atom->deadStrip() == DefinedAtom::deadStripNever &&
+ _ctx.outputMachOType() == llvm::MachO::MH_OBJECT) {
if ((atom->contentType() != DefinedAtom::typeInitializerPtr)
&& (atom->contentType() != DefinedAtom::typeTerminatorPtr))
desc |= N_NO_DEAD_STRIP;
@@ -828,7 +985,7 @@ llvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom,
case Atom::scopeTranslationUnit:
scope = 0;
inGlobalsRegion = false;
- return llvm::Error();
+ return llvm::Error::success();
case Atom::scopeLinkageUnit:
if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) &&
_ctx.exportSymbolNamed(atom->name())) {
@@ -840,38 +997,55 @@ llvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom,
// -keep_private_externs means keep in globals region as N_PEXT.
scope = N_PEXT | N_EXT;
inGlobalsRegion = true;
- return llvm::Error();
+ return llvm::Error::success();
}
}
// scopeLinkageUnit symbols are no longer global once linked.
scope = N_PEXT;
inGlobalsRegion = false;
- return llvm::Error();
+ return llvm::Error::success();
case Atom::scopeGlobal:
if (_ctx.exportRestrictMode()) {
if (_ctx.exportSymbolNamed(atom->name())) {
scope = N_EXT;
inGlobalsRegion = true;
- return llvm::Error();
+ return llvm::Error::success();
} else {
scope = N_PEXT;
inGlobalsRegion = false;
- return llvm::Error();
+ return llvm::Error::success();
}
} else {
scope = N_EXT;
inGlobalsRegion = true;
- return llvm::Error();
+ return llvm::Error::success();
}
break;
}
llvm_unreachable("atom->scope() unknown enum value");
}
+
+
llvm::Error Util::addSymbols(const lld::File &atomFile,
NormalizedFile &file) {
bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
- // Mach-O symbol table has three regions: locals, globals, undefs.
+ // Mach-O symbol table has four regions: stabs, locals, globals, undefs.
+
+ // Add all stabs.
+ for (auto &stab : _stabs) {
+ Symbol sym;
+ sym.type = static_cast<NListType>(stab.type);
+ sym.scope = 0;
+ sym.sect = stab.other;
+ sym.desc = stab.desc;
+ if (stab.atom)
+ sym.value = _atomToAddress[stab.atom];
+ else
+ sym.value = stab.value;
+ sym.name = stab.str;
+ file.stabsSymbols.push_back(sym);
+ }
// Add all local (non-global) symbols in address order
std::vector<AtomAndIndex> globals;
@@ -965,7 +1139,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
file.undefinedSymbols.push_back(sym);
}
- return llvm::Error();
+ return llvm::Error::success();
}
const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
@@ -1040,15 +1214,15 @@ void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
}
}
-void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
+void Util::addDependentDylibs(const lld::File &atomFile,
+ NormalizedFile &nFile) {
// Scan all imported symbols and build up list of dylibs they are from.
int ordinal = 1;
- for (const SharedLibraryAtom *slAtom : atomFile.sharedLibrary()) {
- StringRef loadPath = slAtom->loadName();
- DylibPathToInfo::iterator pos = _dylibInfo.find(loadPath);
+ for (const auto *dylib : _ctx.allDylibs()) {
+ DylibPathToInfo::iterator pos = _dylibInfo.find(dylib->installName());
if (pos == _dylibInfo.end()) {
DylibInfo info;
- bool flatNamespaceAtom = &slAtom->file() == _ctx.flatNamespaceFile();
+ bool flatNamespaceAtom = dylib == _ctx.flatNamespaceFile();
// If we're in -flat_namespace mode (or this atom came from the flat
// namespace file under -undefined dynamic_lookup) then use the flat
@@ -1057,24 +1231,22 @@ void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
else
info.ordinal = ordinal++;
- info.hasWeak = slAtom->canBeNullAtRuntime();
+ info.hasWeak = false;
info.hasNonWeak = !info.hasWeak;
- _dylibInfo[loadPath] = info;
+ _dylibInfo[dylib->installName()] = info;
// Unless this was a flat_namespace atom, record the source dylib.
if (!flatNamespaceAtom) {
DependentDylib depInfo;
- depInfo.path = loadPath;
+ depInfo.path = dylib->installName();
depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
- depInfo.currentVersion = _ctx.dylibCurrentVersion(loadPath);
- depInfo.compatVersion = _ctx.dylibCompatVersion(loadPath);
+ depInfo.currentVersion = _ctx.dylibCurrentVersion(dylib->path());
+ depInfo.compatVersion = _ctx.dylibCompatVersion(dylib->path());
nFile.dependentDylibs.push_back(depInfo);
}
} else {
- if ( slAtom->canBeNullAtRuntime() )
- pos->second.hasWeak = true;
- else
- pos->second.hasNonWeak = true;
+ pos->second.hasWeak = false;
+ pos->second.hasNonWeak = !pos->second.hasWeak;
}
}
// Automatically weak link dylib in which all symbols are weak (canBeNull).
@@ -1404,6 +1576,8 @@ normalizedFromAtoms(const lld::File &atomFile,
util.copySectionInfo(normFile);
util.assignAddressesToSections(normFile);
util.buildAtomToAddressMap();
+ if (auto err = util.synthesizeDebugNotes(normFile))
+ return std::move(err);
util.updateSectionInfo(normFile);
util.copySectionContent(normFile);
if (auto ec = util.addSymbols(atomFile, normFile)) {
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index fc760a3eddd0..4b17f7b3a85f 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -27,7 +27,11 @@
#include "MachONormalizedFileBinaryUtils.h"
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/LEB128.h"
@@ -320,7 +324,7 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
// If section has no symbols and no content, there are no atoms.
if (symbols.empty() && section.content.empty())
- return llvm::Error();
+ return llvm::Error::success();
if (symbols.empty()) {
// Section has no symbols, put all content in one anoymous atom.
@@ -371,7 +375,7 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
});
}
- return llvm::Error();
+ return llvm::Error::success();
}
llvm::Error processSection(DefinedAtom::ContentType atomType,
@@ -483,7 +487,7 @@ llvm::Error processSection(DefinedAtom::ContentType atomType,
offset += size;
}
}
- return llvm::Error();
+ return llvm::Error::success();
}
const Section* findSectionCoveringAddress(const NormalizedFile &normalizedFile,
@@ -499,7 +503,7 @@ const Section* findSectionCoveringAddress(const NormalizedFile &normalizedFile,
const MachODefinedAtom *
findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file,
- uint64_t addr, Reference::Addend *addend) {
+ uint64_t addr, Reference::Addend &addend) {
const Section *sect = nullptr;
sect = findSectionCoveringAddress(normalizedFile, addr);
if (!sect)
@@ -509,7 +513,7 @@ findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file,
uint64_t offsetInSect = addr - sect->address;
auto atom =
file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
- *addend = offsetInTarget;
+ addend = offsetInTarget;
return atom;
}
@@ -540,7 +544,7 @@ llvm::Error convertRelocs(const Section &section,
uint64_t offsetInSect = addr - sect->address;
*atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
*addend = offsetInTarget;
- return llvm::Error();
+ return llvm::Error::success();
};
// Utility function for ArchHandler to find atom by its symbol index.
@@ -548,19 +552,23 @@ llvm::Error convertRelocs(const Section &section,
-> llvm::Error {
// Find symbol from index.
const Symbol *sym = nullptr;
+ uint32_t numStabs = normalizedFile.stabsSymbols.size();
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];
+ assert(symbolIndex >= numStabs && "Searched for stab via atomBySymbol?");
+ if (symbolIndex < numStabs+numLocal) {
+ sym = &normalizedFile.localSymbols[symbolIndex-numStabs];
+ } else if (symbolIndex < numStabs+numLocal+numGlobal) {
+ sym = &normalizedFile.globalSymbols[symbolIndex-numStabs-numLocal];
+ } else if (symbolIndex < numStabs+numLocal+numGlobal+numUndef) {
+ sym = &normalizedFile.undefinedSymbols[symbolIndex-numStabs-numLocal-
+ numGlobal];
} else {
return llvm::make_error<GenericError>(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())
@@ -572,14 +580,14 @@ llvm::Error convertRelocs(const Section &section,
targetOffsetInSect);
if (target) {
*result = target;
- return llvm::Error();
+ return llvm::Error::success();
}
return llvm::make_error<GenericError>("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 llvm::Error();
+ return llvm::Error::success();
}
return llvm::make_error<GenericError>("no undefined atom found for sym");
} else {
@@ -676,7 +684,7 @@ llvm::Error convertRelocs(const Section &section,
kind, offsetInAtom, target, addend);
}
- return llvm::Error();
+ return llvm::Error::success();
}
bool isDebugInfoSection(const Section &section) {
@@ -685,6 +693,301 @@ bool isDebugInfoSection(const Section &section) {
return section.segmentName.equals("__DWARF");
}
+static const Atom* findDefinedAtomByName(MachOFile &file, Twine name) {
+ std::string strName = name.str();
+ for (auto *atom : file.defined())
+ if (atom->name() == strName)
+ return atom;
+ return nullptr;
+}
+
+static StringRef copyDebugString(StringRef str, BumpPtrAllocator &alloc) {
+ char *strCopy = alloc.Allocate<char>(str.size() + 1);
+ memcpy(strCopy, str.data(), str.size());
+ strCopy[str.size()] = '\0';
+ return strCopy;
+}
+
+llvm::Error parseStabs(MachOFile &file,
+ const NormalizedFile &normalizedFile,
+ bool copyRefs) {
+
+ if (normalizedFile.stabsSymbols.empty())
+ return llvm::Error::success();
+
+ // FIXME: Kill this off when we can move to sane yaml parsing.
+ std::unique_ptr<BumpPtrAllocator> allocator;
+ if (copyRefs)
+ allocator = llvm::make_unique<BumpPtrAllocator>();
+
+ enum { start, inBeginEnd } state = start;
+
+ const Atom *currentAtom = nullptr;
+ uint64_t currentAtomAddress = 0;
+ StabsDebugInfo::StabsList stabsList;
+ for (const auto &stabSym : normalizedFile.stabsSymbols) {
+ Stab stab(nullptr, stabSym.type, stabSym.sect, stabSym.desc,
+ stabSym.value, stabSym.name);
+ switch (state) {
+ case start:
+ switch (static_cast<StabType>(stabSym.type)) {
+ case N_BNSYM:
+ state = inBeginEnd;
+ currentAtomAddress = stabSym.value;
+ Reference::Addend addend;
+ currentAtom = findAtomCoveringAddress(normalizedFile, file,
+ currentAtomAddress, addend);
+ if (addend != 0)
+ return llvm::make_error<GenericError>(
+ "Non-zero addend for BNSYM '" + stabSym.name + "' in " +
+ file.path());
+ if (currentAtom)
+ stab.atom = currentAtom;
+ else {
+ // FIXME: ld64 just issues a warning here - should we match that?
+ return llvm::make_error<GenericError>(
+ "can't find atom for stabs BNSYM at " +
+ Twine::utohexstr(stabSym.value) + " in " + file.path());
+ }
+ break;
+ case N_SO:
+ case N_OSO:
+ // Not associated with an atom, just copy.
+ if (copyRefs)
+ stab.str = copyDebugString(stabSym.name, *allocator);
+ else
+ stab.str = stabSym.name;
+ break;
+ case N_GSYM: {
+ auto colonIdx = stabSym.name.find(':');
+ if (colonIdx != StringRef::npos) {
+ StringRef name = stabSym.name.substr(0, colonIdx);
+ currentAtom = findDefinedAtomByName(file, "_" + name);
+ stab.atom = currentAtom;
+ if (copyRefs)
+ stab.str = copyDebugString(stabSym.name, *allocator);
+ else
+ stab.str = stabSym.name;
+ } else {
+ currentAtom = findDefinedAtomByName(file, stabSym.name);
+ stab.atom = currentAtom;
+ if (copyRefs)
+ stab.str = copyDebugString(stabSym.name, *allocator);
+ else
+ stab.str = stabSym.name;
+ }
+ if (stab.atom == nullptr)
+ return llvm::make_error<GenericError>(
+ "can't find atom for N_GSYM stabs" + stabSym.name +
+ " in " + file.path());
+ break;
+ }
+ case N_FUN:
+ return llvm::make_error<GenericError>(
+ "old-style N_FUN stab '" + stabSym.name + "' unsupported");
+ default:
+ return llvm::make_error<GenericError>(
+ "unrecognized stab symbol '" + stabSym.name + "'");
+ }
+ break;
+ case inBeginEnd:
+ stab.atom = currentAtom;
+ switch (static_cast<StabType>(stabSym.type)) {
+ case N_ENSYM:
+ state = start;
+ currentAtom = nullptr;
+ break;
+ case N_FUN:
+ // Just copy the string.
+ if (copyRefs)
+ stab.str = copyDebugString(stabSym.name, *allocator);
+ else
+ stab.str = stabSym.name;
+ break;
+ default:
+ return llvm::make_error<GenericError>(
+ "unrecognized stab symbol '" + stabSym.name + "'");
+ }
+ }
+ llvm::dbgs() << "Adding to stabsList: " << stab << "\n";
+ stabsList.push_back(stab);
+ }
+
+ file.setDebugInfo(llvm::make_unique<StabsDebugInfo>(std::move(stabsList)));
+
+ // FIXME: Kill this off when we fix YAML memory ownership.
+ file.debugInfo()->setAllocator(std::move(allocator));
+
+ return llvm::Error::success();
+}
+
+static llvm::DataExtractor
+dataExtractorFromSection(const NormalizedFile &normalizedFile,
+ const Section &S) {
+ const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
+ const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
+ StringRef SecData(reinterpret_cast<const char*>(S.content.data()),
+ S.content.size());
+ return llvm::DataExtractor(SecData, !isBig, is64 ? 8 : 4);
+}
+
+// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+// inspection" code if possible.
+static uint32_t getCUAbbrevOffset(llvm::DataExtractor abbrevData,
+ uint64_t abbrCode) {
+ uint64_t curCode;
+ uint32_t offset = 0;
+ while ((curCode = abbrevData.getULEB128(&offset)) != abbrCode) {
+ // Tag
+ abbrevData.getULEB128(&offset);
+ // DW_CHILDREN
+ abbrevData.getU8(&offset);
+ // Attributes
+ while (abbrevData.getULEB128(&offset) | abbrevData.getULEB128(&offset))
+ ;
+ }
+ return offset;
+}
+
+// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+// inspection" code if possible.
+static Expected<const char *>
+getIndexedString(const NormalizedFile &normalizedFile,
+ llvm::dwarf::Form form, llvm::DataExtractor infoData,
+ uint32_t &infoOffset, const Section &stringsSection) {
+ if (form == llvm::dwarf::DW_FORM_string)
+ return infoData.getCStr(&infoOffset);
+ if (form != llvm::dwarf::DW_FORM_strp)
+ return llvm::make_error<GenericError>(
+ "string field encoded without DW_FORM_strp");
+ uint32_t stringOffset = infoData.getU32(&infoOffset);
+ llvm::DataExtractor stringsData =
+ dataExtractorFromSection(normalizedFile, stringsSection);
+ return stringsData.getCStr(&stringOffset);
+}
+
+// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+// inspection" code if possible.
+static llvm::Expected<TranslationUnitSource>
+readCompUnit(const NormalizedFile &normalizedFile,
+ const Section &info,
+ const Section &abbrev,
+ const Section &strings,
+ StringRef path) {
+ // FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+ // inspection" code if possible.
+ uint32_t offset = 0;
+ llvm::dwarf::DwarfFormat Format = llvm::dwarf::DwarfFormat::DWARF32;
+ auto infoData = dataExtractorFromSection(normalizedFile, info);
+ uint32_t length = infoData.getU32(&offset);
+ if (length == 0xffffffff) {
+ Format = llvm::dwarf::DwarfFormat::DWARF64;
+ infoData.getU64(&offset);
+ }
+ else if (length > 0xffffff00)
+ return llvm::make_error<GenericError>("Malformed DWARF in " + path);
+
+ uint16_t version = infoData.getU16(&offset);
+
+ if (version < 2 || version > 4)
+ return llvm::make_error<GenericError>("Unsupported DWARF version in " +
+ path);
+
+ infoData.getU32(&offset); // Abbrev offset (should be zero)
+ uint8_t addrSize = infoData.getU8(&offset);
+
+ uint32_t abbrCode = infoData.getULEB128(&offset);
+ auto abbrevData = dataExtractorFromSection(normalizedFile, abbrev);
+ uint32_t abbrevOffset = getCUAbbrevOffset(abbrevData, abbrCode);
+ uint64_t tag = abbrevData.getULEB128(&abbrevOffset);
+ if (tag != llvm::dwarf::DW_TAG_compile_unit)
+ return llvm::make_error<GenericError>("top level DIE is not a compile unit");
+ // DW_CHILDREN
+ abbrevData.getU8(&abbrevOffset);
+ uint32_t name;
+ llvm::dwarf::Form form;
+ TranslationUnitSource tu;
+ while ((name = abbrevData.getULEB128(&abbrevOffset)) |
+ (form = static_cast<llvm::dwarf::Form>(
+ abbrevData.getULEB128(&abbrevOffset))) &&
+ (name != 0 || form != 0)) {
+ switch (name) {
+ case llvm::dwarf::DW_AT_name: {
+ if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
+ strings))
+ tu.name = *eName;
+ else
+ return eName.takeError();
+ break;
+ }
+ case llvm::dwarf::DW_AT_comp_dir: {
+ if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
+ strings))
+ tu.path = *eName;
+ else
+ return eName.takeError();
+ break;
+ }
+ default:
+ llvm::DWARFFormValue::skipValue(form, infoData, &offset, version,
+ addrSize, Format);
+ }
+ }
+ return tu;
+}
+
+llvm::Error parseDebugInfo(MachOFile &file,
+ const NormalizedFile &normalizedFile, bool copyRefs) {
+
+ // Find the interesting debug info sections.
+ const Section *debugInfo = nullptr;
+ const Section *debugAbbrev = nullptr;
+ const Section *debugStrings = nullptr;
+
+ for (auto &s : normalizedFile.sections) {
+ if (s.segmentName == "__DWARF") {
+ if (s.sectionName == "__debug_info")
+ debugInfo = &s;
+ else if (s.sectionName == "__debug_abbrev")
+ debugAbbrev = &s;
+ else if (s.sectionName == "__debug_str")
+ debugStrings = &s;
+ }
+ }
+
+ if (!debugInfo)
+ return parseStabs(file, normalizedFile, copyRefs);
+
+ if (debugInfo->content.size() == 0)
+ return llvm::Error::success();
+
+ if (debugInfo->content.size() < 12)
+ return llvm::make_error<GenericError>("Malformed __debug_info section in " +
+ file.path() + ": too small");
+
+ if (!debugAbbrev)
+ return llvm::make_error<GenericError>("Missing __dwarf_abbrev section in " +
+ file.path());
+
+ if (auto tuOrErr = readCompUnit(normalizedFile, *debugInfo, *debugAbbrev,
+ *debugStrings, file.path())) {
+ // FIXME: Kill of allocator and code under 'copyRefs' when we fix YAML
+ // memory ownership.
+ std::unique_ptr<BumpPtrAllocator> allocator;
+ if (copyRefs) {
+ allocator = llvm::make_unique<BumpPtrAllocator>();
+ tuOrErr->name = copyDebugString(tuOrErr->name, *allocator);
+ tuOrErr->path = copyDebugString(tuOrErr->path, *allocator);
+ }
+ file.setDebugInfo(llvm::make_unique<DwarfDebugInfo>(std::move(*tuOrErr)));
+ if (copyRefs)
+ file.debugInfo()->setAllocator(std::move(allocator));
+ } else
+ return tuOrErr.takeError();
+
+ return llvm::Error::success();
+}
+
static int64_t readSPtr(bool is64, bool isBig, const uint8_t *addr) {
if (is64)
return read64(addr, isBig);
@@ -712,7 +1015,7 @@ static llvm::Error processAugmentationString(const uint8_t *augStr,
if (augStr[0] == '\0') {
len = 1;
- return llvm::Error();
+ return llvm::Error::success();
}
if (augStr[0] != 'z')
@@ -762,7 +1065,7 @@ static llvm::Error processAugmentationString(const uint8_t *augStr,
cieInfo._augmentationDataLength = offsetInAugmentationData;
len = idx + 1;
- return llvm::Error();
+ return llvm::Error::success();
}
static llvm::Error processCIE(const NormalizedFile &normalizedFile,
@@ -853,7 +1156,7 @@ static llvm::Error processCIE(const NormalizedFile &normalizedFile,
const MachODefinedAtom *func = nullptr;
Reference::Addend addend;
func = findAtomCoveringAddress(normalizedFile, file, funcAddress,
- &addend);
+ addend);
atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
handler.unwindRefToPersonalityFunctionKind(),
PersonalityFunctionField, func, addend);
@@ -867,7 +1170,7 @@ static llvm::Error processCIE(const NormalizedFile &normalizedFile,
cieInfos[atom] = std::move(cieInfo);
- return llvm::Error();
+ return llvm::Error::success();
}
static llvm::Error processFDE(const NormalizedFile &normalizedFile,
@@ -936,7 +1239,7 @@ static llvm::Error processFDE(const NormalizedFile &normalizedFile,
}
Reference::Addend addend;
auto *target = findAtomCoveringAddress(normalizedFile, file,
- targetAddress, &addend);
+ targetAddress, addend);
atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
refKind, refAddress, target, addend);
@@ -1011,7 +1314,7 @@ static llvm::Error processFDE(const NormalizedFile &normalizedFile,
}
}
- return llvm::Error();
+ return llvm::Error::success();
}
llvm::Error addEHFrameReferences(const NormalizedFile &normalizedFile,
@@ -1028,9 +1331,9 @@ llvm::Error addEHFrameReferences(const NormalizedFile &normalizedFile,
// No __eh_frame so nothing to do.
if (!ehFrameSection)
- return llvm::Error();
+ return llvm::Error::success();
- llvm::Error ehFrameErr;
+ llvm::Error ehFrameErr = llvm::Error::success();
CIEInfoMap cieInfos;
file.eachAtomInSection(*ehFrameSection,
@@ -1092,10 +1395,9 @@ llvm::Error parseObjCImageInfo(const Section &sect,
file.setSwiftVersion((flags >> 8) & 0xFF);
- return llvm::Error();
+ return llvm::Error::success();
}
-
/// Converts normalized mach-o file into an lld::File and lld::Atoms.
llvm::Expected<std::unique_ptr<lld::File>>
objectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
@@ -1135,11 +1437,11 @@ normalizedObjectToAtoms(MachOFile *file,
// Create atoms from each section.
for (auto &sect : normalizedFile.sections) {
- DEBUG(llvm::dbgs() << "Creating atoms: "; sect.dump());
+
+ // If this is a debug-info section parse it specially.
if (isDebugInfoSection(sect))
continue;
-
// If the file contains an objc_image_info struct, then we should parse the
// ObjC flags and Swift version.
if (isObjCImageInfo(sect)) {
@@ -1248,7 +1550,11 @@ normalizedObjectToAtoms(MachOFile *file,
for (const DefinedAtom* defAtom : file->defined()) {
reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
}
- return llvm::Error();
+
+ if (auto err = parseDebugInfo(*file, normalizedFile, copyRefs))
+ return err;
+
+ return llvm::Error::success();
}
llvm::Error
@@ -1279,7 +1585,7 @@ normalizedDylibToAtoms(MachODylibFile *file,
if (dep.kind == llvm::MachO::LC_REEXPORT_DYLIB)
file->addReExportedDylib(dep.path);
}
- return llvm::Error();
+ return llvm::Error::success();
}
void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
@@ -1324,14 +1630,6 @@ normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
}
}
-#ifndef NDEBUG
-void Section::dump(llvm::raw_ostream &OS) const {
- OS << "Section (\"" << segmentName << ", " << sectionName << "\"";
- OS << ", addr: " << llvm::format_hex(address, 16, true);
- OS << ", size: " << llvm::format_hex(content.size(), 8, true) << ")\n";
-}
-#endif
-
} // namespace normalized
} // namespace mach_o
} // namespace lld
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
index 66be77173983..218170965eca 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
@@ -234,6 +234,8 @@ struct ScalarBitSetTraits<SectionAttr> {
llvm::MachO::S_ATTR_EXT_RELOC);
io.bitSetCase(value, "S_ATTR_LOC_RELOC",
llvm::MachO::S_ATTR_LOC_RELOC);
+ io.bitSetCase(value, "S_ATTR_DEBUG",
+ llvm::MachO::S_ATTR_DEBUG);
}
};
diff --git a/lib/ReaderWriter/MachO/ObjCPass.cpp b/lib/ReaderWriter/MachO/ObjCPass.cpp
index ba24b3fecdf4..4712d8ca969c 100644
--- a/lib/ReaderWriter/MachO/ObjCPass.cpp
+++ b/lib/ReaderWriter/MachO/ObjCPass.cpp
@@ -103,7 +103,7 @@ public:
// Add the image info.
mergedFile.addAtom(*getImageInfo());
- return llvm::Error();
+ return llvm::Error::success();
}
private:
diff --git a/lib/ReaderWriter/MachO/ShimPass.cpp b/lib/ReaderWriter/MachO/ShimPass.cpp
index cd5367146658..ff559d70eabe 100644
--- a/lib/ReaderWriter/MachO/ShimPass.cpp
+++ b/lib/ReaderWriter/MachO/ShimPass.cpp
@@ -66,7 +66,7 @@ public:
}
// Exit early if no shims needed.
if (_targetToShim.empty())
- return llvm::Error();
+ return llvm::Error::success();
// Sort shim atoms so the layout order is stable.
std::vector<const DefinedAtom *> shims;
@@ -83,7 +83,7 @@ public:
for (const DefinedAtom *shim : shims)
mergedFile.addAtom(*shim);
- return llvm::Error();
+ return llvm::Error::success();
}
private:
diff --git a/lib/ReaderWriter/MachO/StubsPass.cpp b/lib/ReaderWriter/MachO/StubsPass.cpp
index d53b78b24d14..19e2bc592f5c 100644
--- a/lib/ReaderWriter/MachO/StubsPass.cpp
+++ b/lib/ReaderWriter/MachO/StubsPass.cpp
@@ -218,7 +218,7 @@ public:
llvm::Error perform(SimpleFile &mergedFile) override {
// Skip this pass if output format uses text relocations instead of stubs.
if (!this->noTextRelocs())
- return llvm::Error();
+ return llvm::Error::success();
// Scan all references in all atoms.
for (const DefinedAtom *atom : mergedFile.defined()) {
@@ -245,7 +245,7 @@ public:
// Exit early if no stubs needed.
if (_targetToUses.empty())
- return llvm::Error();
+ return llvm::Error::success();
// First add help-common and GOT slots used by lazy binding.
SimpleDefinedAtom *helperCommonAtom =
@@ -323,7 +323,7 @@ public:
lazyOffset += target->name().size() + 12;
}
- return llvm::Error();
+ return llvm::Error::success();
}
private:
diff --git a/lib/ReaderWriter/MachO/TLVPass.cpp b/lib/ReaderWriter/MachO/TLVPass.cpp
index 7a8496c20a4e..e362e507ebf2 100644
--- a/lib/ReaderWriter/MachO/TLVPass.cpp
+++ b/lib/ReaderWriter/MachO/TLVPass.cpp
@@ -107,7 +107,7 @@ private:
for (const TLVPEntryAtom *slot : entries)
mergedFile.addAtom(*slot);
- return llvm::Error();
+ return llvm::Error::success();
}
const DefinedAtom *makeTLVPEntry(const Atom *target) {