Results: Implement namespaced, type-safe results.

Because I was working on multiple things at once, this commit also:
- Adds wrappers for/linker flags to wrap CXX exceptions to make them
  abort. This saves ~0x8000 of memory in every system module.
- Broadly replaces lines of the pattern if (cond) { return ResultX; }
  with R_UNLESS(!cond, ResultX());.
- Reworks the R_TRY_CATCH macros (and the result macros in general).
This commit is contained in:
Michael Scire 2019-10-24 01:40:44 -07:00 committed by SciresM
parent 15773e4755
commit 4059dc6187
169 changed files with 2172 additions and 1868 deletions

View file

@ -28,7 +28,7 @@ namespace sts::fatal::srv {
u64 lr;
};
bool IsThreadFatalCaller(u32 error_code, u32 debug_handle, u64 thread_id, u64 thread_tls_addr, ThreadContext *thread_ctx) {
bool IsThreadFatalCaller(Result result, u32 debug_handle, u64 thread_id, u64 thread_tls_addr, ThreadContext *thread_ctx) {
/* Verify that the thread is running or waiting. */
{
u64 _;
@ -71,7 +71,7 @@ namespace sts::fatal::srv {
const struct {
CmifInHeader header;
u32 error_code;
Result result;
} *in_data = decltype(in_data)(request.data.data_words);
static_assert(sizeof(*in_data) == 0x14, "InData!");
@ -112,7 +112,7 @@ namespace sts::fatal::srv {
return false;
}
if (in_data->error_code != error_code) {
if (in_data->result.GetValue() != result.GetValue()) {
return false;
}
}
@ -226,7 +226,7 @@ namespace sts::fatal::srv {
continue;
}
if (IsThreadFatalCaller(ctx->error_code, debug_handle.Get(), cur_thread_id, thread_id_to_tls[cur_thread_id], &thread_ctx)) {
if (IsThreadFatalCaller(ctx->result, debug_handle.Get(), cur_thread_id, thread_id_to_tls[cur_thread_id], &thread_ctx)) {
thread_id = cur_thread_id;
found_fatal_caller = true;
break;

View file

@ -29,12 +29,10 @@ namespace sts::fatal::srv {
std::scoped_lock lk{this->lock};
/* Only allow GetEvent to succeed NumFatalEvents times. */
if (this->num_events_gotten >= FatalEventManager::NumFatalEvents) {
return ResultFatalTooManyEvents;
}
R_UNLESS(this->num_events_gotten < FatalEventManager::NumFatalEvents, ResultTooManyEvents());
*out = this->events[this->num_events_gotten++].revent;
return ResultSuccess;
return ResultSuccess();
}
void FatalEventManager::SignalEvents() {

View file

@ -57,6 +57,12 @@ namespace sts::ams {
}
namespace sts::result {
bool CallFatalOnResultAssertion = false;
}
using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {

View file

@ -106,11 +106,11 @@ namespace sts::fatal::srv {
void CheckRepairStatus() {
if (IsInRepairWithoutVolHeld()) {
ThrowFatalForSelf(ResultFatalInRepairWithoutVolHeld);
ThrowFatalForSelf(ResultInRepairWithoutVolHeld());
}
if (IsInRepairWithoutTimeReviserCartridge()) {
ThrowFatalForSelf(ResultFatalInRepairWithoutTimeReviserCartridge);
ThrowFatalForSelf(ResultInRepairWithoutTimeReviserCartridge());
}
}

View file

@ -33,11 +33,9 @@ namespace sts::fatal::srv {
bool has_thrown;
private:
Result TrySetHasThrown() {
if (this->has_thrown) {
return ResultFatalAlreadyThrown;
}
R_UNLESS(!this->has_thrown, ResultAlreadyThrown());
this->has_thrown = true;
return ResultSuccess;
return ResultSuccess();
}
public:
ServiceContext() {
@ -51,32 +49,30 @@ namespace sts::fatal::srv {
return this->event_manager.GetEvent(out);
}
Result ThrowFatal(u32 error_code, os::ProcessId process_id) {
return this->ThrowFatalWithCpuContext(error_code, process_id, FatalType_ErrorReportAndErrorScreen, {});
Result ThrowFatal(Result result, os::ProcessId process_id) {
return this->ThrowFatalWithCpuContext(result, process_id, FatalType_ErrorReportAndErrorScreen, {});
}
Result ThrowFatalWithPolicy(u32 error_code, os::ProcessId process_id, FatalType policy) {
return this->ThrowFatalWithCpuContext(error_code, process_id, policy, {});
Result ThrowFatalWithPolicy(Result result, os::ProcessId process_id, FatalType policy) {
return this->ThrowFatalWithCpuContext(result, process_id, policy, {});
}
Result ThrowFatalWithCpuContext(u32 error_code, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx);
Result ThrowFatalWithCpuContext(Result result, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx);
};
/* Context global. */
ServiceContext g_context;
/* Throw implementation. */
Result ServiceContext::ThrowFatalWithCpuContext(u32 error_code, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx) {
Result ServiceContext::ThrowFatalWithCpuContext(Result result, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx) {
/* We don't support Error Report only fatals. */
if (policy == FatalType_ErrorReport) {
return ResultSuccess;
}
R_UNLESS(policy != FatalType_ErrorReport, ResultSuccess());
/* Note that we've thrown fatal. */
R_TRY(this->TrySetHasThrown());
/* At this point we have exclusive access to this->context. */
this->context.error_code = error_code;
this->context.result = result;
this->context.cpu_ctx = cpu_ctx;
/* Cap the stack trace to a sane limit. */
@ -108,8 +104,8 @@ namespace sts::fatal::srv {
this->context.generate_error_report = (policy == FatalType_ErrorReportAndErrorScreen);
/* Adjust error code (2000-0000 -> 2162-0002). */
if (this->context.error_code == ResultSuccess) {
this->context.error_code = ResultErrSystemModuleAborted;
if (R_SUCCEEDED(this->context.result)) {
this->context.result = err::ResultSystemModuleAborted();
}
switch (policy) {
@ -126,25 +122,25 @@ namespace sts::fatal::srv {
STS_UNREACHABLE_DEFAULT_CASE();
}
return ResultSuccess;
return ResultSuccess();
}
}
Result ThrowFatalForSelf(Result error_code) {
return g_context.ThrowFatalWithPolicy(static_cast<u32>(error_code), os::GetCurrentProcessId(), FatalType_ErrorScreen);
Result ThrowFatalForSelf(Result result) {
return g_context.ThrowFatalWithPolicy(result, os::GetCurrentProcessId(), FatalType_ErrorScreen);
}
Result UserService::ThrowFatal(u32 error, const sf::ClientProcessId &client_pid) {
return g_context.ThrowFatal(error, client_pid.GetValue());
Result UserService::ThrowFatal(Result result, const sf::ClientProcessId &client_pid) {
return g_context.ThrowFatal(result, client_pid.GetValue());
}
Result UserService::ThrowFatalWithPolicy(u32 error, const sf::ClientProcessId &client_pid, FatalType policy) {
return g_context.ThrowFatalWithPolicy(error, client_pid.GetValue(), policy);
Result UserService::ThrowFatalWithPolicy(Result result, const sf::ClientProcessId &client_pid, FatalType policy) {
return g_context.ThrowFatalWithPolicy(result, client_pid.GetValue(), policy);
}
Result UserService::ThrowFatalWithCpuContext(u32 error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx) {
return g_context.ThrowFatalWithCpuContext(error, client_pid.GetValue(), policy, cpu_ctx);
Result UserService::ThrowFatalWithCpuContext(Result result, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx) {
return g_context.ThrowFatalWithCpuContext(result, client_pid.GetValue(), policy, cpu_ctx);
}
Result PrivateService::GetFatalEvent(sf::OutCopyHandle out_h) {

View file

@ -29,9 +29,9 @@ namespace sts::fatal::srv {
};
private:
/* Actual commands. */
Result ThrowFatal(u32 error, const sf::ClientProcessId &client_pid);
Result ThrowFatalWithPolicy(u32 error, const sf::ClientProcessId &client_pid, FatalType policy);
Result ThrowFatalWithCpuContext(u32 error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx);
Result ThrowFatal(Result error, const sf::ClientProcessId &client_pid);
Result ThrowFatalWithPolicy(Result error, const sf::ClientProcessId &client_pid, FatalType policy);
Result ThrowFatalWithCpuContext(Result error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(ThrowFatal),

View file

@ -53,7 +53,7 @@ namespace sts::fatal::srv {
R_TRY(pcvSetClockRate(module, hz));
}
return ResultSuccess;
return ResultSuccess();
}
Result AdjustClockTask::AdjustClock() {
@ -66,7 +66,7 @@ namespace sts::fatal::srv {
R_TRY(AdjustClockForModule(PcvModule_GPU, GPU_CLOCK_307MHZ));
R_TRY(AdjustClockForModule(PcvModule_EMC, EMC_CLOCK_1331MHZ));
return ResultSuccess;
return ResultSuccess();
}
Result AdjustClockTask::Run() {

View file

@ -86,7 +86,7 @@ namespace sts::fatal::srv {
ON_SCOPE_EXIT { fclose(f_report); };
fprintf(f_report, "Atmosphère Fatal Report (v1.0):\n");
fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->context->error_code, R_MODULE(this->context->error_code), R_DESCRIPTION(this->context->error_code));
fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->context->result.GetValue(), this->context->result.GetModule(), this->context->result.GetDescription());
fprintf(f_report, "Title ID: %016lx\n", static_cast<u64>(this->context->title_id));
if (strlen(this->context->proc_name)) {
fprintf(f_report, "Process Name: %s\n", this->context->proc_name);
@ -144,7 +144,7 @@ namespace sts::fatal::srv {
/* Signal we're done with our job. */
eventFire(const_cast<Event *>(&this->context->erpt_event));
return ResultSuccess;
return ResultSuccess();
}
}

View file

@ -178,18 +178,18 @@ namespace sts::fatal::srv {
Result PowerControlTask::Run() {
this->MonitorBatteryState();
return ResultSuccess;
return ResultSuccess();
}
Result PowerButtonObserveTask::Run() {
this->WaitForPowerButton();
return ResultSuccess;
return ResultSuccess();
}
Result StateTransitionStopTask::Run() {
/* Nintendo ignores the output of this call... */
spsmPutErrorState();
return ResultSuccess;
return ResultSuccess();
}
}

View file

@ -90,9 +90,7 @@ namespace sts::fatal::srv {
ViDisplay temp_display;
/* Try to open the display. */
R_TRY_CATCH(viOpenDisplay("Internal", &temp_display)) {
R_CATCH(ResultViNotFound) {
return ResultSuccess;
}
R_CONVERT(vi::ResultNotFound, ResultSuccess());
} R_END_TRY_CATCH;
/* Guarantee we close the display. */
@ -109,16 +107,14 @@ namespace sts::fatal::srv {
/* Set alpha to 1.0f. */
R_TRY(viSetDisplayAlpha(&temp_display, 1.0f));
return ResultSuccess;
return ResultSuccess();
}
Result ShowFatalTask::SetupDisplayExternal() {
ViDisplay temp_display;
/* Try to open the display. */
R_TRY_CATCH(viOpenDisplay("External", &temp_display)) {
R_CATCH(ResultViNotFound) {
return ResultSuccess;
}
R_CONVERT(vi::ResultNotFound, ResultSuccess());
} R_END_TRY_CATCH;
/* Guarantee we close the display. */
@ -127,7 +123,7 @@ namespace sts::fatal::srv {
/* Set alpha to 1.0f. */
R_TRY(viSetDisplayAlpha(&temp_display, 1.0f));
return ResultSuccess;
return ResultSuccess();
}
Result ShowFatalTask::PrepareScreenForDrawing() {
@ -182,7 +178,7 @@ namespace sts::fatal::srv {
R_TRY(framebufferCreate(&this->fb, &this->win, raw_width, raw_height, PIXEL_FORMAT_RGB_565, 1));
}
return ResultSuccess;
return ResultSuccess();
}
Result ShowFatalTask::ShowFatal() {
@ -195,9 +191,7 @@ namespace sts::fatal::srv {
/* Dequeue a buffer. */
u16 *tiled_buf = reinterpret_cast<u16 *>(framebufferBegin(&this->fb, NULL));
if (tiled_buf == nullptr) {
return ResultFatalNullGraphicsBuffer;
}
R_UNLESS(tiled_buf != nullptr, ResultNullGraphicsBuffer());
/* Let the font manager know about our framebuffer. */
font::ConfigureFontFramebuffer(tiled_buf, GetPixelOffset);
@ -218,13 +212,13 @@ namespace sts::fatal::srv {
/* TODO: Actually draw meaningful shit here. */
font::SetPosition(32, 64);
font::SetFontSize(16.0f);
font::PrintFormat(config.GetErrorMessage(), R_MODULE(this->context->error_code), R_DESCRIPTION(this->context->error_code), this->context->error_code);
font::PrintFormat(config.GetErrorMessage(), this->context->result.GetModule(), this->context->result.GetDescription(), this->context->result.GetValue());
font::AddSpacingLines(0.5f);
font::PrintFormatLine("Title: %016lX", static_cast<u64>(this->context->title_id));
font::AddSpacingLines(0.5f);
font::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", config.GetFirmwareVersion().display_version, ATMOSPHERE_RELEASE_VERSION, ams::GetGitRevision());
font::AddSpacingLines(1.5f);
if (this->context->error_code != ResultAtmosphereVersionMismatch) {
if (!ams::ResultVersionMismatch::Includes(this->context->result)) {
font::Print(config.GetErrorDescription());
} else {
/* Print a special message for atmosphere version mismatch. */
@ -415,7 +409,7 @@ namespace sts::fatal::srv {
/* Enqueue the buffer. */
framebufferEnd(&fb);
return ResultSuccess;
return ResultSuccess();
}
Result ShowFatalTask::Run() {
@ -431,7 +425,7 @@ namespace sts::fatal::srv {
Result BacklightControlTask::Run() {
TurnOnBacklight();
return ResultSuccess;
return ResultSuccess();
}
}

View file

@ -86,7 +86,7 @@ namespace sts::fatal::srv {
Result StopSoundTask::Run() {
StopSound();
return ResultSuccess;
return ResultSuccess();
}
}