diff --git a/nx/include/switch/applets/error.h b/nx/include/switch/applets/error.h index 5e8421ca..cb572ae0 100644 --- a/nx/include/switch/applets/error.h +++ b/nx/include/switch/applets/error.h @@ -16,11 +16,11 @@ typedef struct { /// Common header for the start of the arg storage. typedef struct { u8 type; - u8 unk_x1; + u8 jumpFlag; ///< When clear, this indicates WithoutJump. u8 unk_x2[3]; u8 contextFlag; u8 resultFlag; ///< \ref ErrorCommonArg: When clear, errorCode is used, otherwise the applet generates the error-code from res. - u8 unk_x7; + u8 contextFlag2; ///< Same as contextFlag except for ErrorCommonArg? } ErrorCommonHeader; /// Error arg data for non-{System/Application}. @@ -30,6 +30,12 @@ typedef struct { Result res; } ErrorCommonArg; +/// ResultBacktrace +typedef struct { + s32 count; + Result backtrace[0x20]; +} ErrorResultBacktrace; + typedef struct { ErrorCommonHeader hdr; SetRegion regionCode; @@ -39,6 +45,12 @@ typedef struct { u8 data[0x20000]; } ErrorEulaData; +typedef struct { + ErrorCommonHeader hdr; + u64 errorCode; + u64 timestamp; ///< POSIX timestamp. +} ErrorRecordArg; + /// SystemErrorArg typedef struct { ErrorCommonHeader hdr; @@ -67,6 +79,28 @@ typedef struct { ErrorContext ctx; } ErrorApplicationConfig; +/** + * @brief Creates an ErrorResultBacktrace struct. + * @param backtrace \ref ErrorResultBacktrace struct. + * @param count Total number of entries. + * @param entries Input array of Result. + */ +Result errorResultBacktraceCreate(ErrorResultBacktrace* backtrace, s32 count, Result* entries); + +/** + * @brief Closes an ErrorResultBacktrace struct. + * @param backtrace \ref ErrorResultBacktrace struct. + */ +void errorResultBacktraceClose(ErrorResultBacktrace* backtrace); + +/** + * @brief Launches the applet for \ref ErrorResultBacktrace. + * @param backtrace ErrorResultBacktrace struct. + * @param res Result + * @warning This applet creates an error report that is logged in the system. Proceed at your own risk! + */ +Result errorResultBacktraceShow(Result res, ErrorResultBacktrace* backtrace); + /** * @brief Launches the applet for displaying the EULA. * @param RegionCode \ref SetRegion diff --git a/nx/source/applets/error.c b/nx/source/applets/error.c index 2abb6a5b..af11a403 100644 --- a/nx/source/applets/error.c +++ b/nx/source/applets/error.c @@ -76,6 +76,35 @@ static Result _errorShowContext(const void* indata, size_t insize, ErrorContext* return _errorShow(indata, insize, ctx_ptr, ctx_size); } +// Backtrace + +Result errorResultBacktraceCreate(ErrorResultBacktrace* backtrace, s32 count, Result* entries) { + if (backtrace==NULL || count < 0 || count > sizeof(backtrace->backtrace)/sizeof(Result)) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + memset(backtrace, 0, sizeof(*backtrace)); + backtrace->count = count; + if (backtrace->count) memcpy(&backtrace->backtrace, entries, count); + + return 0; +} + +void errorResultBacktraceClose(ErrorResultBacktrace* backtrace) { + memset(backtrace, 0, sizeof(*backtrace)); +} + +Result errorResultBacktraceShow(Result res, ErrorResultBacktrace* backtrace) { + ErrorCommonArg arg; + + memset(&arg, 0, sizeof(arg)); + arg.hdr.type = 0; + arg.hdr.jumpFlag = 1; + arg.hdr.contextFlag = 1; + arg.res = res; + + return _errorShow(&arg, sizeof(arg), backtrace, sizeof(*backtrace)); +} + // Eula Result errorEulaShow(SetRegion RegionCode) { @@ -83,7 +112,7 @@ Result errorEulaShow(SetRegion RegionCode) { memset(&arg, 0, sizeof(arg)); arg.hdr.type = 3; - arg.hdr.unk_x1 = 1; + arg.hdr.jumpFlag = 1; arg.regionCode = RegionCode; return _errorShow(&arg, sizeof(arg), NULL, 0); @@ -97,7 +126,7 @@ Result errorSystemUpdateEulaShow(SetRegion RegionCode, ErrorEulaData* eula) { memset(&arg, 0, sizeof(arg)); arg.hdr.type = 8; - arg.hdr.unk_x1 = 1; + arg.hdr.jumpFlag = 1; arg.regionCode = RegionCode; rc = _errorAppletCreate(&holder, &arg, sizeof(arg), NULL, 0); @@ -168,7 +197,7 @@ Result errorApplicationCreate(ErrorApplicationConfig* c, const char* dialog_mess memset(c, 0, sizeof(*c)); c->arg.hdr.type = 2; - c->arg.hdr.unk_x1 = 1; + c->arg.hdr.jumpFlag = 1; strncpy(c->arg.dialogMessage, dialog_message, sizeof(c->arg.dialogMessage)-1); if (fullscreen_message) strncpy(c->arg.fullscreenMessage, fullscreen_message, sizeof(c->arg.fullscreenMessage)-1);