forked from len0rd/rockbox
Arm stack unwinder
Simplified stack unwinder for ARM. This is port of http://www.mcternan.me.uk/ArmStackUnwinding/ backtrace() is called from UIE() on native targets and from panicf() on both native and ARM RaaA. Change-Id: I8e4b3c02490dd60b30aa372fe842d193b8929ce0
This commit is contained in:
parent
680c6fcde1
commit
b4eab59951
23 changed files with 2630 additions and 18 deletions
175
lib/unwarminder/unwarmmem.c
Normal file
175
lib/unwarminder/unwarmmem.c
Normal file
|
@ -0,0 +1,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 */
|
Loading…
Add table
Add a link
Reference in a new issue