-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #504 from LedgerHQ/xch/cx-assert
LEDGER_ASSERT improvments and CX_ASSERT addition
- Loading branch information
Showing
11 changed files
with
403 additions
and
241 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,160 +1,95 @@ | ||
#pragma once | ||
|
||
#include <stdbool.h> | ||
|
||
#ifdef HAVE_PRINTF | ||
void assert_print_failed(void); | ||
#endif | ||
|
||
#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO | ||
#define LEDGER_ASSERT_CONFIG_MESSAGE_INFO 1 | ||
#define LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO 1 | ||
#endif | ||
|
||
#ifdef LEDGER_ASSERT_CONFIG_MESSAGE_INFO | ||
#define LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO 1 | ||
#endif | ||
|
||
#if defined(LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO) && defined(HAVE_LEDGER_ASSERT_DISPLAY) | ||
#define LR_AND_PC_SIZE 30 | ||
void assert_display_lr_and_pc(int lr, int pc); | ||
#define ASSERT_DISPLAY_LR_AND_PC(lr, pc) assert_display_lr_and_pc(lr, pc) | ||
#else | ||
#define LR_AND_PC_SIZE 0 | ||
#define ASSERT_DISPLAY_LR_AND_PC(lr, pc) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#if defined(LEDGER_ASSERT_CONFIG_MESSAGE_INFO) && defined(HAVE_LEDGER_ASSERT_DISPLAY) | ||
#define MESSAGE_SIZE 20 | ||
void assert_display_message(const char *message); | ||
#define ASSERT_DISPLAY_MESSAGE(message) assert_display_message(message) | ||
#else | ||
#define MESSAGE_SIZE 0 | ||
#define ASSERT_DISPLAY_MESSAGE(message) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#if defined(LEDGER_ASSERT_CONFIG_FILE_INFO) && defined(HAVE_LEDGER_ASSERT_DISPLAY) | ||
#define FILE_SIZE 50 | ||
void assert_display_file_info(const char *file, unsigned int line); | ||
#define ASSERT_DISPLAY_FILE_INFO(file, line) assert_display_file_info(file, line) | ||
#else | ||
#define FILE_SIZE 0 | ||
#define ASSERT_DISPLAY_FILE_INFO(file, line) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#ifdef HAVE_LEDGER_ASSERT_DISPLAY | ||
#define ASSERT_BUFFER_LEN LR_AND_PC_SIZE + MESSAGE_SIZE + FILE_SIZE | ||
void __attribute__((noreturn)) assert_display_exit(void); | ||
|
||
#define LEDGER_ASSERT_EXIT() assert_display_exit() | ||
#else | ||
void assert_exit(bool confirm); | ||
#define LEDGER_ASSERT_EXIT() assert_exit(true) | ||
#endif | ||
|
||
#if defined(LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO) && defined(HAVE_PRINTF) | ||
void assert_print_lr_and_pc(int lr, int pc); | ||
#define ASSERT_PRINT_LR_AND_PC(lr, pc) assert_print_lr_and_pc(lr, pc) | ||
#else | ||
#define ASSERT_PRINT_LR_AND_PC(lr, pc) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#if defined(LEDGER_ASSERT_CONFIG_MESSAGE_INFO) && defined(HAVE_PRINTF) | ||
void assert_print_message(const char *message); | ||
#define ASSERT_PRINT_MESSAGE(message) assert_print_message(message) | ||
#else | ||
#define ASSERT_PRINT_MESSAGE(message) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#if defined(LEDGER_ASSERT_CONFIG_FILE_INFO) && defined(HAVE_PRINTF) | ||
void assert_print_file_info(const char *file, int line); | ||
#define ASSERT_PRINT_FILE_INFO(file, line) assert_print_file_info(file, line) | ||
#else | ||
#define ASSERT_PRINT_FILE_INFO(file, line) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#ifdef LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO | ||
#define LEDGER_ASSERT_LR_AND_PC() \ | ||
do { \ | ||
int _lr_address = 0; \ | ||
int _pc_address = 0; \ | ||
\ | ||
__asm volatile("mov %0, lr" : "=r"(_lr_address)); \ | ||
__asm volatile("mov %0, pc" : "=r"(_pc_address)); \ | ||
ASSERT_PRINT_LR_AND_PC(_lr_address, _pc_address); \ | ||
ASSERT_DISPLAY_LR_AND_PC(_lr_address, _pc_address); \ | ||
} while (0) | ||
#elif defined(HAVE_PRINTF) | ||
#define LEDGER_ASSERT_LR_AND_PC() assert_print_failed() | ||
#else | ||
#define LEDGER_ASSERT_LR_AND_PC() \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#ifdef LEDGER_ASSERT_CONFIG_MESSAGE_INFO | ||
#define LEDGER_ASSERT_MESSAGE(message) \ | ||
do { \ | ||
ASSERT_PRINT_MESSAGE(message); \ | ||
ASSERT_DISPLAY_MESSAGE(message); \ | ||
} while (0) | ||
#else | ||
#define LEDGER_ASSERT_MESSAGE(message) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO | ||
#define LEDGER_ASSERT_FILE_INFO() \ | ||
do { \ | ||
ASSERT_PRINT_FILE_INFO(__FILE__, __LINE__); \ | ||
ASSERT_DISPLAY_FILE_INFO(__FILE__, __LINE__); \ | ||
} while (0) | ||
#else | ||
#define LEDGER_ASSERT_FILE_INFO() \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#define LEDGER_ASSERT(test, message) \ | ||
do { \ | ||
if (!(test)) { \ | ||
LEDGER_ASSERT_LR_AND_PC(); \ | ||
LEDGER_ASSERT_MESSAGE(message); \ | ||
LEDGER_ASSERT_FILE_INFO(); \ | ||
LEDGER_ASSERT_EXIT(); \ | ||
} \ | ||
} while (0) | ||
|
||
#if defined(HAVE_DEBUG_THROWS) && defined(HAVE_PRINTF) | ||
void throw_print_lr(int e, int lr); | ||
#define THROW_PRINT_LR(e, lr_val) throw_print_lr(e, lr_val) | ||
#else | ||
#define THROW_PRINT_LR(e, lr_val) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#if defined(HAVE_DEBUG_THROWS) | ||
void __attribute__((noreturn)) assert_display_exit(void); | ||
void throw_display_lr(int e, int lr); | ||
#define DEBUG_THROW(e) \ | ||
do { \ | ||
unsigned int lr_val; \ | ||
__asm volatile("mov %0, lr" : "=r"(lr_val)); \ | ||
throw_display_lr(e, lr_val); \ | ||
THROW_PRINT_LR(e, lr_val); \ | ||
#include "ledger_assert_internals.h" | ||
|
||
/***************** | ||
* LEDGER_ASSERT * | ||
****************/ | ||
|
||
/** | ||
* LEDGER_ASSERT - exit the app if assertion is false. | ||
* | ||
* Description: | ||
* This is a C macro that can be used similarly of the libc `assert` macro. | ||
* Therefore, it can help programmers find bugs in their programs, or handle | ||
* exceptional cases via a crash that will produce limited debugging output. | ||
* | ||
* | ||
* Important note: | ||
* Note that contrary to the libc `assert`, the `LEDGER_ASSERT` macro will | ||
* still end the app execution even if build with DEBUG=0 or NDEBUG. | ||
* However, there are configurations explained below that shall be used to | ||
* reduce the code size impact of the `LEDGER_ASSERT` macro to the bare minimum. | ||
* | ||
* | ||
* Examples of usage: | ||
* | ||
* 1/ Simple example always raising with simple message: | ||
* - `LEDGER_ASSERT(false, "Always assert");` | ||
* | ||
* 2/ More complex examples: | ||
* - `LEDGER_ASSERT(len <= sizeof(buf), "Len too long");` | ||
* - `LEDGER_ASSERT(check_value(value) == 0, "check_value failed");` | ||
* | ||
* 3/ Examples showcasing advance message format: | ||
* - `LEDGER_ASSERT(len <= sizeof(buf), "Len too long %d <= %d", len, sizeof(buf));` | ||
* - `int err = check_value(value); LEDGER_ASSERT(err == 0, "check_value failed (%d)", err);` | ||
* | ||
* | ||
* Configuration: | ||
* | ||
* I/ Type of info to expose in PRINTF and screen if enabled. | ||
* | ||
* There are 4 types of information that can be displayed: | ||
* | ||
* 1/ A simple info displaying "LEDGER_ASSERT FAILED" | ||
* => This is always enabled | ||
* | ||
* 2/ An info containing the PC and LR of the instruction that failed. | ||
* This can be used to locate the failing code and flow using the following | ||
* command: `arm-none-eabi-addr2line --exe bin/app.elf -pf 0xC0DE586B` | ||
* => This is enabled when `LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO` is defined. | ||
* | ||
* 3/ An info displaying the `LEDGER_ASSERT` message passed as parameter. | ||
* => This is enabled when `LEDGER_ASSERT_CONFIG_MESSAGE_INFO` is defined. | ||
* | ||
* 4/ An info displaying the file and line position of the failing | ||
* `LEDGER_ASSERT`. | ||
* => This is enabled when `LEDGER_ASSERT_CONFIG_FILE_INFO` is defined. | ||
* | ||
* By default, when an info level X is enabled, all info level below are enabled. | ||
* | ||
* When using `Makefile.standard_app` and building with `DEBUG=1` all info are | ||
* enabled. | ||
* | ||
* Note that enabling these info increase the app code size and is only | ||
* recommended to ease the debugging. | ||
* | ||
* | ||
* II/ Display info on device screen. | ||
* | ||
* Control whether or not a specific screen displaying assert info is shown | ||
* to the app user before exiting the app due to an assert failure. | ||
* | ||
* To enable it, add `DEFINES+=HAVE_LEDGER_ASSERT_DISPLAY` in your app Makefile. | ||
* | ||
* This is enabled by default when using `Makefile.standard_app` and building | ||
* with `DEBUG=1`. It can still be disabled with using | ||
* `DISABLE_DEBUG_LEDGER_ASSERT=1`. | ||
* | ||
* Note that this is increasing the app code size and exposes a non-user | ||
* friendly screen in case of assert. therefore this should not be enabled in | ||
* app release build but only kept for debug purposes. | ||
* | ||
*/ | ||
#define LEDGER_ASSERT(test, format, ...) \ | ||
do { \ | ||
if (!(test)) { \ | ||
LEDGER_ASSERT_LR_AND_PC_PREAMBLE(); \ | ||
PRINTF("LEDGER_ASSERT FAILED\n"); \ | ||
LEDGER_ASSERT_MESSAGE(format, ##__VA_ARGS__); \ | ||
LEDGER_ASSERT_FILE_INFO(); \ | ||
LEDGER_ASSERT_LR_AND_PC(); \ | ||
LEDGER_ASSERT_EXIT(); \ | ||
} \ | ||
} while (0) | ||
#endif |
Oops, something went wrong.