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

📄 mips-tdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.   Copyright 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.   Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "defs.h"#include "target.h"#include "frame.h"#include "inferior.h"#include "symtab.h"#include "value.h"#include "gdbcmd.h"#include "language.h"#ifdef USG#include <sys/types.h>#endif#include <sys/param.h>#include <sys/dir.h>#include <signal.h>#include <sys/ioctl.h>#include "gdbcore.h"#include "symfile.h"#include "objfiles.h"#ifndef	MIPSMAGIC#ifdef MIPSEL#define MIPSMAGIC	MIPSELMAGIC#else#define MIPSMAGIC	MIPSEBMAGIC#endif#endif#define VM_MIN_ADDRESS (unsigned)0x400000#include <sys/user.h>		/* After a.out.h  */#include <sys/file.h>#include <sys/stat.h>#ifdef KERNELDEBUGextern int kernel_debugging;#endif/* * The MIPS architecture does not provide a trace bit.  However, most * (if not all) OS's that run on the MIPS emulate single stepping in * the kernel.  This unfortunately does not work for the kernel debugger. * Thus, we duplicate the functionality here. *//* * For the instruction INSN at PC, if it is a control transfer, return the * target address, otherwise return 0. * * Instruction decoding per "MIPS RISC Architecture" by Gerry Kane * and Joe Heinrich, Prentice Hall, 1992.  Fig. A-3, Page A-143. */CORE_ADDRbranchtarget(insn, pc)	u_long insn;	CORE_ADDR pc;{	int opcode = (insn >> 26) & 0x3f;	u_long v;	switch (opcode) {	case 0x00:		/* SPECIAL */		v = insn & 0x3f;		if (v == 8 || v == 9) {			int rs = (insn >> 21) & 0x1f;			return (read_register(rs));		}		return (0);	case 0x01:		/* REGIMM */		v = (insn >> 16) & 0x1f;		switch (v) {		default:			return (0);		case 0x00:	/* BLTZ */		case 0x01:	/* BGEZ */		case 0x02:	/* BLTZL */		case 0x03:	/* BGEZL */		case 0x10:	/* BLTZAL */		case 0x11:	/* BGEZAL */		case 0x12:	/* BLTZALL */		case 0x13:	/* BGEZALL */			break;		}		/* fall through */	case 0x04:		/* BEQ */	case 0x05:		/* BNE */	case 0x06:		/* BLEZ */	case 0x07:		/* GTRZ */		v = insn & 0xffff;		if (v & 0x8000)			v |= 0xffff0000;		v <<= 2;		return (pc + 4 + v);	case 0x02:		/* J */	case 0x03:		/* JAL */		v = (insn & 0x03ffffff) << 2;		return (((pc + 4) & 0xf0000000) | v);	case 0x10:		/* COP0 */	case 0x11:		/* COP1 */	case 0x12:		/* COP2 */	case 0x13:		/* COP3 */		v = (insn >> 21) & 0x1f;		if (v == 8) {			v = insn & 0xffff;			if (v & 0x8000)				v |= 0xffff0000;			v <<= 2;			return (pc + 4 + v);		}	}	return (0);}intis_call_insn(insn)	u_long insn;{	int opcode = (insn >> 26) & 0x3f;	if (opcode == 3)		/* JAL */		return (1);	if (opcode == 0) {		/* SPECIAL */		int v = insn & 0x3f;		/* JALR */		return (v == 9);	}	if (opcode == 1) {		/* REGIMM */		int v = (insn >> 19) & 3;		/* BLTZAL etc. */		return (v == 2);	}	return (0);}/* * Non-zero if we just simulated a single-step ptrace call.  This is * needed because we cannot remove the breakpoints in the inferior * process until after the `wait' in `wait_for_inferior'.  * Used for sun4. */int one_stepped;/* * single_step() is called just before we want to resume the inferior, * if we want to single-step it but there is no hardware or kernel single-step * support (as on all SPARCs).  We find all the possible targets of the * coming instruction and breakpoint them. * * single_step is also called just after the inferior stops.  If we had * set up a simulated single-step, we undo our damage. * * Code written by Gary Beihl (beihl@mcc.com); modified by Steven McCanne * (mccanne@ee.lbl.gov). */voidsingle_step(signal)	int signal;{	CORE_ADDR pc;	u_long insn;	/*	 * Storage for temporary breakpoints.  XXX There should be a uniform	 * interface for breakpoints, so that we could just set one then 	 * clear it.  Note that we need only two outstanding breakpoints,	 * since there can be at most two possiblilities for control flow.	 */	static CORE_ADDR target0;	static CORE_ADDR target1;	static char shadow0[4];	static char shadow1[4];	pc = read_register(PC_REGNUM);	insn = read_memory_integer(pc, 4);	if (!one_stepped) {		/*		 * This is a hack to special case call instructions.		 * If we are stepping over subroutines, find each call		 * and trap on return, rather than single step until		 * wait_for_inferior() discovers that we hit a new routine.		 * The reason is that stepping over functions in a remote 		 * kernel can have bad results when the function being 		 * stepped over is used by the kernel in between traps.		 * (i.e., a trap instruction gets poked into the function		 * being stepped over).		 */		if (step_over_calls > 0 && is_call_insn(insn)) {			target0 = pc + 8;			target1 = 0;		} else {			target0 = pc + 4;			target1 = branchtarget(insn, pc);			if (target1 != 0) {				/*				 * Punt on stepping through delay slot.				 * On the sparc, this is easy because of				 * npc; on the mips, it's trickier				 * because we'd have to keep track				 * of when we're in the delay slot (and				 * gdb will get confused because the				 * cpu leaves the epc pointing to the				 * previous instruction).  Moreover, the				 * architecture would require that we				 * interpret the branch intruction if				 * we want to set a breakpoint in the				 * delay slot.				 */				target0 += 4;			}			if (target1 == target0)				target1 = 0;		}		target_insert_breakpoint(target0, shadow0);		if (target1)			target_insert_breakpoint(target1, shadow1);		one_stepped = 1;	} else {		/* Remove breakpoints */		if (target1)			target_remove_breakpoint(target1, shadow1);		target_remove_breakpoint(target0, shadow0);		one_stepped = 0;	}}#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */#define PROC_HIGH_ADDR(proc) ((proc)->pdr.iline) /* upper address bound */#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)#define _PROC_MAGIC_ 0x0F0F0F0F#define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym = _PROC_MAGIC_)struct linked_proc_info{  struct mips_extra_func_info info;  struct linked_proc_info *next;} *linked_proc_desc_table = NULL;#define READ_FRAME_REG(fi, regno) read_next_frame_reg((fi)->next, regno)static intread_next_frame_reg(fi, regno)     FRAME fi;     int regno;{#define SIGFRAME_BASE   sizeof(struct sigcontext)#define SIGFRAME_PC_OFF (-SIGFRAME_BASE+ 2*sizeof(int))#define SIGFRAME_SP_OFF (-SIGFRAME_BASE+32*sizeof(int))#define SIGFRAME_RA_OFF (-SIGFRAME_BASE+34*sizeof(int))  for (; fi; fi = fi->next) {#ifdef KERNELDEBUG      if (kernel_debugging && in_trap_handler(fi->pc)) {	  int offset;	  if (regno == PC_REGNUM) offset = 40;	  else if (regno == RA_REGNUM) offset = 34;	  else if (regno == SP_REGNUM) offset = 32;	  else return 0;	  return read_memory_integer(fi->frame + 4 * offset, 4);      }#endif      if (in_sigtramp(fi->pc, 0)) {	  /* No idea if this code works. --PB. */	  int offset;	  if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF;	  else if (regno == RA_REGNUM) offset = SIGFRAME_RA_OFF;	  else if (regno == SP_REGNUM) offset = SIGFRAME_SP_OFF;	  else return 0;	  return read_memory_integer(fi->frame + offset, 4);      }      else if (regno == SP_REGNUM) return fi->frame;      else if (fi->saved_regs->regs[regno])	return read_memory_integer(fi->saved_regs->regs[regno], 4);  }  return read_register(regno);}intmips_frame_saved_pc(frame)     FRAME frame;{  mips_extra_func_info_t proc_desc = frame->proc_desc;  int pcreg = proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM;#ifdef KERNELDEBUG  if (kernel_debugging && in_trap_handler(frame->pc))	  return read_memory_integer(frame->frame + 4 * 40, 4);#endif  if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))      return read_memory_integer(frame->frame - 4, 4);  return read_next_frame_reg(frame, pcreg);}static struct mips_extra_func_info temp_proc_desc;static struct frame_saved_regs temp_saved_regs;static CORE_ADDRheuristic_proc_start(pc)    CORE_ADDR pc;{    CORE_ADDR start_pc = pc;    CORE_ADDR fence = start_pc - 200;    if (start_pc == 0)	return 0;    if (fence < VM_MIN_ADDRESS) fence = VM_MIN_ADDRESS;    /* search back for previous return */    for (start_pc -= 4; ; start_pc -= 4)	if (start_pc < fence) return 0; 	else if (ABOUT_TO_RETURN(start_pc))	    break;    start_pc += 8; /* skip return, and its delay slot */#if 0    /* skip nops (usually 1) 0 - is this */    while (start_pc < pc && read_memory_integer (start_pc, 4) == 0)	start_pc += 4;#endif    return start_pc;}static mips_extra_func_info_theuristic_proc_desc(start_pc, limit_pc, next_frame)    CORE_ADDR start_pc, limit_pc;    FRAME next_frame;{    CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);    CORE_ADDR cur_pc;    int frame_size;    int has_frame_reg = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -