123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /***************************************************************************
- * 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);
|