Skip to content

Commit

Permalink
Partial fix for #381: exit the simulator with failure even if the err…
Browse files Browse the repository at this point in the history
…or handler causes a stack overflow.

This uses a stackless error handler to recover from stack overflow in
the stack-hungry error printing path. The handler just continues to
the simulator_exit call. This is not a very satisfactory solution as
it requires a call to switcher_handler_invocation_count_reset which
could result in an infinite loop if an error occurs in the handler
that is not handled by compartment_error_handler instead of by the
stackless error handler.

The stackless error handler will only be invoked if the compartment
links with the unwind_error_handler library.
  • Loading branch information
rmn30 committed Dec 18, 2024
1 parent c633c64 commit f128435
Showing 1 changed file with 29 additions and 24 deletions.
53 changes: 29 additions & 24 deletions sdk/include/fail-simulator-on-error.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <debug.hh>
#include <priv/riscv.h>
#include <simulator.h>
#include <unwind.h>
#include <switcher.h>

using DebugErrorHandler = ConditionalDebug<
#ifdef NDEBUG
Expand Down Expand Up @@ -40,32 +42,35 @@ using DebugErrorHandler = ConditionalDebug<
extern "C" ErrorRecoveryBehaviour
compartment_error_handler(ErrorState *frame, size_t mcause, size_t mtval)
{
if (mcause == priv::MCAUSE_CHERI)
{
// An unexpected error -- log it and end the simulation with error.
// Note: handle CZR differently as `get_register_value` will return a
// nullptr which we cannot dereference.
switcher_handler_invocation_count_reset();
on_error([&] {
if (mcause == priv::MCAUSE_CHERI)
{
// An unexpected error -- log it and end the simulation with error.
// Note: handle CZR differently as `get_register_value` will return a
// nullptr which we cannot dereference.

auto [exceptionCode, registerNumber] =
CHERI::extract_cheri_mtval(mtval);
auto [exceptionCode, registerNumber] =
CHERI::extract_cheri_mtval(mtval);

DebugErrorHandler::log(
"{} error at {} (return address: {}), with capability register "
"{}: {}",
exceptionCode,
frame->pcc,
frame->get_register_value<CHERI::RegisterNumber::CRA>(),
registerNumber,
registerNumber == CHERI::RegisterNumber::CZR
? nullptr
: *frame->get_register_value(registerNumber));
}
else
{
// other error (e.g. __builtin_trap causes ReservedInstruciton)
// log and end simulation with error.
DebugErrorHandler::log("Unhandled error {} at {}", mcause, frame->pcc);
}
DebugErrorHandler::log(
"{} error at {} (return address: {}), with capability register "
"{}: {}",
exceptionCode,
frame->pcc,
frame->get_register_value<CHERI::RegisterNumber::CRA>(),
registerNumber,
registerNumber == CHERI::RegisterNumber::CZR
? nullptr
: *frame->get_register_value(registerNumber));
}
else
{
// other error (e.g. __builtin_trap causes ReservedInstruciton)
// log and end simulation with error.
DebugErrorHandler::log("Unhandled error {} at {}", mcause, frame->pcc);
}
});

simulation_exit(1);
/*
Expand Down

0 comments on commit f128435

Please sign in to comment.