📄 strace_sh2.c
字号:
/* strace.c: * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#if INCLUDE_STRACE#include "tfs.h"#include "tfsprivate.h"#include "ctype.h"#include "genlib.h"#include "stddefs.h"#define ADDI_INSTR 0x7f /* add #imm,r15 */#define RTS_INSTR 0x000b /* rts */#define STS_PR_R15 0x4f22 /* sts.l pr,@-r15 */extern int getreg();extern int AddrToSym(int,ulong,char *,ulong *);extern ulong ExceptionAddr;char *StraceHelp[] = { "Stack trace", "-[d:F:P:rs:]", " -d # max depth count (def=20)", " -F # specify frame-pointer (don't use content of R1)", " -P # specify PC (don't use content of SRR#)", " -r dump regs", 0,};intStrace(int argc,char *argv[]){ uchar *ftext, dlta; char *symfile, fname[64]; ulong *framepointer, pc, fp, offset; int fdelta, leaf, tfd, opt, maxdepth, debug; tfd = fp = debug = 0; maxdepth = 20; pc = ExceptionAddr; while ((opt=getopt(argc,argv,"Dd:F:P:r")) != -1) { switch(opt) { case 'D': debug = 1; break; case 'd': maxdepth = atoi(optarg); break; case 'F': fp = strtoul(optarg,0,0); break; case 'P': pc = strtoul(optarg,0,0); break; case 'r': showregs(); break; default: return(0); } } /* Start by detecting the presence of a symbol table file... */ symfile = getenv("SYMFILE"); if (!symfile) symfile = SYMFILE; tfd = tfsopen(symfile,TFS_RDONLY,0); if (tfd < 0) { printf("Stack trace needs %s file\n",symfile); return(0); } /* Load initial frame pointer: */ if (!fp) getreg("R14", &framepointer); else framepointer = (ulong *)fp; /* Show current position: */ AddrToSym(tfd,pc,fname,&offset); printf(" 0x%08lx: %s()",pc,fname); if (offset) printf(" + 0x%lx",offset); putchar('\n'); /* Now the tricky stuff... * If there are no arguments passed to the functions in the stack's * function nesting, then all we need to do is jump from one frame * pointer to the next. Unfortunately, this is not usually the case, * so we need to figure out how many arguments each function has as we * are processing the stack trace. Also, for the first function of the * nesting, we must determine if it is a leaf function because the frame * will be a bit different in that case. In either case, we need to * be able to take an address in text space, determine what function it * is, and then determine where the starting address for that function is. * This is done with the AddrToSym() function. It takes in an address, * returns the name of the function as well as the gap between the * incoming address and the actual starting point of the function's text. * Point being: without the symbol table, this is likely not to work. * * Determining if function is a leaf: * This is done by searching through the text of the function and * looking for the "STS.L PR,@-R15" instruction. If this instruction * is found prior to the RTS, then we assume the function is NOT a leaf * because the Procedture Register is being pushed onto the stack * (meaning that the compiler added the code to prepare for the fact * that another function may be called from within the current function). * * Determining number of arguments: * Since the arguments passed into a function are placed on the stack * frame, and the code for a function must be aware of this, we can once * again, look to the code for hints. In this case we look for the * first occurrence of the instruction "ADD #IMM,R15". This is code * that adjusts the stack pointer based on the number of arguments passed * into the function that are on the stack frame. The value of #IMM is * what we use to determine the number of arguments. For example, if * the instruction is ADD #0xFC,R15 then we know that one argument is * using stack space. Similarly "ADD #0xF8,R15" is 2, "ADD #0xF4,R15" * is 3 and so on. */ ftext = (uchar *)pc; ftext -= offset; leaf = 1; fdelta = 0; while((*ftext != ADDI_INSTR) && (*(ushort*)ftext != RTS_INSTR)) { if (*(ushort *)ftext == STS_PR_R15) leaf = 0; ftext+=2; } if (*(ushort*)ftext != RTS_INSTR) { dlta = (int)*(ftext+1); while(dlta) { fdelta++; dlta += 4; } } if (debug) { printf(" FRAME_PTR=0x%08lx, DLTA=%d, LEAF=%d\n", (ulong)framepointer, fdelta, leaf); } framepointer += (fdelta+leaf); /* Now step through the stack frame... */ while(maxdepth) { if (((int)framepointer & 3) || (!framepointer) || (!*framepointer)) break; if (debug) printf(" FUNC_ADDR=0x%08lx\n",*framepointer); if (!AddrToSym(tfd,*framepointer,fname,&offset)) break; printf(" 0x%08lx: %s()",*framepointer,fname); if (offset) printf(" + 0x%lx",offset); putchar('\n'); /* See notes above regarding the computation of fdelta... */ fdelta = 0; ftext = (uchar *)*framepointer; ftext -= offset; while((*ftext != ADDI_INSTR) && (*(ushort*)ftext != RTS_INSTR)) ftext+=2; if (*(ushort*)ftext != RTS_INSTR) { dlta = (int)*(ftext+1); while(dlta) { fdelta++; dlta += 4; } } if (debug) { printf(" FRAME_PTR=0x%08lx, DLTA=%d\n", (ulong)framepointer, fdelta); } framepointer = (ulong *)*(framepointer+1); framepointer += fdelta; maxdepth--; } if (!maxdepth) printf("Max depth termination\n"); if (tfd >= 0) tfsclose(tfd,0); return(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -