1 /***************************************************************************
2 * ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk
4 * This program is PUBLIC DOMAIN.
5 * This means that there is no copyright and anyone is able to take a copy
6 * for free and use it as they wish, with or without modifications, and in
7 * any context, commerically or otherwise. The only limitation is that I
8 * don't guarantee that the software is fit for any purpose or accept any
9 * liablity for it's use or misuse - this software is without warranty.
10 ***************************************************************************
11 * File Description: Internal interface between the ARM unwinding sub-modules.
12 **************************************************************************/
17 /***************************************************************************
18 * Nested Include Files
19 **************************************************************************/
22 #include "unwarminder.h"
24 /***************************************************************************
26 **************************************************************************/
28 /** The maximum number of instructions to interpet in a function.
29 * Unwinding will be unconditionally stopped and UNWIND_EXHAUSTED returned
30 * if more than this number of instructions are interpreted in a single
31 * function without unwinding a stack frame. This prevents infinite loops
32 * or corrupted program memory from preventing unwinding from progressing.
34 #define UNW_MAX_INSTR_COUNT 1000 /* originaly it was 100 */
36 /** The size of the hash used to track reads and writes to memory.
37 * This should be a prime value for efficiency.
39 #define MEM_HASH_SIZE 61 /* originaly it was 31 */
41 /***************************************************************************
43 **************************************************************************/
48 REG_VAL_INVALID
= 0x00,
49 REG_VAL_FROM_STACK
= 0x01,
50 REG_VAL_FROM_MEMORY
= 0x02,
51 REG_VAL_FROM_CONST
= 0x04,
52 REG_VAL_ARITHMETIC
= 0x80
57 /** Type for tracking information about a register.
58 * This stores the register value, as well as other data that helps unwinding.
62 /** The value held in the register. */
65 /** The origin of the register value.
66 * This is used to track how the value in the register was loaded.
73 /** Structure used to track reads and writes to memory.
74 * This structure is used as a hash to store a small number of writes
79 /** Memory contents. */
80 Int32 v
[MEM_HASH_SIZE
];
82 /** Address at which v[n] represents. */
83 Int32 a
[MEM_HASH_SIZE
];
85 /** Indicates whether the data in v[n] and a[n] is occupied.
86 * Each bit represents one hash value.
88 Int8 used
[(MEM_HASH_SIZE
+ 7) / 8];
90 /** Indicates whether the data in v[n] is valid.
91 * This allows a[n] to be set, but for v[n] to be marked as invalid.
92 * Specifically this is needed for when an untracked register value
93 * is written to memory.
95 Int8 tracked
[(MEM_HASH_SIZE
+ 7) / 8];
100 /** Structure that is used to keep track of unwinding meta-data.
101 * This data is passed between all the unwinding functions.
105 /** The register values and meta-data. */
108 /** Memory tracking data. */
111 /** Pointer to the callback functions */
112 const UnwindCallbacks
*cb
;
114 /** Pointer to pass to the report function. */
115 const void *reportData
;
119 /***************************************************************************
121 **************************************************************************/
123 #define M_IsOriginValid(v) (((v) & 0x7f) ? TRUE : FALSE)
124 #define M_Origin2Str(v) ((v) ? "VALID" : "INVALID")
126 #if defined(UNW_DEBUG)
127 #define UnwPrintd1(a) state->cb->printf(a)
128 #define UnwPrintd2(a,b) state->cb->printf(a,b)
129 #define UnwPrintd3(a,b,c) state->cb->printf(a,b,c)
130 #define UnwPrintd4(a,b,c,d) state->cb->printf(a,b,c,d)
131 #define UnwPrintd5(a,b,c,d,e) state->cb->printf(a,b,c,d,e)
132 #define UnwPrintd6(a,b,c,d,e,f) state->cb->printf(a,b,c,d,e,f)
133 #define UnwPrintd7(a,b,c,d,e,f,g) state->cb->printf(a,b,c,d,e,f,g)
134 #define UnwPrintd8(a,b,c,d,e,f,g,h) state->cb->printf(a,b,c,d,e,f,g,h)
136 #define UnwPrintd1(a)
137 #define UnwPrintd2(a,b)
138 #define UnwPrintd3(a,b,c)
139 #define UnwPrintd4(a,b,c,d)
140 #define UnwPrintd5(a,b,c,d,e)
141 #define UnwPrintd6(a,b,c,d,e,f)
142 #define UnwPrintd7(a,b,c,d,e,f,g)
143 #define UnwPrintd8(a,b,c,d,e,f,g,h)
146 /***************************************************************************
147 * Function Prototypes
148 **************************************************************************/
150 UnwResult
UnwStartArm (UnwState
* const state
);
152 UnwResult
UnwStartThumb (UnwState
* const state
);
154 void UnwInvalidateRegisterFile(RegData
*regFile
);
156 void UnwInitState (UnwState
* const state
,
157 const UnwindCallbacks
*cb
,
162 Boolean
UnwReportRetAddr (UnwState
* const state
, Int32 addr
);
164 Boolean
UnwMemWriteRegister (UnwState
* const state
,
166 const RegData
* const reg
);
168 Boolean
UnwMemReadRegister (UnwState
* const state
,
170 RegData
* const reg
);
172 void UnwMemHashGC (UnwState
* const state
);
174 #endif /* UNWARM_H */