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

📄 mips-tdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
    int reg30; /* Value of $r30. Used by gcc for frame-pointer */    unsigned long reg_mask = 0;    if (start_pc == 0) return NULL;    bzero(&temp_proc_desc, sizeof(temp_proc_desc));    bzero(&temp_saved_regs, sizeof(struct frame_saved_regs));    PROC_LOW_ADDR(&temp_proc_desc) = start_pc;    if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200;  restart:    frame_size = 0;    for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {	unsigned long word;	int status;	status = read_memory_nobpt (cur_pc, (char *)&word, 4); 	if (status) memory_error (status, cur_pc); 	SWAP_TARGET_AND_HOST (&word, sizeof (word));	if ((word & 0xFFFF0000) == 0x27bd0000) /* addiu $sp,$sp,-i */	    frame_size += (-word) & 0xFFFF;	else if ((word & 0xFFFF0000) == 0x23bd0000) /* addu $sp,$sp,-i */	    frame_size += (-word) & 0xFFFF;	else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp) */	    int reg = (word & 0x001F0000) >> 16;	    reg_mask |= 1 << reg;	    temp_saved_regs.regs[reg] = sp + (short)word;	}	else if ((word & 0xFFFF0000) == 0x27be0000) { /* addiu $30,$sp,size */	    if ((unsigned short)word != frame_size)		reg30 = sp + (unsigned short)word;	    else if (!has_frame_reg) {		int alloca_adjust;		has_frame_reg = 1;		reg30 = read_next_frame_reg(next_frame, 30);		alloca_adjust = reg30 - (sp + (unsigned short)word);		if (alloca_adjust > 0) {		    /* FP > SP + frame_size. This may be because		    /* of an alloca or somethings similar.		     * Fix sp to "pre-alloca" value, and try again.		     */		    sp += alloca_adjust;		    goto restart;		}	    }	}	else if ((word & 0xFFE00000) == 0xafc00000) { /* sw reg,offset($30) */	    int reg = (word & 0x001F0000) >> 16;	    reg_mask |= 1 << reg;	    temp_saved_regs.regs[reg] = reg30 + (short)word;	}    }    if (has_frame_reg) {	PROC_FRAME_REG(&temp_proc_desc) = 30;	PROC_FRAME_OFFSET(&temp_proc_desc) = 0;    }    else {	PROC_FRAME_REG(&temp_proc_desc) = SP_REGNUM;	PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;    }    PROC_REG_MASK(&temp_proc_desc) = reg_mask;    PROC_PC_REG(&temp_proc_desc) = RA_REGNUM;    return &temp_proc_desc;}static mips_extra_func_info_tfind_proc_desc(pc, next_frame)    CORE_ADDR pc;    FRAME next_frame;{  mips_extra_func_info_t proc_desc;  struct block *b = block_for_pc(pc);  struct symbol *sym =      b ? lookup_symbol(MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL) : NULL;  if (sym)    {	/* IF this is the topmost frame AND	 * (this proc does not have debugging information OR	 * the PC is in the procedure prologue)	 * THEN create a "heuristic" proc_desc (by analyzing	 * the actual code) to replace the "official" proc_desc.	 */	proc_desc = (mips_extra_func_info_t)SYMBOL_VALUE(sym);	if (next_frame == NULL) {	    struct symtab_and_line val;	    struct symbol *proc_symbol =		PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc);	    if (proc_symbol) {		val = find_pc_line (BLOCK_START				    (SYMBOL_BLOCK_VALUE(proc_symbol)),				    0);		val.pc = val.end ? val.end : pc;	    }	    if (!proc_symbol || pc < val.pc) {		mips_extra_func_info_t found_heuristic =		    heuristic_proc_desc(PROC_LOW_ADDR(proc_desc),					pc, next_frame);		if (found_heuristic) proc_desc = found_heuristic;	    }	}    }  else    {      /* Is linked_proc_desc_table really necessary?  It only seems to be used	 by procedure call dummys.  However, the procedures being called ought	 to have their own proc_descs, and even if they don't,	 heuristic_proc_desc knows how to create them! */      register struct linked_proc_info *link;      for (link = linked_proc_desc_table; link; link = link->next)	  if (PROC_LOW_ADDR(&link->info) <= pc	      && PROC_HIGH_ADDR(&link->info) > pc)	      return &link->info;      proc_desc =	  heuristic_proc_desc(heuristic_proc_start(pc), pc, next_frame);    }  return proc_desc;}/* XXX this is not a cache (i.e., you don't invalidate it) */mips_extra_func_info_t cached_proc_desc;FRAME_ADDRmips_frame_chain(frame)    FRAME frame;{    mips_extra_func_info_t proc_desc;    CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);#ifdef KERNELDEBUG    if (kernel_debugging) {	    if (!inside_kernstack(frame->frame))		    return (0);	    if (in_trap_handler(saved_pc)) {		    /* XXX this works? */		    cached_proc_desc = find_proc_desc(saved_pc, frame);		    /*XXX need to lookup frame of parent */		    return read_memory_integer(frame->frame + 4 * 32, 4);	    }    } else#endif	    if (saved_pc == 0 || inside_entry_file (saved_pc))		    return 0;    proc_desc = find_proc_desc(saved_pc, frame);    if (!proc_desc)      return 0;    cached_proc_desc = proc_desc;    return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))      + PROC_FRAME_OFFSET(proc_desc);}voidinit_extra_frame_info(fci)     struct frame_info *fci;{  extern struct obstack frame_cache_obstack;  /* Use proc_desc calculated in frame_chain */  mips_extra_func_info_t proc_desc = fci->next ? cached_proc_desc :      find_proc_desc(fci->pc, fci->next);  fci->saved_regs = (struct frame_saved_regs*)    obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));  bzero(fci->saved_regs, sizeof(struct frame_saved_regs));  fci->proc_desc =      proc_desc == &temp_proc_desc ? 0 : proc_desc;#ifdef KERNELDEBUG  if (kernel_debugging && in_trap_handler(fci->pc)) {	  int i;	  if (fci->next != 0)		  fci->frame = READ_FRAME_REG(fci, SP_REGNUM);	  else		  fci->frame = read_register(SP_REGNUM);	  for (i = 1; i <= 32; ++i)		  fci->saved_regs->regs[i] = fci->frame + 4 * (3 + i);	  return;  }#endif  if (proc_desc)    {      int ireg;      CORE_ADDR reg_position;      unsigned long mask;      /* r0 bit means kernel trap */      int kernel_trap = PROC_REG_MASK(proc_desc) & 1;      /* Fixup frame-pointer - only needed for top frame */      /* This may not be quite right, if proc has a real frame register */      if (fci->pc == PROC_LOW_ADDR(proc_desc))	fci->frame = read_register (SP_REGNUM);      else if (fci->next == 0)	fci->frame = read_register (SP_REGNUM) + PROC_FRAME_OFFSET(proc_desc);      else	fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))	              + PROC_FRAME_OFFSET(proc_desc);      if (proc_desc == &temp_proc_desc)	  *fci->saved_regs = temp_saved_regs;      else      {	  /* find which general-purpose registers were saved */	  reg_position = fci->frame + PROC_REG_OFFSET(proc_desc);	  mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);	  for (ireg= 31; mask; --ireg, mask <<= 1)	      if (mask & 0x80000000)	      {		  fci->saved_regs->regs[ireg] = reg_position;		  reg_position -= 4;	      }	  /* find which floating-point registers were saved */	  reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc);	  /* The freg_offset points to where the first *double* register is saved.	   * So skip to the high-order word. */	  reg_position += 4;	  mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);	  for (ireg = 31; mask; --ireg, mask <<= 1)	      if (mask & 0x80000000)	      {		  fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;		  reg_position -= 4;	      }      }      /* hack: if argument regs are saved, guess these contain args */      if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;      else if ((PROC_REG_MASK(proc_desc) & 0x80) == 0) fci->num_args = 4;      else if ((PROC_REG_MASK(proc_desc) & 0x40) == 0) fci->num_args = 3;      else if ((PROC_REG_MASK(proc_desc) & 0x20) == 0) fci->num_args = 2;      else if ((PROC_REG_MASK(proc_desc) & 0x10) == 0) fci->num_args = 1;      fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];    }}/* MIPS stack frames are almost impenetrable.  When execution stops,   we basically have to look at symbol information for the function   that we stopped in, which tells us *which* register (if any) is   the base of the frame pointer, and what offset from that register   the frame itself is at.     This presents a problem when trying to examine a stack in memory   (that isn't executing at the moment), using the "frame" command.  We   don't have a PC, nor do we have any registers except SP.   This routine takes two arguments, SP and PC, and tries to make the   cached frames look as if these two arguments defined a frame on the   cache.  This allows the rest of info frame to extract the important   arguments without difficulty.  */FRAMEsetup_arbitrary_frame (stack, pc)     FRAME_ADDR stack;     CORE_ADDR pc;{  return create_new_frame (stack, pc);}CORE_ADDRmips_push_arguments(nargs, args, sp, struct_return, struct_addr)  int nargs;  value *args;  CORE_ADDR sp;  int struct_return;  CORE_ADDR struct_addr;{  CORE_ADDR buf;  register i;  int accumulate_size = struct_return ? 4 : 0;  struct mips_arg { char *contents; int len; int offset; };  struct mips_arg *mips_args =      (struct mips_arg*)alloca(nargs * sizeof(struct mips_arg));  register struct mips_arg *m_arg;  for (i = 0, m_arg = mips_args; i < nargs; i++, m_arg++) {    extern value value_arg_coerce();    value arg = value_arg_coerce (args[i]);    m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg));    /* This entire mips-specific routine is because doubles must be aligned     * on 8-byte boundaries. It still isn't quite right, because MIPS decided     * to align 'struct {int a, b}' on 4-byte boundaries (even though this     * breaks their varargs implementation...). A correct solution     * requires an simulation of gcc's 'alignof' (and use of 'alignof'     * in stdarg.h/varargs.h).     */    if (m_arg->len > 4) accumulate_size = (accumulate_size + 7) & -8;    m_arg->offset = accumulate_size;    accumulate_size = (accumulate_size + m_arg->len + 3) & -4;    m_arg->contents = VALUE_CONTENTS(arg);  }  accumulate_size = (accumulate_size + 7) & (-8);  if (accumulate_size < 16) accumulate_size = 16;   sp -= accumulate_size;  for (i = nargs; m_arg--, --i >= 0; )    write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);  if (struct_return) {    buf = struct_addr;    write_memory(sp, (char *)&buf, sizeof(CORE_ADDR));  }  return sp;}/* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */#define MASK(i,j) ((1 << (j)+1)-1 ^ (1 << (i))-1)voidmips_push_dummy_frame(){  int ireg;  struct linked_proc_info *link = (struct linked_proc_info*)      xmalloc(sizeof(struct linked_proc_info));  mips_extra_func_info_t proc_desc = &link->info;  CORE_ADDR sp = read_register (SP_REGNUM);  CORE_ADDR save_address;  REGISTER_TYPE buffer;  link->next = linked_proc_desc_table;  linked_proc_desc_table = link;#define PUSH_FP_REGNUM 16 /* must be a register preserved across calls */#define GEN_REG_SAVE_MASK MASK(1,16)|MASK(24,28)|(1<<31)#define GEN_REG_SAVE_COUNT 22#define FLOAT_REG_SAVE_MASK MASK(0,19)#define FLOAT_REG_SAVE_COUNT 20#define SPECIAL_REG_SAVE_COUNT 4  /*   * The registers we must save are all those not preserved across   * procedure calls. Dest_Reg (see tm-mips.h) must also be saved.   * In addition, we must save the PC, and PUSH_FP_REGNUM.   * (Ideally, we should also save MDLO/-HI and FP Control/Status reg.)   *   * Dummy frame layout:   *  (high memory)   * 	Saved PC   *	Saved MMHI, MMLO, FPC_CSR   *	Saved R31   *	Saved R28   *	...   *	Saved R1   *    Saved D18 (i.e. F19, F18)   *    ...   *    Saved D0 (i.e. F1, F0)   *	CALL_DUMMY (subroutine stub; see tm-mips.h)   *	Parameter build area (not yet implemented)   *  (low memory)   */  PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;  PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;  PROC_REG_OFFSET(proc_desc) = /* offset of (Saved R31) from FP */      -sizeof(long) - 4 * SPECIAL_REG_SAVE_COUNT;  PROC_FREG_OFFSET(proc_desc) = /* offset of (Saved D18) from FP */      -sizeof(double) - 4 * (SPECIAL_REG_SAVE_COUNT + GEN_REG_SAVE_COUNT);  /* save general registers */  save_address = sp + PROC_REG_OFFSET(proc_desc);  for (ireg = 32; --ireg >= 0; )    if (PROC_REG_MASK(proc_desc) & (1 << ireg))      {	buffer = read_register (ireg);	write_memory (save_address, (char *)&buffer, sizeof(REGISTER_TYPE));	save_address -= 4;      }  /* save floating-points registers */  save_address = sp + PROC_FREG_OFFSET(proc_desc);  for (ireg = 32; --ireg >= 0; )    if (PROC_FREG_MASK(proc_desc) & (1 << ireg))      {	buffer = read_register (ireg + FP0_REGNUM);

⌨️ 快捷键说明

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