diff options
| author | Daniel Glöckner <daniel-gl@gmx.net> | 2010-05-14 14:22:32 +0200 |
|---|---|---|
| committer | Daniel Glöckner <daniel-gl@gmx.net> | 2010-05-14 14:22:32 +0200 |
| commit | 20a1cba286eb333443e55c6aba5aa73e85964455 (patch) | |
| tree | 84137385770187f1a50e59fe97369ef55356352c /tccrun.c | |
| parent | 741841d863be133d4fba91933fdd83dec7a83112 (diff) | |
| download | tinycc-20a1cba286eb333443e55c6aba5aa73e85964455.tar.gz tinycc-20a1cba286eb333443e55c6aba5aa73e85964455.tar.bz2 | |
ARM: implement rt_get_caller_pc
Diffstat (limited to 'tccrun.c')
| -rw-r--r-- | tccrun.c | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -497,6 +497,50 @@ static int rt_get_caller_pc(unsigned long *paddr, } /* ------------------------------------------------------------- */ +#elif defined(__arm__) + +/* return the PC at frame level 'level'. Return negative if not found */ +static int rt_get_caller_pc(unsigned long *paddr, + ucontext_t *uc, int level) +{ + uint32_t fp, sp; + int i; + + if (level == 0) { + /* XXX: only supports linux */ +#if defined(__linux__) + *paddr = uc->uc_mcontext.arm_pc; +#else + return -1; +#endif + return 0; + } else { +#if defined(__linux__) + fp = uc->uc_mcontext.arm_fp; + sp = uc->uc_mcontext.arm_sp; + if (sp < 0x1000) + sp = 0x1000; +#else + return -1; +#endif + /* XXX: specific to tinycc stack frames */ + if (fp < sp + 12 || fp & 3) + return -1; + for(i = 1; i < level; i++) { + sp = ((uint32_t *)fp)[-2]; + if (sp < fp || sp - fp > 16 || sp & 3) + return -1; + fp = ((uint32_t *)fp)[-3]; + if (fp <= sp || fp - sp < 12 || fp & 3) + return -1; + } + /* XXX: check address validity with program info */ + *paddr = ((uint32_t *)fp)[-1]; + return 0; + } +} + +/* ------------------------------------------------------------- */ #else #warning add arch specific rt_get_caller_pc() |
