Skip to content

Commit f607723

Browse files
aaronj0anutosh491
authored andcommitted
Add llvm libunwind callback to suppress exceptions on apple silicon
See llvm/llvm-project#49036
1 parent 24746af commit f607723

File tree

3 files changed

+79
-2
lines changed

3 files changed

+79
-2
lines changed

lib/Interpreter/Compatibility.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ static inline char* GetEnv(const char* Var_Name) {
7171
#include "llvm/ADT/SmallString.h"
7272
#include "llvm/ADT/StringRef.h"
7373
#include "llvm/ADT/Twine.h"
74+
#include "llvm/BinaryFormat/MachO.h"
7475
#include "llvm/Config/llvm-config.h"
7576
#include "llvm/ExecutionEngine/JITSymbol.h"
7677
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
78+
#include "llvm/Object/MachO.h"
7779
#include "llvm/Support/Casting.h"
7880
#include "llvm/Support/Path.h"
7981

lib/Interpreter/CppInterOp.cpp

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include <map>
5555
#include <set>
5656
#include <sstream>
57+
#include <stack>
5758
#include <string>
5859

5960
// Stream redirect.
@@ -71,7 +72,43 @@
7172
#include <unistd.h>
7273
#endif // WIN32
7374

74-
#include <stack>
75+
#ifdef __APPLE__
76+
// Define a minimal mach header for JIT'd code, to support exceptions on osx 14
77+
// and later. See llvm/llvm-project#49036
78+
static llvm::MachO::mach_header_64 fake_mach_header = {
79+
.magic = llvm::MachO::MH_MAGIC_64,
80+
.cputype = llvm::MachO::CPU_TYPE_ARM64,
81+
.cpusubtype = llvm::MachO::CPU_SUBTYPE_ARM64_ALL,
82+
.filetype = llvm::MachO::MH_DYLIB,
83+
.ncmds = 0,
84+
.sizeofcmds = 0,
85+
.flags = 0,
86+
.reserved = 0};
87+
88+
// Declare libunwind SPI types and functions.
89+
struct unw_dynamic_unwind_sections {
90+
uintptr_t dso_base;
91+
uintptr_t dwarf_section;
92+
size_t dwarf_section_length;
93+
uintptr_t compact_unwind_section;
94+
size_t compact_unwind_section_length;
95+
};
96+
97+
int find_dynamic_unwind_sections(uintptr_t addr,
98+
unw_dynamic_unwind_sections* info) {
99+
info->dso_base = (uintptr_t)&fake_mach_header;
100+
info->dwarf_section = 0;
101+
info->dwarf_section_length = 0;
102+
info->compact_unwind_section = 0;
103+
info->compact_unwind_section_length = 0;
104+
return 1;
105+
}
106+
107+
// Typedef for callback above.
108+
typedef int (*unw_find_dynamic_unwind_sections)(
109+
uintptr_t addr, struct unw_dynamic_unwind_sections* info);
110+
111+
#endif // __APPLE__
75112

76113
namespace Cpp {
77114

@@ -88,7 +125,15 @@ namespace Cpp {
88125
// This might fix the issue https://reviews.llvm.org/D107087
89126
// FIXME: For now we just leak the Interpreter.
90127
struct InterpDeleter {
91-
~InterpDeleter() = default;
128+
~InterpDeleter() {
129+
#ifdef __APPLE__
130+
if (auto* unw_remove_find_dynamic_unwind_sections = (int (*)(
131+
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections))
132+
dlsym(RTLD_DEFAULT, "__unw_remove_find_dynamic_unwind_sections"))
133+
unw_remove_find_dynamic_unwind_sections(find_dynamic_unwind_sections);
134+
#endif
135+
// sInterpreter.release();
136+
}
92137
} Deleter;
93138

94139
static compat::Interpreter& getInterp() {
@@ -2977,6 +3022,14 @@ namespace Cpp {
29773022
// FIXME: Enable this assert once we figure out how to fix the multiple
29783023
// calls to CreateInterpreter.
29793024
//assert(!sInterpreter && "Interpreter already set.");
3025+
#ifdef __APPLE__
3026+
// Add a handler to support exceptions from interpreted code.
3027+
// See llvm/llvm-project#49036
3028+
if (auto* unw_add_find_dynamic_unwind_sections = (int (*)(
3029+
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections))
3030+
dlsym(RTLD_DEFAULT, "__unw_add_find_dynamic_unwind_sections"))
3031+
unw_add_find_dynamic_unwind_sections(find_dynamic_unwind_sections);
3032+
#endif // __APPLE__
29803033
sInterpreter = I;
29813034
return I;
29823035
}

unittests/CppInterOp/InterpreterTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,25 @@ if (llvm::sys::RunningOnValgrind())
305305
delete ExtInterp;
306306
#endif
307307
}
308+
309+
TEST(InterpreterTest, InterpreterExceptions) {
310+
Cpp::CreateInterpreter();
311+
EXPECT_TRUE(Cpp::Declare("int f() { throw 1; return 2; }") == 0);
312+
EXPECT_TRUE(
313+
Cpp::Process(
314+
"int ex() { try { f(); return 0; } catch(...){return 1;} }") == 0);
315+
EXPECT_EQ(Cpp::Evaluate("ex()"), 1)
316+
<< "Failed to catch exceptions in interpreter";
317+
}
318+
319+
TEST(InterpreterTest, InterpreterExceptionsCompiledCode) {
320+
Cpp::CreateInterpreter();
321+
bool caught = false;
322+
try {
323+
EXPECT_TRUE(Cpp::Declare("int f() { throw 1; return 2; }") == 0);
324+
EXPECT_TRUE(Cpp::Process("int res = f();") == 0);
325+
} catch (...) {
326+
caught = true;
327+
}
328+
EXPECT_TRUE(caught) << "Unable to catch exception coming from interpreter";
329+
}

0 commit comments

Comments
 (0)