⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 traceframestack4arm.c

📁 ARM下类似tornado tt的实现
💻 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, &regSet);
    //ixtrcStack(&regSet, (FUNCPTR) dbgPrintCall, tid);
    w_trcStack(&regSet, 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 + -