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, 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 **************************************************************************/
14 #define MODULE_NAME "UNWARM"
16 /***************************************************************************
18 **************************************************************************/
25 #include "unwarmmem.h"
27 /***************************************************************************
29 **************************************************************************/
32 /***************************************************************************
34 **************************************************************************/
37 /***************************************************************************
39 **************************************************************************/
42 /***************************************************************************
44 **************************************************************************/
47 /***************************************************************************
49 **************************************************************************/
52 /***************************************************************************
54 **************************************************************************/
56 #if defined(UNW_DEBUG)
58 * This is used such that alternative outputs for any output can be selected
59 * by modification of this wrapper function.
61 void UnwPrintf(const char *format
, ...)
65 va_start( args
, format
);
66 vprintf(format
, args
);
70 /** Invalidate all general purpose registers.
72 void UnwInvalidateRegisterFile(RegData
*regFile
)
78 regFile
[t
].o
= REG_VAL_INVALID
;
86 /** Initialise the data used for unwinding.
88 void 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. */
94 UnwInvalidateRegisterFile(state
->regData
);
96 /* Store the pointer to the callbacks */
98 state
->reportData
= rptData
;
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
;
106 UnwPrintd3("\nInitial: PC=0x%08x SP=0x%08x\n", pcValue
, spValue
);
108 /* Invalidate all memory addresses */
109 memset(state
->memData
.used
, 0, sizeof(state
->memData
.used
));
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.
117 Boolean
UnwReportRetAddr(UnwState
* const state
, Int32 addr
)
119 /* Cast away const from reportData.
120 * The const is only to prevent the unw module modifying the data.
122 return state
->cb
->report((void *)state
->reportData
, addr
);
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.
134 Boolean
UnwMemWriteRegister(UnwState
* const state
,
136 const RegData
* const reg
)
138 return UnwMemHashWrite(&state
->memData
,
141 M_IsOriginValid(reg
->o
));
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.
158 Boolean
UnwMemReadRegister(UnwState
* const state
,
164 /* Check if the value can be found in the hash */
165 if(UnwMemHashRead(&state
->memData
, addr
, ®
->v
, &tracked
))
167 reg
->o
= tracked
? REG_VAL_FROM_MEMORY
: REG_VAL_INVALID
;
170 /* Not in the hash, so read from real memory */
171 else if(state
->cb
->readW(addr
, ®
->v
))
173 reg
->o
= REG_VAL_FROM_MEMORY
;
176 /* Not in the hash, and failed to read from memory */