/*************************************************************************** * ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk * * 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: Unwinder client that reads local memory. * This client reads from local memory and is designed to run on target * along with the unwinder. Memory read requests are implemented by * casting a point to read the memory directly, although checks for * alignment should probably also be made if this is to be used in * production code, as otherwise the ARM may return the memory in a * rotated/rolled format, or the MMU may generate an alignment exception * if present and so configured. **************************************************************************/ /*************************************************************************** * Includes ***************************************************************************/ #include "backtrace.h" #include "safe_read.h" /*************************************************************************** * Prototypes ***************************************************************************/ static Boolean CliReport(void *data, Int32 address); static Boolean CliReadW(Int32 a, Int32 *v); static Boolean CliReadH(Int32 a, Int16 *v); static Boolean CliReadB(Int32 a, Int8 *v); /*************************************************************************** * Variables ***************************************************************************/ /* Table of function pointers for passing to the unwinder */ const UnwindCallbacks cliCallbacks = { CliReport, CliReadW, CliReadH, CliReadB #if defined(UNW_DEBUG) ,printf #endif }; /*************************************************************************** * Callbacks ***************************************************************************/ /*************************************************************************** * * Function: CliReport * * Parameters: data - Pointer to data passed to UnwindStart() * address - The return address of a stack frame. * * Returns: TRUE if unwinding should continue, otherwise FALSE to * indicate that unwinding should stop. * * Description: This function is called from the unwinder each time a stack * frame has been unwound. The LSB of address indicates if * the processor is in ARM mode (LSB clear) or Thumb (LSB * set). * ***************************************************************************/ static Boolean CliReport(void *data, Int32 address) { /* CliStack *s = (CliStack *)data; */ unsigned *line = (unsigned *)data; lcd_putsf(0, (*line)++, " %c: %08x", (address & 0x1) ? 'T' : 'A', address & (~0x1)); lcd_update(); return TRUE; } static Boolean CliReadW(const Int32 a, Int32 *v) { return safe_read32((uint32_t *)a, (uint32_t *)v); } static Boolean CliReadH(const Int32 a, Int16 *v) { return safe_read16((void *)a, (uint16_t *)v); } static Boolean CliReadB(const Int32 a, Int8 *v) { return safe_read8((void *)a, (uint8_t *)v); } Boolean CliInvalidateW(const Int32 a) { *(Int32 *)a = 0xdeadbeef; return TRUE; } void backtrace(int pcAddr, int spAddr, unsigned *line) { lcd_putsf(0, (*line)++, "pc:%08x sp:%08x", pcAddr, spAddr); lcd_update(); UnwindStart(pcAddr, spAddr, &cliCallbacks, (void *)line); lcd_puts(0, (*line)++, "bt end"); lcd_update(); } /* END OF FILE */