summaryrefslogtreecommitdiffstats
path: root/lib/unwarminder/unwarmmem.c
blob: 5991720412590b61eb7bc8359e1e8a9638b225bd (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
/***************************************************************************
 * 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: Implementation of the memory tracking sub-system.
 **************************************************************************/

#define MODULE_NAME "UNWARMMEM"

/***************************************************************************
 * Include Files
 **************************************************************************/

#include "types.h"
#include <stdio.h>
#include "unwarmmem.h"
#include "unwarm.h"

/***************************************************************************
 * Manifest Constants
 **************************************************************************/


/***************************************************************************
 * Type Definitions
 **************************************************************************/


/***************************************************************************
 * Variables
 **************************************************************************/


/***************************************************************************
 * Macros
 **************************************************************************/


#define M_IsIdxUsed(a, v) (((a)[v >> 3] & (1 << (v & 0x7))) ? TRUE : FALSE)

#define M_SetIdxUsed(a, v) ((a)[v >> 3] |= (1 << (v & 0x7)))

#define M_ClrIdxUsed(a, v) ((a)[v >> 3] &= ~(1 << (v & 0x7)))

/***************************************************************************
 * Local Functions
 **************************************************************************/

/** Search the memory hash to see if an entry is stored in the hash already.
 * This will search the hash and either return the index where the item is
 * stored, or -1 if the item was not found.
 */
static SignedInt16 memHashIndex(MemData * const memData,
                                const Int32     addr)
{
    const Int16 v = addr % MEM_HASH_SIZE;
    Int16       s = v;

    do
    {
        /* Check if the element is occupied */
        if(M_IsIdxUsed(memData->used, s))
        {
            /* Check if it is occupied with the sought data */
            if(memData->a[s] == addr)
            {
                return s;
            }
        }
        else
        {
            /* Item is free, this is where the item should be stored */
            return s;
        }

        /* Search the next entry */
        s++;
        if(s > MEM_HASH_SIZE)
        {
            s = 0;
        }
    }
    while(s != v);

    /* Search failed, hash is full and the address not stored */
    return -1;
}



/***************************************************************************
 * Global Functions
 **************************************************************************/

Boolean UnwMemHashRead(MemData * const memData,
                       Int32           addr,
                       Int32   * const data,
                       Boolean * const tracked)
{
    SignedInt16 i = memHashIndex(memData, addr);

    if(i >= 0 && M_IsIdxUsed(memData->used, i) && memData->a[i] == addr)
    {
        *data    = memData->v[i];
        *tracked = M_IsIdxUsed(memData->tracked, i);
        return TRUE;
    }
    else
    {
        /* Address not found in the hash */
        return FALSE;
    }
}

Boolean UnwMemHashWrite(MemData * const memData,
                        Int32           addr,
                        Int32           val,
                        Boolean         valValid)
{
    SignedInt16 i = memHashIndex(memData, addr);

    if(i < 0)
    {
        /* Hash full */
        return FALSE;
    }
    else
    {
        /* Store the item */
        memData->a[i] = addr;
        M_SetIdxUsed(memData->used, i);

        if(valValid)
        {
            memData->v[i] = val;
            M_SetIdxUsed(memData->tracked, i);
        }
        else
        {
#if defined(UNW_DEBUG)
            memData->v[i] = 0xdeadbeef;
#endif
            M_ClrIdxUsed(memData->tracked, i);
        }

        return TRUE;
    }
}


void UnwMemHashGC(UnwState * const state)
{
    const Int32 minValidAddr = state->regData[13].v;
    MemData * const memData  = &state->memData;
    Int16       t;

    for(t = 0; t < MEM_HASH_SIZE; t++)
    {
        if(M_IsIdxUsed(memData->used, t) && (memData->a[t] < minValidAddr))
        {
            UnwPrintd3("MemHashGC: Free elem %d, addr 0x%08x\n",
                       t, memData->a[t]);

            M_ClrIdxUsed(memData->used, t);
        }
    }
}

/* END OF FILE */