summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp31
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h9
-rw-r--r--llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.obin0 -> 1056 bytes
-rw-r--r--llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test5
-rw-r--r--llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s30
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink.cpp48
6 files changed, 74 insertions, 49 deletions
diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
index 6517b3b0d0c..c531df82446 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
@@ -163,8 +163,7 @@ Error EHFrameParser::processCIE() {
LLVM_DEBUG(dbgs() << " Record is CIE\n");
- /// Reset state for the new CIE.
- LSDAFieldPresent = false;
+ CIEInformation CIEInfo(*CurRecordAtom);
uint8_t Version = 0;
if (auto Err = EHFrameReader.readInteger(Version))
@@ -219,7 +218,7 @@ Error EHFrameParser::processCIE() {
while (uint8_t Field = *NextField++) {
switch (Field) {
case 'L': {
- LSDAFieldPresent = true;
+ CIEInfo.FDEsHaveLSDAField = true;
uint8_t LSDAPointerEncoding;
if (auto Err = EHFrameReader.readInteger(LSDAPointerEncoding))
return Err;
@@ -268,6 +267,10 @@ Error EHFrameParser::processCIE() {
return make_error<JITLinkError>("Read past the end of the augmentation "
"data while parsing fields");
+ assert(!CIEInfos.count(CurRecordAtom->getAddress()) &&
+ "Multiple CIEs recorded at the same address?");
+ CIEInfos[CurRecordAtom->getAddress()] = std::move(CIEInfo);
+
return Error::success();
}
@@ -280,14 +283,18 @@ Error EHFrameParser::processFDE(JITTargetAddress CIEPointerAddress,
<< format("0x%016" PRIx64, CIEPointerAddress - CIEPointer) << "\n";
});
- auto CIEAtom = G.findAtomByAddress(CIEPointerAddress - CIEPointer);
- if (!CIEAtom)
- return CIEAtom.takeError();
+ auto CIEInfoItr = CIEInfos.find(CIEPointerAddress - CIEPointer);
+ if (CIEInfoItr == CIEInfos.end())
+ return make_error<JITLinkError>(
+ "FDE at " + formatv("{0:x16}", CurRecordAtom->getAddress()) +
+ " points to non-existant CIE at " +
+ formatv("{0:x16}", CIEPointerAddress - CIEPointer));
+ auto &CIEInfo = CIEInfoItr->second;
// The CIEPointer looks good. Add a relocation.
CurRecordAtom->addEdge(FDEToCIERelocKind,
CIEPointerAddress - CurRecordAtom->getAddress(),
- *CIEAtom, 0);
+ *CIEInfo.CIEAtom, 0);
// Read and sanity check the PC-start pointer and size.
JITTargetAddress PCBeginAddress = EHFrameAddress + EHFrameReader.getOffset();
@@ -329,15 +336,15 @@ Error EHFrameParser::processFDE(JITTargetAddress CIEPointerAddress,
if (auto Err = EHFrameReader.skip(G.getPointerSize()))
return Err;
- if (LSDAFieldPresent) {
+ if (CIEInfo.FDEsHaveLSDAField) {
uint64_t AugmentationDataSize;
if (auto Err = EHFrameReader.readULEB128(AugmentationDataSize))
return Err;
if (AugmentationDataSize != G.getPointerSize())
- return make_error<JITLinkError>("Unexpected FDE augmentation data size "
- "(expected " +
- Twine(G.getPointerSize()) + ", got " +
- Twine(AugmentationDataSize) + ")");
+ return make_error<JITLinkError>(
+ "Unexpected FDE augmentation data size (expected " +
+ Twine(G.getPointerSize()) + ", got " + Twine(AugmentationDataSize) +
+ ") for FDE at " + formatv("{0:x16}", CurRecordAtom->getAddress()));
JITTargetAddress LSDAAddress = EHFrameAddress + EHFrameReader.getOffset();
auto LSDADelta = readAbsolutePointer();
if (!LSDADelta)
diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
index 78be89cfca9..d679edef7ea 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
@@ -44,13 +44,20 @@ private:
Error processCIE();
Error processFDE(JITTargetAddress CIEPointerAddress, uint32_t CIEPointer);
+ struct CIEInformation {
+ CIEInformation() = default;
+ CIEInformation(DefinedAtom &CIEAtom) : CIEAtom(&CIEAtom) {}
+ DefinedAtom *CIEAtom = nullptr;
+ bool FDEsHaveLSDAField = false;
+ };
+
AtomGraph &G;
Section &EHFrameSection;
StringRef EHFrameContent;
JITTargetAddress EHFrameAddress;
BinaryStreamReader EHFrameReader;
DefinedAtom *CurRecordAtom = nullptr;
- bool LSDAFieldPresent = false;
+ DenseMap<JITTargetAddress, CIEInformation> CIEInfos;
Edge::Kind FDEToCIERelocKind;
Edge::Kind FDEToTargetRelocKind;
};
diff --git a/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o
new file mode 100644
index 00000000000..ba489b0cd9b
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o
Binary files differ
diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
new file mode 100644
index 00000000000..84bc14e3b23
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
@@ -0,0 +1,5 @@
+# RUN: llvm-jitlink -noexec %S/Inputs/MachO_x86-64_ehframe.o
+#
+# Perform a no-exec link of MachO_x86-64_ehframe and verify that it does not
+# generate any errors despite the last FDE referring to the first CIE (rather
+# than the most recent). \ No newline at end of file
diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s
index c1f6bc955e9..330695aebe1 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s
@@ -1,6 +1,6 @@
# RUN: rm -rf %t && mkdir -p %t
-# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/test_x86-64.o %s
-# RUN: llvm-jitlink -noexec -define-abs external_data=0xdeadbeef -define-abs external_func=0xcafef00d -check=%s %t/test_x86-64.o
+# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/macho_reloc.o %s
+# RUN: llvm-jitlink -noexec -define-abs external_data=0xdeadbeef -define-abs external_func=0xcafef00d -check=%s %t/macho_reloc.o
.section __TEXT,__text,regular,pure_instructions
@@ -32,8 +32,8 @@ _main:
# Validate both the reference to the GOT entry, and also the content of the GOT
# entry.
#
-# jitlink-check: decode_operand(test_gotld, 4) = got_addr(test_x86-64.o, external_data) - next_pc(test_gotld)
-# jitlink-check: *{8}(got_addr(test_x86-64.o, external_data)) = external_data
+# jitlink-check: decode_operand(test_gotld, 4) = got_addr(macho_reloc.o, external_data) - next_pc(test_gotld)
+# jitlink-check: *{8}(got_addr(macho_reloc.o, external_data)) = external_data
.globl test_gotld
.align 4, 0x90
test_gotld:
@@ -43,8 +43,8 @@ test_gotld:
# Check that calls to external functions trigger the generation of stubs and GOT
# entries.
#
-# jitlink-check: decode_operand(test_external_call, 0) = stub_addr(test_x86-64.o, external_func) - next_pc(test_external_call)
-# jitlink-check: *{8}(got_addr(test_x86-64.o, external_func)) = external_func
+# jitlink-check: decode_operand(test_external_call, 0) = stub_addr(macho_reloc.o, external_func) - next_pc(test_external_call)
+# jitlink-check: *{8}(got_addr(macho_reloc.o, external_func)) = external_func
.globl test_external_call
.align 4, 0x90
test_external_call:
@@ -84,22 +84,22 @@ signed4:
movl $0xAAAAAAAA, named_data(%rip)
.globl signedanon
-# jitlink-check: decode_operand(signedanon, 4) = section_addr(test_x86-64.o, __data) - next_pc(signedanon)
+# jitlink-check: decode_operand(signedanon, 4) = section_addr(macho_reloc.o, __data) - next_pc(signedanon)
signedanon:
movq Lanon_data(%rip), %rax
.globl signed1anon
-# jitlink-check: decode_operand(signed1anon, 3) = section_addr(test_x86-64.o, __data) - next_pc(signed1anon)
+# jitlink-check: decode_operand(signed1anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed1anon)
signed1anon:
movb $0xAA, Lanon_data(%rip)
.globl signed2anon
-# jitlink-check: decode_operand(signed2anon, 3) = section_addr(test_x86-64.o, __data) - next_pc(signed2anon)
+# jitlink-check: decode_operand(signed2anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed2anon)
signed2anon:
movw $0xAAAA, Lanon_data(%rip)
.globl signed4anon
-# jitlink-check: decode_operand(signed4anon, 3) = section_addr(test_x86-64.o, __data) - next_pc(signed4anon)
+# jitlink-check: decode_operand(signed4anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed4anon)
signed4anon:
movl $0xAAAAAAAA, Lanon_data(%rip)
@@ -117,13 +117,13 @@ Lanon_data:
# invalid because the minuend can not be local.
#
# Note: +8 offset in expression below to accounts for sizeof(Lanon_data).
-# jitlink-check: *{8}(section_addr(test_x86-64.o, __data) + 8) = (section_addr(test_x86-64.o, __data) + 8) - named_data + 2
+# jitlink-check: *{8}(section_addr(macho_reloc.o, __data) + 8) = (section_addr(macho_reloc.o, __data) + 8) - named_data + 2
.p2align 3
Lanon_minuend_quad:
.quad Lanon_minuend_quad - named_data + 2
# Note: +16 offset in expression below to accounts for sizeof(Lanon_data) + sizeof(Lanon_minuend_long).
-# jitlink-check: *{4}(section_addr(test_x86-64.o, __data) + 16) = ((section_addr(test_x86-64.o, __data) + 16) - named_data + 2)[31:0]
+# jitlink-check: *{4}(section_addr(macho_reloc.o, __data) + 16) = ((section_addr(macho_reloc.o, __data) + 16) - named_data + 2)[31:0]
.p2align 2
Lanon_minuend_long:
.long Lanon_minuend_long - named_data + 2
@@ -147,7 +147,7 @@ named_func_addr:
# Check X86_64_RELOC_UNSIGNED / non-extern handling by putting the address of a
# local anonymous function in a pointer variable.
#
-# jitlink-check: *{8}anon_func_addr = section_addr(test_x86-64.o, __text)
+# jitlink-check: *{8}anon_func_addr = section_addr(macho_reloc.o, __text)
.globl anon_func_addr
.p2align 3
anon_func_addr:
@@ -155,7 +155,7 @@ anon_func_addr:
# X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend
#
-# jitlink-check: *{8}minuend_quad1 = section_addr(test_x86-64.o, __data) - minuend_quad1 + 2
+# jitlink-check: *{8}minuend_quad1 = section_addr(macho_reloc.o, __data) - minuend_quad1 + 2
# Only the form "B: .quad LA - B + C" is tested. The form "B: .quad B - LA + C" is
# invalid because the minuend can not be local.
.globl minuend_quad1
@@ -163,7 +163,7 @@ anon_func_addr:
minuend_quad1:
.quad Lanon_data - minuend_quad1 + 2
-# jitlink-check: *{4}minuend_long1 = (section_addr(test_x86-64.o, __data) - minuend_long1 + 2)[31:0]
+# jitlink-check: *{4}minuend_long1 = (section_addr(macho_reloc.o, __data) - minuend_long1 + 2)[31:0]
.globl minuend_long1
.p2align 2
minuend_long1:
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index f3333f23faf..29516f093fe 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -326,14 +326,37 @@ Session::findSymbolInfo(StringRef SymbolName, Twine ErrorMsgStem) {
} // end namespace llvm
+Triple getFirstFileTriple() {
+ assert(!InputFiles.empty() && "InputFiles can not be empty");
+ auto ObjBuffer =
+ ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
+ auto Obj = ExitOnErr(
+ object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
+ return Obj->makeTriple();
+}
+
+void setEntryPointNameIfNotProvided(const Session &S) {
+ if (EntryPointName.empty()) {
+ if (S.TT.getObjectFormat() == Triple::MachO)
+ EntryPointName = "_main";
+ else
+ EntryPointName = "main";
+ }
+}
+
Error loadProcessSymbols(Session &S) {
std::string ErrMsg;
if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &ErrMsg))
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
char GlobalPrefix = S.TT.getObjectFormat() == Triple::MachO ? '_' : '\0';
- S.ES.getMainJITDylib().setGenerator(ExitOnErr(
- orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(GlobalPrefix)));
+ auto InternedEntryPointName = S.ES.intern(EntryPointName);
+ auto FilterMainEntryPoint = [InternedEntryPointName](SymbolStringPtr Name) {
+ return Name != InternedEntryPointName;
+ };
+ S.ES.getMainJITDylib().setGenerator(
+ ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
+ GlobalPrefix, FilterMainEntryPoint)));
return Error::success();
}
@@ -352,15 +375,6 @@ Error loadDylibs() {
return Error::success();
}
-Triple getFirstFileTriple() {
- assert(!InputFiles.empty() && "InputFiles can not be empty");
- auto ObjBuffer =
- ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
- auto Obj = ExitOnErr(
- object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
- return Obj->makeTriple();
-}
-
Error loadObjects(Session &S) {
std::map<unsigned, JITDylib *> IdxToJLD;
@@ -542,16 +556,6 @@ static void dumpSessionStats(Session &S) {
}
static Expected<JITEvaluatedSymbol> getMainEntryPoint(Session &S) {
-
- // First, if the entry point has not been set, set it to a sensible default
- // for this process.
- if (EntryPointName.empty()) {
- if (S.TT.getObjectFormat() == Triple::MachO)
- EntryPointName = "_main";
- else
- EntryPointName = "main";
- }
-
return S.ES.lookup(S.JDSearchOrder, EntryPointName);
}
@@ -584,6 +588,8 @@ int main(int argc, char *argv[]) {
Session S(getFirstFileTriple());
+ setEntryPointNameIfNotProvided(S);
+
if (!NoProcessSymbols)
ExitOnErr(loadProcessSymbols(S));
ExitOnErr(loadDylibs());
OpenPOWER on IntegriCloud