123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /***************************************************************************
- * 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, 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 Description: Internal interface between the ARM unwinding sub-modules.
- **************************************************************************/
-
- #pragma once
-
- #include "unwinder.h"
-
- /** The maximum number of instructions to interpet in a function.
- * Unwinding will be unconditionally stopped and UNWIND_EXHAUSTED returned
- * if more than this number of instructions are interpreted in a single
- * function without unwinding a stack frame. This prevents infinite loops
- * or corrupted program memory from preventing unwinding from progressing.
- */
- #define UNW_MAX_INSTR_COUNT 500
-
- /** The size of the hash used to track reads and writes to memory.
- * This should be a prime value for efficiency.
- */
- #define MEM_HASH_SIZE 31
-
- /***************************************************************************
- * Type Definitions
- **************************************************************************/
-
- typedef enum {
- /** Invalid value. */
- REG_VAL_INVALID = 0x00,
- REG_VAL_FROM_STACK = 0x01,
- REG_VAL_FROM_MEMORY = 0x02,
- REG_VAL_FROM_CONST = 0x04,
- REG_VAL_ARITHMETIC = 0x80
- } RegValOrigin;
-
-
- /** Type for tracking information about a register.
- * This stores the register value, as well as other data that helps unwinding.
- */
- typedef struct {
-
- /** The value held in the register. */
- uint32_t v;
-
- /** The origin of the register value.
- * This is used to track how the value in the register was loaded.
- */
- int o; /* (RegValOrigin) */
- } RegData;
-
-
- /** Structure used to track reads and writes to memory.
- * This structure is used as a hash to store a small number of writes
- * to memory.
- */
- typedef struct {
- /** Memory contents. */
- uint32_t v[MEM_HASH_SIZE];
-
- /** Address at which v[n] represents. */
- uint32_t a[MEM_HASH_SIZE];
-
- /** Indicates whether the data in v[n] and a[n] is occupied.
- * Each bit represents one hash value.
- */
- uint8_t used[(MEM_HASH_SIZE + 7) / 8];
-
- /** Indicates whether the data in v[n] is valid.
- * This allows a[n] to be set, but for v[n] to be marked as invalid.
- * Specifically this is needed for when an untracked register value
- * is written to memory.
- */
- uint8_t tracked[(MEM_HASH_SIZE + 7) / 8];
- } MemData;
-
-
- /** Structure that is used to keep track of unwinding meta-data.
- * This data is passed between all the unwinding functions.
- */
- typedef struct {
- /** The register values and meta-data. */
- RegData regData[16];
-
- /** Memory tracking data. */
- MemData memData;
-
- /** Pointer to the callback functions */
- const UnwindCallbacks *cb;
-
- /** Pointer to pass to the report function. */
- const void *reportData;
- } UnwState;
-
- /***************************************************************************
- * Macros
- **************************************************************************/
-
- #define M_IsOriginValid(v) !!((v) & 0x7F)
- #define M_Origin2Str(v) ((v) ? "VALID" : "INVALID")
-
- #ifdef UNW_DEBUG
- #define UnwPrintd1(a) state->cb->printf(a)
- #define UnwPrintd2(a,b) state->cb->printf(a,b)
- #define UnwPrintd3(a,b,c) state->cb->printf(a,b,c)
- #define UnwPrintd4(a,b,c,d) state->cb->printf(a,b,c,d)
- #define UnwPrintd5(a,b,c,d,e) state->cb->printf(a,b,c,d,e)
- #define UnwPrintd6(a,b,c,d,e,f) state->cb->printf(a,b,c,d,e,f)
- #define UnwPrintd7(a,b,c,d,e,f,g) state->cb->printf(a,b,c,d,e,f,g)
- #define UnwPrintd8(a,b,c,d,e,f,g,h) state->cb->printf(a,b,c,d,e,f,g,h)
- #else
- #define UnwPrintd1(a)
- #define UnwPrintd2(a,b)
- #define UnwPrintd3(a,b,c)
- #define UnwPrintd4(a,b,c,d)
- #define UnwPrintd5(a,b,c,d,e)
- #define UnwPrintd6(a,b,c,d,e,f)
- #define UnwPrintd7(a,b,c,d,e,f,g)
- #define UnwPrintd8(a,b,c,d,e,f,g,h)
- #endif
-
- /***************************************************************************
- * Function Prototypes
- **************************************************************************/
-
- UnwResult UnwStartArm(UnwState * const state);
- UnwResult UnwStartThumb(UnwState * const state);
- void UnwInvalidateRegisterFile(RegData *regFile);
- void UnwInitState(UnwState * const state, const UnwindCallbacks *cb, void *rptData, uint32_t pcValue, uint32_t spValue);
- bool UnwReportRetAddr(UnwState * const state, uint32_t addr);
- bool UnwMemWriteRegister(UnwState * const state, const uint32_t addr, const RegData * const reg);
- bool UnwMemReadRegister(UnwState * const state, const uint32_t addr, RegData * const reg);
- void UnwMemHashGC(UnwState * const state);
|