2018-09-07 16:00:13 +01:00
|
|
|
/*
|
2020-01-24 10:10:40 +00:00
|
|
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
2018-09-07 16:00:13 +01:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2018-05-21 02:50:53 +01:00
|
|
|
#include <inttypes.h>
|
|
|
|
|
2018-05-21 01:24:41 +01:00
|
|
|
#include "exception_handlers.h"
|
|
|
|
#include "utils.h"
|
2018-09-26 01:18:50 +01:00
|
|
|
#include "lib/log.h"
|
2018-05-21 01:24:41 +01:00
|
|
|
|
|
|
|
#define CODE_DUMP_SIZE 0x30
|
|
|
|
#define STACK_DUMP_SIZE 0x60
|
|
|
|
|
|
|
|
extern const uint32_t exception_handler_table[];
|
|
|
|
|
|
|
|
static const char *exception_names[] = {
|
|
|
|
"Reset", "Undefined instruction", "SWI", "Prefetch abort", "Data abort", "Reserved", "IRQ", "FIQ",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *register_names[] = {
|
|
|
|
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12",
|
|
|
|
"SP", "LR", "PC", "CPSR",
|
|
|
|
};
|
|
|
|
|
|
|
|
void setup_exception_handlers(void) {
|
|
|
|
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
if (exception_handler_table[i] != 0) {
|
|
|
|
bpmp_exception_handler_table[i] = exception_handler_table[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
|
|
|
|
uint8_t code_dump[CODE_DUMP_SIZE];
|
|
|
|
uint8_t stack_dump[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;
|
|
|
|
|
2018-09-26 01:18:50 +01:00
|
|
|
print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
|
2018-05-21 02:39:18 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2018-09-26 01:18:50 +01:00
|
|
|
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");
|
2018-05-21 01:24:41 +01:00
|
|
|
|
|
|
|
/* Print r0 to pc. */
|
|
|
|
for (int i = 0; i < 16; i += 2) {
|
2018-09-26 01:18:50 +01:00
|
|
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
|
|
|
|
register_names[i], registers[i], register_names[i+1], registers[i+1]);
|
2018-05-21 01:24:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Print cpsr. */
|
2018-09-26 01:18:50 +01:00
|
|
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
|
2018-05-21 01:24:41 +01:00
|
|
|
|
2018-09-26 01:18:50 +01:00
|
|
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n");
|
2018-05-21 01:24:41 +01:00
|
|
|
hexdump(code_dump, code_dump_size, instr_addr);
|
2018-09-26 01:18:50 +01:00
|
|
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n");
|
2018-05-21 02:39:18 +01:00
|
|
|
hexdump(stack_dump, stack_dump_size, registers[13]);
|
2018-09-26 01:18:50 +01:00
|
|
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
|
2018-05-21 01:24:41 +01:00
|
|
|
fatal_error("An exception occured!\n");
|
|
|
|
}
|