fusee/sept: fix error printing

This commit is contained in:
hexkyz 2020-07-14 18:12:31 +01:00
parent 51dd668c7c
commit 72afe34cf9
15 changed files with 197 additions and 177 deletions

View file

@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <inttypes.h>
#include "exception_handlers.h"
@ -22,7 +23,7 @@
#include "lib/log.h"
#define CODE_DUMP_SIZE 0x30
#define STACK_DUMP_SIZE 0x60
#define STACK_DUMP_SIZE 0x30
extern const uint32_t exception_handler_table[];
@ -35,6 +36,40 @@ static const char *register_names[] = {
"SP", "LR", "PC", "CPSR",
};
/* Adapted from https://gist.github.com/ccbrown/9722406 */
static void hexdump(const void* data, size_t size, uintptr_t addrbase, char* strbuf) {
const uint8_t *d = (const uint8_t *)data;
char ascii[17];
ascii[16] = '\0';
for (size_t i = 0; i < size; i++) {
if (i % 16 == 0) {
strbuf += sprintf(strbuf, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
}
strbuf += sprintf(strbuf, "%02X ", d[i]);
if (d[i] >= ' ' && d[i] <= '~') {
ascii[i % 16] = d[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
strbuf += sprintf(strbuf, " ");
if ((i+1) % 16 == 0) {
strbuf += sprintf(strbuf, "| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
strbuf += sprintf(strbuf, " ");
}
for (size_t j = (i+1) % 16; j < 16; j++) {
strbuf += sprintf(strbuf, " ");
}
strbuf += sprintf(strbuf, "| %s \n", ascii);
}
}
}
}
void setup_exception_handlers(void) {
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
for (int i = 0; i < 8; i++) {
@ -45,38 +80,40 @@ void setup_exception_handlers(void) {
}
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
char exception_log[0x400];
uint8_t code_dump[CODE_DUMP_SIZE];
uint8_t stack_dump[STACK_DUMP_SIZE];
size_t code_dump_size;
size_t stack_dump_size;
size_t code_dump_size;
size_t stack_dump_size;
uint32_t pc = registers[15];
uint32_t cpsr = registers[16];
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
sprintf(exception_log + strlen(exception_log), "An exception occured!\n");
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE);
stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
exception_names[exception_type]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n");
sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]);
sprintf(exception_log + strlen(exception_log), "\nRegisters:\n");
/* Print r0 to pc. */
for (int i = 0; i < 16; i += 2) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
register_names[i], registers[i], register_names[i+1], registers[i+1]);
}
/* Print cpsr. */
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
fatal_error("An exception occurred!\n");
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
/* Print code and stack regions. */
sprintf(exception_log + strlen(exception_log), "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\n");
/* Throw fatal error with the full exception log. */
fatal_error(exception_log);
}