| /*************************************************************************** |
| * 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 |
| * liablity for it's use or misuse - this software is without warranty. |
| *************************************************************************** |
| * File Description: Internal interface between the ARM unwinding sub-modules. |
| **************************************************************************/ |
| |
| #ifndef UNWARM_H |
| #define UNWARM_H |
| |
| /*************************************************************************** |
| * Nested Include Files |
| **************************************************************************/ |
| |
| #include "types.h" |
| #include "unwarminder.h" |
| |
| /*************************************************************************** |
| * Manifest Constants |
| **************************************************************************/ |
| |
| /** 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 1000 /* originaly it was 100 */ |
| |
| /** 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 61 /* originaly it was 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. */ |
| Int32 v; |
| |
| /** The origin of the register value. |
| * This is used to track how the value in the register was loaded. |
| */ |
| RegValOrigin o; |
| } |
| 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. */ |
| Int32 v[MEM_HASH_SIZE]; |
| |
| /** Address at which v[n] represents. */ |
| Int32 a[MEM_HASH_SIZE]; |
| |
| /** Indicates whether the data in v[n] and a[n] is occupied. |
| * Each bit represents one hash value. |
| */ |
| Int8 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. |
| */ |
| Int8 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) ? TRUE : FALSE) |
| #define M_Origin2Str(v) ((v) ? "VALID" : "INVALID") |
| |
| #if defined(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, |
| Int32 pcValue, |
| Int32 spValue); |
| |
| Boolean UnwReportRetAddr (UnwState * const state, Int32 addr); |
| |
| Boolean UnwMemWriteRegister (UnwState * const state, |
| const Int32 addr, |
| const RegData * const reg); |
| |
| Boolean UnwMemReadRegister (UnwState * const state, |
| const Int32 addr, |
| RegData * const reg); |
| |
| void UnwMemHashGC (UnwState * const state); |
| |
| #endif /* UNWARM_H */ |
| |
| /* END OF FILE */ |
| |
| |