summaryrefslogtreecommitdiffstats
path: root/lib/unwarminder/unwarm.h
blob: 45508bd39f156d34826598ca2b5a041cf148c559 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/***************************************************************************
 * 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 */