summaryrefslogtreecommitdiff
path: root/lib/unwarminder/unwarm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/unwarminder/unwarm.c')
-rw-r--r--lib/unwarminder/unwarm.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/lib/unwarminder/unwarm.c b/lib/unwarminder/unwarm.c
new file mode 100644
index 0000000000..99f6a12ccb
--- /dev/null
+++ b/lib/unwarminder/unwarm.c
@@ -0,0 +1,183 @@
1/***************************************************************************
2 * ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk
3 *
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, commercially or otherwise. The only limitation is that I
8 * don't guarantee that the software is fit for any purpose or accept any
9 * liability for it's use or misuse - this software is without warranty.
10 ***************************************************************************
11 * File Description: Utility functions and glue for ARM unwinding sub-modules.
12 **************************************************************************/
13
14#define MODULE_NAME "UNWARM"
15
16/***************************************************************************
17 * Include Files
18 **************************************************************************/
19
20#include "types.h"
21#include <stdio.h>
22#include <stdarg.h>
23#include <string.h>
24#include "unwarm.h"
25#include "unwarmmem.h"
26
27/***************************************************************************
28 * Manifest Constants
29 **************************************************************************/
30
31
32/***************************************************************************
33 * Type Definitions
34 **************************************************************************/
35
36
37/***************************************************************************
38 * Variables
39 **************************************************************************/
40
41
42/***************************************************************************
43 * Macros
44 **************************************************************************/
45
46
47/***************************************************************************
48 * Local Functions
49 **************************************************************************/
50
51
52/***************************************************************************
53 * Global Functions
54 **************************************************************************/
55
56#if defined(UNW_DEBUG)
57/** Printf wrapper.
58 * This is used such that alternative outputs for any output can be selected
59 * by modification of this wrapper function.
60 */
61void UnwPrintf(const char *format, ...)
62{
63 va_list args;
64
65 va_start( args, format );
66 vprintf(format, args );
67}
68#endif
69
70/** Invalidate all general purpose registers.
71 */
72void UnwInvalidateRegisterFile(RegData *regFile)
73{
74 Int8 t = 0;
75
76 do
77 {
78 regFile[t].o = REG_VAL_INVALID;
79 t++;
80 }
81 while(t < 13);
82
83}
84
85
86/** Initialise the data used for unwinding.
87 */
88void UnwInitState(UnwState * const state, /**< Pointer to structure to fill. */
89 const UnwindCallbacks *cb, /**< Callbacks. */
90 void *rptData, /**< Data to pass to report function. */
91 Int32 pcValue, /**< PC at which to start unwinding. */
92 Int32 spValue) /**< SP at which to start unwinding. */
93{
94 UnwInvalidateRegisterFile(state->regData);
95
96 /* Store the pointer to the callbacks */
97 state->cb = cb;
98 state->reportData = rptData;
99
100 /* Setup the SP and PC */
101 state->regData[13].v = spValue;
102 state->regData[13].o = REG_VAL_FROM_CONST;
103 state->regData[15].v = pcValue;
104 state->regData[15].o = REG_VAL_FROM_CONST;
105
106 UnwPrintd3("\nInitial: PC=0x%08x SP=0x%08x\n", pcValue, spValue);
107
108 /* Invalidate all memory addresses */
109 memset(state->memData.used, 0, sizeof(state->memData.used));
110}
111
112
113/** Call the report function to indicate some return address.
114 * This returns the value of the report function, which if TRUE
115 * indicates that unwinding may continue.
116 */
117Boolean UnwReportRetAddr(UnwState * const state, Int32 addr)
118{
119 /* Cast away const from reportData.
120 * The const is only to prevent the unw module modifying the data.
121 */
122 return state->cb->report((void *)state->reportData, addr);
123}
124
125
126/** Write some register to memory.
127 * This will store some register and meta data onto the virtual stack.
128 * The address for the write
129 * \param state [in/out] The unwinding state.
130 * \param wAddr [in] The address at which to write the data.
131 * \param reg [in] The register to store.
132 * \return TRUE if the write was successful, FALSE otherwise.
133 */
134Boolean UnwMemWriteRegister(UnwState * const state,
135 const Int32 addr,
136 const RegData * const reg)
137{
138 return UnwMemHashWrite(&state->memData,
139 addr,
140 reg->v,
141 M_IsOriginValid(reg->o));
142}
143
144/** Read a register from memory.
145 * This will read a register from memory, and setup the meta data.
146 * If the register has been previously written to memory using
147 * UnwMemWriteRegister, the local hash will be used to return the
148 * value while respecting whether the data was valid or not. If the
149 * register was previously written and was invalid at that point,
150 * REG_VAL_INVALID will be returned in *reg.
151 * \param state [in] The unwinding state.
152 * \param addr [in] The address to read.
153 * \param reg [out] The result, containing the data value and the origin
154 * which will be REG_VAL_FROM_MEMORY, or REG_VAL_INVALID.
155 * \return TRUE if the address could be read and *reg has been filled in.
156 * FALSE is the data could not be read.
157 */
158Boolean UnwMemReadRegister(UnwState * const state,
159 const Int32 addr,
160 RegData * const reg)
161{
162 Boolean tracked;
163
164 /* Check if the value can be found in the hash */
165 if(UnwMemHashRead(&state->memData, addr, &reg->v, &tracked))
166 {
167 reg->o = tracked ? REG_VAL_FROM_MEMORY : REG_VAL_INVALID;
168 return TRUE;
169 }
170 /* Not in the hash, so read from real memory */
171 else if(state->cb->readW(addr, &reg->v))
172 {
173 reg->o = REG_VAL_FROM_MEMORY;
174 return TRUE;
175 }
176 /* Not in the hash, and failed to read from memory */
177 else
178 {
179 return FALSE;
180 }
181}
182
183/* END OF FILE */