aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/HAL/shared/backtrace/unwinder.h
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/HAL/shared/backtrace/unwinder.h')
-rw-r--r--Marlin/src/HAL/shared/backtrace/unwinder.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/Marlin/src/HAL/shared/backtrace/unwinder.h b/Marlin/src/HAL/shared/backtrace/unwinder.h
new file mode 100644
index 0000000..157808d
--- /dev/null
+++ b/Marlin/src/HAL/shared/backtrace/unwinder.h
@@ -0,0 +1,172 @@
+/***************************************************************************
+ * 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
+ * liability for its use or misuse - this software is without warranty.
+ **************************************************************************/
+/** \file
+ * Interface to the ARM stack unwinding module.
+ **************************************************************************/
+
+#pragma once
+
+#include <stdint.h>
+
+/** \def UNW_DEBUG
+ * If this define is set, additional information will be produced while
+ * unwinding the stack to allow debug of the unwind module itself.
+ */
+/* #define UNW_DEBUG 1 */
+
+/***************************************************************************
+ * Type Definitions
+ **************************************************************************/
+
+/** Possible results for UnwindStart to return.
+ */
+typedef enum {
+ /** Unwinding was successful and complete. */
+ UNWIND_SUCCESS = 0,
+
+ /** Not an error: More frames are available. */
+ UNWIND_MORE_AVAILABLE = 1,
+
+ /** Unsupported DWARF unwind personality. */
+ UNWIND_UNSUPPORTED_DWARF_PERSONALITY = -1,
+
+ /** Refused to perform unwind. */
+ UNWIND_REFUSED = -2,
+
+ /** Reached an invalid SP. */
+ UNWIND_INVALID_SP = -3,
+
+ /** Reached an invalid PC */
+ UNWIND_INVALID_PC = -4,
+
+ /** Unsupported DWARF instruction */
+ UNWIND_UNSUPPORTED_DWARF_INSTR = -5,
+
+ /** More than UNW_MAX_INSTR_COUNT instructions were interpreted. */
+ UNWIND_EXHAUSTED = -6,
+
+ /** Unwinding stopped because the reporting func returned false. */
+ UNWIND_TRUNCATED = -7,
+
+ /** Read data was found to be inconsistent. */
+ UNWIND_INCONSISTENT = -8,
+
+ /** Unsupported instruction or data found. */
+ UNWIND_UNSUPPORTED = -9,
+
+ /** General failure. */
+ UNWIND_FAILURE = -10,
+
+ /** Illegal instruction. */
+ UNWIND_ILLEGAL_INSTR = -11,
+
+ /** Unwinding hit the reset vector. */
+ UNWIND_RESET = -12,
+
+ /** Failed read for an instruction word. */
+ UNWIND_IREAD_W_FAIL = -13,
+
+ /** Failed read for an instruction half-word. */
+ UNWIND_IREAD_H_FAIL = -14,
+
+ /** Failed read for an instruction byte. */
+ UNWIND_IREAD_B_FAIL = -15,
+
+ /** Failed read for a data word. */
+ UNWIND_DREAD_W_FAIL = -16,
+
+ /** Failed read for a data half-word. */
+ UNWIND_DREAD_H_FAIL = -17,
+
+ /** Failed read for a data byte. */
+ UNWIND_DREAD_B_FAIL = -18,
+
+ /** Failed write for a data word. */
+ UNWIND_DWRITE_W_FAIL = -19
+
+} UnwResult;
+
+/** A backtrace report */
+typedef struct {
+ uint32_t function; /** Starts address of function */
+ const char *name; /** Function name, or null if not available */
+ uint32_t address; /** PC on that function */
+} UnwReport;
+
+/** Type for function pointer for result callback.
+ * The function is passed two parameters, the first is a void * pointer,
+ * and the second is the return address of the function. The bottom bit
+ * of the passed address indicates the execution mode; if it is set,
+ * the execution mode at the return address is Thumb, otherwise it is
+ * ARM.
+ *
+ * The return value of this function determines whether unwinding should
+ * continue or not. If true is returned, unwinding will continue and the
+ * report function maybe called again in future. If false is returned,
+ * unwinding will stop with UnwindStart() returning UNWIND_TRUNCATED.
+ */
+typedef bool (*UnwindReportFunc)(void* data, const UnwReport* bte);
+
+/** Structure that holds memory callback function pointers.
+ */
+typedef struct {
+
+ /** Report an unwind result. */
+ UnwindReportFunc report;
+
+ /** Read a 32 bit word from memory.
+ * The memory address to be read is passed as \a address, and
+ * \a *val is expected to be populated with the read value.
+ * If the address cannot or should not be read, false can be
+ * returned to indicate that unwinding should stop. If true
+ * is returned, \a *val is assumed to be valid and unwinding
+ * will continue.
+ */
+ bool (*readW)(const uint32_t address, uint32_t *val);
+
+ /** Read a 16 bit half-word from memory.
+ * This function has the same usage as for readW, but is expected
+ * to read only a 16 bit value.
+ */
+ bool (*readH)(const uint32_t address, uint16_t *val);
+
+ /** Read a byte from memory.
+ * This function has the same usage as for readW, but is expected
+ * to read only an 8 bit value.
+ */
+ bool (*readB)(const uint32_t address, uint8_t *val);
+
+ #ifdef UNW_DEBUG
+ /** Print a formatted line for debug. */
+ void (*printf)(const char *format, ...);
+ #endif
+} UnwindCallbacks;
+
+/* A frame */
+typedef struct {
+ uint32_t fp;
+ uint32_t sp;
+ uint32_t lr;
+ uint32_t pc;
+} UnwindFrame;
+
+/** 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
+ * supplied.
+ *
+ * -If the program was compiled with -funwind-tables it will use them to
+ * perform the traceback. Otherwise, brute force will be employed
+ * -If the program was compiled with -mpoke-function-name, then you will
+ * get function names in the traceback. Otherwise, you will not.
+ */
+UnwResult UnwindStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data);