119 lines
3.3 KiB
C++
119 lines
3.3 KiB
C++
/***************************************************************************
|
|
* ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk
|
|
* Updated, adapted and several bug fixes on 2018 by Eduardo José Tagle
|
|
*
|
|
* 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.
|
|
**************************************************************************/
|
|
|
|
#if defined(__arm__) || defined(__thumb__)
|
|
#define MODULE_NAME "UNWARMMEM"
|
|
|
|
#include <stdio.h>
|
|
#include "unwarmmem.h"
|
|
#include "unwarm.h"
|
|
|
|
#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)))
|
|
|
|
/** 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 int16_t memHashIndex(MemData * const memData, const uint32_t addr) {
|
|
|
|
const uint16_t v = addr % MEM_HASH_SIZE;
|
|
uint16_t 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;
|
|
}
|
|
|
|
bool UnwMemHashRead(MemData * const memData, uint32_t addr,uint32_t * const data, bool * const tracked) {
|
|
|
|
int16_t 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;
|
|
}
|
|
}
|
|
|
|
bool UnwMemHashWrite(MemData * const memData, uint32_t addr, uint32_t val, bool valValid) {
|
|
|
|
int16_t 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 uint32_t minValidAddr = state->regData[13].v;
|
|
MemData * const memData = &state->memData;
|
|
uint16_t 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // __arm__ || __thumb__
|