📄 traceframestack4arm.c
字号:
/*
* name: traceFrameStatck4ARM.c
* function: stack backtrace for arm
*/
/* include */
#include <vxworks.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <os/private/windLibP.h>
#include <sysLib.h>
#include <taskLib.h>
#include <symbol.h>
#include <symLib.h>
#include <sysSymTbl.h>
#include <usrLib.h>
#define SYSBT_MAX_FUNC_WORDS 4096
#define DBG_TASK_NOT_FOUND "Task not found\n"
enum gdb_regnum {
ARM_A1_REGNUM = 0, /* first integer-like argument */
ARM_A4_REGNUM = 3, /* last integer-like argument */
ARM_AP_REGNUM = 11,
ARM_SP_REGNUM = 13, /* Contains address of top of stack */
ARM_LR_REGNUM = 14, /* address to return to from a function call */
ARM_PC_REGNUM = 15, /* Contains program counter */
ARM_F0_REGNUM = 16, /* first floating point register */
ARM_F3_REGNUM = 19, /* last floating point argument register */
ARM_F7_REGNUM = 23, /* last floating point register */
ARM_FPS_REGNUM = 24, /* floating point status register */
ARM_PS_REGNUM = 25, /* Contains processor status */
ARM_FP_REGNUM = 11, /* Frame register in ARM code, if used. */
THUMB_FP_REGNUM = 7, /* Frame register in Thumb code, if used. */
ARM_NUM_ARG_REGS = 4,
ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
ARM_NUM_FP_ARG_REGS = 4,
ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
};
int w_trcStack(REG_SET *pRegSet, int tid );
void getName(UINT addr)
{
extern SYMTAB_ID sysSymTbl;
UINT symVal;
SYM_TYPE symType;
char name[256]={0};
if (symFindByValue(sysSymTbl,
(UINT) addr,
name, &symVal, &symType) == ERROR)
sprintf(name, "0x%x", addr);
else if (symVal < addr)
sprintf(name + strlen(name),
" + 0x%x", addr - symVal);
else if (symVal > addr)
sprintf(name + strlen(name),
" - 0x%x", symVal - addr);
printf("%s\n",name);
}
void sysbt_addr2sym(char *symName, UINT addr)
{
extern SYMTAB_ID sysSymTbl;
UINT symVal;
SYM_TYPE symType;
if (symFindByValue(sysSymTbl,
(UINT) addr,
symName, &symVal, &symType) == ERROR)
sprintf(symName, "0x%x", addr);
else if (symVal < addr)
sprintf(symName + strlen(symName),
" + 0x%x", addr - symVal);
else if (symVal > addr)
sprintf(symName + strlen(symName),
" - 0x%x", symVal - addr);
}
UINT getPrologue(UINT addr);
int gg(int taskNameOrId /* task name or task ID */)
{
REG_SET regSet;
BOOL resumeIt = FALSE; /* flag to remember if resuming is necessary */
int tid = taskIdFigure(taskNameOrId); /* convert to task id */
if (tid == ERROR)
{
printErr(DBG_TASK_NOT_FOUND);
return (ERROR);
}
tid = taskIdDefault (tid); /* set default task id */
/* get caller task's id and make sure it is not the task to be traced */
if (tid == taskIdSelf () || tid == 0)
{
printErr ("Sorry, traces of my own stack begin at tt ().\n");
return (ERROR);
}
/* make sure the task exists */
if (taskIdVerify (tid) != OK)
{
printErr ("Can't trace task %#x: invalid task id.\n", tid);
return (ERROR);
}
/* if the task is not already suspended, suspend it while we trace it */
if (!taskIsSuspended (tid))
{
resumeIt = TRUE; /* we want to resume it later */
taskSuspend (tid); /* suspend the task if need be */
}
/* trace the stack */
taskRegsGet(tid, ®Set);
//ixtrcStack(®Set, (FUNCPTR) dbgPrintCall, tid);
w_trcStack(®Set, tid);
if (resumeIt)
taskResume(tid); /* resume task if we suspended it */
return (OK);
}
int w_trcStack(REG_SET *pRegSet, int tid)
{
UINT pc = (UINT)(pRegSet->pc);
UINT sp = (UINT) (pRegSet->spReg);
UINT prologue_start,prologue_end;
UINT current_pc;
int regno, sp_offset, fp_offset, ip_offset;
int lr_offset=0;
UINT framesize;
UINT back_sp,lr_addr;
unsigned int insn;
char symName[256]={0};
while (1)
{
if ( pc < 0x100 ||pc >= (UINT) sysPhysMemTop())
{
printf("PC 0x%x out of range\n", pc);
return -1;
}
if((prologue_start = getPrologue(pc)) == 0)
{
printf("no information in sym table\n");
return -1;
}
prologue_end = prologue_start + 164>pc?pc:prologue_start + 164;
sysbt_addr2sym(symName, pc);
printf("FUNC = 0x%x, PC = 0x%x (%s), SP = 0x%x\n",
(UINT) prologue_start, (UINT) pc, symName, sp);
if(prologue_start ==(UINT)( (char *)vxTaskEntry))break;
sp_offset = fp_offset = ip_offset = 0;
for (current_pc = prologue_start;
current_pc < prologue_end;
current_pc += 4)
{
insn = *((UINT *)(current_pc));
if (insn == 0xe1a0c00d) /* mov ip, sp */
{
ip_offset = 0;
continue;
}
else if ((insn & 0xfffff000) == 0xe28dc000) /* add ip, sp #n */
{
unsigned imm = insn & 0xff; /* immediate value */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
ip_offset = imm;
continue;
}
else if ((insn & 0xfffff000) == 0xe24dc000) /* sub ip, sp #n */
{
unsigned imm = insn & 0xff; /* immediate value */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
ip_offset = -imm;
continue;
}
else if (insn == 0xe52de004) /* str lr, [sp, #-4]! */
{
sp_offset -= 4;
lr_offset = sp_offset;
continue;
}
else if ((insn & 0xffff0000) == 0xe92d0000)
/* stmfd sp!, {..., fp, ip, lr, pc}
or
stmfd sp!, {a1, a2, a3, a4} */
{
int mask = insn & 0xffff;
/* Calculate offsets of saved registers. */
for (regno = ARM_PC_REGNUM; regno >= 0; regno--)
if (mask & (1 << regno))
{
sp_offset -= 4;
if(regno == ARM_LR_REGNUM)
lr_offset = sp_offset;
}
}
else if ((insn & 0xffffc000) == 0xe54b0000 || /* strb rx,[r11,#-n] */
(insn & 0xffffc0f0) == 0xe14b00b0 || /* strh rx,[r11,#-n] */
(insn & 0xffffc000) == 0xe50b0000) /* str rx,[r11,#-n] */
{
/* No need to add this to saved_regs -- it's just an arg reg. */
continue;
}
else if ((insn & 0xffffc000) == 0xe5cd0000 || /* strb rx,[sp,#n] */
(insn & 0xffffc0f0) == 0xe1cd00b0 || /* strh rx,[sp,#n] */
(insn & 0xffffc000) == 0xe58d0000) /* str rx,[sp,#n] */
{
/* No need to add this to saved_regs -- it's just an arg reg. */
continue;
}
else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
{
unsigned imm = insn & 0xff; /* immediate value */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
fp_offset = -imm + ip_offset;
}
else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
{
unsigned imm = insn & 0xff; /* immediate value */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
sp_offset -= imm;
}
else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
{
sp_offset -= 12;
//printf("meet stfe f?, [sp, -#c]! ,sp_offset decrsed with 12\n");
regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
//cache->saved_regs[regno].addr = sp_offset;
if(regno == ARM_LR_REGNUM)
lr_offset = sp_offset;
}
else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
{
int n_saved_fp_regs;
unsigned int fp_start_reg, fp_bound_reg;
if ((insn & 0x800) == 0x800) /* N0 is set */
{
if ((insn & 0x40000) == 0x40000) /* N1 is set */
n_saved_fp_regs = 3;
else
n_saved_fp_regs = 1;
}
else
{
if ((insn & 0x40000) == 0x40000) /* N1 is set */
n_saved_fp_regs = 2;
else
n_saved_fp_regs = 4;
}
fp_start_reg = ARM_F0_REGNUM + ((insn >> 12) & 0x7);
fp_bound_reg = fp_start_reg + n_saved_fp_regs;
for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
{
sp_offset -= 12;
if(fp_start_reg == ARM_LR_REGNUM)lr_offset = sp_offset;
fp_start_reg++;
}
}
else if ((insn & 0xf0000000) != 0xe0000000)
break; /* Condition not true, exit early */
else if ((insn & 0xfe200000) == 0xe8200000) /* ldm? */
break; /* Don't scan past a block load */
else
/* The optimizer might shove anything into the prologue,
so we just skip what we don't recognize. */
continue;
}
framesize = -sp_offset;
back_sp = sp+framesize;
lr_addr = lr_offset + back_sp;
sp=back_sp;
pc=*((UINT *)lr_addr);
}
return 0;
}
UINT getPrologue(UINT addr)
{
extern SYMTAB_ID sysSymTbl;
UINT symVal;
SYM_TYPE symType;
char name[256] = { 0 };
if (symFindByValue(sysSymTbl,
(UINT) addr,
name, &symVal, &symType) == ERROR) /* if no sym information */
{
sprintf(name, "0x%x", addr);
printf("cannot alloc prologue\n");
return 0;
}
return symVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -