Skip to content

Commit 218edea

Browse files
committed
rewrite catchjmp asm to use normal relocations instead of manual editing
1 parent a8d7b68 commit 218edea

File tree

5 files changed

+78
-97
lines changed

5 files changed

+78
-97
lines changed

src/cgmemmgr.cpp

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -833,28 +833,6 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
833833
mapAddresses(Dyld, ro_alloc);
834834
mapAddresses(Dyld, exe_alloc);
835835
}
836-
#ifdef _OS_WINDOWS_
837-
template <typename Alloc>
838-
void *lookupWriteAddressFor(void *rt_addr, Alloc &&allocator)
839-
{
840-
for (auto &alloc: allocator->allocations) {
841-
if (alloc.rt_addr == rt_addr) {
842-
return alloc.wr_addr;
843-
}
844-
}
845-
return nullptr;
846-
}
847-
void *lookupWriteAddressFor(void *rt_addr)
848-
{
849-
if (!ro_alloc)
850-
return rt_addr;
851-
if (void *ptr = lookupWriteAddressFor(rt_addr, ro_alloc))
852-
return ptr;
853-
if (void *ptr = lookupWriteAddressFor(rt_addr, exe_alloc))
854-
return ptr;
855-
return rt_addr;
856-
}
857-
#endif // _OS_WINDOWS_
858836
};
859837

860838
uint8_t *RTDyldMemoryManagerJL::allocateCodeSection(uintptr_t Size,
@@ -947,13 +925,6 @@ void RTDyldMemoryManagerJL::deregisterEHFrames(uint8_t *Addr,
947925

948926
}
949927

950-
#ifdef _OS_WINDOWS_
951-
void *lookupWriteAddressFor(RTDyldMemoryManager *memmgr, void *rt_addr)
952-
{
953-
return ((RTDyldMemoryManagerJL*)memmgr)->lookupWriteAddressFor(rt_addr);
954-
}
955-
#endif
956-
957928
RTDyldMemoryManager* createRTDyldMemoryManager()
958929
{
959930
return new RTDyldMemoryManagerJL();

src/codegen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10371,6 +10371,7 @@ static void init_jit_functions(void)
1037110371

1037210372
#ifdef _OS_WINDOWS_
1037310373
#if defined(_CPU_X86_64_)
10374+
add_named_global("__julia_personality", &__julia_personality);
1037410375
#if defined(_COMPILER_GCC_)
1037510376
add_named_global("___chkstk_ms", &___chkstk_ms);
1037610377
#else

src/debug-registry.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,7 @@ class JITDebugInfoRegistry
145145
void add_code_in_flight(llvm::StringRef name, jl_code_instance_t *codeinst, const llvm::DataLayout &DL) JL_NOTSAFEPOINT;
146146
jl_method_instance_t *lookupLinfo(size_t pointer) JL_NOTSAFEPOINT;
147147
void registerJITObject(const llvm::object::ObjectFile &Object,
148-
std::function<uint64_t(const llvm::StringRef &)> getLoadAddress,
149-
std::function<void*(void*)> lookupWriteAddress);
148+
std::function<uint64_t(const llvm::StringRef &)> getLoadAddress);
150149
objectmap_t& getObjectMap() JL_NOTSAFEPOINT;
151150
void add_image_info(image_info_t info) JL_NOTSAFEPOINT;
152151
bool get_image_info(uint64_t base, image_info_t *info) const JL_NOTSAFEPOINT;

src/debuginfo.cpp

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,21 @@ static void create_PRUNTIME_FUNCTION(uint8_t *Code, size_t Size, StringRef fnnam
223223
#endif
224224

225225
void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object,
226-
std::function<uint64_t(const StringRef &)> getLoadAddress,
227-
std::function<void*(void*)> lookupWriteAddress)
226+
std::function<uint64_t(const StringRef &)> getLoadAddress)
228227
{
229228
object::section_iterator EndSection = Object.section_end();
230229

230+
bool anyfunctions = false;
231+
for (const object::SymbolRef &sym_iter : Object.symbols()) {
232+
object::SymbolRef::Type SymbolType = cantFail(sym_iter.getType());
233+
if (SymbolType != object::SymbolRef::ST_Function)
234+
continue;
235+
anyfunctions = true;
236+
break;
237+
}
238+
if (!anyfunctions)
239+
return;
240+
231241
#ifdef _CPU_ARM_
232242
// ARM does not have/use .eh_frame
233243
uint64_t arm_exidx_addr = 0;
@@ -281,14 +291,13 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object,
281291
#if defined(_OS_WINDOWS_)
282292
uint64_t SectionAddrCheck = 0;
283293
uint64_t SectionLoadCheck = 0; (void)SectionLoadCheck;
284-
uint64_t SectionWriteCheck = 0; (void)SectionWriteCheck;
285294
uint8_t *UnwindData = NULL;
286295
#if defined(_CPU_X86_64_)
287296
uint8_t *catchjmp = NULL;
288297
for (const object::SymbolRef &sym_iter : Object.symbols()) {
289298
StringRef sName = cantFail(sym_iter.getName());
290299
if (sName.equals("__UnwindData") || sName.equals("__catchjmp")) {
291-
uint64_t Addr = cantFail(sym_iter.getAddress());
300+
uint64_t Addr = cantFail(sym_iter.getAddress()); // offset into object (including section offset)
292301
auto Section = cantFail(sym_iter.getSection());
293302
assert(Section != EndSection && Section->isText());
294303
uint64_t SectionAddr = Section->getAddress();
@@ -300,10 +309,7 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object,
300309
SectionLoadCheck == SectionLoadAddr);
301310
SectionAddrCheck = SectionAddr;
302311
SectionLoadCheck = SectionLoadAddr;
303-
SectionWriteCheck = SectionLoadAddr;
304-
if (lookupWriteAddress)
305-
SectionWriteCheck = (uintptr_t)lookupWriteAddress((void*)SectionLoadAddr);
306-
Addr += SectionWriteCheck - SectionLoadCheck;
312+
Addr += SectionLoadAddr - SectionAddr;
307313
if (sName.equals("__UnwindData")) {
308314
UnwindData = (uint8_t*)Addr;
309315
}
@@ -314,25 +320,7 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object,
314320
}
315321
assert(catchjmp);
316322
assert(UnwindData);
317-
assert(SectionAddrCheck);
318323
assert(SectionLoadCheck);
319-
assert(!memcmp(catchjmp, "\0\0\0\0\0\0\0\0\0\0\0\0", 12) &&
320-
!memcmp(UnwindData, "\0\0\0\0\0\0\0\0\0\0\0\0", 12));
321-
catchjmp[0] = 0x48;
322-
catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [&__julia_personality]
323-
*(uint64_t*)(&catchjmp[2]) = (uint64_t)&__julia_personality;
324-
catchjmp[10] = 0xff;
325-
catchjmp[11] = 0xe0; // jmp RAX
326-
UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER
327-
UnwindData[1] = 4; // size of prolog (bytes)
328-
UnwindData[2] = 2; // count of unwind codes (slots)
329-
UnwindData[3] = 0x05; // frame register (rbp) = rsp
330-
UnwindData[4] = 4; // second instruction
331-
UnwindData[5] = 0x03; // mov RBP, RSP
332-
UnwindData[6] = 1; // first instruction
333-
UnwindData[7] = 0x50; // push RBP
334-
*(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - (uint8_t*)SectionWriteCheck); // relative location of catchjmp
335-
UnwindData -= SectionWriteCheck - SectionLoadCheck;
336324
#endif // defined(_OS_X86_64_)
337325
#endif // defined(_OS_WINDOWS_)
338326

@@ -353,7 +341,7 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object,
353341
uint64_t SectionAddr = Section->getAddress();
354342
StringRef secName = cantFail(Section->getName());
355343
uint64_t SectionLoadAddr = getLoadAddress(secName);
356-
Addr -= SectionAddr - SectionLoadAddr;
344+
Addr += SectionLoadAddr - SectionAddr;
357345
StringRef sName = cantFail(sym_iter.getName());
358346
uint64_t SectionSize = Section->getSize();
359347
size_t Size = sym_size.second;
@@ -404,10 +392,9 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object,
404392
}
405393

406394
void jl_register_jit_object(const object::ObjectFile &Object,
407-
std::function<uint64_t(const StringRef &)> getLoadAddress,
408-
std::function<void *(void *)> lookupWriteAddress)
395+
std::function<uint64_t(const StringRef &)> getLoadAddress)
409396
{
410-
getJITDebugRegistry().registerJITObject(Object, getLoadAddress, lookupWriteAddress);
397+
getJITDebugRegistry().registerJITObject(Object, getLoadAddress);
411398
}
412399

413400
// TODO: convert the safe names from aotcomile.cpp:makeSafeName back into symbols

src/jitlayers.cpp

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,7 @@ static Expected<orc::ThreadSafeModule> selectOptLevel(orc::ThreadSafeModule TSM,
665665
}
666666

667667
void jl_register_jit_object(const object::ObjectFile &debugObj,
668-
std::function<uint64_t(const StringRef &)> getLoadAddress,
669-
std::function<void *(void *)> lookupWriteAddress);
668+
std::function<uint64_t(const StringRef &)> getLoadAddress);
670669

671670
namespace {
672671

@@ -726,7 +725,7 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin {
726725
return result->second;
727726
};
728727

729-
jl_register_jit_object(*NewInfo->Object, getLoadAddress, nullptr);
728+
jl_register_jit_object(*NewInfo->Object, getLoadAddress);
730729
PendingObjs.erase(&MR);
731730
}
732731

@@ -957,10 +956,6 @@ class ForwardingMemoryManager : public RuntimeDyld::MemoryManager {
957956
};
958957

959958

960-
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
961-
void *lookupWriteAddressFor(RTDyldMemoryManager *MemMgr, void *rt_addr);
962-
#endif
963-
964959
void registerRTDyldJITObject(const object::ObjectFile &Object,
965960
const RuntimeDyld::LoadedObjectInfo &L,
966961
const std::shared_ptr<RTDyldMemoryManager> &MemMgr)
@@ -983,14 +978,7 @@ void registerRTDyldJITObject(const object::ObjectFile &Object,
983978
};
984979

985980
auto DebugObject = L.getObjectForDebug(Object); // ELF requires us to make a copy to mutate the header with the section load addresses. On other platforms this is a no-op.
986-
jl_register_jit_object(DebugObject.getBinary() ? *DebugObject.getBinary() : Object,
987-
getLoadAddress,
988-
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
989-
[MemMgr](void *p) { return lookupWriteAddressFor(MemMgr.get(), p); }
990-
#else
991-
nullptr
992-
#endif
993-
);
981+
jl_register_jit_object(DebugObject.getBinary() ? *DebugObject.getBinary() : Object, getLoadAddress);
994982
}
995983
namespace {
996984
static std::unique_ptr<TargetMachine> createTargetMachine() JL_NOTSAFEPOINT {
@@ -1281,8 +1269,9 @@ namespace {
12811269
}
12821270

12831271
// Windows needs some inline asm to help
1284-
// build unwind tables
1285-
jl_decorate_module(M);
1272+
// build unwind tables, if they have any functions to decorate
1273+
if (!M.functions().empty())
1274+
jl_decorate_module(M);
12861275
});
12871276
return std::move(TSM);
12881277
}
@@ -2255,30 +2244,64 @@ static void jl_decorate_module(Module &M) {
22552244
if (TT.isOSWindows() && TT.getArch() == Triple::x86_64) {
22562245
// Add special values used by debuginfo to build the UnwindData table registration for Win64
22572246
// This used to be GV, but with https://reviews.llvm.org/D100944 we no longer can emit GV into `.text`
2258-
// TODO: The data is set in debuginfo.cpp but it should be okay to actually emit it here.
2259-
std::string inline_asm = "\
2260-
.section ";
2261-
inline_asm +=
2247+
// and with JITLink it became difficult to change the content afterwards, but we
2248+
// would prefer that this simple content wasn't recompiled in every single module,
2249+
// so we emit the necessary PLT trampoline as inline assembly.
2250+
// This is somewhat duplicated with the .pdata section, but we haven't been able to
2251+
// use that yet due to relocation issues.
2252+
#define ASM_USES_ELF // use ELF or COFF syntax based on FORCE_ELF
2253+
StringRef inline_asm(
2254+
".section"
22622255
#if JL_LLVM_VERSION >= 180000
2263-
".ltext,\"ax\",@progbits";
2256+
" .ltext,\"ax\",@progbits\n"
22642257
#else
2265-
".text";
2258+
" .text\n"
22662259
#endif
2267-
inline_asm += "\n\
2268-
.type __UnwindData,@object \n\
2269-
.p2align 2, 0x90 \n\
2270-
__UnwindData: \n\
2271-
.zero 12 \n\
2272-
.size __UnwindData, 12 \n\
2273-
\n\
2274-
.type __catchjmp,@object \n\
2275-
.p2align 2, 0x90 \n\
2276-
__catchjmp: \n\
2277-
.zero 12 \n\
2278-
.size __catchjmp, 12";
2279-
2260+
".globl __julia_personality\n"
2261+
"\n"
2262+
#ifdef ASM_USES_ELF
2263+
".type __UnwindData,@object\n"
2264+
#else
2265+
".def __UnwindData\n"
2266+
".scl 2\n"
2267+
".type 0\n"
2268+
".endef\n"
2269+
#endif
2270+
".p2align 2, 0x90\n"
2271+
"__UnwindData:\n"
2272+
" .byte 0x09;\n" // version info, UNW_FLAG_EHANDLER
2273+
" .byte 4;\n" // size of prolog (bytes)
2274+
" .byte 2;\n" // count of unwind codes (slots)
2275+
" .byte 0x05;\n" // frame register (rbp) = rsp
2276+
" .byte 4;\n" // second instruction
2277+
" .byte 0x03;\n" // mov RBP, RSP
2278+
" .byte 1;\n" // first instruction
2279+
" .byte 0x50;\n" // push RBP
2280+
" .int __catchjmp - "
2281+
#if JL_LLVM_VERSION >= 180000
2282+
".ltext;\n" // Section-relative offset (if using COFF and JITLink, this can be relative to __ImageBase instead, though then we could possibly use pdata/xdata directly then)
2283+
#else
2284+
".text;\n"
2285+
#endif
2286+
".size __UnwindData, 12\n"
2287+
"\n"
2288+
#ifdef ASM_USES_ELF
2289+
".type __catchjmp,@function\n"
2290+
#else
2291+
".def __catchjmp\n"
2292+
".scl 2\n"
2293+
".type 32\n"
2294+
".endef\n"
2295+
#endif
2296+
".p2align 2, 0x90\n"
2297+
"__catchjmp:\n"
2298+
" movabsq $__julia_personality, %rax\n"
2299+
" jmpq *%rax\n"
2300+
".size __catchjmp, . - __catchjmp\n"
2301+
"\n");
22802302
M.appendModuleInlineAsm(inline_asm);
22812303
}
2304+
#undef ASM_USES_ELF
22822305
}
22832306

22842307
#ifndef JL_USE_JITLINK

0 commit comments

Comments
 (0)