Skip to content

Commit

Permalink
Add llvm libunwind callback to suppress exceptions on apple silicon
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronj0 authored and vgvassilev committed May 3, 2024
1 parent 244d1ab commit a7ae7ef
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/Interpreter/Compatibility.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Path.h"

Expand Down
52 changes: 51 additions & 1 deletion lib/Interpreter/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,51 @@
#include <unistd.h>
#endif // WIN32

#ifdef __APPLE__
// Define a minimal mach header for JIT'd code, to support exceptions on osx 14
// and later. See llvm/llvm-project#49036
static llvm::MachO::mach_header_64 fake_mach_header = {
.magic = llvm::MachO::MH_MAGIC_64,
.cputype = llvm::MachO::CPU_TYPE_ARM64,
.cpusubtype = llvm::MachO::CPU_SUBTYPE_ARM64_ALL,
.filetype = llvm::MachO::MH_DYLIB,
.ncmds = 0,
.sizeofcmds = 0,
.flags = 0,
.reserved = 0};

// Declare libunwind SPI types and functions.
struct unw_dynamic_unwind_sections {
uintptr_t dso_base;
uintptr_t dwarf_section;
size_t dwarf_section_length;
uintptr_t compact_unwind_section;
size_t compact_unwind_section_length;
};

int find_dynamic_unwind_sections(uintptr_t addr,
unw_dynamic_unwind_sections* info) {
info->dso_base = (uintptr_t)&fake_mach_header;
info->dwarf_section = 0;
info->dwarf_section_length = 0;
info->compact_unwind_section = 0;
info->compact_unwind_section_length = 0;
return 1;
}

// Typedef for callback above.
typedef int (*unw_find_dynamic_unwind_sections)(
uintptr_t addr, struct unw_dynamic_unwind_sections* info);

void removeFindDynamicUnwindSections() {
if (auto* unw_remove_find_dynamic_unwind_sections = (int (*)(
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections))
dlsym(RTLD_DEFAULT, "__unw_remove_find_dynamic_unwind_sections"))
unw_remove_find_dynamic_unwind_sections(find_dynamic_unwind_sections);
}

#endif // __APPLE__

namespace Cpp {

using namespace clang;
Expand All @@ -62,7 +107,12 @@ namespace Cpp {
// This might fix the issue https://reviews.llvm.org/D107087
// FIXME: For now we just leak the Interpreter.
struct InterpDeleter {
~InterpDeleter() { sInterpreter.release(); }
~InterpDeleter() {
#ifdef __APPLE__
removeFindDynamicUnwindSections();
#endif
sInterpreter.release();
}
} Deleter;

static compat::Interpreter& getInterp() {
Expand Down
12 changes: 12 additions & 0 deletions unittests/CppInterOp/InterpreterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,15 @@ TEST(InterpreterTest, DetectSystemCompilerIncludePaths) {
Cpp::DetectSystemCompilerIncludePaths(includes);
EXPECT_FALSE(includes.empty());
}

TEST(InterpreterTest, InterpreterExceptions) {
Cpp::CreateInterpreter();
bool caught = false;
try {
EXPECT_TRUE(Cpp::Declare("int f() { throw; return 1; }") == 0);
EXPECT_TRUE(Cpp::Process("int res = f();") == 0);
} catch (...) {
caught = true;
}
EXPECT_TRUE(caught) << "Unable to catch exception coming from interpreter";
}

0 comments on commit a7ae7ef

Please sign in to comment.