From 749f19e5027b126dc8cb0e36c12512641ea528ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Wed, 28 Mar 2018 15:13:20 -0300 Subject: [PATCH] [2.0.x] Move backtrace to a shared location (#10237) - And implement the `backtrace()` function call --- Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp | 66 ++-- Marlin/src/backtrace/backtrace.cpp | 102 +++++++ Marlin/src/backtrace/backtrace.h | 29 ++ .../unwarm.c => backtrace/unwarm.cpp} | 3 +- .../src/{HAL/HAL_DUE => }/backtrace/unwarm.h | 10 +- .../unwarm_arm.c => backtrace/unwarm_arm.cpp} | 8 +- .../unwarm_thumb.cpp} | 284 +++++++++--------- .../unwarmbytab.cpp} | 6 +- .../{HAL/HAL_DUE => }/backtrace/unwarmbytab.h | 8 - .../unwarmmem.c => backtrace/unwarmmem.cpp} | 2 +- .../{HAL/HAL_DUE => }/backtrace/unwarmmem.h | 8 - .../unwinder.c => backtrace/unwinder.cpp} | 6 +- .../{HAL/HAL_DUE => }/backtrace/unwinder.h | 9 - Marlin/src/backtrace/unwmemaccess.cpp | 136 +++++++++ Marlin/src/backtrace/unwmemaccess.h | 26 ++ 15 files changed, 466 insertions(+), 237 deletions(-) create mode 100644 Marlin/src/backtrace/backtrace.cpp create mode 100644 Marlin/src/backtrace/backtrace.h rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarm.c => backtrace/unwarm.cpp} (99%) rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwarm.h (98%) rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarm_arm.c => backtrace/unwarm_arm.cpp} (98%) rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarm_thumb.c => backtrace/unwarm_thumb.cpp} (85%) rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarmbytab.c => backtrace/unwarmbytab.cpp} (98%) rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwarmbytab.h (94%) rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarmmem.c => backtrace/unwarmmem.cpp} (98%) rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwarmmem.h (94%) rename Marlin/src/{HAL/HAL_DUE/backtrace/unwinder.c => backtrace/unwinder.cpp} (93%) rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwinder.h (98%) create mode 100644 Marlin/src/backtrace/unwmemaccess.cpp create mode 100644 Marlin/src/backtrace/unwmemaccess.h diff --git a/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp b/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp index cd00165bc..849ee89f9 100644 --- a/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp +++ b/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp @@ -24,7 +24,8 @@ #include "../../inc/MarlinConfig.h" #include "../../Marlin.h" -#include "backtrace/unwinder.h" +#include "../../backtrace/unwinder.h" +#include "../../backtrace/unwmemaccess.h" // Debug monitor that dumps to the Programming port all status when // an exception or WDT timeout happens - And then resets the board @@ -112,45 +113,6 @@ static void TXDec(uint32_t v) { } while (p != &nbrs[0]); } -/* Validate address */ -static bool validate_addr(uint32_t addr) { - - // Address must be in SRAM (0x20070000 - 0x20088000) - if (addr >= 0x20070000 && addr < 0x20088000) - return true; - - // Or in FLASH (0x00080000 - 0x00100000) - if (addr >= 0x00080000 && addr < 0x00100000) - return true; - - return false; -} - -static bool UnwReadW(const uint32_t a, uint32_t *v) { - if (!validate_addr(a)) - return false; - - *v = *(uint32_t *)a; - return true; -} - -static bool UnwReadH(const uint32_t a, uint16_t *v) { - if (!validate_addr(a)) - return false; - - *v = *(uint16_t *)a; - return true; -} - -static bool UnwReadB(const uint32_t a, uint8_t *v) { - if (!validate_addr(a)) - return false; - - *v = *(uint8_t *)a; - return true; -} - - // Dump a backtrace entry static bool UnwReportOut(void* ctx, const UnwReport* bte) { int* p = (int*)ctx; @@ -270,7 +232,8 @@ void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause } __attribute__((naked)) void NMI_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" @@ -282,7 +245,8 @@ __attribute__((naked)) void NMI_Handler(void) { } __attribute__((naked)) void HardFault_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" @@ -294,7 +258,8 @@ __attribute__((naked)) void HardFault_Handler(void) { } __attribute__((naked)) void MemManage_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" @@ -306,7 +271,8 @@ __attribute__((naked)) void MemManage_Handler(void) { } __attribute__((naked)) void BusFault_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" @@ -318,7 +284,8 @@ __attribute__((naked)) void BusFault_Handler(void) { } __attribute__((naked)) void UsageFault_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" @@ -330,7 +297,8 @@ __attribute__((naked)) void UsageFault_Handler(void) { } __attribute__((naked)) void DebugMon_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" @@ -343,7 +311,8 @@ __attribute__((naked)) void DebugMon_Handler(void) { /* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */ __attribute__((naked)) void WDT_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" @@ -355,7 +324,8 @@ __attribute__((naked)) void WDT_Handler(void) { } __attribute__((naked)) void RSTC_Handler(void) { - __asm volatile ( + __asm__ __volatile__ ( + ".syntax unified \n" " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" diff --git a/Marlin/src/backtrace/backtrace.cpp b/Marlin/src/backtrace/backtrace.cpp new file mode 100644 index 000000000..fab68416a --- /dev/null +++ b/Marlin/src/backtrace/backtrace.cpp @@ -0,0 +1,102 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 . + * + */ + +#include "backtrace.h" + +#if defined(__arm__) || defined(__thumb__) + +#include "unwinder.h" +#include "unwmemaccess.h" +#include "../Marlin.h" + +// Dump a backtrace entry +static bool UnwReportOut(void* ctx, const UnwReport* bte) { + int* p = (int*)ctx; + + (*p)++; + + SERIAL_CHAR('#'); SERIAL_PRINT(*p,DEC); SERIAL_ECHOPGM(" : "); + SERIAL_ECHOPGM(bte->name?bte->name:"unknown"); SERIAL_ECHOPGM("@0x"); SERIAL_PRINT(bte->function,HEX); + SERIAL_CHAR('+'); SERIAL_PRINT(bte->address - bte->function,DEC); + SERIAL_ECHOPGM(" PC:"); SERIAL_PRINT(bte->address,HEX); SERIAL_CHAR('\n'); + return true; +} + +#if defined(UNW_DEBUG) +void UnwPrintf(const char* format, ...) { + char dest[256]; + va_list argptr; + va_start(argptr, format); + vsprintf(dest, format, argptr); + va_end(argptr); + TX(&dest[0]); +} +#endif + +/* Table of function pointers for passing to the unwinder */ +static const UnwindCallbacks UnwCallbacks = { + UnwReportOut, + UnwReadW, + UnwReadH, + UnwReadB +#if defined(UNW_DEBUG) + ,UnwPrintf +#endif +}; + +void backtrace(void) { + + UnwindFrame btf; + uint32_t sp,lr,pc; + + // Capture the values of the registers to perform the traceback + __asm__ __volatile__ ( + " mov %[lrv],lr\n" + " mov %[spv],sp\n" + " mov %[pcv],pc\n" + : [spv]"+r"( sp ), + [lrv]"+r"( lr ), + [pcv]"+r"( pc ) + :: + ); + + // Fill the traceback structure + btf.sp = sp; + btf.fp = btf.sp; + btf.lr = lr; + btf.pc = pc | 1; // Force Thumb, as CORTEX only support it + + // Perform a backtrace + SERIAL_ERROR_START(); + SERIAL_ERRORLNPGM("Backtrace:"); + int ctr = 0; + UnwindStart(&btf, &UnwCallbacks, &ctr); +} + +#else + +void backtrace(void) {} + +#endif + + + diff --git a/Marlin/src/backtrace/backtrace.h b/Marlin/src/backtrace/backtrace.h new file mode 100644 index 000000000..c2761b9f5 --- /dev/null +++ b/Marlin/src/backtrace/backtrace.h @@ -0,0 +1,29 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 . + * + */ + +#ifndef _BACKTRACE_H_ +#define _BACKTRACE_H_ + +// Perform a backtrace to the serial port +void backtrace(void); + +#endif \ No newline at end of file diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.c b/Marlin/src/backtrace/unwarm.cpp similarity index 99% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm.c rename to Marlin/src/backtrace/unwarm.cpp index 9da3be4e0..1229e7a73 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.c +++ b/Marlin/src/backtrace/unwarm.cpp @@ -12,12 +12,11 @@ * File Description: Utility functions and glue for ARM unwinding sub-modules. **************************************************************************/ -#ifdef ARDUINO_ARCH_SAM +#if defined(__arm__) || defined(__thumb__) #define MODULE_NAME "UNWARM" #include -#include #include #include #include diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.h b/Marlin/src/backtrace/unwarm.h similarity index 98% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm.h rename to Marlin/src/backtrace/unwarm.h index 23c1f96c2..4e4e07e33 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.h +++ b/Marlin/src/backtrace/unwarm.h @@ -54,7 +54,7 @@ typedef struct { /** The origin of the register value. * This is used to track how the value in the register was loaded. */ - RegValOrigin o; + int o; /* (RegValOrigin) */ } RegData; @@ -131,10 +131,6 @@ typedef struct { * Function Prototypes **************************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - UnwResult UnwStartArm(UnwState * const state); UnwResult UnwStartThumb(UnwState * const state); void UnwInvalidateRegisterFile(RegData *regFile); @@ -144,10 +140,6 @@ bool UnwMemWriteRegister(UnwState * const state, const uint32_t addr, const RegD bool UnwMemReadRegister(UnwState * const state, const uint32_t addr, RegData * const reg); void UnwMemHashGC(UnwState * const state); -#ifdef __cplusplus -} -#endif - #endif /* UNWARM_H */ /* END OF FILE */ diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_arm.c b/Marlin/src/backtrace/unwarm_arm.cpp similarity index 98% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm_arm.c rename to Marlin/src/backtrace/unwarm_arm.cpp index 9170534b5..faf3523be 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_arm.c +++ b/Marlin/src/backtrace/unwarm_arm.cpp @@ -12,7 +12,7 @@ * File Description: Abstract interpreter for ARM mode. **************************************************************************/ -#ifdef ARDUINO_ARCH_SAM +#if defined(__arm__) || defined(__thumb__) #define MODULE_NAME "UNWARM_ARM" @@ -180,7 +180,7 @@ UnwResult UnwStartArm(UnwState * const state) { uint8_t rd = (instr & 0x0000f000) >> 12; uint16_t operand2 = (instr & 0x00000fff); uint32_t op2val; - RegValOrigin op2origin; + int op2origin; switch(opcode) { case 0: UnwPrintd4("AND%s r%d,r%d,", S ? "S" : "", rd, rn); break; @@ -344,7 +344,7 @@ UnwResult UnwStartArm(UnwState * const state) { } else { state->regData[rd].o = state->regData[rn].o; - state->regData[rd].o |= op2origin; + state->regData[rd].o = (RegValOrigin)(state->regData[rd].o | op2origin); } break; @@ -363,7 +363,7 @@ UnwResult UnwStartArm(UnwState * const state) { case 13: /* MOV: Rd:= Op2 */ case 15: /* MVN: Rd:= NOT Op2 */ - state->regData[rd].o = op2origin; + state->regData[rd].o = (RegValOrigin) op2origin; break; } diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_thumb.c b/Marlin/src/backtrace/unwarm_thumb.cpp similarity index 85% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm_thumb.c rename to Marlin/src/backtrace/unwarm_thumb.cpp index 38f091e52..8c14f6ecd 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_thumb.c +++ b/Marlin/src/backtrace/unwarm_thumb.cpp @@ -12,7 +12,7 @@ * File Description: Abstract interpretation for Thumb mode. **************************************************************************/ -#ifdef ARDUINO_ARCH_SAM +#if defined(__arm__) || defined(__thumb__) #define MODULE_NAME "UNWARM_THUMB" @@ -243,40 +243,40 @@ UnwResult UnwStartThumb(UnwState * const state) { UnwPrintd3(" r%d = 0x%08x\n", r, state->regData[r].v); } - /* - * TBB / TBH - */ - else if ((instr & 0xfff0) == 0xe8d0 && (instr2 & 0xffe0) == 0xf000) { - /* We are only interested in - * the forms - * TBB [PC, ...] - * TBH [PC, ..., LSL #1] - * as those are used by the C compiler to implement - * the switch clauses - */ - uint8_t rn = instr & 0xf; - uint8_t rm = instr2 & 0xf; - bool H = (instr2 & 0x10) ? true : false; - - UnwPrintd5("TB%c [r%d,r%d%s]\n", H ? 'H' : 'B', rn, rm, H ? ",LSL #1" : ""); - - // We are only interested if the RN is the PC. Let´s choose the 1st destination - if (rn == 15) { - if (H) { - uint16_t rv; - if(!state->cb->readH((state->regData[15].v & (~1)) + 2, &rv)) { - return UNWIND_DREAD_H_FAIL; - } - state->regData[15].v += rv * 2; - } else { - uint8_t rv; - if(!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv)) { - return UNWIND_DREAD_B_FAIL; - } - state->regData[15].v += rv * 2; - } - } - } + /* + * TBB / TBH + */ + else if ((instr & 0xfff0) == 0xe8d0 && (instr2 & 0xffe0) == 0xf000) { + /* We are only interested in + * the forms + * TBB [PC, ...] + * TBH [PC, ..., LSL #1] + * as those are used by the C compiler to implement + * the switch clauses + */ + uint8_t rn = instr & 0xf; + uint8_t rm = instr2 & 0xf; + bool H = (instr2 & 0x10) ? true : false; + + UnwPrintd5("TB%c [r%d,r%d%s]\n", H ? 'H' : 'B', rn, rm, H ? ",LSL #1" : ""); + + // We are only interested if the RN is the PC. Let´s choose the 1st destination + if (rn == 15) { + if (H) { + uint16_t rv; + if(!state->cb->readH((state->regData[15].v & (~1)) + 2, &rv)) { + return UNWIND_DREAD_H_FAIL; + } + state->regData[15].v += rv * 2; + } else { + uint8_t rv; + if(!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv)) { + return UNWIND_DREAD_B_FAIL; + } + state->regData[15].v += rv * 2; + } + } + } /* * Unconditional branch */ @@ -408,118 +408,118 @@ UnwResult UnwStartThumb(UnwState * const state) { UnwPrintd2(" New PC=%x", state->regData[15].v + 2); } } - /* - * PC-relative load + /* + * PC-relative load * LDR Rd,[PC, #+/-imm] */ - else if((instr & 0xff7f) == 0xf85f) { - uint8_t rt = (instr2 & 0xf000) >> 12; - uint8_t imm12 = (instr2 & 0x0fff); - bool A = (instr & 0x80) ? true : false; - uint32_t address; + else if((instr & 0xff7f) == 0xf85f) { + uint8_t rt = (instr2 & 0xf000) >> 12; + uint8_t imm12 = (instr2 & 0x0fff); + bool A = (instr & 0x80) ? true : false; + uint32_t address; - /* Compute load address, adding a word to account for prefetch */ - address = (state->regData[15].v & (~0x3)) + 4; - if (A) address += imm12; - else address -= imm12; + /* Compute load address, adding a word to account for prefetch */ + address = (state->regData[15].v & (~0x3)) + 4; + if (A) address += imm12; + else address -= imm12; - UnwPrintd4("LDR r%d,[PC #%c0x%08x]", rt, A?'+':'-', address); + UnwPrintd4("LDR r%d,[PC #%c0x%08x]", rt, A?'+':'-', address); - if(!UnwMemReadRegister(state, address, &state->regData[rt])) { - return UNWIND_DREAD_W_FAIL; - } - } - /* - * LDR immediate. - * We are only interested when destination is PC. - * LDR Rt,[Rn , #n] - */ - else if ((instr & 0xfff0) == 0xf8d0) { - uint8_t rn = (instr & 0xf); - uint8_t rt = (instr2 & 0xf000) >> 12; - uint16_t imm12 = (instr2 & 0xfff); - - /* If destination is PC and we don't know the source value, then fail */ - if (!M_IsOriginValid(state->regData[rn].o)) { - state->regData[rt].o = state->regData[rn].o; - } else { - uint32_t address = state->regData[rn].v + imm12; - if(!UnwMemReadRegister(state, address, &state->regData[rt])) { - return UNWIND_DREAD_W_FAIL; - } - } - } - /* - * LDR immediate - * We are only interested when destination is PC. - * LDR Rt,[Rn , #-n] - * LDR Rt,[Rn], #+/-n] - * LDR Rt,[Rn, #+/-n]! - */ - else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0800) == 0x0800) { - uint8_t rn = (instr & 0xf); - uint8_t rt = (instr2 & 0xf000) >> 12; - uint16_t imm8 = (instr2 & 0xff); - bool P = (instr2 & 0x400) ? true : false; - bool U = (instr2 & 0x200) ? true : false; - bool W = (instr2 & 0x100) ? true : false; - - if (!M_IsOriginValid(state->regData[rn].o)) { - state->regData[rt].o = state->regData[rn].o; - } else { - uint32_t offaddress = state->regData[rn].v + imm8; - if (U) offaddress += imm8; - else offaddress -= imm8; - - uint32_t address; - if (P) { - address = offaddress; - } else { - address = state->regData[rn].v; - } - - if(!UnwMemReadRegister(state, address, &state->regData[rt])) { - return UNWIND_DREAD_W_FAIL; - } - - if (W) { - state->regData[rn].v = offaddress; - } - } - } - /* - * LDR (register). - * We are interested in the form - * ldr Rt, [Rn, Rm, lsl #x] - * Where Rt is PC, Rn value is known, Rm is not known or unknown - */ - else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0fc0) == 0x0000) { - uint8_t rn = (instr & 0xf); - uint8_t rt = (instr2 & 0xf000) >> 12; - uint8_t rm = (instr2 & 0xf); - uint8_t imm2 = (instr2 & 0x30) >> 4; - - if (!M_IsOriginValid(state->regData[rn].o) || - !M_IsOriginValid(state->regData[rm].o)) { - - /* If Rt is PC, and Rn is known, then do an exception and assume - Rm equals 0 => This takes the first case in a switch() */ - if (rt == 15 && M_IsOriginValid(state->regData[rn].o)) { - uint32_t address = state->regData[rn].v; - if(!UnwMemReadRegister(state, address, &state->regData[rt])) { - return UNWIND_DREAD_W_FAIL; - } - } else { - /* Propagate unknown value */ - state->regData[rt].o = state->regData[rn].o; - } - } else { - uint32_t address = state->regData[rn].v + (state->regData[rm].v << imm2); - if(!UnwMemReadRegister(state, address, &state->regData[rt])) { - return UNWIND_DREAD_W_FAIL; - } - } - } + if(!UnwMemReadRegister(state, address, &state->regData[rt])) { + return UNWIND_DREAD_W_FAIL; + } + } + /* + * LDR immediate. + * We are only interested when destination is PC. + * LDR Rt,[Rn , #n] + */ + else if ((instr & 0xfff0) == 0xf8d0) { + uint8_t rn = (instr & 0xf); + uint8_t rt = (instr2 & 0xf000) >> 12; + uint16_t imm12 = (instr2 & 0xfff); + + /* If destination is PC and we don't know the source value, then fail */ + if (!M_IsOriginValid(state->regData[rn].o)) { + state->regData[rt].o = state->regData[rn].o; + } else { + uint32_t address = state->regData[rn].v + imm12; + if(!UnwMemReadRegister(state, address, &state->regData[rt])) { + return UNWIND_DREAD_W_FAIL; + } + } + } + /* + * LDR immediate + * We are only interested when destination is PC. + * LDR Rt,[Rn , #-n] + * LDR Rt,[Rn], #+/-n] + * LDR Rt,[Rn, #+/-n]! + */ + else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0800) == 0x0800) { + uint8_t rn = (instr & 0xf); + uint8_t rt = (instr2 & 0xf000) >> 12; + uint16_t imm8 = (instr2 & 0xff); + bool P = (instr2 & 0x400) ? true : false; + bool U = (instr2 & 0x200) ? true : false; + bool W = (instr2 & 0x100) ? true : false; + + if (!M_IsOriginValid(state->regData[rn].o)) { + state->regData[rt].o = state->regData[rn].o; + } else { + uint32_t offaddress = state->regData[rn].v + imm8; + if (U) offaddress += imm8; + else offaddress -= imm8; + + uint32_t address; + if (P) { + address = offaddress; + } else { + address = state->regData[rn].v; + } + + if(!UnwMemReadRegister(state, address, &state->regData[rt])) { + return UNWIND_DREAD_W_FAIL; + } + + if (W) { + state->regData[rn].v = offaddress; + } + } + } + /* + * LDR (register). + * We are interested in the form + * ldr Rt, [Rn, Rm, lsl #x] + * Where Rt is PC, Rn value is known, Rm is not known or unknown + */ + else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0fc0) == 0x0000) { + uint8_t rn = (instr & 0xf); + uint8_t rt = (instr2 & 0xf000) >> 12; + uint8_t rm = (instr2 & 0xf); + uint8_t imm2 = (instr2 & 0x30) >> 4; + + if (!M_IsOriginValid(state->regData[rn].o) || + !M_IsOriginValid(state->regData[rm].o)) { + + /* If Rt is PC, and Rn is known, then do an exception and assume + Rm equals 0 => This takes the first case in a switch() */ + if (rt == 15 && M_IsOriginValid(state->regData[rn].o)) { + uint32_t address = state->regData[rn].v; + if(!UnwMemReadRegister(state, address, &state->regData[rt])) { + return UNWIND_DREAD_W_FAIL; + } + } else { + /* Propagate unknown value */ + state->regData[rt].o = state->regData[rn].o; + } + } else { + uint32_t address = state->regData[rn].v + (state->regData[rm].v << imm2); + if(!UnwMemReadRegister(state, address, &state->regData[rt])) { + return UNWIND_DREAD_W_FAIL; + } + } + } else { UnwPrintd1("???? (32)"); diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.c b/Marlin/src/backtrace/unwarmbytab.cpp similarity index 98% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.c rename to Marlin/src/backtrace/unwarmbytab.cpp index 334654601..9827f25f6 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.c +++ b/Marlin/src/backtrace/unwarmbytab.cpp @@ -11,7 +11,7 @@ * for exceptions for debugging purposes in 2018 by Eduardo José Tagle. */ -#ifdef ARDUINO_ARCH_SAM +#if defined(__arm__) || defined(__thumb__) #include "unwarmbytab.h" @@ -19,8 +19,8 @@ #include /* These symbols point to the unwind index and should be provide by the linker script */ -extern const UnwTabEntry __exidx_start[]; -extern const UnwTabEntry __exidx_end[]; +extern "C" const UnwTabEntry __exidx_start[]; +extern "C" const UnwTabEntry __exidx_end[]; /* This prevents the linking of libgcc unwinder code */ void __aeabi_unwind_cpp_pr0(void) {}; diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.h b/Marlin/src/backtrace/unwarmbytab.h similarity index 94% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.h rename to Marlin/src/backtrace/unwarmbytab.h index cdf114c51..a17a6f7d6 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.h +++ b/Marlin/src/backtrace/unwarmbytab.h @@ -29,16 +29,8 @@ typedef struct { uint32_t insn; } UnwTabEntry; -#ifdef __cplusplus -extern "C" { -#endif - UnwResult UnwindByTableStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data); -#ifdef __cplusplus -} -#endif - #endif /* END OF FILE */ diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.c b/Marlin/src/backtrace/unwarmmem.cpp similarity index 98% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.c rename to Marlin/src/backtrace/unwarmmem.cpp index 57fb011fe..bac3c8989 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.c +++ b/Marlin/src/backtrace/unwarmmem.cpp @@ -12,7 +12,7 @@ * File Description: Implementation of the memory tracking sub-system. **************************************************************************/ -#ifdef ARDUINO_ARCH_SAM +#if defined(__arm__) || defined(__thumb__) #define MODULE_NAME "UNWARMMEM" #include diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.h b/Marlin/src/backtrace/unwarmmem.h similarity index 94% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.h rename to Marlin/src/backtrace/unwarmmem.h index 107286b82..f30846b34 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.h +++ b/Marlin/src/backtrace/unwarmmem.h @@ -17,17 +17,9 @@ #include "unwarm.h" -#ifdef __cplusplus -extern "C" { -#endif - bool UnwMemHashRead(MemData * const memData, uint32_t addr, uint32_t * const data, bool * const tracked); bool UnwMemHashWrite(MemData * const memData, uint32_t addr, uint32_t val, bool valValid); void UnwMemHashGC(UnwState * const state); -#ifdef __cplusplus -} -#endif - #endif diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.c b/Marlin/src/backtrace/unwinder.cpp similarity index 93% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwinder.c rename to Marlin/src/backtrace/unwinder.cpp index a6e572186..88a61ee64 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.c +++ b/Marlin/src/backtrace/unwinder.cpp @@ -12,7 +12,7 @@ * File Description: Implementation of the interface into the ARM unwinder. **************************************************************************/ -#ifdef ARDUINO_ARCH_SAM +#if defined(__arm__) || defined(__thumb__) #define MODULE_NAME "UNWINDER" @@ -23,8 +23,8 @@ #include "unwarmbytab.h" /* These symbols point to the unwind index and should be provide by the linker script */ -extern const UnwTabEntry __exidx_start[]; -extern const UnwTabEntry __exidx_end[]; +extern "C" const UnwTabEntry __exidx_start[]; +extern "C" const UnwTabEntry __exidx_end[]; // Detect if unwind information is present or not static int HasUnwindTableInfo(void) { diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.h b/Marlin/src/backtrace/unwinder.h similarity index 98% rename from Marlin/src/HAL/HAL_DUE/backtrace/unwinder.h rename to Marlin/src/backtrace/unwinder.h index 8ff80ebc8..683a29e33 100644 --- a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.h +++ b/Marlin/src/backtrace/unwinder.h @@ -17,7 +17,6 @@ #define UNWINDER_H #include -#include /** \def UNW_DEBUG * If this define is set, additional information will be produced while @@ -161,10 +160,6 @@ typedef struct { uint32_t pc; } UnwindFrame; -#ifdef __cplusplus -extern "C" { -#endif - /** Start unwinding the current stack. * This will unwind the stack starting at the PC value supplied to in the * link register (i.e. not a normal register) and the stack pointer value @@ -177,8 +172,4 @@ extern "C" { */ UnwResult UnwindStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data); -#ifdef __cplusplus -} -#endif - #endif /* UNWINDER_H */ diff --git a/Marlin/src/backtrace/unwmemaccess.cpp b/Marlin/src/backtrace/unwmemaccess.cpp new file mode 100644 index 000000000..f7041d52d --- /dev/null +++ b/Marlin/src/backtrace/unwmemaccess.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + * ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk + * Updated, adapted and several bug fixes on 2018 by Eduardo José Tagle + * + * This program is PUBLIC DOMAIN. + * This means that there is no copyright and anyone is able to take a copy + * for free and use it as they wish, with or without modifications, and in + * any context, commercially or otherwise. The only limitation is that I + * don't guarantee that the software is fit for any purpose or accept any + * liability for it's use or misuse - this software is without warranty. + *************************************************************************** + * File Description: Utility functions to access memory + **************************************************************************/ + +#if defined(__arm__) || defined(__thumb__) + +#include "unwmemaccess.h" + +/* Validate address */ + +#ifdef ARDUINO_ARCH_SAM +// For DUE, valid address ranges are +// SRAM (0x20070000 - 0x20088000) (96kb) +// FLASH (0x00080000 - 0x00100000) (512kb) +// +#define START_SRAM_ADDR 0x20070000 +#define END_SRAM_ADDR 0x20088000 +#define START_FLASH_ADDR 0x00080000 +#define END_FLASH_ADDR 0x00100000 +#endif + +#ifdef TARGET_LPC1768 +// For LPC1769: +// SRAM (0x10000000 - 0x10008000) (32kb) +// FLASH (0x00000000 - 0x00080000) (512kb) +// +#define START_SRAM_ADDR 0x10000000 +#define END_SRAM_ADDR 0x10008000 +#define START_FLASH_ADDR 0x00000000 +#define END_FLASH_ADDR 0x00080000 +#endif + +#if 0 +// For STM32F103CBT6 +// SRAM (0x20000000 - 0x20005000) (20kb) +// FLASH (0x00000000 - 0x00020000) (128kb) +// +#define START_SRAM_ADDR 0x20000000 +#define END_SRAM_ADDR 0x20005000 +#define START_FLASH_ADDR 0x00000000 +#define END_FLASH_ADDR 0x00020000 +#endif + +#ifdef __STM32F1__ +// For STM32F103ZET6/STM32F103VET6 +// SRAM (0x20000000 - 0x20010000) (64kb) +// FLASH (0x00000000 - 0x00080000) (512kb) +// +#define START_SRAM_ADDR 0x20000000 +#define END_SRAM_ADDR 0x20010000 +#define START_FLASH_ADDR 0x00000000 +#define END_FLASH_ADDR 0x00080000 +#endif + +#ifdef STM32F7 +// For STM32F765 in BORG +// SRAM (0x20000000 - 0x20080000) (512kb) +// FLASH (0x08000000 - 0x08100000) (1024kb) +// +#define START_SRAM_ADDR 0x20000000 +#define END_SRAM_ADDR 0x20080000 +#define START_FLASH_ADDR 0x08000000 +#define END_FLASH_ADDR 0x08100000 +#endif + +#ifdef __MK64FX512__ +// For MK64FX512 in TEENSY 3.5 +// SRAM (0x1FFF0000 - 0x20020000) (192kb) +// FLASH (0x00000000 - 0x00080000) (512kb) +// +#define START_SRAM_ADDR 0x1FFF0000 +#define END_SRAM_ADDR 0x20020000 +#define START_FLASH_ADDR 0x00000000 +#define END_FLASH_ADDR 0x00080000 +#endif + +#ifdef __MK66FX1M0__ +// For MK66FX1M0 in TEENSY 3.6 +// SRAM (0x1FFF0000 - 0x20030000) (256kb) +// FLASH (0x00000000 - 0x00140000) (1.25Mb) +// +#define START_SRAM_ADDR 0x1FFF0000 +#define END_SRAM_ADDR 0x20030000 +#define START_FLASH_ADDR 0x00000000 +#define END_FLASH_ADDR 0x00140000 +#endif + +static bool validate_addr(uint32_t addr) { + + // Address must be in SRAM range + if (addr >= START_SRAM_ADDR && addr < END_SRAM_ADDR) + return true; + + // Or in FLASH range + if (addr >= START_FLASH_ADDR && addr < END_FLASH_ADDR) + return true; + + return false; +} + +bool UnwReadW(const uint32_t a, uint32_t *v) { + if (!validate_addr(a)) + return false; + + *v = *(uint32_t *)a; + return true; +} + +bool UnwReadH(const uint32_t a, uint16_t *v) { + if (!validate_addr(a)) + return false; + + *v = *(uint16_t *)a; + return true; +} + +bool UnwReadB(const uint32_t a, uint8_t *v) { + if (!validate_addr(a)) + return false; + + *v = *(uint8_t *)a; + return true; +} + +#endif + diff --git a/Marlin/src/backtrace/unwmemaccess.h b/Marlin/src/backtrace/unwmemaccess.h new file mode 100644 index 000000000..5405f3a67 --- /dev/null +++ b/Marlin/src/backtrace/unwmemaccess.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk + * Updated, adapted and several bug fixes on 2018 by Eduardo José Tagle + * + * This program is PUBLIC DOMAIN. + * This means that there is no copyright and anyone is able to take a copy + * for free and use it as they wish, with or without modifications, and in + * any context, commerically or otherwise. The only limitation is that I + * don't guarantee that the software is fit for any purpose or accept any + * liablity for it's use or misuse - this software is without warranty. + *************************************************************************** + * File Description: Utility functions to access memory + **************************************************************************/ + +#ifndef UNWMEMACCESS_H +#define UNWMEMACCESS_H + +#include "unwarm.h" +#include + +bool UnwReadW(const uint32_t a, uint32_t *v); +bool UnwReadH(const uint32_t a, uint16_t *v); +bool UnwReadB(const uint32_t a, uint8_t *v); + +#endif +