Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helper to allow easier debugging of Throw #410

Merged
merged 2 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions lib_standard_app/debug.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*****************************************************************************
* (c) 2020 Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/

#include <stdint.h> // uint*_t
#include <string.h> // memset, explicit_bzero

#include "os.h"
#include "io.h"

#ifdef HAVE_NBGL
#include "nbgl_use_case.h"
#endif

#ifdef HAVE_DEBUG_THROWS
static char errordata[20];

WEAK void app_throw_info(unsigned int exception, unsigned int lr_val) {
snprintf(errordata,
sizeof(errordata),
"n%d, LR=0x%08X",
exception,
lr_val);
}

static void review_choice(bool confirm) {
UNUSED(confirm);
os_sched_exit(-1);
}

#ifdef HAVE_BAGL
UX_STEP_CB(ux_error,
bnnn_paging,
review_choice(true),
{
.title = "App error",
.text = errordata,
});
UX_FLOW(ux_error_flow, &ux_error);
#endif

WEAK void __attribute__((noreturn)) debug_display_throw_error(int exception) {
UNUSED(exception);

#ifdef HAVE_BAGL
ux_flow_init(0, ux_error_flow, NULL);
#endif

#ifdef HAVE_NBGL
nbgl_useCaseChoice(&C_round_warning_64px,
"App error",
errordata,
"Exit app",
"Exit app",
review_choice);
#endif

// Block until the user approve and the app is quit
while (1) {
io_seproxyhal_io_heartbeat();
}
}

#endif
3 changes: 3 additions & 0 deletions lib_standard_app/debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

WEAK void __attribute__((noreturn)) debug_display_throw_error(int exception);
20 changes: 20 additions & 0 deletions lib_standard_app/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "os.h"
#include "io.h"
#include "debug.h"

#ifdef HAVE_SWAP
#include "swap.h"
Expand Down Expand Up @@ -62,6 +63,25 @@ static void standalone_app_main(void) {
}
CATCH_OTHER(e) {
PRINTF("Exiting following exception: %d\n", e);

#ifdef HAVE_DEBUG_THROWS
// Disable USB and BLE, the app have crashed and is going to be exited
// This is necessary to avoid device freeze while displaying throw error
// in a specific case:
// - the app receives an APDU
// - the app throws before replying
// - the app displays the error on screen
// - the user unplug the NanoX instead of confirming the screen
// - the NanoX goes on battery power and display the lock screen
// - the user plug the NanoX instead of entering its pin
// - the device is frozen, battery should be removed
USB_power(0);
#ifdef HAVE_BLE
BLE_power(0, NULL);
#endif
// Display crash info on screen for debug purpose
debug_display_throw_error(e);
#endif
}
FINALLY {
}
Expand Down
19 changes: 18 additions & 1 deletion src/os.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,29 @@ char os_secure_memcmp(const void *src1, const void* src2, size_t length) {
}

#ifndef HAVE_BOLOS
#define MAIN_LINKER_SCRIPT_LOCATION 0xC0DE0000
int main(void);

// This function can be used to declare a callback to THROW in the application
__attribute((weak)) void app_throw_info(unsigned int exception, unsigned int lr_val) {
UNUSED(exception);
UNUSED(lr_val);
}

void os_longjmp(unsigned int exception) {
#ifdef HAVE_PRINTF
unsigned int lr_val;
__asm volatile("mov %0, lr" :"=r"(lr_val));

// Compute location before relocation (sort of anti PIC)
lr_val = lr_val - (unsigned int)main + MAIN_LINKER_SCRIPT_LOCATION;

#ifdef HAVE_PRINTF
PRINTF("exception[%d]: LR=0x%08X\n", exception, lr_val);
#endif // HAVE_PRINTF

// Send to the app the info of exception and LR for debug purpose
app_throw_info(exception, lr_val);

longjmp(try_context_get()->jmp_buf, exception);
}
#endif // HAVE_BOLOS
Expand Down