Skip to content

Commit

Permalink
Fix incorrect exception handling on aarch64
Browse files Browse the repository at this point in the history
Fixes #3874
  • Loading branch information
SeanTAllen committed Apr 2, 2022
1 parent c3b03ec commit a36cc0e
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 10 deletions.
11 changes: 8 additions & 3 deletions src/libponyrt/lang/lsda.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ static bool lsda_init(lsda_t* lsda, exception_context_t* context)
return true;
}

bool ponyint_lsda_scan(exception_context_t* context, uintptr_t* lp)
bool ponyint_lsda_scan(uintptr_t* ttype_index,
exception_context_t* context,
uintptr_t* lp)
{
lsda_t lsda;

Expand All @@ -231,8 +233,11 @@ bool ponyint_lsda_scan(exception_context_t* context, uintptr_t* lp)
uintptr_t length = read_encoded_ptr(&p, lsda.call_site_encoding);
uintptr_t landing_pad = read_encoded_ptr(&p, lsda.call_site_encoding);

// Pony ignores the action index, since it uses only cleanup landing pads.
read_uleb128(&p);
uintptr_t action_index = read_uleb128(&p);

const uint8_t* action = lsda.action_table + (action_index - 1);
int64_t tti = read_sleb128(&action);
ttype_index = (uintptr_t*)&tti;

if((start <= lsda.ip_offset) && (lsda.ip_offset < (start + length)))
{
Expand Down
4 changes: 3 additions & 1 deletion src/libponyrt/lang/lsda.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ typedef struct _Unwind_Context exception_context_t;
typedef DISPATCHER_CONTEXT exception_context_t;
#endif

bool ponyint_lsda_scan(exception_context_t* context, uintptr_t* lp);
bool ponyint_lsda_scan(uintptr_t* ttype_index,
exception_context_t* context,
uintptr_t* lp);

PONY_EXTERN_C_END

Expand Down
15 changes: 10 additions & 5 deletions src/libponyrt/lang/posix_except.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ PONY_API void pony_error()
abort();
}

static void set_registers(struct _Unwind_Exception* exception,
static void set_registers(uintptr_t ttype_index,
struct _Unwind_Exception* exception,
struct _Unwind_Context* context)
{
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
(uintptr_t)exception);
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0);
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1), ttype_index);
_Unwind_SetIP(context, landing_pad);
}

Expand Down Expand Up @@ -79,7 +80,8 @@ PONY_API _Unwind_Reason_Code ponyint_personality_v0(_Unwind_State state,
{
case _US_VIRTUAL_UNWIND_FRAME:
{
if(!ponyint_lsda_scan(context, &landing_pad))
uintptr_t ignore;
if(!ponyint_lsda_scan(&ignore, context, &landing_pad))
return continue_unwind(exception, context);

// Save r13.
Expand Down Expand Up @@ -133,10 +135,13 @@ PONY_API _Unwind_Reason_Code ponyint_personality_v0(int version,
if(ex_class != PONY_EXCEPTION_CLASS)
return _URC_CONTINUE_UNWIND;

uintptr_t ttype_index;
bool scan_result = ponyint_lsda_scan(&ttype_index, context, &landing_pad);

// The search phase sets up the landing pad.
if(actions & _UA_SEARCH_PHASE)
{
if(!ponyint_lsda_scan(context, &landing_pad))
if(!scan_result)
return _URC_CONTINUE_UNWIND;

return _URC_HANDLER_FOUND;
Expand All @@ -148,7 +153,7 @@ PONY_API _Unwind_Reason_Code ponyint_personality_v0(int version,
return _URC_CONTINUE_UNWIND;

// No need to search again, just set the registers.
set_registers(exception, context);
set_registers(ttype_index, exception, context);
return _URC_INSTALL_CONTEXT;
}

Expand Down
3 changes: 2 additions & 1 deletion src/libponyrt/lang/win_except.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ PONY_API EXCEPTION_DISPOSITION ponyint_personality_v0(
if(!(ExcRecord->ExceptionFlags &
(EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)))
{
if(!ponyint_lsda_scan(DispatcherContext, &landing_pad))
uintptr_t ignore;
if(!ponyint_lsda_scan(&ignore, DispatcherContext, &landing_pad))
return ExceptionContinueSearch;

RtlUnwindEx(EstablisherFrame, (PVOID)landing_pad, ExcRecord,
Expand Down
14 changes: 14 additions & 0 deletions test/libponyc-run/regression-3874-case-1/main.pony
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
actor Main
new create(env: Env) =>
foo("hello")

fun foo(s: String) =>
try
one(s)
error
else
one(s)
end

fun one(s: String) =>
s.clone()
17 changes: 17 additions & 0 deletions test/libponyc-run/regression-3874-case-2/main.pony
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
actor Main
let _out: OutStream

new create(env: Env) =>
_out = env.out
foo("hello")

fun foo(s: String) =>
try
one("h")
error
else
one("e")
end

fun one(s: String) =>
_out.print(s)

0 comments on commit a36cc0e

Please sign in to comment.