示例#1
0
void
fill_gregset (const struct regcache *regcache, gregset_t *gregsetp, int regno)
{
  int regi, size;
  greg_t *regp = &(*gregsetp)[0];
  gdb_byte buf[MAX_REGISTER_SIZE];
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

  /* Under Irix6, if GDB is built with N32 ABI and is debugging an O32
     executable, we have to sign extend the registers to 64 bits before
     filling in the gregset structure.  */

  for (regi = 0; regi <= CTX_RA; regi++)
    if ((regno == -1) || (regno == regi))
      {
	size = register_size (gdbarch, regi);
	regcache_raw_collect (regcache, regi, buf);
	*(regp + regi) = extract_signed_integer (buf, size, byte_order);
      }

  if ((regno == -1) || (regno == mips_regnum (gdbarch)->pc))
    {
      regi = mips_regnum (gdbarch)->pc;
      size = register_size (gdbarch, regi);
      regcache_raw_collect (regcache, regi, buf);
      *(regp + CTX_EPC) = extract_signed_integer (buf, size, byte_order);
    }

  if ((regno == -1) || (regno == mips_regnum (gdbarch)->cause))
    {
      regi = mips_regnum (gdbarch)->cause;
      size = register_size (gdbarch, regi);
      regcache_raw_collect (regcache, regi, buf);
      *(regp + CTX_CAUSE) = extract_signed_integer (buf, size, byte_order);
    }

  if ((regno == -1) || (regno == mips_regnum (gdbarch)->hi))
    {
      regi = mips_regnum (gdbarch)->hi;
      size = register_size (gdbarch, regi);
      regcache_raw_collect (regcache, regi, buf);
      *(regp + CTX_MDHI) = extract_signed_integer (buf, size, byte_order);
    }

  if ((regno == -1) || (regno == mips_regnum (gdbarch)->lo))
    {
      regi = mips_regnum (gdbarch)->lo;
      size = register_size (gdbarch, regi);
      regcache_raw_collect (regcache, regi, buf);
      *(regp + CTX_MDLO) = extract_signed_integer (buf, size, byte_order);
    }
}
示例#2
0
int
scm_val_print (struct type *type, const gdb_byte *valaddr,
	       int embedded_offset, CORE_ADDR address,
	       struct ui_file *stream, int format, int deref_ref,
	       int recurse, enum val_prettyprint pretty)
{
  if (is_scmvalue_type (type))
    {
      LONGEST svalue = extract_signed_integer (valaddr, TYPE_LENGTH (type));
      if (scm_inferior_print (svalue, stream, format,
			      deref_ref, recurse, pretty) >= 0)
	{
	}
      else
	{
	  scm_scmval_print (svalue, stream, format,
			    deref_ref, recurse, pretty);
	}

      gdb_flush (stream);
      return (0);
    }
  else
    {
      return c_val_print (type, valaddr, 0, address, stream, format,
			  deref_ref, recurse, pretty);
    }
}
示例#3
0
/* Return the current system call's number present in the
   r0 register.  When the function fails, it returns -1.  */
static LONGEST
ppc_linux_get_syscall_number (struct gdbarch *gdbarch,
                              ptid_t ptid)
{
  struct regcache *regcache = get_thread_regcache (ptid);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  struct cleanup *cleanbuf;
  /* The content of a register */
  gdb_byte *buf;
  /* The result */
  LONGEST ret;

  /* Make sure we're in a 32- or 64-bit machine */
  gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8);

  buf = (gdb_byte *) xmalloc (tdep->wordsize * sizeof (gdb_byte));

  cleanbuf = make_cleanup (xfree, buf);

  /* Getting the system call number from the register.
     When dealing with PowerPC architecture, this information
     is stored at 0th register.  */
  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum, buf);

  ret = extract_signed_integer (buf, tdep->wordsize, byte_order);
  do_cleanups (cleanbuf);

  return ret;
}
示例#4
0
void
mips64_fill_gregset (const struct regcache *regcache,
		     mips64_elf_gregset_t *gregsetp, int regno)
{
  int regaddr, regi;
  mips64_elf_greg_t *regp = *gregsetp;
  void *src, *dst;

  if (regno == -1)
    {
      memset (regp, 0, sizeof (mips64_elf_gregset_t));
      for (regi = 1; regi < 32; regi++)
        mips64_fill_gregset (regcache, gregsetp, regi);
      mips64_fill_gregset (regcache, gregsetp,
			   mips_regnum (current_gdbarch)->lo);
      mips64_fill_gregset (regcache, gregsetp,
			   mips_regnum (current_gdbarch)->hi);
      mips64_fill_gregset (regcache, gregsetp,
			   mips_regnum (current_gdbarch)->pc);
      mips64_fill_gregset (regcache, gregsetp,
			   mips_regnum (current_gdbarch)->badvaddr);
      mips64_fill_gregset (regcache, gregsetp, MIPS_PS_REGNUM);
      mips64_fill_gregset (regcache, gregsetp,
			   mips_regnum (current_gdbarch)->cause);
      mips64_fill_gregset (regcache, gregsetp, MIPS_RESTART_REGNUM);
      return;
   }

  if (regno > 0 && regno < 32)
    regaddr = regno + MIPS64_EF_REG0;
  else if (regno == mips_regnum (current_gdbarch)->lo)
    regaddr = MIPS64_EF_LO;
  else if (regno == mips_regnum (current_gdbarch)->hi)
    regaddr = MIPS64_EF_HI;
  else if (regno == mips_regnum (current_gdbarch)->pc)
    regaddr = MIPS64_EF_CP0_EPC;
  else if (regno == mips_regnum (current_gdbarch)->badvaddr)
    regaddr = MIPS64_EF_CP0_BADVADDR;
  else if (regno == MIPS_PS_REGNUM)
    regaddr = MIPS64_EF_CP0_STATUS;
  else if (regno == mips_regnum (current_gdbarch)->cause)
    regaddr = MIPS64_EF_CP0_CAUSE;
  else if (mips_linux_restart_reg_p (current_gdbarch)
	   && regno == MIPS_RESTART_REGNUM)
    regaddr = MIPS64_EF_REG0;
  else
    regaddr = -1;

  if (regaddr != -1)
    {
      gdb_byte buf[MAX_REGISTER_SIZE];
      LONGEST val;

      regcache_raw_collect (regcache, regno, buf);
      val = extract_signed_integer (buf,
				    register_size (current_gdbarch, regno));
      dst = regp + regaddr;
      store_signed_integer (dst, 8, val);
    }
}
示例#5
0
static LONGEST
mips_linux_get_syscall_number (struct gdbarch *gdbarch,
			       ptid_t ptid)
{
  struct regcache *regcache = get_thread_regcache (ptid);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  int regsize = register_size (gdbarch, MIPS_V0_REGNUM);
  /* The content of a register */
  gdb_byte buf[8];
  /* The result */
  LONGEST ret;

  /* Make sure we're in a known ABI */
  gdb_assert (tdep->mips_abi == MIPS_ABI_O32
	      || tdep->mips_abi == MIPS_ABI_N32
	      || tdep->mips_abi == MIPS_ABI_N64);

  gdb_assert (regsize <= sizeof (buf));

  /* Getting the system call number from the register.
     syscall number is in v0 or $2.  */
  regcache_cooked_read (regcache, MIPS_V0_REGNUM, buf);

  ret = extract_signed_integer (buf, regsize, byte_order);

  return ret;
}
示例#6
0
static CORE_ADDR
amd64_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  gdb_byte op;

  target_read_memory (pc, &op, 1);
  if (op == 0xe8)
    {
      gdb_byte buf[4];

      if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
 	{
 	  struct bound_minimal_symbol s;
 	  CORE_ADDR call_dest;

	  call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
 	  s = lookup_minimal_symbol_by_pc (call_dest);
 	  if (s.minsym != NULL
 	      && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL
 	      && strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__main") == 0)
 	    pc += 5;
 	}
    }

  return pc;
}
示例#7
0
LONGEST
read_memory_integer(CORE_ADDR memaddr, int len)
{
  char buf[sizeof(LONGEST)];

  read_memory(memaddr, (gdb_byte *)buf, len);
  return extract_signed_integer((const gdb_byte *)buf, len);
}
示例#8
0
static void
supply_32bit_reg (struct regcache *regcache, int regnum, const void *addr)
{
  gdb_byte buf[MAX_REGISTER_SIZE];
  store_signed_integer (buf, register_size (current_gdbarch, regnum),
                        extract_signed_integer (addr, 4));
  regcache_raw_supply (regcache, regnum, buf);
}
示例#9
0
LONGEST
scm_get_field (LONGEST svalue, int index)
{
  char buffer[20];
  read_memory (SCM2PTR (svalue) + index * TYPE_LENGTH (builtin_type_scm),
	       buffer, TYPE_LENGTH (builtin_type_scm));
  return extract_signed_integer (buffer, TYPE_LENGTH (builtin_type_scm));
}
static void
supply_32bit_reg (struct regcache *regcache, int regnum, const void *addr)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  gdb_byte buf[MAX_REGISTER_SIZE];
  store_signed_integer (buf, register_size (gdbarch, regnum), byte_order,
                        extract_signed_integer (addr, 4, byte_order));
  regcache_raw_supply (regcache, regnum, buf);
}
示例#11
0
static int
gnuv3_decode_method_ptr (struct gdbarch *gdbarch,
			 const gdb_byte *contents,
			 CORE_ADDR *value_p,
			 LONGEST *adjustment_p)
{
  struct type *funcptr_type = builtin_type (gdbarch)->builtin_func_ptr;
  struct type *offset_type = vtable_ptrdiff_type (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  CORE_ADDR ptr_value;
  LONGEST voffset, adjustment;
  int vbit;

  /* Extract the pointer to member.  The first element is either a pointer
     or a vtable offset.  For pointers, we need to use extract_typed_address
     to allow the back-end to convert the pointer to a GDB address -- but
     vtable offsets we must handle as integers.  At this point, we do not
     yet know which case we have, so we extract the value under both
     interpretations and choose the right one later on.  */
  ptr_value = extract_typed_address (contents, funcptr_type);
  voffset = extract_signed_integer (contents,
				    TYPE_LENGTH (funcptr_type), byte_order);
  contents += TYPE_LENGTH (funcptr_type);
  adjustment = extract_signed_integer (contents,
				       TYPE_LENGTH (offset_type), byte_order);

  if (!gdbarch_vbit_in_delta (gdbarch))
    {
      vbit = voffset & 1;
      voffset = voffset ^ vbit;
    }
  else
    {
      vbit = adjustment & 1;
      adjustment = adjustment >> 1;
    }

  *value_p = vbit? voffset : ptr_value;
  *adjustment_p = adjustment;
  return vbit;
}
示例#12
0
static LONGEST
i386_linux_get_syscall_number_from_regcache (struct regcache *regcache)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  /* The content of a register.  */
  gdb_byte buf[4];
  /* The result.  */
  LONGEST ret;

  /* Getting the system call number from the register.
     When dealing with x86 architecture, this information
     is stored at %eax register.  */
  regcache_cooked_read (regcache, I386_LINUX_ORIG_EAX_REGNUM, buf);

  ret = extract_signed_integer (buf, 4, byte_order);

  return ret;
}
示例#13
0
static LONGEST
aarch64_linux_get_syscall_number (struct gdbarch *gdbarch,
				  ptid_t ptid)
{
  struct regcache *regs = get_thread_regcache (ptid);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

  /* The content of register x8.  */
  gdb_byte buf[X_REGISTER_SIZE];
  /* The result.  */
  LONGEST ret;

  /* Getting the system call number from the register x8.  */
  regcache_cooked_read (regs, AARCH64_DWARF_X0 + 8, buf);

  ret = extract_signed_integer (buf, X_REGISTER_SIZE, byte_order);

  return ret;
}
示例#14
0
static LONGEST
sparc64_linux_get_syscall_number (struct gdbarch *gdbarch,
				  thread_info *thread)
{
  struct regcache *regcache = get_thread_regcache (thread);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  /* The content of a register.  */
  gdb_byte buf[8];
  /* The result.  */
  LONGEST ret;

  /* Getting the system call number from the register.
     When dealing with the sparc architecture, this information
     is stored at the %g1 register.  */
  regcache->cooked_read (SPARC_G1_REGNUM, buf);

  ret = extract_signed_integer (buf, 8, byte_order);

  return ret;
}
示例#15
0
static void
mips_fbsd_collect_reg (const struct regcache *regcache, int regnum, void *addr,
		       size_t len)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);

  if (register_size (gdbarch, regnum) == len)
    regcache_raw_collect (regcache, regnum, addr);
  else
    {
      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
      gdb_byte buf[MAX_REGISTER_SIZE];
      LONGEST val;

      regcache_raw_collect (regcache, regnum, buf);
      val = extract_signed_integer (buf, register_size (gdbarch, regnum),
				    byte_order);
      store_signed_integer ((gdb_byte *) addr, len, byte_order, val);
    }
}
static LONGEST
bfin_linux_get_syscall_number (struct gdbarch *gdbarch,
                               ptid_t ptid)
{
  struct regcache *regcache = get_thread_regcache (ptid);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  /* The content of a register.  */
  gdb_byte buf[4];
  /* The result.  */
  LONGEST ret;

  /* Getting the system call number from the register.
     When dealing with Blackfin architecture, this information
     is stored at %p0 register.  */
  regcache_cooked_read (regcache, BFIN_P0_REGNUM, buf);

  ret = extract_signed_integer (buf, 4, byte_order);

  return ret;
}
示例#17
0
LONGEST
scm_unpack (struct type *type, char *valaddr, enum type_code context)
{
  if (is_scmvalue_type (type))
    {
      LONGEST svalue = extract_signed_integer (valaddr, TYPE_LENGTH (type));
      if (context == TYPE_CODE_BOOL)
	{
	  if (svalue == SCM_BOOL_F)
	    return 0;
	  else
	    return 1;
	}
      switch (7 & (int) svalue)
	{
	case 2:
	case 6:		/* fixnum */
	  return svalue >> 2;
	case 4:		/* other immediate value */
	  if (SCM_ICHRP (svalue))	/* character */
	    return SCM_ICHR (svalue);
	  else if (SCM_IFLAGP (svalue))
	    {
	      switch ((int) svalue)
		{
#ifndef SICP
		case SCM_EOL:
#endif
		case SCM_BOOL_F:
		  return 0;
		case SCM_BOOL_T:
		  return 1;
		}
	    }
	  error ("Value can't be converted to integer.");
	default:
	  return svalue;
	}
    }
  else
    return unpack_long (type, valaddr);
示例#18
0
/* Scan an FR-V prologue, starting at PC, until frame->PC.
   If FRAME is non-zero, fill in its saved_regs with appropriate addresses.
   We assume FRAME's saved_regs array has already been allocated and cleared.
   Return the first PC value after the prologue.

   Note that, for unoptimized code, we almost don't need this function
   at all; all arguments and locals live on the stack, so we just need
   the FP to find everything.  The catch: structures passed by value
   have their addresses living in registers; they're never spilled to
   the stack.  So if you ever want to be able to get to these
   arguments in any frame but the top, you'll need to do this serious
   prologue analysis.  */
static CORE_ADDR
frv_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
		      struct frame_info *this_frame,
                      struct frv_unwind_cache *info)
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

  /* When writing out instruction bitpatterns, we use the following
     letters to label instruction fields:
     P - The parallel bit.  We don't use this.
     J - The register number of GRj in the instruction description.
     K - The register number of GRk in the instruction description.
     I - The register number of GRi.
     S - a signed imediate offset.
     U - an unsigned immediate offset.

     The dots below the numbers indicate where hex digit boundaries
     fall, to make it easier to check the numbers.  */

  /* Non-zero iff we've seen the instruction that initializes the
     frame pointer for this function's frame.  */
  int fp_set = 0;

  /* If fp_set is non_zero, then this is the distance from
     the stack pointer to frame pointer: fp = sp + fp_offset.  */
  int fp_offset = 0;

  /* Total size of frame prior to any alloca operations.  */
  int framesize = 0;

  /* Flag indicating if lr has been saved on the stack.  */
  int lr_saved_on_stack = 0;

  /* The number of the general-purpose register we saved the return
     address ("link register") in, or -1 if we haven't moved it yet.  */
  int lr_save_reg = -1;

  /* Offset (from sp) at which lr has been saved on the stack.  */

  int lr_sp_offset = 0;

  /* If gr_saved[i] is non-zero, then we've noticed that general
     register i has been saved at gr_sp_offset[i] from the stack
     pointer.  */
  char gr_saved[64];
  int gr_sp_offset[64];

  /* The address of the most recently scanned prologue instruction.  */
  CORE_ADDR last_prologue_pc;

  /* The address of the next instruction.  */
  CORE_ADDR next_pc;

  /* The upper bound to of the pc values to scan.  */
  CORE_ADDR lim_pc;

  memset (gr_saved, 0, sizeof (gr_saved));

  last_prologue_pc = pc;

  /* Try to compute an upper limit (on how far to scan) based on the
     line number info.  */
  lim_pc = skip_prologue_using_sal (gdbarch, pc);
  /* If there's no line number info, lim_pc will be 0.  In that case,
     set the limit to be 100 instructions away from pc.  Hopefully, this
     will be far enough away to account for the entire prologue.  Don't
     worry about overshooting the end of the function.  The scan loop
     below contains some checks to avoid scanning unreasonably far.  */
  if (lim_pc == 0)
    lim_pc = pc + 400;

  /* If we have a frame, we don't want to scan past the frame's pc.  This
     will catch those cases where the pc is in the prologue.  */
  if (this_frame)
    {
      CORE_ADDR frame_pc = get_frame_pc (this_frame);
      if (frame_pc < lim_pc)
	lim_pc = frame_pc;
    }

  /* Scan the prologue.  */
  while (pc < lim_pc)
    {
      gdb_byte buf[frv_instr_size];
      LONGEST op;

      if (target_read_memory (pc, buf, sizeof buf) != 0)
	break;
      op = extract_signed_integer (buf, sizeof buf, byte_order);

      next_pc = pc + 4;

      /* The tests in this chain of ifs should be in order of
	 decreasing selectivity, so that more particular patterns get
	 to fire before less particular patterns.  */

      /* Some sort of control transfer instruction: stop scanning prologue.
	 Integer Conditional Branch:
	  X XXXX XX 0000110 XX XXXXXXXXXXXXXXXX
	 Floating-point / media Conditional Branch:
	  X XXXX XX 0000111 XX XXXXXXXXXXXXXXXX
	 LCR Conditional Branch to LR
	  X XXXX XX 0001110 XX XX 001 X XXXXXXXXXX
	 Integer conditional Branches to LR
	  X XXXX XX 0001110 XX XX 010 X XXXXXXXXXX
	  X XXXX XX 0001110 XX XX 011 X XXXXXXXXXX
	 Floating-point/Media Branches to LR
	  X XXXX XX 0001110 XX XX 110 X XXXXXXXXXX
	  X XXXX XX 0001110 XX XX 111 X XXXXXXXXXX
	 Jump and Link
	  X XXXXX X 0001100 XXXXXX XXXXXX XXXXXX
	  X XXXXX X 0001101 XXXXXX XXXXXX XXXXXX
	 Call
	  X XXXXXX 0001111 XXXXXXXXXXXXXXXXXX
	 Return from Trap
	  X XXXXX X 0000101 XXXXXX XXXXXX XXXXXX
	 Integer Conditional Trap
	  X XXXX XX 0000100 XXXXXX XXXX 00 XXXXXX
	  X XXXX XX 0011100 XXXXXX XXXXXXXXXXXX
	 Floating-point /media Conditional Trap
	  X XXXX XX 0000100 XXXXXX XXXX 01 XXXXXX
	  X XXXX XX 0011101 XXXXXX XXXXXXXXXXXX
	 Break
	  X XXXX XX 0000100 XXXXXX XXXX 11 XXXXXX
	 Media Trap
	  X XXXX XX 0000100 XXXXXX XXXX 10 XXXXXX */
      if ((op & 0x01d80000) == 0x00180000 /* Conditional branches and Call */
          || (op & 0x01f80000) == 0x00300000  /* Jump and Link */
	  || (op & 0x01f80000) == 0x00100000  /* Return from Trap, Trap */
	  || (op & 0x01f80000) == 0x00700000) /* Trap immediate */
	{
	  /* Stop scanning; not in prologue any longer.  */
	  break;
	}

      /* Loading something from memory into fp probably means that
         we're in the epilogue.  Stop scanning the prologue.
         ld @(GRi, GRk), fp
	 X 000010 0000010 XXXXXX 000100 XXXXXX
	 ldi @(GRi, d12), fp
	 X 000010 0110010 XXXXXX XXXXXXXXXXXX */
      else if ((op & 0x7ffc0fc0) == 0x04080100
               || (op & 0x7ffc0000) == 0x04c80000)
	{
	  break;
	}

      /* Setting the FP from the SP:
	 ori sp, 0, fp
	 P 000010 0100010 000001 000000000000 = 0x04881000
	 0 111111 1111111 111111 111111111111 = 0x7fffffff
             .    .   .    .   .    .   .   .
	 We treat this as part of the prologue.  */
      else if ((op & 0x7fffffff) == 0x04881000)
	{
	  fp_set = 1;
	  fp_offset = 0;
	  last_prologue_pc = next_pc;
	}

      /* Move the link register to the scratch register grJ, before saving:
         movsg lr, grJ
         P 000100 0000011 010000 000111 JJJJJJ = 0x080d01c0
         0 111111 1111111 111111 111111 000000 = 0x7fffffc0
             .    .   .    .   .    .    .   .
	 We treat this as part of the prologue.  */
      else if ((op & 0x7fffffc0) == 0x080d01c0)
        {
          int gr_j = op & 0x3f;

          /* If we're moving it to a scratch register, that's fine.  */
          if (is_caller_saves_reg (gr_j))
	    {
	      lr_save_reg = gr_j;
	      last_prologue_pc = next_pc;
	    }
        }

      /* To save multiple callee-saves registers on the stack, at
         offset zero:

	 std grK,@(sp,gr0)
	 P KKKKKK 0000011 000001 000011 000000 = 0x000c10c0
	 0 000000 1111111 111111 111111 111111 = 0x01ffffff

	 stq grK,@(sp,gr0)
	 P KKKKKK 0000011 000001 000100 000000 = 0x000c1100
	 0 000000 1111111 111111 111111 111111 = 0x01ffffff
             .    .   .    .   .    .    .   .
         We treat this as part of the prologue, and record the register's
	 saved address in the frame structure.  */
      else if ((op & 0x01ffffff) == 0x000c10c0
            || (op & 0x01ffffff) == 0x000c1100)
	{
	  int gr_k = ((op >> 25) & 0x3f);
	  int ope  = ((op >> 6)  & 0x3f);
          int count;
	  int i;

          /* Is it an std or an stq?  */
          if (ope == 0x03)
            count = 2;
          else
            count = 4;

	  /* Is it really a callee-saves register?  */
	  if (is_callee_saves_reg (gr_k))
	    {
	      for (i = 0; i < count; i++)
	        {
		  gr_saved[gr_k + i] = 1;
		  gr_sp_offset[gr_k + i] = 4 * i;
		}
	      last_prologue_pc = next_pc;
	    }
	}

      /* Adjusting the stack pointer.  (The stack pointer is GR1.)
	 addi sp, S, sp
         P 000001 0010000 000001 SSSSSSSSSSSS = 0x02401000
         0 111111 1111111 111111 000000000000 = 0x7ffff000
             .    .   .    .   .    .   .   .
	 We treat this as part of the prologue.  */
      else if ((op & 0x7ffff000) == 0x02401000)
示例#19
0
static void
execute_stack_op (struct dwarf_expr_context *ctx,
		  gdb_byte *op_ptr, gdb_byte *op_end)
{
  enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
  ctx->location = DWARF_VALUE_MEMORY;
  ctx->initialized = 1;  /* Default is initialized.  */

  if (ctx->recursion_depth > ctx->max_recursion_depth)
    error (_("DWARF-2 expression error: Loop detected (%d)."),
	   ctx->recursion_depth);
  ctx->recursion_depth++;

  while (op_ptr < op_end)
    {
      enum dwarf_location_atom op = *op_ptr++;
      CORE_ADDR result;
      /* Assume the value is not in stack memory.
	 Code that knows otherwise sets this to 1.
	 Some arithmetic on stack addresses can probably be assumed to still
	 be a stack address, but we skip this complication for now.
	 This is just an optimization, so it's always ok to punt
	 and leave this as 0.  */
      int in_stack_memory = 0;
      ULONGEST uoffset, reg;
      LONGEST offset;

      switch (op)
	{
	case DW_OP_lit0:
	case DW_OP_lit1:
	case DW_OP_lit2:
	case DW_OP_lit3:
	case DW_OP_lit4:
	case DW_OP_lit5:
	case DW_OP_lit6:
	case DW_OP_lit7:
	case DW_OP_lit8:
	case DW_OP_lit9:
	case DW_OP_lit10:
	case DW_OP_lit11:
	case DW_OP_lit12:
	case DW_OP_lit13:
	case DW_OP_lit14:
	case DW_OP_lit15:
	case DW_OP_lit16:
	case DW_OP_lit17:
	case DW_OP_lit18:
	case DW_OP_lit19:
	case DW_OP_lit20:
	case DW_OP_lit21:
	case DW_OP_lit22:
	case DW_OP_lit23:
	case DW_OP_lit24:
	case DW_OP_lit25:
	case DW_OP_lit26:
	case DW_OP_lit27:
	case DW_OP_lit28:
	case DW_OP_lit29:
	case DW_OP_lit30:
	case DW_OP_lit31:
	  result = op - DW_OP_lit0;
	  break;

	case DW_OP_addr:
	  result = dwarf2_read_address (ctx->gdbarch,
					op_ptr, op_end, ctx->addr_size);
	  op_ptr += ctx->addr_size;
	  break;

	case DW_OP_const1u:
	  result = extract_unsigned_integer (op_ptr, 1, byte_order);
	  op_ptr += 1;
	  break;
	case DW_OP_const1s:
	  result = extract_signed_integer (op_ptr, 1, byte_order);
	  op_ptr += 1;
	  break;
	case DW_OP_const2u:
	  result = extract_unsigned_integer (op_ptr, 2, byte_order);
	  op_ptr += 2;
	  break;
	case DW_OP_const2s:
	  result = extract_signed_integer (op_ptr, 2, byte_order);
	  op_ptr += 2;
	  break;
	case DW_OP_const4u:
	  result = extract_unsigned_integer (op_ptr, 4, byte_order);
	  op_ptr += 4;
	  break;
	case DW_OP_const4s:
	  result = extract_signed_integer (op_ptr, 4, byte_order);
	  op_ptr += 4;
	  break;
	case DW_OP_const8u:
	  result = extract_unsigned_integer (op_ptr, 8, byte_order);
	  op_ptr += 8;
	  break;
	case DW_OP_const8s:
	  result = extract_signed_integer (op_ptr, 8, byte_order);
	  op_ptr += 8;
	  break;
	case DW_OP_constu:
	  op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
	  result = uoffset;
	  break;
	case DW_OP_consts:
	  op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	  result = offset;
	  break;

	/* The DW_OP_reg operations are required to occur alone in
	   location expressions.  */
	case DW_OP_reg0:
	case DW_OP_reg1:
	case DW_OP_reg2:
	case DW_OP_reg3:
	case DW_OP_reg4:
	case DW_OP_reg5:
	case DW_OP_reg6:
	case DW_OP_reg7:
	case DW_OP_reg8:
	case DW_OP_reg9:
	case DW_OP_reg10:
	case DW_OP_reg11:
	case DW_OP_reg12:
	case DW_OP_reg13:
	case DW_OP_reg14:
	case DW_OP_reg15:
	case DW_OP_reg16:
	case DW_OP_reg17:
	case DW_OP_reg18:
	case DW_OP_reg19:
	case DW_OP_reg20:
	case DW_OP_reg21:
	case DW_OP_reg22:
	case DW_OP_reg23:
	case DW_OP_reg24:
	case DW_OP_reg25:
	case DW_OP_reg26:
	case DW_OP_reg27:
	case DW_OP_reg28:
	case DW_OP_reg29:
	case DW_OP_reg30:
	case DW_OP_reg31:
	  if (op_ptr != op_end 
	      && *op_ptr != DW_OP_piece
	      && *op_ptr != DW_OP_GNU_uninit)
	    error (_("DWARF-2 expression error: DW_OP_reg operations must be "
		   "used either alone or in conjuction with DW_OP_piece."));

	  result = op - DW_OP_reg0;
	  ctx->location = DWARF_VALUE_REGISTER;
	  break;

	case DW_OP_regx:
	  op_ptr = read_uleb128 (op_ptr, op_end, &reg);
	  require_composition (op_ptr, op_end, "DW_OP_regx");

	  result = reg;
	  ctx->location = DWARF_VALUE_REGISTER;
	  break;

	case DW_OP_implicit_value:
	  {
	    ULONGEST len;
	    op_ptr = read_uleb128 (op_ptr, op_end, &len);
	    if (op_ptr + len > op_end)
	      error (_("DW_OP_implicit_value: too few bytes available."));
	    ctx->len = len;
	    ctx->data = op_ptr;
	    ctx->location = DWARF_VALUE_LITERAL;
	    op_ptr += len;
	    require_composition (op_ptr, op_end, "DW_OP_implicit_value");
	  }
	  goto no_push;

	case DW_OP_stack_value:
	  ctx->location = DWARF_VALUE_STACK;
	  require_composition (op_ptr, op_end, "DW_OP_stack_value");
	  goto no_push;

	case DW_OP_breg0:
	case DW_OP_breg1:
	case DW_OP_breg2:
	case DW_OP_breg3:
	case DW_OP_breg4:
	case DW_OP_breg5:
	case DW_OP_breg6:
	case DW_OP_breg7:
	case DW_OP_breg8:
	case DW_OP_breg9:
	case DW_OP_breg10:
	case DW_OP_breg11:
	case DW_OP_breg12:
	case DW_OP_breg13:
	case DW_OP_breg14:
	case DW_OP_breg15:
	case DW_OP_breg16:
	case DW_OP_breg17:
	case DW_OP_breg18:
	case DW_OP_breg19:
	case DW_OP_breg20:
	case DW_OP_breg21:
	case DW_OP_breg22:
	case DW_OP_breg23:
	case DW_OP_breg24:
	case DW_OP_breg25:
	case DW_OP_breg26:
	case DW_OP_breg27:
	case DW_OP_breg28:
	case DW_OP_breg29:
	case DW_OP_breg30:
	case DW_OP_breg31:
	  {
	    op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	    result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0);
	    result += offset;
	  }
	  break;
	case DW_OP_bregx:
	  {
	    op_ptr = read_uleb128 (op_ptr, op_end, &reg);
	    op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	    result = (ctx->read_reg) (ctx->baton, reg);
	    result += offset;
	  }
	  break;
	case DW_OP_fbreg:
	  {
	    gdb_byte *datastart;
	    size_t datalen;
	    unsigned int before_stack_len;

	    op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	    /* Rather than create a whole new context, we simply
	       record the stack length before execution, then reset it
	       afterwards, effectively erasing whatever the recursive
	       call put there.  */
	    before_stack_len = ctx->stack_len;
	    /* FIXME: cagney/2003-03-26: This code should be using
               get_frame_base_address(), and then implement a dwarf2
               specific this_base method.  */
	    (ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
	    dwarf_expr_eval (ctx, datastart, datalen);
	    if (ctx->location == DWARF_VALUE_LITERAL
		|| ctx->location == DWARF_VALUE_STACK)
	      error (_("Not implemented: computing frame base using explicit value operator"));
	    result = dwarf_expr_fetch (ctx, 0);
	    if (ctx->location == DWARF_VALUE_REGISTER)
	      result = (ctx->read_reg) (ctx->baton, result);
	    result = result + offset;
	    in_stack_memory = 1;
	    ctx->stack_len = before_stack_len;
	    ctx->location = DWARF_VALUE_MEMORY;
	  }
	  break;

	case DW_OP_dup:
	  result = dwarf_expr_fetch (ctx, 0);
	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
	  break;

	case DW_OP_drop:
	  dwarf_expr_pop (ctx);
	  goto no_push;

	case DW_OP_pick:
	  offset = *op_ptr++;
	  result = dwarf_expr_fetch (ctx, offset);
	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, offset);
	  break;
	  
	case DW_OP_swap:
	  {
	    struct dwarf_stack_value t1, t2;

	    if (ctx->stack_len < 2)
	       error (_("Not enough elements for DW_OP_swap. Need 2, have %d."),
		      ctx->stack_len);
	    t1 = ctx->stack[ctx->stack_len - 1];
	    t2 = ctx->stack[ctx->stack_len - 2];
	    ctx->stack[ctx->stack_len - 1] = t2;
	    ctx->stack[ctx->stack_len - 2] = t1;
	    goto no_push;
	  }

	case DW_OP_over:
	  result = dwarf_expr_fetch (ctx, 1);
	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 1);
	  break;

	case DW_OP_rot:
	  {
	    struct dwarf_stack_value t1, t2, t3;

	    if (ctx->stack_len < 3)
	       error (_("Not enough elements for DW_OP_rot. Need 3, have %d."),
		      ctx->stack_len);
	    t1 = ctx->stack[ctx->stack_len - 1];
	    t2 = ctx->stack[ctx->stack_len - 2];
	    t3 = ctx->stack[ctx->stack_len - 3];
	    ctx->stack[ctx->stack_len - 1] = t2;
	    ctx->stack[ctx->stack_len - 2] = t3;
	    ctx->stack[ctx->stack_len - 3] = t1;
	    goto no_push;
	  }

	case DW_OP_deref:
	case DW_OP_deref_size:
	case DW_OP_abs:
	case DW_OP_neg:
	case DW_OP_not:
	case DW_OP_plus_uconst:
	  /* Unary operations.  */
	  result = dwarf_expr_fetch (ctx, 0);
	  dwarf_expr_pop (ctx);

	  switch (op)
	    {
	    case DW_OP_deref:
	      {
		gdb_byte *buf = alloca (ctx->addr_size);
		(ctx->read_mem) (ctx->baton, buf, result, ctx->addr_size);
		result = dwarf2_read_address (ctx->gdbarch,
					      buf, buf + ctx->addr_size,
					      ctx->addr_size);
	      }
	      break;

	    case DW_OP_deref_size:
	      {
		int addr_size = *op_ptr++;
		gdb_byte *buf = alloca (addr_size);
		(ctx->read_mem) (ctx->baton, buf, result, addr_size);
		result = dwarf2_read_address (ctx->gdbarch,
					      buf, buf + addr_size,
					      addr_size);
	      }
	      break;

	    case DW_OP_abs:
	      if ((signed int) result < 0)
		result = -result;
	      break;
	    case DW_OP_neg:
	      result = -result;
	      break;
	    case DW_OP_not:
	      result = ~result;
	      break;
	    case DW_OP_plus_uconst:
	      op_ptr = read_uleb128 (op_ptr, op_end, &reg);
	      result += reg;
	      break;
	    }
	  break;

	case DW_OP_and:
	case DW_OP_div:
	case DW_OP_minus:
	case DW_OP_mod:
	case DW_OP_mul:
	case DW_OP_or:
	case DW_OP_plus:
	case DW_OP_shl:
	case DW_OP_shr:
	case DW_OP_shra:
	case DW_OP_xor:
	case DW_OP_le:
	case DW_OP_ge:
	case DW_OP_eq:
	case DW_OP_lt:
	case DW_OP_gt:
	case DW_OP_ne:
	  {
	    /* Binary operations.  Use the value engine to do computations in
	       the right width.  */
	    CORE_ADDR first, second;
	    enum exp_opcode binop;
	    struct value *val1 = NULL, *val2 = NULL;
	    struct type *stype, *utype;

	    second = dwarf_expr_fetch (ctx, 0);
	    dwarf_expr_pop (ctx);

	    first = dwarf_expr_fetch (ctx, 0);
	    dwarf_expr_pop (ctx);

	    utype = unsigned_address_type (ctx->gdbarch, ctx->addr_size);
	    stype = signed_address_type (ctx->gdbarch, ctx->addr_size);

	    switch (op)
	      {
	      case DW_OP_and:
		binop = BINOP_BITWISE_AND;
		break;
	      case DW_OP_div:
		binop = BINOP_DIV;
		val1 = value_from_longest (stype, first);
		val2 = value_from_longest (stype, second);
                break;
	      case DW_OP_minus:
		binop = BINOP_SUB;
		break;
	      case DW_OP_mod:
		binop = BINOP_MOD;
		break;
	      case DW_OP_mul:
		binop = BINOP_MUL;
		break;
	      case DW_OP_or:
		binop = BINOP_BITWISE_IOR;
		break;
	      case DW_OP_plus:
		binop = BINOP_ADD;
		break;
	      case DW_OP_shl:
		binop = BINOP_LSH;
		break;
	      case DW_OP_shr:
		binop = BINOP_RSH;
                break;
	      case DW_OP_shra:
		binop = BINOP_RSH;
		val1 = value_from_longest (stype, first);
		break;
	      case DW_OP_xor:
		binop = BINOP_BITWISE_XOR;
		break;
	      case DW_OP_le:
		binop = BINOP_LEQ;
		val1 = value_from_longest (stype, first);
		val2 = value_from_longest (stype, second);
		break;
	      case DW_OP_ge:
		binop = BINOP_GEQ;
		val1 = value_from_longest (stype, first);
		val2 = value_from_longest (stype, second);
		break;
	      case DW_OP_eq:
		binop = BINOP_EQUAL;
		val1 = value_from_longest (stype, first);
		val2 = value_from_longest (stype, second);
		break;
	      case DW_OP_lt:
		binop = BINOP_LESS;
		val1 = value_from_longest (stype, first);
		val2 = value_from_longest (stype, second);
		break;
	      case DW_OP_gt:
		binop = BINOP_GTR;
		val1 = value_from_longest (stype, first);
		val2 = value_from_longest (stype, second);
		break;
	      case DW_OP_ne:
		binop = BINOP_NOTEQUAL;
		val1 = value_from_longest (stype, first);
		val2 = value_from_longest (stype, second);
		break;
	      default:
		internal_error (__FILE__, __LINE__,
				_("Can't be reached."));
	      }

	    /* We use unsigned operands by default.  */
	    if (val1 == NULL)
	      val1 = value_from_longest (utype, first);
	    if (val2 == NULL)
	      val2 = value_from_longest (utype, second);

	    result = value_as_long (value_binop (val1, val2, binop));
	  }
	  break;

	case DW_OP_call_frame_cfa:
	  result = (ctx->get_frame_cfa) (ctx->baton);
	  in_stack_memory = 1;
	  break;

	case DW_OP_GNU_push_tls_address:
	  /* Variable is at a constant offset in the thread-local
	  storage block into the objfile for the current thread and
	  the dynamic linker module containing this expression. Here
	  we return returns the offset from that base.  The top of the
	  stack has the offset from the beginning of the thread
	  control block at which the variable is located.  Nothing
	  should follow this operator, so the top of stack would be
	  returned.  */
	  result = dwarf_expr_fetch (ctx, 0);
	  dwarf_expr_pop (ctx);
	  result = (ctx->get_tls_address) (ctx->baton, result);
	  break;

	case DW_OP_skip:
	  offset = extract_signed_integer (op_ptr, 2, byte_order);
	  op_ptr += 2;
	  op_ptr += offset;
	  goto no_push;

	case DW_OP_bra:
	  offset = extract_signed_integer (op_ptr, 2, byte_order);
	  op_ptr += 2;
	  if (dwarf_expr_fetch (ctx, 0) != 0)
	    op_ptr += offset;
	  dwarf_expr_pop (ctx);
	  goto no_push;

	case DW_OP_nop:
	  goto no_push;

        case DW_OP_piece:
          {
            ULONGEST size;

            /* Record the piece.  */
            op_ptr = read_uleb128 (op_ptr, op_end, &size);
	    add_piece (ctx, size);

            /* Pop off the address/regnum, and reset the location
	       type.  */
	    if (ctx->location != DWARF_VALUE_LITERAL)
	      dwarf_expr_pop (ctx);
            ctx->location = DWARF_VALUE_MEMORY;
          }
          goto no_push;

	case DW_OP_GNU_uninit:
	  if (op_ptr != op_end)
	    error (_("DWARF-2 expression error: DW_OP_GNU_uninit must always "
		   "be the very last op."));

	  ctx->initialized = 0;
	  goto no_push;

	default:
	  error (_("Unhandled dwarf expression opcode 0x%x"), op);
	}

      /* Most things push a result value.  */
      dwarf_expr_push (ctx, result, in_stack_memory);
    no_push:;
    }

  ctx->recursion_depth--;
  gdb_assert (ctx->recursion_depth >= 0);
}
示例#20
0
static CORE_ADDR
mn10300_analyze_prologue (struct frame_info *fi, CORE_ADDR pc)
{
  CORE_ADDR func_addr, func_end, addr, stop;
  CORE_ADDR stack_size;
  int imm_size;
  unsigned char buf[4];
  int status, movm_args = 0;
  char *name;

  /* Use the PC in the frame if it's provided to look up the
     start of this function.  */
  pc = (fi ? fi->pc : pc);

  /* Find the start of this function.  */
  status = find_pc_partial_function (pc, &name, &func_addr, &func_end);

  /* Do nothing if we couldn't find the start of this function or if we're
     stopped at the first instruction in the prologue.  */
  if (status == 0)
    {
      return pc;
    }

  /* If we're in start, then give up.  */
  if (strcmp (name, "start") == 0)
    {
      if (fi != NULL)
	fi->extra_info->status = NO_MORE_FRAMES;
      return pc;
    }

  /* At the start of a function our frame is in the stack pointer.  */
  if (fi)
    fi->extra_info->status = MY_FRAME_IN_SP;

  /* Get the next two bytes into buf, we need two because rets is a two
     byte insn and the first isn't enough to uniquely identify it.  */
  status = read_memory_nobpt (pc, buf, 2);
  if (status != 0)
    return pc;

  /* If we're physically on an "rets" instruction, then our frame has
     already been deallocated.  Note this can also be true for retf
     and ret if they specify a size of zero.

     In this case fi->frame is bogus, we need to fix it.  */
  if (fi && buf[0] == 0xf0 && buf[1] == 0xfc)
    {
      if (fi->next == NULL)
	fi->frame = read_sp ();
      return fi->pc;
    }

  /* Similarly if we're stopped on the first insn of a prologue as our
     frame hasn't been allocated yet.  */
  if (fi && fi->pc == func_addr)
    {
      if (fi->next == NULL)
	fi->frame = read_sp ();
      return fi->pc;
    }

  /* Figure out where to stop scanning.  */
  stop = fi ? fi->pc : func_end;

  /* Don't walk off the end of the function.  */
  stop = stop > func_end ? func_end : stop;

  /* Start scanning on the first instruction of this function.  */
  addr = func_addr;

  /* Suck in two bytes.  */
  status = read_memory_nobpt (addr, buf, 2);
  if (status != 0)
    {
      fix_frame_pointer (fi, 0);
      return addr;
    }

  /* First see if this insn sets the stack pointer from a register; if
     so, it's probably the initialization of the stack pointer in _start,
     so mark this as the bottom-most frame.  */
  if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0)
    {
      if (fi)
	fi->extra_info->status = NO_MORE_FRAMES;
      return addr;
    }

  /* Now look for movm [regs],sp, which saves the callee saved registers.

     At this time we don't know if fi->frame is valid, so we only note
     that we encountered a movm instruction.  Later, we'll set the entries
     in fsr.regs as needed.  */
  if (buf[0] == 0xcf)
    {
      /* Extract the register list for the movm instruction.  */
      status = read_memory_nobpt (addr + 1, buf, 1);
      movm_args = *buf;

      addr += 2;

      /* Quit now if we're beyond the stop point.  */
      if (addr >= stop)
	{
	  /* Fix fi->frame since it's bogus at this point.  */
	  if (fi && fi->next == NULL)
	    fi->frame = read_sp ();

	  /* Note if/where callee saved registers were saved.  */
	  set_movm_offsets (fi, movm_args);
	  return addr;
	}

      /* Get the next two bytes so the prologue scan can continue.  */
      status = read_memory_nobpt (addr, buf, 2);
      if (status != 0)
	{
	  /* Fix fi->frame since it's bogus at this point.  */
	  if (fi && fi->next == NULL)
	    fi->frame = read_sp ();

	  /* Note if/where callee saved registers were saved.  */
	  set_movm_offsets (fi, movm_args);
	  return addr;
	}
    }

  /* Now see if we set up a frame pointer via "mov sp,a3" */
  if (buf[0] == 0x3f)
    {
      addr += 1;

      /* The frame pointer is now valid.  */
      if (fi)
	{
	  fi->extra_info->status |= MY_FRAME_IN_FP;
	  fi->extra_info->status &= ~MY_FRAME_IN_SP;
	}

      /* Quit now if we're beyond the stop point.  */
      if (addr >= stop)
	{
	  /* Fix fi->frame if it's bogus at this point.  */
	  fix_frame_pointer (fi, 0);

	  /* Note if/where callee saved registers were saved.  */
	  set_movm_offsets (fi, movm_args);
	  return addr;
	}

      /* Get two more bytes so scanning can continue.  */
      status = read_memory_nobpt (addr, buf, 2);
      if (status != 0)
	{
	  /* Fix fi->frame if it's bogus at this point.  */
	  fix_frame_pointer (fi, 0);

	  /* Note if/where callee saved registers were saved.  */
	  set_movm_offsets (fi, movm_args);
	  return addr;
	}
    }

  /* Next we should allocate the local frame.  No more prologue insns
     are found after allocating the local frame.

     Search for add imm8,sp (0xf8feXX)
     or add imm16,sp (0xfafeXXXX)
     or add imm32,sp (0xfcfeXXXXXXXX).

     If none of the above was found, then this prologue has no 
     additional stack.  */

  status = read_memory_nobpt (addr, buf, 2);
  if (status != 0)
    {
      /* Fix fi->frame if it's bogus at this point.  */
      fix_frame_pointer (fi, 0);

      /* Note if/where callee saved registers were saved.  */
      set_movm_offsets (fi, movm_args);
      return addr;
    }

  imm_size = 0;
  if (buf[0] == 0xf8 && buf[1] == 0xfe)
    imm_size = 1;
  else if (buf[0] == 0xfa && buf[1] == 0xfe)
    imm_size = 2;
  else if (buf[0] == 0xfc && buf[1] == 0xfe)
    imm_size = 4;

  if (imm_size != 0)
    {
      /* Suck in imm_size more bytes, they'll hold the size of the
         current frame.  */
      status = read_memory_nobpt (addr + 2, buf, imm_size);
      if (status != 0)
	{
	  /* Fix fi->frame if it's bogus at this point.  */
	  fix_frame_pointer (fi, 0);

	  /* Note if/where callee saved registers were saved.  */
	  set_movm_offsets (fi, movm_args);
	  return addr;
	}

      /* Note the size of the stack in the frame info structure.  */
      stack_size = extract_signed_integer (buf, imm_size);
      if (fi)
	fi->extra_info->stack_size = stack_size;

      /* We just consumed 2 + imm_size bytes.  */
      addr += 2 + imm_size;

      /* No more prologue insns follow, so begin preparation to return.  */
      /* Fix fi->frame if it's bogus at this point.  */
      fix_frame_pointer (fi, stack_size);

      /* Note if/where callee saved registers were saved.  */
      set_movm_offsets (fi, movm_args);
      return addr;
    }

  /* We never found an insn which allocates local stack space, regardless
     this is the end of the prologue.  */
  /* Fix fi->frame if it's bogus at this point.  */
  fix_frame_pointer (fi, 0);

  /* Note if/where callee saved registers were saved.  */
  set_movm_offsets (fi, movm_args);
  return addr;
}
示例#21
0
static void
trace_save (const char *filename, struct trace_file_writer *writer,
	    int target_does_save)
{
  struct trace_status *ts = current_trace_status ();
  struct uploaded_tp *uploaded_tps = NULL, *utp;
  struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;

  ULONGEST offset = 0;
#define MAX_TRACE_UPLOAD 2000
  gdb_byte buf[MAX_TRACE_UPLOAD];
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());

  /* If the target is to save the data to a file on its own, then just
     send the command and be done with it.  */
  if (target_does_save)
    {
      if (!writer->ops->target_save (writer, filename))
	error (_("Target failed to save trace data to '%s'."),
	       filename);
      return;
    }

  /* Get the trace status first before opening the file, so if the
     target is losing, we can get out without touching files.  Since
     we're just calling this for side effects, we ignore the
     result.  */
  target_get_trace_status (ts);

  writer->ops->start (writer, filename);

  writer->ops->write_header (writer);

  /* Write descriptive info.  */

  /* Write out the size of a register block.  */
  writer->ops->write_regblock_type (writer, trace_regblock_size);

  /* Write out the target description info.  */
  writer->ops->write_tdesc (writer);

  /* Write out status of the tracing run (aka "tstatus" info).  */
  writer->ops->write_status (writer, ts);

  /* Note that we want to upload tracepoints and save those, rather
     than simply writing out the local ones, because the user may have
     changed tracepoints in GDB in preparation for a future tracing
     run, or maybe just mass-deleted all types of breakpoints as part
     of cleaning up.  So as not to contaminate the session, leave the
     data in its uploaded form, don't make into real tracepoints.  */

  /* Get trace state variables first, they may be checked when parsing
     uploaded commands.  */

  target_upload_trace_state_variables (&uploaded_tsvs);

  for (utsv = uploaded_tsvs; utsv; utsv = utsv->next)
    writer->ops->write_uploaded_tsv (writer, utsv);

  free_uploaded_tsvs (&uploaded_tsvs);

  target_upload_tracepoints (&uploaded_tps);

  for (utp = uploaded_tps; utp; utp = utp->next)
    target_get_tracepoint_status (NULL, utp);

  for (utp = uploaded_tps; utp; utp = utp->next)
    writer->ops->write_uploaded_tp (writer, utp);

  free_uploaded_tps (&uploaded_tps);

  /* Mark the end of the definition section.  */
  writer->ops->write_definition_end (writer);

  /* Get and write the trace data proper.  */
  while (1)
    {
      LONGEST gotten = 0;

      /* The writer supports writing the contents of trace buffer
	  directly to trace file.  Don't parse the contents of trace
	  buffer.  */
      if (writer->ops->write_trace_buffer != NULL)
	{
	  /* We ask for big blocks, in the hopes of efficiency, but
	     will take less if the target has packet size limitations
	     or some such.  */
	  gotten = target_get_raw_trace_data (buf, offset,
					      MAX_TRACE_UPLOAD);
	  if (gotten < 0)
	    error (_("Failure to get requested trace buffer data"));
	  /* No more data is forthcoming, we're done.  */
	  if (gotten == 0)
	    break;

	  writer->ops->write_trace_buffer (writer, buf, gotten);

	  offset += gotten;
	}
      else
	{
	  uint16_t tp_num;
	  uint32_t tf_size;
	  /* Parse the trace buffers according to how data are stored
	     in trace buffer in GDBserver.  */

	  gotten = target_get_raw_trace_data (buf, offset, 6);

	  if (gotten == 0)
	    break;

	  /* Read the first six bytes in, which is the tracepoint
	     number and trace frame size.  */
	  tp_num = (uint16_t)
	    extract_unsigned_integer (&buf[0], 2, byte_order);

	  tf_size = (uint32_t)
	    extract_unsigned_integer (&buf[2], 4, byte_order);

	  writer->ops->frame_ops->start (writer, tp_num);
	  gotten = 6;

	  if (tf_size > 0)
	    {
	      unsigned int block;

	      offset += 6;

	      for (block = 0; block < tf_size; )
		{
		  gdb_byte block_type;

		  /* We'll fetch one block each time, in order to
		     handle the extremely large 'M' block.  We first
		     fetch one byte to get the type of the block.  */
		  gotten = target_get_raw_trace_data (buf, offset, 1);
		  if (gotten < 1)
		    error (_("Failure to get requested trace buffer data"));

		  gotten = 1;
		  block += 1;
		  offset += 1;

		  block_type = buf[0];
		  switch (block_type)
		    {
		    case 'R':
		      gotten
			= target_get_raw_trace_data (buf, offset,
						     trace_regblock_size);
		      if (gotten < trace_regblock_size)
			error (_("Failure to get requested trace"
				 " buffer data"));

		      TRACE_WRITE_R_BLOCK (writer, buf,
					   trace_regblock_size);
		      break;
		    case 'M':
		      {
			unsigned short mlen;
			ULONGEST addr;
			LONGEST t;
			int j;

			t = target_get_raw_trace_data (buf,offset, 10);
			if (t < 10)
			  error (_("Failure to get requested trace"
				   " buffer data"));

			offset += 10;
			block += 10;

			gotten = 0;
			addr = (ULONGEST)
			  extract_unsigned_integer (buf, 8,
						    byte_order);
			mlen = (unsigned short)
			  extract_unsigned_integer (&buf[8], 2,
						    byte_order);

			TRACE_WRITE_M_BLOCK_HEADER (writer, addr,
						    mlen);

			/* The memory contents in 'M' block may be
			   very large.  Fetch the data from the target
			   and write them into file one by one.  */
			for (j = 0; j < mlen; )
			  {
			    unsigned int read_length;

			    if (mlen - j > MAX_TRACE_UPLOAD)
			      read_length = MAX_TRACE_UPLOAD;
			    else
			      read_length = mlen - j;

			    t = target_get_raw_trace_data (buf,
							   offset + j,
							   read_length);
			    if (t < read_length)
			      error (_("Failure to get requested"
				       " trace buffer data"));

			    TRACE_WRITE_M_BLOCK_MEMORY (writer, buf,
							read_length);

			    j += read_length;
			    gotten += read_length;
			  }

			break;
		      }
		    case 'V':
		      {
			int vnum;
			LONGEST val;

			gotten
			  = target_get_raw_trace_data (buf, offset,
						       12);
			if (gotten < 12)
			  error (_("Failure to get requested"
				   " trace buffer data"));

			vnum  = (int) extract_signed_integer (buf,
							      4,
							      byte_order);
			val
			  = extract_signed_integer (&buf[4], 8,
						    byte_order);

			TRACE_WRITE_V_BLOCK (writer, vnum, val);
		      }
		      break;
		    default:
		      error (_("Unknown block type '%c' (0x%x) in"
			       " trace frame"),
			     block_type, block_type);
		    }

		  block += gotten;
		  offset += gotten;
		}
	    }
	  else
	    offset += gotten;

	  writer->ops->frame_ops->end (writer);
	}
    }

  writer->ops->end (writer);
}
示例#22
0
文件: jv-lang.c 项目: NalaGinrut/gdb
static struct value *
evaluate_subexp_java (struct type *expect_type, struct expression *exp,
		      int *pos, enum noside noside)
{
  int pc = *pos;
  int i;
  const char *name;
  enum exp_opcode op = exp->elts[*pos].opcode;
  struct value *arg1;
  struct value *arg2;
  struct type *type;

  switch (op)
    {
    case UNOP_IND:
      if (noside == EVAL_SKIP)
	goto standard;
      (*pos)++;
      arg1 = evaluate_subexp_java (NULL_TYPE, exp, pos, EVAL_NORMAL);
      if (is_object_type (value_type (arg1)))
	{
	  struct type *type;

	  type = type_from_class (exp->gdbarch, java_class_from_object (arg1));
	  arg1 = value_cast (lookup_pointer_type (type), arg1);
	}
      return value_ind (arg1);

    case BINOP_SUBSCRIPT:
      (*pos)++;
      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
      if (noside == EVAL_SKIP)
	goto nosideret;
      /* If the user attempts to subscript something that is not an
         array or pointer type (like a plain int variable for example),
         then report this as an error.  */

      arg1 = coerce_ref (arg1);
      type = check_typedef (value_type (arg1));
      if (TYPE_CODE (type) == TYPE_CODE_PTR)
	type = check_typedef (TYPE_TARGET_TYPE (type));
      name = TYPE_NAME (type);
      if (name == NULL)
	name = TYPE_TAG_NAME (type);
      i = name == NULL ? 0 : strlen (name);
      if (TYPE_CODE (type) == TYPE_CODE_STRUCT
	  && i > 2 && name[i - 1] == ']')
	{
	  enum bfd_endian byte_order = gdbarch_byte_order (exp->gdbarch);
	  CORE_ADDR address;
	  long length, index;
	  struct type *el_type;
	  gdb_byte buf4[4];

	  struct value *clas = java_class_from_object (arg1);
	  struct value *temp = clas;
	  /* Get CLASS_ELEMENT_TYPE of the array type.  */
	  temp = value_struct_elt (&temp, NULL, "methods",
				   NULL, "structure");
	  deprecated_set_value_type (temp, value_type (clas));
	  el_type = type_from_class (exp->gdbarch, temp);
	  if (TYPE_CODE (el_type) == TYPE_CODE_STRUCT)
	    el_type = lookup_pointer_type (el_type);

	  if (noside == EVAL_AVOID_SIDE_EFFECTS)
	    return value_zero (el_type, VALUE_LVAL (arg1));
	  address = value_as_address (arg1);
	  address += get_java_object_header_size (exp->gdbarch);
	  read_memory (address, buf4, 4);
	  length = (long) extract_signed_integer (buf4, 4, byte_order);
	  index = (long) value_as_long (arg2);
	  if (index >= length || index < 0)
	    error (_("array index (%ld) out of bounds (length: %ld)"),
		   index, length);
	  address = (address + 4) + index * TYPE_LENGTH (el_type);
	  return value_at (el_type, address);
	}
      else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
	{
	  if (noside == EVAL_AVOID_SIDE_EFFECTS)
	    return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
	  else
	    return value_subscript (arg1, value_as_long (arg2));
	}
      if (name)
	error (_("cannot subscript something of type `%s'"), name);
      else
	error (_("cannot subscript requested type"));

    case OP_STRING:
      (*pos)++;
      i = longest_to_int (exp->elts[pc + 1].longconst);
      (*pos) += 3 + BYTES_TO_EXP_ELEM (i + 1);
      if (noside == EVAL_SKIP)
	goto nosideret;
      return java_value_string (&exp->elts[pc + 2].string, i);

    case STRUCTOP_PTR:
      arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
      /* Convert object field (such as TYPE.class) to reference.  */
      if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_STRUCT)
	arg1 = value_addr (arg1);
      return arg1;
    default:
      break;
    }
standard:
  return evaluate_subexp_standard (expect_type, exp, pos, noside);
nosideret:
  return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
}
示例#23
0
int
java_value_print (struct value *val, struct ui_file *stream, 
		  const struct value_print_options *options)
{
  struct gdbarch *gdbarch = get_type_arch (value_type (val));
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  struct type *type;
  CORE_ADDR address;
  int i;
  char *name;
  struct value_print_options opts;

  type = value_type (val);
  address = value_address (val);

  if (is_object_type (type))
    {
      CORE_ADDR obj_addr;

      /* Get the run-time type, and cast the object into that */

      obj_addr = unpack_pointer (type, value_contents (val));

      if (obj_addr != 0)
	{
	  type = type_from_class (gdbarch, java_class_from_object (val));
	  type = lookup_pointer_type (type);

	  val = value_at (type, address);
	}
    }

  if (TYPE_CODE (type) == TYPE_CODE_PTR && !value_logical_not (val))
    type_print (TYPE_TARGET_TYPE (type), "", stream, -1);

  name = TYPE_TAG_NAME (type);
  if (TYPE_CODE (type) == TYPE_CODE_STRUCT && name != NULL
      && (i = strlen (name), name[i - 1] == ']'))
    {
      gdb_byte buf4[4];
      long length;
      unsigned int things_printed = 0;
      int reps;
      struct type *el_type
	= java_primitive_type_from_name (gdbarch, name, i - 2);
      i = 0;
      read_memory (address + get_java_object_header_size (gdbarch), buf4, 4);

      length = (long) extract_signed_integer (buf4, 4, byte_order);
      fprintf_filtered (stream, "{length: %ld", length);

      if (el_type == NULL)
	{
	  CORE_ADDR element;
	  CORE_ADDR next_element = -1; /* dummy initial value */

	  /* Skip object header and length. */
	  address += get_java_object_header_size (gdbarch) + 4;

	  while (i < length && things_printed < options->print_max)
	    {
	      gdb_byte *buf;

	      buf = alloca (gdbarch_ptr_bit (gdbarch) / HOST_CHAR_BIT);
	      fputs_filtered (", ", stream);
	      wrap_here (n_spaces (2));

	      if (i > 0)
		element = next_element;
	      else
		{
		  read_memory (address, buf, sizeof (buf));
		  address += gdbarch_ptr_bit (gdbarch) / HOST_CHAR_BIT;
		  /* FIXME: cagney/2003-05-24: Bogus or what.  It
                     pulls a host sized pointer out of the target and
                     then extracts that as an address (while assuming
                     that the address is unsigned)!  */
		  element = extract_unsigned_integer (buf, sizeof (buf),
						      byte_order);
		}

	      for (reps = 1; i + reps < length; reps++)
		{
		  read_memory (address, buf, sizeof (buf));
		  address += gdbarch_ptr_bit (gdbarch) / HOST_CHAR_BIT;
		  /* FIXME: cagney/2003-05-24: Bogus or what.  It
                     pulls a host sized pointer out of the target and
                     then extracts that as an address (while assuming
                     that the address is unsigned)!  */
		  next_element = extract_unsigned_integer (buf, sizeof (buf),
							   byte_order);
		  if (next_element != element)
		    break;
		}

	      if (reps == 1)
		fprintf_filtered (stream, "%d: ", i);
	      else
		fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1);

	      if (element == 0)
		fprintf_filtered (stream, "null");
	      else
		fprintf_filtered (stream, "@%s", paddress (gdbarch, element));

	      things_printed++;
	      i += reps;
	    }
	}
      else
	{
	  struct value *v = allocate_value (el_type);
	  struct value *next_v = allocate_value (el_type);

	  set_value_address (v, (address
				 + get_java_object_header_size (gdbarch) + 4));
	  set_value_address (next_v, value_raw_address (v));

	  while (i < length && things_printed < options->print_max)
	    {
	      fputs_filtered (", ", stream);
	      wrap_here (n_spaces (2));

	      if (i > 0)
		{
		  struct value *tmp;

		  tmp = next_v;
		  next_v = v;
		  v = tmp;
		}
	      else
		{
		  set_value_lazy (v, 1);
		  set_value_offset (v, 0);
		}

	      set_value_offset (next_v, value_offset (v));

	      for (reps = 1; i + reps < length; reps++)
		{
		  set_value_lazy (next_v, 1);
		  set_value_offset (next_v, value_offset (next_v) + TYPE_LENGTH (el_type));
		  if (memcmp (value_contents (v), value_contents (next_v),
			      TYPE_LENGTH (el_type)) != 0)
		    break;
		}

	      if (reps == 1)
		fprintf_filtered (stream, "%d: ", i);
	      else
		fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1);

	      opts = *options;
	      opts.deref_ref = 1;
	      common_val_print (v, stream, 1, &opts, current_language);

	      things_printed++;
	      i += reps;
	    }
	}

      if (i < length)
	fprintf_filtered (stream, "...");

      fprintf_filtered (stream, "}");

      return 0;
    }

  /* If it's type String, print it */

  if (TYPE_CODE (type) == TYPE_CODE_PTR
      && TYPE_TARGET_TYPE (type)
      && TYPE_TAG_NAME (TYPE_TARGET_TYPE (type))
      && strcmp (TYPE_TAG_NAME (TYPE_TARGET_TYPE (type)),
		 "java.lang.String") == 0
      && (options->format == 0 || options->format == 's')
      && address != 0
      && value_as_address (val) != 0)
    {
      struct type *char_type;
      struct value *data_val;
      CORE_ADDR data;
      struct value *boffset_val;
      unsigned long boffset;
      struct value *count_val;
      unsigned long count;
      struct value *mark;

      mark = value_mark ();	/* Remember start of new values */

      data_val = value_struct_elt (&val, NULL, "data", NULL, NULL);
      data = value_as_address (data_val);

      boffset_val = value_struct_elt (&val, NULL, "boffset", NULL, NULL);
      boffset = value_as_address (boffset_val);

      count_val = value_struct_elt (&val, NULL, "count", NULL, NULL);
      count = value_as_address (count_val);

      value_free_to_mark (mark);	/* Release unnecessary values */

      char_type = builtin_java_type (gdbarch)->builtin_char;
      val_print_string (char_type, data + boffset, count, stream, options);

      return 0;
    }

  opts = *options;
  opts.deref_ref = 1;
  return common_val_print (val, stream, 0, &opts, current_language);
}
示例#24
0
文件: scm-exp.c 项目: davearrama/gdb
static void
scm_lreadr (int skipping)
{
  int c, j;
  struct stoken str;
  LONGEST svalue = 0;
tryagain:
  c = *lexptr++;
  switch (c)
    {
    case '\0':
      lexptr--;
      return;
    case '[':
    case '(':
      scm_lreadparen (skipping);
      return;
    case ']':
    case ')':
      error ("unexpected #\\%c", c);
      goto tryagain;
    case '\'':
    case '`':
      str.ptr = lexptr - 1;
      scm_lreadr (skipping);
      if (!skipping)
	{
	  struct value *val = scm_evaluate_string (str.ptr, lexptr - str.ptr);
	  if (!is_scmvalue_type (value_type (val)))
	    error ("quoted scm form yields non-SCM value");
	  svalue = extract_signed_integer (value_contents (val),
					   TYPE_LENGTH (value_type (val)));
	  goto handle_immediate;
	}
      return;
    case ',':
      c = *lexptr++;
      if ('@' != c)
	lexptr--;
      scm_lreadr (skipping);
      return;
    case '#':
      c = *lexptr++;
      switch (c)
	{
	case '[':
	case '(':
	  scm_lreadparen (skipping);
	  return;
	case 't':
	case 'T':
	  svalue = SCM_BOOL_T;
	  goto handle_immediate;
	case 'f':
	case 'F':
	  svalue = SCM_BOOL_F;
	  goto handle_immediate;
	case 'b':
	case 'B':
	case 'o':
	case 'O':
	case 'd':
	case 'D':
	case 'x':
	case 'X':
	case 'i':
	case 'I':
	case 'e':
	case 'E':
	  lexptr--;
	  c = '#';
	  goto num;
	case '*':		/* bitvector */
	  scm_read_token (c, 0);
	  return;
	case '{':
	  scm_read_token (c, 1);
	  return;
	case '\\':		/* character */
	  c = *lexptr++;
	  scm_read_token (c, 0);
	  return;
	case '|':
	  j = 1;		/* here j is the comment nesting depth */
	lp:
	  c = *lexptr++;
	lpc:
	  switch (c)
	    {
	    case '\0':
	      error ("unbalanced comment");
	    default:
	      goto lp;
	    case '|':
	      if ('#' != (c = *lexptr++))
		goto lpc;
	      if (--j)
		goto lp;
	      break;
	    case '#':
	      if ('|' != (c = *lexptr++))
		goto lpc;
	      ++j;
	      goto lp;
	    }
	  goto tryagain;
	case '.':
	default:
#if 0
	callshrp:
#endif
	  scm_lreadr (skipping);
	  return;
	}
    case '\"':
      while ('\"' != (c = *lexptr++))
	{
	  if (c == '\\')
	    switch (c = *lexptr++)
	      {
	      case '\0':
		error ("non-terminated string literal");
	      case '\n':
		continue;
	      case '0':
	      case 'f':
	      case 'n':
	      case 'r':
	      case 't':
	      case 'a':
	      case 'v':
		break;
	      }
	}
      return;
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    case '.':
    case '-':
    case '+':
    num:
      {
	str.ptr = lexptr - 1;
	scm_read_token (c, 0);
	if (!skipping)
	  {
	    svalue = scm_istring2number (str.ptr, lexptr - str.ptr, 10);
	    if (svalue != SCM_BOOL_F)
	      goto handle_immediate;
	    goto tok;
	  }
      }
      return;
    case ':':
      scm_read_token ('-', 0);
      return;
#if 0
    do_symbol:
#endif
    default:
      str.ptr = lexptr - 1;
      scm_read_token (c, 0);
    tok:
      if (!skipping)
	{
	  str.length = lexptr - str.ptr;
	  if (str.ptr[0] == '$')
	    {
	      write_dollar_variable (str);
	      return;
	    }
	  write_exp_elt_opcode (OP_NAME);
	  write_exp_string (str);
	  write_exp_elt_opcode (OP_NAME);
	}
      return;
    }
handle_immediate:
  if (!skipping)
    {
      write_exp_elt_opcode (OP_LONG);
      write_exp_elt_type (builtin_type_scm);
      write_exp_elt_longcst (svalue);
      write_exp_elt_opcode (OP_LONG);
    }
}
示例#25
0
int
java_value_print (struct value *val, struct ui_file *stream, int format,
		  enum val_prettyprint pretty)
{
  struct type *type;
  CORE_ADDR address;
  int i;
  char *name;

  type = VALUE_TYPE (val);
  address = VALUE_ADDRESS (val) + VALUE_OFFSET (val);

  if (is_object_type (type))
    {
      CORE_ADDR obj_addr;

      /* Get the run-time type, and cast the object into that */

      obj_addr = unpack_pointer (type, VALUE_CONTENTS (val));

      if (obj_addr != 0)
	{
	  type = type_from_class (java_class_from_object (val));
	  type = lookup_pointer_type (type);

	  val = value_at (type, address, NULL);
	}
    }

  if (TYPE_CODE (type) == TYPE_CODE_PTR && !value_logical_not (val))
    type_print (TYPE_TARGET_TYPE (type), "", stream, -1);

  name = TYPE_TAG_NAME (type);
  if (TYPE_CODE (type) == TYPE_CODE_STRUCT && name != NULL
      && (i = strlen (name), name[i - 1] == ']'))
    {
      char buf4[4];
      long length;
      unsigned int things_printed = 0;
      int reps;
      struct type *el_type = java_primitive_type_from_name (name, i - 2);

      i = 0;
      read_memory (address + JAVA_OBJECT_SIZE, buf4, 4);

      length = (long) extract_signed_integer (buf4, 4);
      fprintf_filtered (stream, "{length: %ld", length);

      if (el_type == NULL)
	{
	  CORE_ADDR element;
	  CORE_ADDR next_element = -1; /* dummy initial value */

	  address += JAVA_OBJECT_SIZE + 4;	/* Skip object header and length. */

	  while (i < length && things_printed < print_max)
	    {
	      char *buf;

	      buf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT);
	      fputs_filtered (", ", stream);
	      wrap_here (n_spaces (2));

	      if (i > 0)
		element = next_element;
	      else
		{
		  read_memory (address, buf, sizeof (buf));
		  address += TARGET_PTR_BIT / HOST_CHAR_BIT;
		  element = extract_address (buf, sizeof (buf));
		}

	      for (reps = 1; i + reps < length; reps++)
		{
		  read_memory (address, buf, sizeof (buf));
		  address += TARGET_PTR_BIT / HOST_CHAR_BIT;
		  next_element = extract_address (buf, sizeof (buf));
		  if (next_element != element)
		    break;
		}

	      if (reps == 1)
		fprintf_filtered (stream, "%d: ", i);
	      else
		fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1);

	      if (element == 0)
		fprintf_filtered (stream, "null");
	      else
		fprintf_filtered (stream, "@%s", paddr_nz (element));

	      things_printed++;
	      i += reps;
	    }
	}
      else
	{
	  struct value *v = allocate_value (el_type);
	  struct value *next_v = allocate_value (el_type);

	  VALUE_ADDRESS (v) = address + JAVA_OBJECT_SIZE + 4;
	  VALUE_ADDRESS (next_v) = VALUE_ADDRESS (v);

	  while (i < length && things_printed < print_max)
	    {
	      fputs_filtered (", ", stream);
	      wrap_here (n_spaces (2));

	      if (i > 0)
		{
		  struct value *tmp;

		  tmp = next_v;
		  next_v = v;
		  v = tmp;
		}
	      else
		{
		  VALUE_LAZY (v) = 1;
		  VALUE_OFFSET (v) = 0;
		}

	      VALUE_OFFSET (next_v) = VALUE_OFFSET (v);

	      for (reps = 1; i + reps < length; reps++)
		{
		  VALUE_LAZY (next_v) = 1;
		  VALUE_OFFSET (next_v) += TYPE_LENGTH (el_type);
		  if (memcmp (VALUE_CONTENTS (v), VALUE_CONTENTS (next_v),
			      TYPE_LENGTH (el_type)) != 0)
		    break;
		}

	      if (reps == 1)
		fprintf_filtered (stream, "%d: ", i);
	      else
		fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1);

	      val_print (VALUE_TYPE (v), VALUE_CONTENTS (v), 0, 0,
			 stream, format, 2, 1, pretty);

	      things_printed++;
	      i += reps;
	    }
	}

      if (i < length)
	fprintf_filtered (stream, "...");

      fprintf_filtered (stream, "}");

      return 0;
    }

  /* If it's type String, print it */

  if (TYPE_CODE (type) == TYPE_CODE_PTR
      && TYPE_TARGET_TYPE (type)
      && TYPE_NAME (TYPE_TARGET_TYPE (type))
      && strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "java.lang.String") == 0
      && (format == 0 || format == 's')
      && address != 0
      && value_as_address (val) != 0)
    {
      struct value *data_val;
      CORE_ADDR data;
      struct value *boffset_val;
      unsigned long boffset;
      struct value *count_val;
      unsigned long count;
      struct value *mark;

      mark = value_mark ();	/* Remember start of new values */

      data_val = value_struct_elt (&val, NULL, "data", NULL, NULL);
      data = value_as_address (data_val);

      boffset_val = value_struct_elt (&val, NULL, "boffset", NULL, NULL);
      boffset = value_as_address (boffset_val);

      count_val = value_struct_elt (&val, NULL, "count", NULL, NULL);
      count = value_as_address (count_val);

      value_free_to_mark (mark);	/* Release unnecessary values */

      val_print_string (data + boffset, count, 2, stream);

      return 0;
    }

  return (val_print (type, VALUE_CONTENTS (val), 0, address,
		     stream, format, 1, 0, pretty));
}
void
mips64_fill_fpregset (const struct regcache *regcache,
		      mips64_elf_fpregset_t *fpregsetp, int regno)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  gdb_byte *to;

  if ((regno >= gdbarch_fp0_regnum (gdbarch))
      && (regno < gdbarch_fp0_regnum (gdbarch) + 32))
    {
      /* See mips_linux_o32_sigframe_init for a description of the
	 peculiar FP register layout.  */
      if (register_size (gdbarch, regno) == 4)
	{
	  int regi = regno - gdbarch_fp0_regnum (gdbarch);

	  to = (gdb_byte *) (*fpregsetp + (regi & ~1));
	  if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (regi & 1))
	    to += 4;
	  regcache_raw_collect (regcache, regno, to);
	}
      else
	{
	  to = (gdb_byte *) (*fpregsetp + regno - gdbarch_fp0_regnum (gdbarch));
	  regcache_raw_collect (regcache, regno, to);
	}
    }
  else if (regno == mips_regnum (gdbarch)->fp_control_status)
    {
      gdb_byte buf[MAX_REGISTER_SIZE];
      LONGEST val;

      regcache_raw_collect (regcache, regno, buf);
      val = extract_signed_integer (buf, register_size (gdbarch, regno),
				    byte_order);
      to = (gdb_byte *) (*fpregsetp + 32);
      store_signed_integer (to, 4, byte_order, val);
    }
  else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
    {
      gdb_byte buf[MAX_REGISTER_SIZE];
      LONGEST val;

      regcache_raw_collect (regcache, regno, buf);
      val = extract_signed_integer (buf, register_size (gdbarch, regno),
				    byte_order);
      to = (gdb_byte *) (*fpregsetp + 32) + 4;
      store_signed_integer (to, 4, byte_order, val);
    }
  else if (regno == -1)
    {
      int regi;

      for (regi = 0; regi < 32; regi++)
	mips64_fill_fpregset (regcache, fpregsetp,
			      gdbarch_fp0_regnum (gdbarch) + regi);
      mips64_fill_fpregset (regcache, fpregsetp,
			    mips_regnum (gdbarch)->fp_control_status);
      mips64_fill_fpregset (regcache, fpregsetp,
			    (mips_regnum (gdbarch)
			      ->fp_implementation_revision));
    }
}
示例#27
0
static CORE_ADDR
mn10300_analyze_prologue (struct frame_info *fi, 
			  void **this_cache, 
			  CORE_ADDR pc)
{
  CORE_ADDR func_addr, func_end, addr, stop;
  long      stack_size;
  int imm_size;
  unsigned char buf[4];
  int status, movm_args = 0;
  char *name;

  /* Use the PC in the frame if it's provided to look up the
     start of this function.

     Note: kevinb/2003-07-16: We used to do the following here:
	pc = (fi ? get_frame_pc (fi) : pc);
     But this is (now) badly broken when called from analyze_dummy_frame().
  */
  if (fi)
    {
      pc = (pc ? pc : get_frame_pc (fi));
      /* At the start of a function our frame is in the stack pointer.  */
      my_frame_is_in_sp (fi, this_cache);
    }

  /* Find the start of this function.  */
  status = find_pc_partial_function (pc, &name, &func_addr, &func_end);

  /* Do nothing if we couldn't find the start of this function 

     MVS: comment went on to say "or if we're stopped at the first
     instruction in the prologue" -- but code doesn't reflect that, 
     and I don't want to do that anyway.  */
  if (status == 0)
    {
      return pc;
    }

  /* If we're in start, then give up.  */
  if (strcmp (name, "start") == 0)
    {
      if (fi != NULL)
	my_frame_is_last (fi);
      return pc;
    }

#if 0
  /* Get the next two bytes into buf, we need two because rets is a two
     byte insn and the first isn't enough to uniquely identify it.  */
  status = deprecated_read_memory_nobpt (pc, buf, 2);
  if (status != 0)
    return pc;

  /* Note: kevinb/2003-07-16: We shouldn't be making these sorts of
     changes to the frame in prologue examination code.  */
  /* If we're physically on an "rets" instruction, then our frame has
     already been deallocated.  Note this can also be true for retf
     and ret if they specify a size of zero.

     In this case fi->frame is bogus, we need to fix it.  */
  if (fi && buf[0] == 0xf0 && buf[1] == 0xfc)
    {
      if (get_next_frame (fi) == NULL)
	deprecated_update_frame_base_hack (fi, read_sp ());
      return get_frame_pc (fi);
    }

  /* Similarly if we're stopped on the first insn of a prologue as our
     frame hasn't been allocated yet.  */
  if (fi && get_frame_pc (fi) == func_addr)
    {
      if (get_next_frame (fi) == NULL)
	deprecated_update_frame_base_hack (fi, read_sp ());
      return get_frame_pc (fi);
    }
#endif

  /* NOTE: from here on, we don't want to return without jumping to
     finish_prologue.  */


  /* Figure out where to stop scanning.  */
  stop = fi ? pc : func_end;

  /* Don't walk off the end of the function.  */
  stop = stop > func_end ? func_end : stop;

  /* Start scanning on the first instruction of this function.  */
  addr = func_addr;

  /* Suck in two bytes.  */
  if (addr + 2 >= stop
      || (status = deprecated_read_memory_nobpt (addr, buf, 2)) != 0)
    goto finish_prologue;

  /* First see if this insn sets the stack pointer from a register; if
     so, it's probably the initialization of the stack pointer in _start,
     so mark this as the bottom-most frame.  */
  if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0)
    {
      if (fi)
	my_frame_is_last (fi);
      goto finish_prologue;
    }

  /* Now look for movm [regs],sp, which saves the callee saved registers.

     At this time we don't know if fi->frame is valid, so we only note
     that we encountered a movm instruction.  Later, we'll set the entries
     in fsr.regs as needed.  */
  if (buf[0] == 0xcf)
    {
      /* Extract the register list for the movm instruction.  */
      movm_args = buf[1];

      addr += 2;

      /* Quit now if we're beyond the stop point.  */
      if (addr >= stop)
	goto finish_prologue;

      /* Get the next two bytes so the prologue scan can continue.  */
      status = deprecated_read_memory_nobpt (addr, buf, 2);
      if (status != 0)
	goto finish_prologue;
    }

  /* Now see if we set up a frame pointer via "mov sp,a3" */
  if (buf[0] == 0x3f)
    {
      addr += 1;

      /* The frame pointer is now valid.  */
      if (fi)
	{
	  my_frame_is_in_fp (fi, this_cache);
	}

      /* Quit now if we're beyond the stop point.  */
      if (addr >= stop)
	goto finish_prologue;

      /* Get two more bytes so scanning can continue.  */
      status = deprecated_read_memory_nobpt (addr, buf, 2);
      if (status != 0)
	goto finish_prologue;
    }

  /* Next we should allocate the local frame.  No more prologue insns
     are found after allocating the local frame.

     Search for add imm8,sp (0xf8feXX)
     or add imm16,sp (0xfafeXXXX)
     or add imm32,sp (0xfcfeXXXXXXXX).

     If none of the above was found, then this prologue has no 
     additional stack.  */

  imm_size = 0;
  if (buf[0] == 0xf8 && buf[1] == 0xfe)
    imm_size = 1;
  else if (buf[0] == 0xfa && buf[1] == 0xfe)
    imm_size = 2;
  else if (buf[0] == 0xfc && buf[1] == 0xfe)
    imm_size = 4;

  if (imm_size != 0)
    {
      /* Suck in imm_size more bytes, they'll hold the size of the
         current frame.  */
      status = deprecated_read_memory_nobpt (addr + 2, buf, imm_size);
      if (status != 0)
	goto finish_prologue;

      /* Note the size of the stack in the frame info structure.  */
      stack_size = extract_signed_integer (buf, imm_size);
      if (fi)
	set_my_stack_size (fi, stack_size);

      /* We just consumed 2 + imm_size bytes.  */
      addr += 2 + imm_size;

      /* No more prologue insns follow, so begin preparation to return.  */
      goto finish_prologue;
    }
  /* Do the essentials and get out of here.  */
 finish_prologue:
  /* Note if/where callee saved registers were saved.  */
  if (fi)
    set_movm_offsets (fi, this_cache, movm_args);
  return addr;
}
示例#28
0
文件: dwarf2expr.c 项目: DonCN/haiku
static void
execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
		  unsigned char *op_end)
{
  ctx->in_reg = 0;

  while (op_ptr < op_end)
    {
      enum dwarf_location_atom op = *op_ptr++;
      CORE_ADDR result;
      ULONGEST uoffset, reg;
      LONGEST offset;
      int bytes_read;

      switch (op)
	{
	case DW_OP_lit0:
	case DW_OP_lit1:
	case DW_OP_lit2:
	case DW_OP_lit3:
	case DW_OP_lit4:
	case DW_OP_lit5:
	case DW_OP_lit6:
	case DW_OP_lit7:
	case DW_OP_lit8:
	case DW_OP_lit9:
	case DW_OP_lit10:
	case DW_OP_lit11:
	case DW_OP_lit12:
	case DW_OP_lit13:
	case DW_OP_lit14:
	case DW_OP_lit15:
	case DW_OP_lit16:
	case DW_OP_lit17:
	case DW_OP_lit18:
	case DW_OP_lit19:
	case DW_OP_lit20:
	case DW_OP_lit21:
	case DW_OP_lit22:
	case DW_OP_lit23:
	case DW_OP_lit24:
	case DW_OP_lit25:
	case DW_OP_lit26:
	case DW_OP_lit27:
	case DW_OP_lit28:
	case DW_OP_lit29:
	case DW_OP_lit30:
	case DW_OP_lit31:
	  result = op - DW_OP_lit0;
	  break;

	case DW_OP_addr:
	  result = dwarf2_read_address (op_ptr, op_end, &bytes_read);
	  op_ptr += bytes_read;
	  break;

	case DW_OP_const1u:
	  result = extract_unsigned_integer (op_ptr, 1);
	  op_ptr += 1;
	  break;
	case DW_OP_const1s:
	  result = extract_signed_integer (op_ptr, 1);
	  op_ptr += 1;
	  break;
	case DW_OP_const2u:
	  result = extract_unsigned_integer (op_ptr, 2);
	  op_ptr += 2;
	  break;
	case DW_OP_const2s:
	  result = extract_signed_integer (op_ptr, 2);
	  op_ptr += 2;
	  break;
	case DW_OP_const4u:
	  result = extract_unsigned_integer (op_ptr, 4);
	  op_ptr += 4;
	  break;
	case DW_OP_const4s:
	  result = extract_signed_integer (op_ptr, 4);
	  op_ptr += 4;
	  break;
	case DW_OP_const8u:
	  result = extract_unsigned_integer (op_ptr, 8);
	  op_ptr += 8;
	  break;
	case DW_OP_const8s:
	  result = extract_signed_integer (op_ptr, 8);
	  op_ptr += 8;
	  break;
	case DW_OP_constu:
	  op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
	  result = uoffset;
	  break;
	case DW_OP_consts:
	  op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	  result = offset;
	  break;

	/* The DW_OP_reg operations are required to occur alone in
	   location expressions.  */
	case DW_OP_reg0:
	case DW_OP_reg1:
	case DW_OP_reg2:
	case DW_OP_reg3:
	case DW_OP_reg4:
	case DW_OP_reg5:
	case DW_OP_reg6:
	case DW_OP_reg7:
	case DW_OP_reg8:
	case DW_OP_reg9:
	case DW_OP_reg10:
	case DW_OP_reg11:
	case DW_OP_reg12:
	case DW_OP_reg13:
	case DW_OP_reg14:
	case DW_OP_reg15:
	case DW_OP_reg16:
	case DW_OP_reg17:
	case DW_OP_reg18:
	case DW_OP_reg19:
	case DW_OP_reg20:
	case DW_OP_reg21:
	case DW_OP_reg22:
	case DW_OP_reg23:
	case DW_OP_reg24:
	case DW_OP_reg25:
	case DW_OP_reg26:
	case DW_OP_reg27:
	case DW_OP_reg28:
	case DW_OP_reg29:
	case DW_OP_reg30:
	case DW_OP_reg31:
	  if (op_ptr != op_end && *op_ptr != DW_OP_piece)
	    error ("DWARF-2 expression error: DW_OP_reg operations must be "
		   "used either alone or in conjuction with DW_OP_piece.");

	  result = op - DW_OP_reg0;
	  ctx->in_reg = 1;

	  break;

	case DW_OP_regx:
	  op_ptr = read_uleb128 (op_ptr, op_end, &reg);
	  if (op_ptr != op_end && *op_ptr != DW_OP_piece)
	    error ("DWARF-2 expression error: DW_OP_reg operations must be "
		   "used either alone or in conjuction with DW_OP_piece.");

	  result = reg;
	  ctx->in_reg = 1;
	  break;

	case DW_OP_breg0:
	case DW_OP_breg1:
	case DW_OP_breg2:
	case DW_OP_breg3:
	case DW_OP_breg4:
	case DW_OP_breg5:
	case DW_OP_breg6:
	case DW_OP_breg7:
	case DW_OP_breg8:
	case DW_OP_breg9:
	case DW_OP_breg10:
	case DW_OP_breg11:
	case DW_OP_breg12:
	case DW_OP_breg13:
	case DW_OP_breg14:
	case DW_OP_breg15:
	case DW_OP_breg16:
	case DW_OP_breg17:
	case DW_OP_breg18:
	case DW_OP_breg19:
	case DW_OP_breg20:
	case DW_OP_breg21:
	case DW_OP_breg22:
	case DW_OP_breg23:
	case DW_OP_breg24:
	case DW_OP_breg25:
	case DW_OP_breg26:
	case DW_OP_breg27:
	case DW_OP_breg28:
	case DW_OP_breg29:
	case DW_OP_breg30:
	case DW_OP_breg31:
	  {
	    op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	    result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0);
	    result += offset;
	  }
	  break;
	case DW_OP_bregx:
	  {
	    op_ptr = read_uleb128 (op_ptr, op_end, &reg);
	    op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	    result = (ctx->read_reg) (ctx->baton, reg);
	    result += offset;
	  }
	  break;
	case DW_OP_fbreg:
	  {
	    unsigned char *datastart;
	    size_t datalen;
	    unsigned int before_stack_len;

	    op_ptr = read_sleb128 (op_ptr, op_end, &offset);
	    /* Rather than create a whole new context, we simply
	       record the stack length before execution, then reset it
	       afterwards, effectively erasing whatever the recursive
	       call put there.  */
	    before_stack_len = ctx->stack_len;
	    /* FIXME: cagney/2003-03-26: This code should be using
               get_frame_base_address(), and then implement a dwarf2
               specific this_base method.  */
	    (ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
	    dwarf_expr_eval (ctx, datastart, datalen);
	    result = dwarf_expr_fetch (ctx, 0);
	    if (ctx->in_reg)
	      result = (ctx->read_reg) (ctx->baton, result);
	    result = result + offset;
	    ctx->stack_len = before_stack_len;
	    ctx->in_reg = 0;
	  }
	  break;
	case DW_OP_dup:
	  result = dwarf_expr_fetch (ctx, 0);
	  break;

	case DW_OP_drop:
	  dwarf_expr_pop (ctx);
	  goto no_push;

	case DW_OP_pick:
	  offset = *op_ptr++;
	  result = dwarf_expr_fetch (ctx, offset);
	  break;

	case DW_OP_over:
	  result = dwarf_expr_fetch (ctx, 1);
	  break;

	case DW_OP_rot:
	  {
	    CORE_ADDR t1, t2, t3;

	    if (ctx->stack_len < 3)
	       error ("Not enough elements for DW_OP_rot. Need 3, have %d\n",
		      ctx->stack_len);
	    t1 = ctx->stack[ctx->stack_len - 1];
	    t2 = ctx->stack[ctx->stack_len - 2];
	    t3 = ctx->stack[ctx->stack_len - 3];
	    ctx->stack[ctx->stack_len - 1] = t2;
	    ctx->stack[ctx->stack_len - 2] = t3;
	    ctx->stack[ctx->stack_len - 3] = t1;
	    goto no_push;
	  }

	case DW_OP_deref:
	case DW_OP_deref_size:
	case DW_OP_abs:
	case DW_OP_neg:
	case DW_OP_not:
	case DW_OP_plus_uconst:
	  /* Unary operations.  */
	  result = dwarf_expr_fetch (ctx, 0);
	  dwarf_expr_pop (ctx);

	  switch (op)
	    {
	    case DW_OP_deref:
	      {
		char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
		int bytes_read;

		(ctx->read_mem) (ctx->baton, buf, result,
				 TARGET_ADDR_BIT / TARGET_CHAR_BIT);
		result = dwarf2_read_address (buf,
					      buf + (TARGET_ADDR_BIT
						     / TARGET_CHAR_BIT),
					      &bytes_read);
	      }
	      break;

	    case DW_OP_deref_size:
	      {
		char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
		int bytes_read;

		(ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
		result = dwarf2_read_address (buf,
					      buf + (TARGET_ADDR_BIT
						     / TARGET_CHAR_BIT),
					      &bytes_read);
	      }
	      break;

	    case DW_OP_abs:
	      if ((signed int) result < 0)
		result = -result;
	      break;
	    case DW_OP_neg:
	      result = -result;
	      break;
	    case DW_OP_not:
	      result = ~result;
	      break;
	    case DW_OP_plus_uconst:
	      op_ptr = read_uleb128 (op_ptr, op_end, &reg);
	      result += reg;
	      break;
	    }
	  break;

	case DW_OP_and:
	case DW_OP_div:
	case DW_OP_minus:
	case DW_OP_mod:
	case DW_OP_mul:
	case DW_OP_or:
	case DW_OP_plus:
	case DW_OP_shl:
	case DW_OP_shr:
	case DW_OP_shra:
	case DW_OP_xor:
	case DW_OP_le:
	case DW_OP_ge:
	case DW_OP_eq:
	case DW_OP_lt:
	case DW_OP_gt:
	case DW_OP_ne:
	  {
	    /* Binary operations.  Use the value engine to do computations in
	       the right width.  */
	    CORE_ADDR first, second;
	    enum exp_opcode binop;
	    struct value *val1, *val2;

	    second = dwarf_expr_fetch (ctx, 0);
	    dwarf_expr_pop (ctx);

	    first = dwarf_expr_fetch (ctx, 0);
	    dwarf_expr_pop (ctx);

	    val1 = value_from_longest (unsigned_address_type (), first);
	    val2 = value_from_longest (unsigned_address_type (), second);

	    switch (op)
	      {
	      case DW_OP_and:
		binop = BINOP_BITWISE_AND;
		break;
	      case DW_OP_div:
		binop = BINOP_DIV;
                break;
	      case DW_OP_minus:
		binop = BINOP_SUB;
		break;
	      case DW_OP_mod:
		binop = BINOP_MOD;
		break;
	      case DW_OP_mul:
		binop = BINOP_MUL;
		break;
	      case DW_OP_or:
		binop = BINOP_BITWISE_IOR;
		break;
	      case DW_OP_plus:
		binop = BINOP_ADD;
		break;
	      case DW_OP_shl:
		binop = BINOP_LSH;
		break;
	      case DW_OP_shr:
		binop = BINOP_RSH;
                break;
	      case DW_OP_shra:
		binop = BINOP_RSH;
		val1 = value_from_longest (signed_address_type (), first);
		break;
	      case DW_OP_xor:
		binop = BINOP_BITWISE_XOR;
		break;
	      case DW_OP_le:
		binop = BINOP_LEQ;
		break;
	      case DW_OP_ge:
		binop = BINOP_GEQ;
		break;
	      case DW_OP_eq:
		binop = BINOP_EQUAL;
		break;
	      case DW_OP_lt:
		binop = BINOP_LESS;
		break;
	      case DW_OP_gt:
		binop = BINOP_GTR;
		break;
	      case DW_OP_ne:
		binop = BINOP_NOTEQUAL;
		break;
	      default:
		internal_error (__FILE__, __LINE__,
				"Can't be reached.");
	      }
	    result = value_as_long (value_binop (val1, val2, binop));
	  }
	  break;

	case DW_OP_GNU_push_tls_address:
	  /* Variable is at a constant offset in the thread-local
	  storage block into the objfile for the current thread and
	  the dynamic linker module containing this expression. Here
	  we return returns the offset from that base.  The top of the
	  stack has the offset from the beginning of the thread
	  control block at which the variable is located.  Nothing
	  should follow this operator, so the top of stack would be
	  returned.  */
	  result = dwarf_expr_fetch (ctx, 0);
	  dwarf_expr_pop (ctx);
	  result = (ctx->get_tls_address) (ctx->baton, result);
	  break;

	case DW_OP_skip:
	  offset = extract_signed_integer (op_ptr, 2);
	  op_ptr += 2;
	  op_ptr += offset;
	  goto no_push;

	case DW_OP_bra:
	  offset = extract_signed_integer (op_ptr, 2);
	  op_ptr += 2;
	  if (dwarf_expr_fetch (ctx, 0) != 0)
	    op_ptr += offset;
	  dwarf_expr_pop (ctx);
	  goto no_push;

	case DW_OP_nop:
	  goto no_push;

        case DW_OP_piece:
          {
            ULONGEST size;
            CORE_ADDR addr_or_regnum;

            /* Record the piece.  */
            op_ptr = read_uleb128 (op_ptr, op_end, &size);
            addr_or_regnum = dwarf_expr_fetch (ctx, 0);
            add_piece (ctx, ctx->in_reg, addr_or_regnum, size);

            /* Pop off the address/regnum, and clear the in_reg flag.  */
            dwarf_expr_pop (ctx);
            ctx->in_reg = 0;
          }
          goto no_push;

	default:
	  error ("Unhandled dwarf expression opcode 0x%x", op);
	}

      /* Most things push a result value.  */
      dwarf_expr_push (ctx, result);
    no_push:;
    }
}
示例#29
0
static int
amd64_windows_frame_decode_epilogue (struct frame_info *this_frame,
				     struct amd64_windows_frame_cache *cache)
{
  /* According to MSDN an epilogue "must consist of either an add RSP,constant
     or lea RSP,constant[FPReg], followed by a series of zero or more 8-byte
     register pops and a return or a jmp".

     Furthermore, according to RtlVirtualUnwind, the complete list of
     epilog marker is:
     - ret                      [c3]
     - ret n                    [c2 imm16]
     - rep ret                  [f3 c3]
     - jmp imm8 | imm32         [eb rel8] or [e9 rel32]
     - jmp qword ptr imm32                 - not handled
     - rex.w jmp reg            [4X ff eY]
  */

  CORE_ADDR pc = cache->pc;
  CORE_ADDR cur_sp = cache->sp;
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  gdb_byte op;
  gdb_byte rex;

  /* We don't care about the instruction deallocating the frame:
     if it hasn't been executed, the pc is still in the body,
     if it has been executed, the following epilog decoding will work.  */

  /* First decode:
     -  pop reg                 [41 58-5f] or [58-5f].  */

  while (1)
    {
      /* Read opcode. */
      if (target_read_memory (pc, &op, 1) != 0)
	return -1;

      if (op >= 0x40 && op <= 0x4f)
	{
	  /* REX prefix.  */
	  rex = op;

	  /* Read opcode. */
	  if (target_read_memory (pc + 1, &op, 1) != 0)
	    return -1;
	}
      else
	rex = 0;

      if (op >= 0x58 && op <= 0x5f)
	{
	  /* pop reg  */
	  gdb_byte reg = (op & 0x0f) | ((rex & 1) << 3);

	  cache->prev_reg_addr[amd64_windows_w2gdb_regnum[reg]] = cur_sp;
	  cur_sp += 8;
	}
      else
	break;

      /* Allow the user to break this loop.  This shouldn't happen as the
	 number of consecutive pop should be small.  */
      QUIT;
    }

  /* Then decode the marker.  */

  /* Read opcode.  */
  if (target_read_memory (pc, &op, 1) != 0)
    return -1;

  switch (op)
    {
    case 0xc3:
      /* Ret.  */
      cache->prev_rip_addr = cur_sp;
      cache->prev_sp = cur_sp + 8;
      return 1;

    case 0xeb:
      {
	/* jmp rel8  */
	gdb_byte rel8;
	CORE_ADDR npc;

	if (target_read_memory (pc + 1, &rel8, 1) != 0)
	  return -1;
	npc = pc + 2 + (signed char) rel8;

	/* If the jump is within the function, then this is not a marker,
	   otherwise this is a tail-call.  */
	return !pc_in_range (npc, cache);
      }

    case 0xec:
      {
	/* jmp rel32  */
	gdb_byte rel32[4];
	CORE_ADDR npc;

	if (target_read_memory (pc + 1, rel32, 4) != 0)
	  return -1;
	npc = pc + 5 + extract_signed_integer (rel32, 4, byte_order);

	/* If the jump is within the function, then this is not a marker,
	   otherwise this is a tail-call.  */
	return !pc_in_range (npc, cache);
      }

    case 0xc2:
      {
	/* ret n  */
	gdb_byte imm16[2];

	if (target_read_memory (pc + 1, imm16, 2) != 0)
	  return -1;
	cache->prev_rip_addr = cur_sp;
	cache->prev_sp = cur_sp
	  + extract_unsigned_integer (imm16, 4, byte_order);
	return 1;
      }

    case 0xf3:
      {
	/* rep; ret  */
	gdb_byte op1;

	if (target_read_memory (pc + 2, &op1, 1) != 0)
	  return -1;
	if (op1 != 0xc3)
	  return 0;

	cache->prev_rip_addr = cur_sp;
	cache->prev_sp = cur_sp + 8;
	return 1;
      }

    case 0x40:
    case 0x41:
    case 0x42:
    case 0x43:
    case 0x44:
    case 0x45:
    case 0x46:
    case 0x47:
    case 0x48:
    case 0x49:
    case 0x4a:
    case 0x4b:
    case 0x4c:
    case 0x4d:
    case 0x4e:
    case 0x4f:
      /* Got a REX prefix, read next byte.  */
      rex = op;
      if (target_read_memory (pc + 1, &op, 1) != 0)
	return -1;

      if (op == 0xff)
	{
	  /* rex jmp reg  */
	  gdb_byte op1;
	  unsigned int reg;
	  gdb_byte buf[8];

	  if (target_read_memory (pc + 2, &op1, 1) != 0)
	    return -1;
	  return (op1 & 0xf8) == 0xe0;
	}
      else
	return 0;

    default:
      /* Not REX, so unknown.  */
      return 0;
    }
}