Skip to content

Commit

Permalink
Merge pull request #11667 from JuliaLang/kf/unwinder
Browse files Browse the repository at this point in the history
Register JIT frames with the correct unwinder when linking LLVM dylib
  • Loading branch information
Keno committed Jun 11, 2015
2 parents debb22e + 47f697b commit b3a7342
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ endif
LLVMLINK = $(call exec,$(LLVM_CONFIG) --ldflags) $(call exec,$(LLVM_CONFIG) --libs) $(call exec,$(LLVM_CONFIG) --ldflags) $(call exec,$(LLVM_CONFIG) --system-libs 2> /dev/null)
ifeq ($(USE_LLVM_SHLIB),1)
LLVMLINK = $(call exec,$(LLVM_CONFIG) --ldflags) -lLLVM-$(call exec,$(LLVM_CONFIG) --version)
FLAGS += -DLLVM_SHLIB
endif

COMMON_LIBS = -L$(build_shlibdir) -L$(build_libdir) $(LIBUV) $(LIBUTF8PROC) $(NO_WHOLE_ARCHIVE) $(LLVMLINK) $(OSLIBS)
Expand Down
6 changes: 6 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ static GlobalVariable *jldll_var;
extern JITMemoryManager* createJITMemoryManagerWin();
#endif
#endif //_OS_WINDOWS_
#if defined(_OS_DARWIN_) && defined(LLVM37) && defined(LLVM_SHLIB)
#define CUSTOM_MEMORY_MANAGER 1
extern RTDyldMemoryManager* createRTDyldMemoryManagerOSX();
#endif

// important functions
static Function *jlnew_func;
Expand Down Expand Up @@ -5623,6 +5627,8 @@ extern "C" void jl_init_codegen(void)
eb .setEngineKind(EngineKind::JIT)
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) && !defined(USE_MCJIT)
.setJITMemoryManager(createJITMemoryManagerWin())
#elif defined(CUSTOM_MEMORY_MANAGER)
.setMCJITMemoryManager(std::move(std::unique_ptr<RTDyldMemoryManager>{createRTDyldMemoryManagerOSX()}))
#endif
.setTargetOptions(options)
.setRelocationModel(Reloc::PIC_)
Expand Down
71 changes: 71 additions & 0 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,77 @@ int jl_get_llvmf_info(uint64_t fptr, uint64_t *symsize, uint64_t *slide,
}


#if defined(_OS_DARWIN_) && defined(LLVM37) && defined(LLVM_SHLIB)

/*
* We use a custom unwinder, so we need to make sure that when registering dynamic
* frames, we do so with our unwinder rather than with the system one. If LLVM is
* statically linked everything works out fine, but if it's dynamically linked
* it would usually pick up the system one, so we need to do the registration
* ourselves to ensure the right one gets picked.
*/

#include "llvm/ExecutionEngine/SectionMemoryManager.h"
class RTDyldMemoryManagerOSX : public SectionMemoryManager
{
RTDyldMemoryManagerOSX(const RTDyldMemoryManagerOSX&) = delete;
void operator=(const RTDyldMemoryManagerOSX&) = delete;

public:
RTDyldMemoryManagerOSX() {};
~RTDyldMemoryManagerOSX() override {};
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size);
};

extern "C" void __register_frame(void*);
extern "C" void __deregister_frame(void*);

static const char *processFDE(const char *Entry, bool isDeregister) {
const char *P = Entry;
uint32_t Length = *((const uint32_t *)P);
P += 4;
uint32_t Offset = *((const uint32_t *)P);
if (Offset != 0) {
if (isDeregister)
__deregister_frame(const_cast<char *>(Entry));
else
__register_frame(const_cast<char *>(Entry));
}
return P + Length;
}

// This implementation handles frame registration for local targets.
// Memory managers for remote targets should re-implement this function
// and use the LoadAddr parameter.
void RTDyldMemoryManagerOSX::registerEHFrames(uint8_t *Addr,
uint64_t LoadAddr,
size_t Size) {
// On OS X OS X __register_frame takes a single FDE as an argument.
// See http:https://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061768.html
const char *P = (const char *)Addr;
const char *End = P + Size;
do {
P = processFDE(P, false);
} while(P != End);
}

void RTDyldMemoryManagerOSX::deregisterEHFrames(uint8_t *Addr,
uint64_t LoadAddr,
size_t Size) {
const char *P = (const char *)Addr;
const char *End = P + Size;
do {
P = processFDE(P, true);
} while(P != End);
}

RTDyldMemoryManager* createRTDyldMemoryManagerOSX() {
return new RTDyldMemoryManagerOSX();
}

#endif

#if defined(_OS_WINDOWS_)
#ifdef USE_MCJIT
extern "C"
Expand Down

0 comments on commit b3a7342

Please sign in to comment.