?? trclib.c
字號:
(* _func_printErr) ("%x", args[ix]); } if (doingDefault) (* _func_printErr) ("]"); (* _func_printErr) (")\n"); }/****************************************************************************** trcFindCall - get address from which function was called** RETURNS: address from which current subroutine was called, or NULL.*/LOCAL INSTR *trcFindCall ( INSTR *returnAdrs /* return address */ ) { FAST INSTR *addr; /* starting at the word preceding the return adrs, search for jsr or bsr */ for (addr = returnAdrs - 1; addr != NULL; --addr) if (((*addr & 0xffc0) == 0x4e80) || ((*addr & 0xff00) == 0x6100)) return (addr); /* found it */ return (NULL); /* not found */ }/****************************************************************************** trcFindDest - find destination of call instruction** RETURNS: address to which call instruction (jsr) will branch, or NULL if* unknown*/LOCAL INSTR *trcFindDest ( INSTR *callAdrs ) { if (*callAdrs == JSR_ABS) /* jsr absolute long mode? */ return ((INSTR *) *(int *)(callAdrs + 1)); /* return next long */ return (NULL); /* don't know destination */ }/****************************************************************************** trcCountArgs - find number of arguments to function** This routine finds the number of arguments passed to the called function* by examining the stack-pop at the return address. Many compilers offer* optimization that defeats this (e.g., by coalescing stack-pops), so a return* value of 0 may mean "don't know".** RETURNS: number of arguments of function*/LOCAL int trcCountArgs ( FAST INSTR *returnAdrs /* return address of function call */ ) { FAST INSTR inst; FAST int nargs; FAST int tmpNargs; nargs = 0; /* if inst is a BRA, use the target of the BRA as the returnAdrs */ returnAdrs = trcFollowBra (returnAdrs); inst = *returnAdrs; /* get the instruction */ if (inst == ADD_W) nargs = *(returnAdrs + 1) >> 2; /* ADD.W */ else if (inst == ADD_L) nargs = *(int *)(returnAdrs + 1) >> 2; /* ADD.L */ else if (((inst & 0xF1FF) == ADDQ_W) || ((inst & 0xF1FF) == ADDQ_L)) { /* there may be multiple addq's at the return addrs */ do { /* get the number of bytes and div by 4 to get the number of args */ tmpNargs = (inst & 0x0E00) >> 11; /* ADDQ.L or ADDQ.W */ if (tmpNargs == 0) tmpNargs = 2; /* 0 => 8 in quick mode */ nargs += tmpNargs; returnAdrs++; /* sizeof ADDQ */ inst = *returnAdrs; /* check next instruction */ } while (((inst & 0xF1FF) == ADDQ_W) || ((inst & 0xF1FF) == ADDQ_L)); } else if (inst == LEA_A7) nargs = *(returnAdrs + 1) >> 2; /* LEA $x(A7),A7 */ else if ((inst & 0xFFC0) == MOVE_L_A7) nargs = 1; /* MOVE.L xxx,(A7) */ else if (inst == MOVE_L_A6_A7) nargs = 8; /* MOVE.L (xxx,A6),A7 # of args unknowable */ else nargs = 0; /* no args, or unknown */ return (nargs); }/****************************************************************************** trcFindFuncStart - find the starting address of a function** This routine finds the starting address of a function by one of several ways.** If the given frame pointer points to a legitimate frame pointer, then the* long word following the frame pointer pointed to by the frame pointer should* be the return address of the function call. Then the instruction preceding* the return address would be the function call, and the address can be gotten* from there, provided that the jsr was to an absolute address. If it was,* use that address as the function address. Note that a routine that is* called by other than a jsr-absolute (e.g., indirectly) will not meet these* requirements.** If the above check fails, we search backward from the given pc until a* LINK instruction is found. If the compiler is putting LINK instructions* as the first instruction of ALL subroutines, then this will reliably find* the start of the routine. However, some compilers allow routines, especially* "leaf" routines that don't call any other routines, to NOT have stack frames,* which will cause this search to fail.** In either of the above cases, the value is bounded by the nearest routine* in the system symbol table, if there is one. If neither method returns a* legitimate value, then the value from the symbol table is used. Note that* the routine may not be in the symbol table if it is LOCAL, etc.** Note that the start of a routine that is not called by jsr-absolute and* doesn't start with a LINK and isn't in the symbol table, may not be possible* to locate.*/LOCAL INSTR *trcFindFuncStart ( int *fp, /* frame pointer resulting from function call */ FAST INSTR *pc /* address somewhere within the function */ ) { FAST INSTR *ip; /* instruction pointer */ FAST INSTR *minPc; /* lower bound on program counter */ int val; /* address gotten from symbol table */ char name[MAX_SYS_SYM_LEN+1]; /* string associated with val */ SYM_TYPE type; /* type associated with val */ /* * if there is a symbol table, use value from table that's <= pc as * lower bound for function start */ minPc = NULL; if ((sysSymTbl != NULL) && (_func_symFindByValue != NULL) && ((* _func_symFindByValue) (sysSymTbl, (int) pc, name, &val, &type) == OK)) { minPc = (INSTR *) val; } /* try to find current function by looking up call */ if (fp != NULL) /* frame pointer legit? */ { ip = trcFindCall ((INSTR *) *(fp + 1)); if (ip != NULL) { ip = trcFindDest (ip); if ((ip != NULL) && (ip >= minPc) && (ip <= pc)) return (ip); } } /* search backward for LINK A6,#xxxx */ for (; pc >= minPc; --pc) { if (*trcFollowBra (pc) == LINK_A6) return (pc); /* return address of LINK_A6 */ } return (minPc); /* return nearest symbol in sym tbl */ }/*********************************************************************** trcFollowBra - resolve any BRA instructions to final destination** This routine returns a pointer to the next non-BRA instruction to be* executed if the pc were at the specified <adrs>. That is, if the instruction* at <adrs> is not a BRA, then <adrs> is returned. Otherwise, if the* instruction at <adrs> is a BRA, then the destination of the BRA is* computed, which then becomes the new <adrs> which is tested as before.* Thus we will eventually return the address of the first non-BRA instruction* to be executed.** The need for this arises because compilers may put BRAs to instructions* that we are interested in, instead of the instruction itself. For example,* optimizers may replace a stack pop with a BRA to a stack pop. Or in very* UNoptimized code, the first instruction of a subroutine may be a BRA to* a LINK, instead of a LINK (compiler may omit routine "post-amble" at end* of parsing the routine!). We call this routine anytime we are looking* for a specific kind of instruction, to help handle such cases.** RETURNS: address that chain of branches points to.*/LOCAL INSTR *trcFollowBra ( FAST INSTR *adrs ) { FAST INSTR inst = *adrs; /* 16 bit instruction at adrs */ FAST int displacement; /* while instruction is a BRA, get destination adrs */ while ((inst & 0xff00) == 0x6000) { ++adrs; /* point to word following instr */ switch (inst & 0xff) { case 0: /* 16 bit displacement */ displacement = (short) *adrs; break; case 0xff: /* 32 bit displacement */ displacement = (*adrs << 16) | *(adrs + 1); break; default: /* 8 bit displacement */ displacement = (char) (inst & 0xff); /* check for branch to self, or to odd displacement */ if ((displacement == 0xfe) || (displacement & 0x01)) return (--adrs); /* don't follow it */ break; } adrs = (INSTR *) ((char *) adrs + displacement); inst = *adrs; /* get the instruction */ } return (adrs); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -