📄 nextaddr.c
字号:
/*- * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)nextaddr.c 8.1 (Berkeley) 6/6/93";#endif /* not lint *//* * Calculate the next address that will be executed from the current one. * * If the next address depends on runtime data (e.g. a conditional * branch will depend on the value on top of the stack), * we must execute up to the given address with "stepto". * * If the second argument is TRUE, we treat a CALL instruction as * straight line rather than following it as a branch. */#include "defs.h"#include "machine.h"#include "process.h"#include "breakpoint.h"#include "sym.h"#include "pxops.h"#include "optab.h"#include "mappings.h"#include "runtime.h"#include "process/pxinfo.h"#include "process/process.rep"#ifdef tahoe#define EVEN 3#else#define EVEN 1#endifLOCAL ADDRESS docase(), dofor();ADDRESS nextaddr(beginaddr, isnext)ADDRESS beginaddr;BOOLEAN isnext;{ register PXOP op; ADDRESS addr; short offset; int nextbyte; SYM *s; union { short word; char byte[2]; } o;#ifdef tahoe doret(process);#endif addr = beginaddr; iread(&o.word, addr, sizeof(o.word)); op = (PXOP) o.byte[0]; nextbyte = o.byte[1]; addr += sizeof(short); switch(op) { /* * The version of px we are using assumes that the instruction * at the entry point of a function is a TRA4 to the beginning * of the block. */ case O_CALL: { ADDRESS eaddr; if (isnext) { addr += sizeof(int);#ifdef tahoe addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);#endif } else {#ifdef tahoe addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);#endif iread(&eaddr, addr, sizeof(eaddr)); addr = eaddr + sizeof(short);#ifdef tahoe addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);#endif iread(&addr, addr, sizeof(addr)); stepto(addr); if (linelookup(addr) == 0) { bpact(); addr = pc; } if (ss_lines && trcond()) { s = whatblock(addr); if (s == NIL) { panic("bad call addr"); } printentry(s); } } break; } case O_FCALL: { ADDRESS eaddr; ADDRESS *fparam; if (!isnext) { stepto(addr - sizeof(short));#ifdef tahoe doret(process);#endif dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam)); dread(&eaddr, fparam, sizeof(eaddr)); addr = eaddr - ENDOFF; stepto(addr);#ifdef tahoe doret(process);#endif if (linelookup(addr) == 0) { bpact(); addr = pc; } if (ss_lines && trcond()) { s = whatblock(addr); if (s == NIL) { panic("bad call addr"); } printentry(s); } } break; } case O_END: if ((addr - sizeof(short)) == lastaddr()) { stepto(addr - sizeof(short)); endprogram(); } else { addr = return_addr(); s = whatblock(pc); stepto(addr); if (ss_lines && trcond()) { printexit(s); } if (linelookup(addr) == 0) { bpact(); addr = pc; } } break; case O_TRA4: case O_GOTO:#ifdef tahoe addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);#endif iread(&addr, addr, sizeof(addr)); break; case O_TRA: iread(&offset, addr, sizeof(offset)); addr += offset; break; case O_CON: { short consize; if (nextbyte == 0) {#ifdef tahoe addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);#endif iread(&consize, addr, sizeof(consize)); addr += sizeof(consize); } else { consize = nextbyte; } addr += consize; break; } case O_CASE1OP: addr = docase(nextbyte, 1, addr); break; case O_CASE2OP: addr = docase(nextbyte, 2, addr); break; case O_CASE4OP: addr = docase(nextbyte, 4, addr); break; case O_FOR1U: addr = dofor(2, addr, nextbyte, 1); break; case O_FOR2U: addr = dofor(2, addr, nextbyte, 1); break; case O_FOR4U: addr = dofor(4, addr, nextbyte, 1); break; case O_FOR1D: addr = dofor(2, addr, nextbyte, -1); break; case O_FOR2D: addr = dofor(2, addr, nextbyte, -1); break; case O_FOR4D: addr = dofor(4, addr, nextbyte, -1); break; case O_IF: stepto(addr - sizeof(short));#ifdef tahoe doret(process); dread(&offset, process->sp+sizeof(int)-sizeof(offset), sizeof(offset));#else dread(&offset, process->sp, sizeof(offset));#endif if (offset == 0) { iread(&offset, addr, sizeof(offset)); addr += offset; } else { addr += sizeof(offset); } break; default: { int i; for (i = 0; optab[op].argtype[i] != 0; i++) { switch(optab[op].argtype[i]) { case ADDR4: case LWORD: addr += 4;#ifdef tahoe addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);#endif break; case SUBOP: break; case ADDR2: case HWORD: case PSUBOP: case DISP: case VLEN: if (i != 0 || nextbyte == 0) { addr += sizeof(short); } break; case STRING: { char c; while (nextbyte > 0) { iread(&c, addr, 1); if (c == '\0') { break; } nextbyte--; addr++; } addr++; addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); break; } default: panic("bad argtype"); /*NOTREACHED*/ } } break; } } return addr;}/* * Find the next address that will be executed after the * case statement at the given address. */LOCAL ADDRESS docase(ncases, size, addr)int ncases;int size;ADDRESS addr;{ register ADDRESS i; ADDRESS firstval, lastval, jmptable; short offset; long swtval, caseval; stepto(addr - 2);#ifdef tahoe doret(process);#endif if (ncases == 0) { iread(&ncases, addr, sizeof(ncases)); addr += sizeof(short); } jmptable = addr; firstval = jmptable + ncases*sizeof(short);#ifdef tahoe if (size == 4) { firstval = (ADDRESS)(((int)firstval + EVEN) & ~EVEN); }#endif lastval = firstval + ncases*size;#ifdef tahoe if (size <= 4) { dread(&swtval, process->sp, 4);#else if (size <= 2) { dread(&swtval, process->sp, 2);#endif } else { dread(&swtval, process->sp, size); } for (i = firstval; i < lastval; i += size) { caseval = 0;#ifdef tahoe iread((char *)&caseval + sizeof caseval - size, i, size); if (swtval == caseval)#else iread(&caseval, i, size); if (cmp(&swtval, &caseval, size) == 0)#endif { i = ((i - firstval) / size) * sizeof(offset); iread(&offset, jmptable + i, sizeof(offset)); addr = jmptable + offset; return addr; } } return((lastval+1)&~1);}LOCAL ADDRESS dofor(size, addr, subop, incr)int size;ADDRESS addr;short subop;int incr;{ register PROCESS *p; long i, limit; ADDRESS valaddr; stepto(addr - sizeof(short)); p = process;#ifdef tahoe doret(p);#endif i = limit = 0; if (subop == 0) { dread(&subop, addr, sizeof (short)); addr += sizeof (short); } dread(&valaddr, p->sp, sizeof(valaddr));#ifdef tahoe dread((char *)&i + sizeof i - size, valaddr, size);#else dread(&i, valaddr, size);#endif dread(&limit, p->sp + sizeof(valaddr), sizeof limit); i += incr;/* * It is very slow to go through the loop again and again. * If it is desired to just skip to the end, the next 4 lines * should be skipped. */ if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { return(addr + subop); } else { return(addr); }}/* * Determine whether or not the given address corresponds to the * end of a procedure. */BOOLEAN isendofproc(addr)ADDRESS addr;{ PXOP op; iread(&op, addr, sizeof(op)); return (op == O_END);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -