summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-08-24 23:51:40 +0000
committerRui Ueyama <ruiu@google.com>2017-08-24 23:51:40 +0000
commitea65b5aa498c42b7dc8bf44fa418ed9725871164 (patch)
tree3fbe42d7e2ee7914ceee8cd4d18f647e97c41ec4 /lld/lib
parentcdb8341e620759698e574e4b2a99103a814c948c (diff)
downloadbcm5719-llvm-ea65b5aa498c42b7dc8bf44fa418ed9725871164.tar.gz
bcm5719-llvm-ea65b5aa498c42b7dc8bf44fa418ed9725871164.zip
[MACH-O] Fix the ASM code generated for __stub_helpers section
Patch by Patricio Villalobos. I discovered that lld for darwin is generating the wrong code for lazy bindings in the __stub_helper section (at least for osx 10.12). This is the way i can reproduce this problem, using this program: #include <stdio.h> int main(int argc, char **argv) { printf("C: printf!\n"); puts("C: puts!\n"); return 0; } Then I link it using i have tested it in 3.9, 4.0 and 4.1 versions: $ clang -c hello.c $ lld -flavor darwin hello.o -o h1 -lc When i execute the binary h1 the system gives me the following error: C: printf! dyld: lazy symbol binding failed: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment 4 which is too large (0..3) dyld: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment 4 which is too large (0..3) Trace/BPT trap: 5 Investigating the code, it seems that the problem is that the asm code generated in the file StubPass.cpp, specifically in the line 323,when it adds, what it seems an arbitrary number (12) to the offset into the lazy bind opcodes section, but it should be calculated depending on the MachONormalizedFileBinaryWrite::lazyBindingInfo result. I confirmed this bug by patching the code manually in the binary and writing the right offset in the asm code (__stub_helper). This patch fixes the content of the atom that contains the assembly code when the offset is known. Differential Revision: https://reviews.llvm.org/D35387 llvm-svn: 311734
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler.h4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp57
6 files changed, 77 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler.h b/lld/lib/ReaderWriter/MachO/ArchHandler.h
index 70a63bd1004..6028006ca9d 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler.h
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler.h
@@ -112,6 +112,10 @@ public:
/// info in final executables.
virtual bool isLazyPointer(const Reference &);
+ /// Reference from an __stub_helper entry to the required offset of the
+ /// lazy bind commands.
+ virtual Reference::KindValue lazyImmediateLocationKind() = 0;
+
/// Returns true if the specified relocation is paired to the next relocation.
virtual bool isPairedReloc(const normalized::Relocation &) = 0;
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index 7d1544854cf..2f663c660f5 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -67,6 +67,10 @@ public:
return invalid;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
Reference::KindValue pointerKind() override {
return invalid;
}
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
index 10360b5c6dd..b9c815c5a32 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
@@ -127,6 +127,10 @@ public:
return pointer64;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
uint32_t dwarfCompactUnwindType() override {
return 0x03000000;
}
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
index 2272bff65cc..a2c68092724 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
@@ -70,6 +70,10 @@ public:
return delta32;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
Reference::KindValue unwindRefToEhFrameKind() override {
return invalid;
}
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
index d687ca5de5b..aee9959ca6b 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
@@ -116,6 +116,10 @@ public:
return unwindFDEToFunction;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
Reference::KindValue unwindRefToEhFrameKind() override {
return unwindInfoToEhFrame;
}
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index e58e3d2e7a4..f2e5ed78167 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -172,6 +172,8 @@ private:
SymbolScope &symbolScope);
void appendSection(SectionInfo *si, NormalizedFile &file);
uint32_t sectionIndexForAtom(const Atom *atom);
+ void fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
+ NormalizedFile &file);
typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
@@ -1423,6 +1425,8 @@ void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
uint8_t segmentIndex;
uint64_t segmentStartAddr;
+ uint32_t offsetInBindInfo = 0;
+
for (SectionInfo *sect : _sectionInfos) {
segIndexForSection(sect, segmentIndex, segmentStartAddr);
for (const AtomInfo &info : sect->atomsAndOffsets) {
@@ -1467,6 +1471,59 @@ void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
bind.symbolName = targ->name();
bind.addend = ref->addend();
nFile.lazyBindingInfo.push_back(bind);
+
+ // Now that we know the segmentOffset and the ordinal attribute,
+ // we can fix the helper's code
+
+ fixLazyReferenceImm(atom, offsetInBindInfo, nFile);
+
+ // 5 bytes for opcodes + variable sizes (target name + \0 and offset
+ // encode's size)
+ offsetInBindInfo +=
+ 6 + targ->name().size() + llvm::getULEB128Size(bind.segOffset);
+ if (bind.ordinal > BIND_IMMEDIATE_MASK)
+ offsetInBindInfo += llvm::getULEB128Size(bind.ordinal);
+ }
+ }
+ }
+ }
+}
+
+void Util::fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
+ NormalizedFile &file) {
+ for (const auto &ref : *atom) {
+ const DefinedAtom *da = dyn_cast<DefinedAtom>(ref->target());
+ if (da == nullptr)
+ return;
+
+ const Reference *helperRef = nullptr;
+ for (const Reference *hr : *da) {
+ if (hr->kindValue() == _archHandler.lazyImmediateLocationKind()) {
+ helperRef = hr;
+ break;
+ }
+ }
+ if (helperRef == nullptr)
+ continue;
+
+ // TODO: maybe get the fixed atom content from _archHandler ?
+ for (SectionInfo *sectInfo : _sectionInfos) {
+ for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) {
+ if (atomInfo.atom == helperRef->target()) {
+ auto sectionContent =
+ file.sections[sectInfo->normalizedSectionIndex].content;
+ uint8_t *rawb =
+ file.ownedAllocations.Allocate<uint8_t>(sectionContent.size());
+ llvm::MutableArrayRef<uint8_t> newContent{rawb,
+ sectionContent.size()};
+ std::copy(sectionContent.begin(), sectionContent.end(),
+ newContent.begin());
+ llvm::support::ulittle32_t *loc =
+ reinterpret_cast<llvm::support::ulittle32_t *>(
+ &newContent[atomInfo.offsetInSection +
+ helperRef->offsetInAtom()]);
+ *loc = offset;
+ file.sections[sectInfo->normalizedSectionIndex].content = newContent;
}
}
}
OpenPOWER on IntegriCloud