Example #1
0
static int
amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc,
				CORE_ADDR *unwind_info,
				CORE_ADDR *image_base,
				CORE_ADDR *start_rva,
				CORE_ADDR *end_rva)
{
  struct obj_section *sec;
  pe_data_type *pe;
  IMAGE_DATA_DIRECTORY *dir;
  struct objfile *objfile;
  unsigned long lo, hi;
  CORE_ADDR base;
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

  /* Get the corresponding exception directory.  */
  sec = find_pc_section (pc);
  if (sec == NULL)
    return -1;
  objfile = sec->objfile;
  pe = pe_data (sec->objfile->obfd);
  dir = &pe->pe_opthdr.DataDirectory[PE_EXCEPTION_TABLE];

  base = pe->pe_opthdr.ImageBase
    + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
  *image_base = base;

  /* Find the entry.

     Note: This does not handle dynamically added entries (for JIT
     engines).  For this, we would need to ask the kernel directly,
     which means getting some info from the native layer.  For the
     rest of the code, however, it's probably faster to search
     the entry ourselves.  */
  lo = 0;
  hi = dir->Size / sizeof (struct external_pex64_runtime_function);
  *unwind_info = 0;
  while (lo <= hi)
    {
      unsigned long mid = lo + (hi - lo) / 2;
      struct external_pex64_runtime_function d;
      CORE_ADDR sa, ea;

      if (target_read_memory (base + dir->VirtualAddress + mid * sizeof (d),
			      (gdb_byte *) &d, sizeof (d)) != 0)
	return -1;

      sa = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order);
      ea = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order);
      if (pc < base + sa)
	hi = mid - 1;
      else if (pc >= base + ea)
	lo = mid + 1;
      else if (pc >= base + sa && pc < base + ea)
	{
	  /* Got it.  */
	  *start_rva = sa;
	  *end_rva = ea;
	  *unwind_info =
	    extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);
	  break;
	}
      else
	break;
    }

  if (frame_debug)
    fprintf_unfiltered
      (gdb_stdlog,
       "amd64_windows_find_unwind_data:  image_base=%s, unwind_data=%s\n",
       paddress (gdbarch, base), paddress (gdbarch, *unwind_info));

  if (*unwind_info & 1)
    {
      /* Unofficially documented unwind info redirection, when UNWIND_INFO
	 address is odd (http://www.codemachine.com/article_x64deepdive.html).
      */
      struct external_pex64_runtime_function d;
      CORE_ADDR sa, ea;

      if (target_read_memory (base + (*unwind_info & ~1),
			      (gdb_byte *) &d, sizeof (d)) != 0)
	return -1;

      *start_rva =
	extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order);
      *end_rva = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order);
      *unwind_info =
	extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);

    }
  return 0;
}
Example #2
0
static void
store_register (struct regcache *regcache, int regno)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  int addr[MAX_REGISTER_SIZE];
  int nr, isfloat;

  /* Fetch the register's value from the register cache.  */
  regcache_raw_collect (regcache, regno, addr);

  /* -1 can be a successful return value, so infer errors from errno.  */
  errno = 0;

  nr = regmap (gdbarch, regno, &isfloat);

  /* Floating-point registers.  */
  if (isfloat)
    rs6000_ptrace32 (PT_WRITE_FPR, ptid_get_pid (inferior_ptid), addr, nr, 0);

  /* Bogus register number.  */
  else if (nr < 0)
    {
      if (regno >= gdbarch_num_regs (gdbarch))
	fprintf_unfiltered (gdb_stderr,
			    "gdb error: register no %d not implemented.\n",
			    regno);
    }

  /* Fixed-point registers.  */
  else
    {
      if (regno == gdbarch_sp_regnum (gdbarch))
	/* Execute one dummy instruction (which is a breakpoint) in inferior
	   process to give kernel a chance to do internal housekeeping.
	   Otherwise the following ptrace(2) calls will mess up user stack
	   since kernel will get confused about the bottom of the stack
	   (%sp).  */
	exec_one_dummy_insn (regcache);

      /* The PT_WRITE_GPR operation is rather odd.  For 32-bit inferiors,
         the register's value is passed by value, but for 64-bit inferiors,
	 the address of a buffer containing the value is passed.  */
      if (!ARCH64 ())
	rs6000_ptrace32 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid),
			 (int *) nr, *addr, 0);
      else
	{
	  /* PT_WRITE_GPR requires the buffer parameter to point to an 8-byte
	     area, even if the register is really only 32 bits.  */
	  long long buf;
	  if (register_size (gdbarch, regno) == 8)
	    memcpy (&buf, addr, 8);
	  else
	    buf = *addr;
	  rs6000_ptrace64 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid),
			   nr, 0, &buf);
	}
    }

  if (errno)
    {
      perror (_("ptrace write"));
      errno = 0;
    }
}
Example #3
0
static void
amd64_windows_frame_decode_insns (struct frame_info *this_frame,
				  struct amd64_windows_frame_cache *cache,
				  CORE_ADDR unwind_info)
{
  CORE_ADDR save_addr = 0;
  CORE_ADDR cur_sp = cache->sp;
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  int j;

  for (j = 0; ; j++)
    {
      struct external_pex64_unwind_info ex_ui;
      /* There are at most 256 16-bit unwind insns.  */
      gdb_byte insns[2 * 256];
      gdb_byte *p;
      gdb_byte *end_insns;
      unsigned char codes_count;
      unsigned char frame_reg;
      unsigned char frame_off;

      /* Read and decode header.  */
      if (target_read_memory (cache->image_base + unwind_info,
			      (gdb_byte *) &ex_ui, sizeof (ex_ui)) != 0)
	return;

      if (frame_debug)
	fprintf_unfiltered
	  (gdb_stdlog,
	   "amd64_windows_frame_decodes_insn: "
	   "%s: ver: %02x, plgsz: %02x, cnt: %02x, frame: %02x\n",
	   paddress (gdbarch, unwind_info),
	   ex_ui.Version_Flags, ex_ui.SizeOfPrologue,
	   ex_ui.CountOfCodes, ex_ui.FrameRegisterOffset);

      /* Check version.  */
      if (PEX64_UWI_VERSION (ex_ui.Version_Flags) != 1
	  && PEX64_UWI_VERSION (ex_ui.Version_Flags) != 2)
	return;

      if (j == 0
	  && (cache->pc >=
	      cache->image_base + cache->start_rva + ex_ui.SizeOfPrologue))
	{
	  /* Not in the prologue.  We want to detect if the PC points to an
	     epilogue. If so, the epilogue detection+decoding function is
	     sufficient.  Otherwise, the unwinder will consider that the PC
	     is in the body of the function and will need to decode unwind
	     info.  */
	  if (amd64_windows_frame_decode_epilogue (this_frame, cache) == 1)
	    return;

	  /* Not in an epilog.  Clear possible side effects.  */
	  memset (cache->prev_reg_addr, 0, sizeof (cache->prev_reg_addr));
	}

      codes_count = ex_ui.CountOfCodes;
      frame_reg = PEX64_UWI_FRAMEREG (ex_ui.FrameRegisterOffset);

      if (frame_reg != 0)
	{
	  /* According to msdn:
	     If an FP reg is used, then any unwind code taking an offset must
	     only be used after the FP reg is established in the prolog.  */
	  gdb_byte buf[8];
	  int frreg = amd64_windows_w2gdb_regnum[frame_reg];

	  get_frame_register (this_frame, frreg, buf);
	  save_addr = extract_unsigned_integer (buf, 8, byte_order);

	  if (frame_debug)
	    fprintf_unfiltered (gdb_stdlog, "   frame_reg=%s, val=%s\n",
				gdbarch_register_name (gdbarch, frreg),
				paddress (gdbarch, save_addr));
	}

      /* Read opcodes.  */
      if (codes_count != 0
	  && target_read_memory (cache->image_base + unwind_info
				 + sizeof (ex_ui),
				 insns, codes_count * 2) != 0)
	return;

      end_insns = &insns[codes_count * 2];
      p = insns;

      /* Skip opcodes 6 of version 2.  This opcode is not documented.  */
      if (PEX64_UWI_VERSION (ex_ui.Version_Flags) == 2)
	{
	  for (; p < end_insns; p += 2)
	    if (PEX64_UNWCODE_CODE (p[1]) != 6)
	      break;
	}

      for (; p < end_insns; p += 2)
	{
	  int reg;

	  if (frame_debug)
	    fprintf_unfiltered
	      (gdb_stdlog, "   op #%u: off=0x%02x, insn=0x%02x\n",
	       (unsigned) (p - insns), p[0], p[1]);

	  /* Virtually execute the operation.  */
	  if (cache->pc >= cache->image_base + cache->start_rva + p[0])
	    {
	      /* If there is no frame registers defined, the current value of
		 rsp is used instead.  */
	      if (frame_reg == 0)
		save_addr = cur_sp;

	      switch (PEX64_UNWCODE_CODE (p[1]))
		{
		case UWOP_PUSH_NONVOL:
		  /* Push pre-decrements RSP.  */
		  reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])];
		  cache->prev_reg_addr[reg] = cur_sp;
		  cur_sp += 8;
		  break;
		case UWOP_ALLOC_LARGE:
		  if (PEX64_UNWCODE_INFO (p[1]) == 0)
		    cur_sp +=
		      8 * extract_unsigned_integer (p + 2, 2, byte_order);
		  else if (PEX64_UNWCODE_INFO (p[1]) == 1)
		    cur_sp += extract_unsigned_integer (p + 2, 4, byte_order);
		  else
		    return;
		  break;
		case UWOP_ALLOC_SMALL:
		  cur_sp += 8 + 8 * PEX64_UNWCODE_INFO (p[1]);
		  break;
		case UWOP_SET_FPREG:
		  cur_sp = save_addr
		    - PEX64_UWI_FRAMEOFF (ex_ui.FrameRegisterOffset) * 16;
		  break;
		case UWOP_SAVE_NONVOL:
		  reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])];
		  cache->prev_reg_addr[reg] = save_addr
		    - 8 * extract_unsigned_integer (p + 2, 2, byte_order);
		  break;
		case UWOP_SAVE_NONVOL_FAR:
		  reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])];
		  cache->prev_reg_addr[reg] = save_addr
		    - 8 * extract_unsigned_integer (p + 2, 4, byte_order);
		  break;
		case UWOP_SAVE_XMM128:
		  cache->prev_xmm_addr[PEX64_UNWCODE_INFO (p[1])] =
		    save_addr
		    - 16 * extract_unsigned_integer (p + 2, 2, byte_order);
		  break;
		case UWOP_SAVE_XMM128_FAR:
		  cache->prev_xmm_addr[PEX64_UNWCODE_INFO (p[1])] =
		    save_addr
		    - 16 * extract_unsigned_integer (p + 2, 4, byte_order);
		  break;
		case UWOP_PUSH_MACHFRAME:
		  if (PEX64_UNWCODE_INFO (p[1]) == 0)
		    {
		      cache->prev_rip_addr = cur_sp + 0;
		      cache->prev_rsp_addr = cur_sp + 24;
		      cur_sp += 40;
		    }
		  else if (PEX64_UNWCODE_INFO (p[1]) == 1)
		    {
		      cache->prev_rip_addr = cur_sp + 8;
		      cache->prev_rsp_addr = cur_sp + 32;
		      cur_sp += 48;
		    }
		  else
		    return;
		  break;
		default:
		  return;
		}
	    }

	  /* Adjust with the length of the opcode.  */
	  switch (PEX64_UNWCODE_CODE (p[1]))
	    {
	    case UWOP_PUSH_NONVOL:
	    case UWOP_ALLOC_SMALL:
	    case UWOP_SET_FPREG:
	    case UWOP_PUSH_MACHFRAME:
	      break;
	    case UWOP_ALLOC_LARGE:
	      if (PEX64_UNWCODE_INFO (p[1]) == 0)
		p += 2;
	      else if (PEX64_UNWCODE_INFO (p[1]) == 1)
		p += 4;
	      else
		return;
	      break;
	    case UWOP_SAVE_NONVOL:
	    case UWOP_SAVE_XMM128:
	      p += 2;
	      break;
	    case UWOP_SAVE_NONVOL_FAR:
	    case UWOP_SAVE_XMM128_FAR:
	      p += 4;
	      break;
	    default:
	      return;
	    }
	}
      if (PEX64_UWI_FLAGS (ex_ui.Version_Flags) != UNW_FLAG_CHAININFO)
	break;
      else
	{
	  /* Read the chained unwind info.  */
	  struct external_pex64_runtime_function d;
	  CORE_ADDR chain_vma;

	  chain_vma = cache->image_base + unwind_info
	    + sizeof (ex_ui) + ((codes_count + 1) & ~1) * 2;

	  if (target_read_memory (chain_vma, (gdb_byte *) &d, sizeof (d)) != 0)
	    return;

	  cache->start_rva =
	    extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order);
	  cache->end_rva =
	    extract_unsigned_integer (d.rva_EndAddress, 4, byte_order);
	  unwind_info =
	    extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);

	  if (frame_debug)
	    fprintf_unfiltered
	      (gdb_stdlog,
	       "amd64_windows_frame_decodes_insn (next in chain):"
	       " unwind_data=%s, start_rva=%s, end_rva=%s\n",
	       paddress (gdbarch, unwind_info),
	       paddress (gdbarch, cache->start_rva),
	       paddress (gdbarch, cache->end_rva));
	}

      /* Allow the user to break this loop.  */
      QUIT;
    }
  /* PC is saved by the call.  */
  if (cache->prev_rip_addr == 0)
    cache->prev_rip_addr = cur_sp;
  cache->prev_sp = cur_sp + 8;

  if (frame_debug)
    fprintf_unfiltered (gdb_stdlog, "   prev_sp: %s, prev_pc @%s\n",
			paddress (gdbarch, cache->prev_sp),
			paddress (gdbarch, cache->prev_rip_addr));
}
Example #4
0
static void
sparclite_udp_write (bfd *from_bfd, asection *from_sec, file_ptr from_addr,
		     bfd_vma to_addr, int len)
{
  unsigned char buffer[2000];
  unsigned short checksum;
  static int pkt_num = 0;
  static unsigned long old_addr = -1;
  int i;

  while (1)
    {
      if (to_addr != old_addr)
	{
	  buffer[0] = 0x1;	/* Load command */
	  buffer[1] = 0x1;	/* Loading address */
	  buffer[2] = to_addr >> 24;
	  buffer[3] = to_addr >> 16;
	  buffer[4] = to_addr >> 8;
	  buffer[5] = to_addr;

	  checksum = 0;
	  for (i = 0; i < 6; i++)
	    checksum += buffer[i];
	  checksum &= 0xff;

	  send_udp_buf (udp_fd, buffer, 6);
	  i = recv_udp_buf (udp_fd, buffer, sizeof buffer, -1);

	  if (i < 1)
	    error ("Got back short checksum for load addr.");

	  if (checksum != buffer[0])
	    error ("Got back bad checksum for load addr.");

	  pkt_num = 0;		/* Load addr resets packet seq # */
	  old_addr = to_addr;
	}

      bfd_get_section_contents (from_bfd, from_sec, buffer + 6, from_addr,
				len);

      checksum = calc_checksum (buffer + 6, len);

      buffer[0] = 0x1;		/* Load command */
      buffer[1] = 0x2;		/* Loading data */
      buffer[2] = pkt_num >> 8;
      buffer[3] = pkt_num;
      buffer[4] = checksum >> 8;
      buffer[5] = checksum;

      send_udp_buf (udp_fd, buffer, len + 6);
      i = recv_udp_buf (udp_fd, buffer, sizeof buffer, 3);

      if (i == 0)
	{
	  fprintf_unfiltered (gdb_stderr, "send_data: timeout sending %d bytes to address 0x%x retrying\n", len, to_addr);
	  continue;
	}

      if (buffer[0] != 0xff)
	error ("Got back bad response for load data.");

      old_addr += len;
      pkt_num++;

      return;
    }
static int
enable_break2 (void)
{
  int success = 0;
  char **bkpt_namep;
  asection *interp_sect;

  if (!enable_break1_done || enable_break2_done)
    return 1;

  enable_break2_done = 1;

  /* First, remove all the solib event breakpoints.  Their addresses
     may have changed since the last time we ran the program.  */
  remove_solib_event_breakpoints ();

  interp_text_sect_low = interp_text_sect_high = 0;
  interp_plt_sect_low = interp_plt_sect_high = 0;

  /* Find the .interp section; if not found, warn the user and drop
     into the old breakpoint at symbol code.  */
  interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
  if (interp_sect)
    {
      unsigned int interp_sect_size;
      gdb_byte *buf;
      bfd *tmp_bfd = NULL;
      int status;
      CORE_ADDR addr, interp_loadmap_addr;
      gdb_byte addr_buf[FRV_PTR_SIZE];
      struct int_elf32_fdpic_loadmap *ldm;
      volatile struct gdb_exception ex;

      /* Read the contents of the .interp section into a local buffer;
         the contents specify the dynamic linker this program uses.  */
      interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
      buf = alloca (interp_sect_size);
      bfd_get_section_contents (exec_bfd, interp_sect,
				buf, 0, interp_sect_size);

      /* Now we need to figure out where the dynamic linker was
         loaded so that we can load its symbols and place a breakpoint
         in the dynamic linker itself.

         This address is stored on the stack.  However, I've been unable
         to find any magic formula to find it for Solaris (appears to
         be trivial on GNU/Linux).  Therefore, we have to try an alternate
         mechanism to find the dynamic linker's base address.  */

      TRY_CATCH (ex, RETURN_MASK_ALL)
        {
          tmp_bfd = solib_bfd_open (buf);
        }
      if (tmp_bfd == NULL)
	{
	  enable_break_failure_warning ();
	  return 0;
	}

      status = frv_fdpic_loadmap_addresses (target_gdbarch,
                                            &interp_loadmap_addr, 0);
      if (status < 0)
	{
	  warning (_("Unable to determine dynamic linker loadmap address."));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
	                    "enable_break: interp_loadmap_addr = %s\n",
			    hex_string_custom (interp_loadmap_addr, 8));

      ldm = fetch_loadmap (interp_loadmap_addr);
      if (ldm == NULL)
	{
	  warning (_("Unable to load dynamic linker loadmap at address %s."),
	           hex_string_custom (interp_loadmap_addr, 8));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}

      /* Record the relocated start and end address of the dynamic linker
         text and plt section for svr4_in_dynsym_resolve_code.  */
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
      if (interp_sect)
	{
	  interp_text_sect_low
	    = bfd_section_vma (tmp_bfd, interp_sect);
	  interp_text_sect_low
	    += displacement_from_map (ldm, interp_text_sect_low);
	  interp_text_sect_high
	    = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
	}
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
      if (interp_sect)
	{
	  interp_plt_sect_low =
	    bfd_section_vma (tmp_bfd, interp_sect);
	  interp_plt_sect_low
	    += displacement_from_map (ldm, interp_plt_sect_low);
	  interp_plt_sect_high =
	    interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
	}

      addr = bfd_lookup_symbol (tmp_bfd, "_dl_debug_addr");
      if (addr == 0)
	{
	  warning (_("Could not find symbol _dl_debug_addr in dynamic linker"));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
	                    "enable_break: _dl_debug_addr (prior to relocation) = %s\n",
			    hex_string_custom (addr, 8));

      addr += displacement_from_map (ldm, addr);

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
	                    "enable_break: _dl_debug_addr (after relocation) = %s\n",
			    hex_string_custom (addr, 8));

      /* Fetch the address of the r_debug struct.  */
      if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch contents of _dl_debug_addr (at address %s) from dynamic linker"),
	           hex_string_custom (addr, 8));
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);

      /* Fetch the r_brk field.  It's 8 bytes from the start of
         _dl_debug_addr.  */
      if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch _dl_debug_addr->r_brk (at address %s) from dynamic linker"),
	           hex_string_custom (addr + 8, 8));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);

      /* Now fetch the function entry point.  */
      if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
	{
	  warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point (at address %s) from dynamic linker"),
	           hex_string_custom (addr, 8));
	  enable_break_failure_warning ();
	  bfd_close (tmp_bfd);
	  return 0;
	}
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);

      /* We're done with the temporary bfd.  */
      bfd_close (tmp_bfd);

      /* We're also done with the loadmap.  */
      xfree (ldm);

      /* Now (finally!) create the solib breakpoint.  */
      create_solib_event_breakpoint (addr);

      return 1;
    }
static struct so_list *
frv_current_sos (void)
{
  CORE_ADDR lm_addr, mgot;
  struct so_list *sos_head = NULL;
  struct so_list **sos_next_ptr = &sos_head;

  /* Make sure that the main executable has been relocated.  This is
     required in order to find the address of the global offset table,
     which in turn is used to find the link map info.  (See lm_base()
     for details.)

     Note that the relocation of the main executable is also performed
     by SOLIB_CREATE_INFERIOR_HOOK(), however, in the case of core
     files, this hook is called too late in order to be of benefit to
     SOLIB_ADD.  SOLIB_ADD eventually calls this this function,
     frv_current_sos, and also precedes the call to
     SOLIB_CREATE_INFERIOR_HOOK().   (See post_create_inferior() in
     infcmd.c.)  */
  if (main_executable_lm_info == 0 && core_bfd != NULL)
    frv_relocate_main_executable ();

  /* Fetch the GOT corresponding to the main executable.  */
  mgot = main_got ();

  /* Locate the address of the first link map struct.  */
  lm_addr = lm_base ();

  /* We have at least one link map entry.  Fetch the the lot of them,
     building the solist chain.  */
  while (lm_addr)
    {
      struct ext_link_map lm_buf;
      CORE_ADDR got_addr;

      if (solib_frv_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "current_sos: reading link_map entry at %s\n",
			    hex_string_custom (lm_addr, 8));

      if (target_read_memory (lm_addr, (gdb_byte *) &lm_buf, sizeof (lm_buf)) != 0)
	{
	  warning (_("frv_current_sos: Unable to read link map entry.  Shared object chain may be incomplete."));
	  break;
	}

      got_addr
	= extract_unsigned_integer (lm_buf.l_addr.got_value,
				    sizeof (lm_buf.l_addr.got_value));
      /* If the got_addr is the same as mgotr, then we're looking at the
	 entry for the main executable.  By convention, we don't include
	 this in the list of shared objects.  */
      if (got_addr != mgot)
	{
	  int errcode;
	  char *name_buf;
	  struct int_elf32_fdpic_loadmap *loadmap;
	  struct so_list *sop;
	  CORE_ADDR addr;

	  /* Fetch the load map address.  */
	  addr = extract_unsigned_integer (lm_buf.l_addr.map,
					   sizeof lm_buf.l_addr.map);
	  loadmap = fetch_loadmap (addr);
	  if (loadmap == NULL)
	    {
	      warning (_("frv_current_sos: Unable to fetch load map.  Shared object chain may be incomplete."));
	      break;
	    }

	  sop = xcalloc (1, sizeof (struct so_list));
	  sop->lm_info = xcalloc (1, sizeof (struct lm_info));
	  sop->lm_info->map = loadmap;
	  sop->lm_info->got_value = got_addr;
	  sop->lm_info->lm_addr = lm_addr;
	  /* Fetch the name.  */
	  addr = extract_unsigned_integer (lm_buf.l_name,
					   sizeof (lm_buf.l_name));
	  target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
			      &errcode);

	  if (solib_frv_debug)
	    fprintf_unfiltered (gdb_stdlog, "current_sos: name = %s\n",
	                        name_buf);
	  
	  if (errcode != 0)
	    warning (_("Can't read pathname for link map entry: %s."),
		     safe_strerror (errcode));
	  else
	    {
	      strncpy (sop->so_name, name_buf, SO_NAME_MAX_PATH_SIZE - 1);
	      sop->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
	      xfree (name_buf);
	      strcpy (sop->so_original_name, sop->so_name);
	    }

	  *sos_next_ptr = sop;
	  sos_next_ptr = &sop->next;
	}
      else
	{
	  main_lm_addr = lm_addr;
	}

      lm_addr = extract_unsigned_integer (lm_buf.l_next, sizeof (lm_buf.l_next));
    }

  enable_break2 ();

  return sos_head;
}
Example #7
0
/* Standard implementation of print_subexp for use in language_defn
   vectors.  */
void
print_subexp_standard (struct expression *exp, int *pos,
		       struct ui_file *stream, enum precedence prec)
{
  unsigned tem;
  const struct op_print *op_print_tab;
  int pc;
  unsigned nargs;
  char *op_str;
  int assign_modify = 0;
  enum exp_opcode opcode;
  enum precedence myprec = PREC_NULL;
  /* Set to 1 for a right-associative operator.  */
  int assoc = 0;
  struct value *val;
  char *tempstr = NULL;

  op_print_tab = exp->language_defn->la_op_print_tab;
  pc = (*pos)++;
  opcode = exp->elts[pc].opcode;
  switch (opcode)
    {
      /* Common ops */

    case OP_SCOPE:
      myprec = PREC_PREFIX;
      assoc = 0;
      fputs_filtered (type_name_no_tag (exp->elts[pc + 1].type), stream);
      fputs_filtered ("::", stream);
      nargs = longest_to_int (exp->elts[pc + 2].longconst);
      (*pos) += 4 + BYTES_TO_EXP_ELEM (nargs + 1);
      fputs_filtered (&exp->elts[pc + 3].string, stream);
      return;

    case OP_LONG:
      {
	struct value_print_options opts;

	get_raw_print_options (&opts);
	(*pos) += 3;
	value_print (value_from_longest (exp->elts[pc + 1].type,
					 exp->elts[pc + 2].longconst),
		     stream, &opts);
      }
      return;

    case OP_DOUBLE:
      {
	struct value_print_options opts;

	get_raw_print_options (&opts);
	(*pos) += 3;
	value_print (value_from_double (exp->elts[pc + 1].type,
					exp->elts[pc + 2].doubleconst),
		     stream, &opts);
      }
      return;

    case OP_VAR_VALUE:
      {
	struct block *b;

	(*pos) += 3;
	b = exp->elts[pc + 1].block;
	if (b != NULL
	    && BLOCK_FUNCTION (b) != NULL
	    && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)) != NULL)
	  {
	    fputs_filtered (SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)), stream);
	    fputs_filtered ("::", stream);
	  }
	fputs_filtered (SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol), stream);
      }
      return;

    case OP_LAST:
      (*pos) += 2;
      fprintf_filtered (stream, "$%d",
			longest_to_int (exp->elts[pc + 1].longconst));
      return;

    case OP_REGISTER:
      {
	const char *name = &exp->elts[pc + 2].string;

	(*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
	fprintf_filtered (stream, "$%s", name);
	return;
      }

    case OP_BOOL:
      (*pos) += 2;
      fprintf_filtered (stream, "%s",
			longest_to_int (exp->elts[pc + 1].longconst)
			? "TRUE" : "FALSE");
      return;

    case OP_INTERNALVAR:
      (*pos) += 2;
      fprintf_filtered (stream, "$%s",
			internalvar_name (exp->elts[pc + 1].internalvar));
      return;

    case OP_FUNCALL:
      (*pos) += 2;
      nargs = longest_to_int (exp->elts[pc + 1].longconst);
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered (" (", stream);
      for (tem = 0; tem < nargs; tem++)
	{
	  if (tem != 0)
	    fputs_filtered (", ", stream);
	  print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
	}
      fputs_filtered (")", stream);
      return;

    case OP_NAME:
      nargs = longest_to_int (exp->elts[pc + 1].longconst);
      (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
      fputs_filtered (&exp->elts[pc + 2].string, stream);
      return;

    case OP_STRING:
      {
	struct value_print_options opts;

	nargs = longest_to_int (exp->elts[pc + 1].longconst);
	(*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
	/* LA_PRINT_STRING will print using the current repeat count threshold.
	   If necessary, we can temporarily set it to zero, or pass it as an
	   additional parameter to LA_PRINT_STRING.  -fnf */
	get_user_print_options (&opts);
	LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
			 &exp->elts[pc + 2].string, nargs, NULL, 0, &opts);
      }
      return;

    case OP_BITSTRING:
      nargs = longest_to_int (exp->elts[pc + 1].longconst);
      (*pos)
	+= 3 + BYTES_TO_EXP_ELEM ((nargs + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT);
      fprintf_unfiltered (stream, "B'<unimplemented>'");
      return;

    case OP_OBJC_NSSTRING:	/* Objective-C Foundation Class
				   NSString constant.  */
      {
	struct value_print_options opts;

	nargs = longest_to_int (exp->elts[pc + 1].longconst);
	(*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
	fputs_filtered ("@\"", stream);
	get_user_print_options (&opts);
	LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
			 &exp->elts[pc + 2].string, nargs, NULL, 0, &opts);
	fputs_filtered ("\"", stream);
      }
      return;

    case OP_OBJC_MSGCALL:
      {			/* Objective C message (method) call.  */
	char *selector;

	(*pos) += 3;
	nargs = longest_to_int (exp->elts[pc + 2].longconst);
	fprintf_unfiltered (stream, "[");
	print_subexp (exp, pos, stream, PREC_SUFFIX);
	if (0 == target_read_string (exp->elts[pc + 1].longconst,
				     &selector, 1024, NULL))
	  {
	    error (_("bad selector"));
	    return;
	  }
	if (nargs)
	  {
	    char *s, *nextS;

	    s = alloca (strlen (selector) + 1);
	    strcpy (s, selector);
	    for (tem = 0; tem < nargs; tem++)
	      {
		nextS = strchr (s, ':');
		gdb_assert (nextS);	/* Make sure we found ':'.  */
		*nextS = '\0';
		fprintf_unfiltered (stream, " %s: ", s);
		s = nextS + 1;
		print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
	      }
	  }
	else
	  {
	    fprintf_unfiltered (stream, " %s", selector);
	  }
	fprintf_unfiltered (stream, "]");
	/* "selector" was malloc'd by target_read_string.  Free it.  */
	xfree (selector);
	return;
      }

    case OP_ARRAY:
      (*pos) += 3;
      nargs = longest_to_int (exp->elts[pc + 2].longconst);
      nargs -= longest_to_int (exp->elts[pc + 1].longconst);
      nargs++;
      tem = 0;
      if (exp->elts[pc + 4].opcode == OP_LONG
	  && exp->elts[pc + 5].type
	     == builtin_type (exp->gdbarch)->builtin_char
	  && exp->language_defn->la_language == language_c)
	{
	  /* Attempt to print C character arrays using string syntax.
	     Walk through the args, picking up one character from each
	     of the OP_LONG expression elements.  If any array element
	     does not match our expection of what we should find for
	     a simple string, revert back to array printing.  Note that
	     the last expression element is an explicit null terminator
	     byte, which doesn't get printed.  */
	  tempstr = alloca (nargs);
	  pc += 4;
	  while (tem < nargs)
	    {
	      if (exp->elts[pc].opcode != OP_LONG
		  || exp->elts[pc + 1].type
		     != builtin_type (exp->gdbarch)->builtin_char)
		{
		  /* Not a simple array of char, use regular array
		     printing.  */
		  tem = 0;
		  break;
		}
	      else
		{
		  tempstr[tem++] =
		    longest_to_int (exp->elts[pc + 2].longconst);
		  pc += 4;
		}
	    }
	}
      if (tem > 0)
	{
	  struct value_print_options opts;

	  get_user_print_options (&opts);
	  LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
			   tempstr, nargs - 1, NULL, 0, &opts);
	  (*pos) = pc;
	}
      else
	{
	  fputs_filtered (" {", stream);
	  for (tem = 0; tem < nargs; tem++)
	    {
	      if (tem != 0)
		{
		  fputs_filtered (", ", stream);
		}
	      print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
	    }
	  fputs_filtered ("}", stream);
	}
      return;

    case OP_LABELED:
      tem = longest_to_int (exp->elts[pc + 1].longconst);
      (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
      /* Gcc support both these syntaxes.  Unsure which is preferred.  */
#if 1
      fputs_filtered (&exp->elts[pc + 2].string, stream);
      fputs_filtered (": ", stream);
#else
      fputs_filtered (".", stream);
      fputs_filtered (&exp->elts[pc + 2].string, stream);
      fputs_filtered ("=", stream);
#endif
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      return;

    case TERNOP_COND:
      if ((int) prec > (int) PREC_COMMA)
	fputs_filtered ("(", stream);
      /* Print the subexpressions, forcing parentheses
         around any binary operations within them.
         This is more parentheses than are strictly necessary,
         but it looks clearer.  */
      print_subexp (exp, pos, stream, PREC_HYPER);
      fputs_filtered (" ? ", stream);
      print_subexp (exp, pos, stream, PREC_HYPER);
      fputs_filtered (" : ", stream);
      print_subexp (exp, pos, stream, PREC_HYPER);
      if ((int) prec > (int) PREC_COMMA)
	fputs_filtered (")", stream);
      return;

    case TERNOP_SLICE:
    case TERNOP_SLICE_COUNT:
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered ("(", stream);
      print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
      fputs_filtered (opcode == TERNOP_SLICE ? " : " : " UP ", stream);
      print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
      fputs_filtered (")", stream);
      return;

    case STRUCTOP_STRUCT:
      tem = longest_to_int (exp->elts[pc + 1].longconst);
      (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered (".", stream);
      fputs_filtered (&exp->elts[pc + 2].string, stream);
      return;

      /* Will not occur for Modula-2.  */
    case STRUCTOP_PTR:
      tem = longest_to_int (exp->elts[pc + 1].longconst);
      (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered ("->", stream);
      fputs_filtered (&exp->elts[pc + 2].string, stream);
      return;

    case STRUCTOP_MEMBER:
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered (".*", stream);
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      return;

    case STRUCTOP_MPTR:
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered ("->*", stream);
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      return;

    case BINOP_SUBSCRIPT:
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered ("[", stream);
      print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
      fputs_filtered ("]", stream);
      return;

    case UNOP_POSTINCREMENT:
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered ("++", stream);
      return;

    case UNOP_POSTDECREMENT:
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fputs_filtered ("--", stream);
      return;

    case UNOP_CAST:
      (*pos) += 2;
      if ((int) prec > (int) PREC_PREFIX)
	fputs_filtered ("(", stream);
      fputs_filtered ("(", stream);
      type_print (exp->elts[pc + 1].type, "", stream, 0);
      fputs_filtered (") ", stream);
      print_subexp (exp, pos, stream, PREC_PREFIX);
      if ((int) prec > (int) PREC_PREFIX)
	fputs_filtered (")", stream);
      return;

    case UNOP_DYNAMIC_CAST:
    case UNOP_REINTERPRET_CAST:
      fputs_filtered (opcode == UNOP_DYNAMIC_CAST ? "dynamic_cast"
		      : "reinterpret_cast", stream);
      fputs_filtered ("<", stream);
      (*pos) += 2;
      type_print (exp->elts[pc + 1].type, "", stream, 0);
      fputs_filtered ("> (", stream);
      print_subexp (exp, pos, stream, PREC_PREFIX);
      fputs_filtered (")", stream);
      return;

    case UNOP_MEMVAL:
      (*pos) += 2;
      if ((int) prec > (int) PREC_PREFIX)
	fputs_filtered ("(", stream);
      if (TYPE_CODE (exp->elts[pc + 1].type) == TYPE_CODE_FUNC
	  && exp->elts[pc + 3].opcode == OP_LONG)
	{
	  struct value_print_options opts;

	  /* We have a minimal symbol fn, probably.  It's encoded
	     as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address).
	     Swallow the OP_LONG (including both its opcodes); ignore
	     its type; print the value in the type of the MEMVAL.  */
	  (*pos) += 4;
	  val = value_at_lazy (exp->elts[pc + 1].type,
			       (CORE_ADDR) exp->elts[pc + 5].longconst);
	  get_raw_print_options (&opts);
	  value_print (val, stream, &opts);
	}
      else
	{
	  fputs_filtered ("{", stream);
	  type_print (exp->elts[pc + 1].type, "", stream, 0);
	  fputs_filtered ("} ", stream);
	  print_subexp (exp, pos, stream, PREC_PREFIX);
	}
      if ((int) prec > (int) PREC_PREFIX)
	fputs_filtered (")", stream);
      return;

    case UNOP_MEMVAL_TLS:
      (*pos) += 3;
      if ((int) prec > (int) PREC_PREFIX)
	fputs_filtered ("(", stream);
      fputs_filtered ("{", stream);
      type_print (exp->elts[pc + 2].type, "", stream, 0);
      fputs_filtered ("} ", stream);
      print_subexp (exp, pos, stream, PREC_PREFIX);
      if ((int) prec > (int) PREC_PREFIX)
	fputs_filtered (")", stream);
      return;

    case BINOP_ASSIGN_MODIFY:
      opcode = exp->elts[pc + 1].opcode;
      (*pos) += 2;
      myprec = PREC_ASSIGN;
      assoc = 1;
      assign_modify = 1;
      op_str = "???";
      for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
	if (op_print_tab[tem].opcode == opcode)
	  {
	    op_str = op_print_tab[tem].string;
	    break;
	  }
      if (op_print_tab[tem].opcode != opcode)
	/* Not found; don't try to keep going because we don't know how
	   to interpret further elements.  */
	error (_("Invalid expression"));
      break;

      /* C++ ops */

    case OP_THIS:
      ++(*pos);
      fputs_filtered ("this", stream);
      return;

      /* Objective-C ops */

    case OP_OBJC_SELF:
      ++(*pos);
      fputs_filtered ("self", stream);	/* The ObjC equivalent of "this".  */
      return;

      /* Modula-2 ops */

    case MULTI_SUBSCRIPT:
      (*pos) += 2;
      nargs = longest_to_int (exp->elts[pc + 1].longconst);
      print_subexp (exp, pos, stream, PREC_SUFFIX);
      fprintf_unfiltered (stream, " [");
      for (tem = 0; tem < nargs; tem++)
	{
	  if (tem != 0)
	    fprintf_unfiltered (stream, ", ");
	  print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
	}
      fprintf_unfiltered (stream, "]");
      return;

    case BINOP_VAL:
      (*pos) += 2;
      fprintf_unfiltered (stream, "VAL(");
      type_print (exp->elts[pc + 1].type, "", stream, 0);
      fprintf_unfiltered (stream, ",");
      print_subexp (exp, pos, stream, PREC_PREFIX);
      fprintf_unfiltered (stream, ")");
      return;

    case TYPE_INSTANCE:
      {
	LONGEST count = exp->elts[pc + 1].longconst;

	/* The COUNT.  */
	(*pos)++;
	fputs_unfiltered ("TypesInstance(", stream);
	while (count-- > 0)
	  {
	    type_print (exp->elts[(*pos)++].type, "", stream, 0);
	    if (count > 0)
	      fputs_unfiltered (",", stream);
	  }
	fputs_unfiltered (",", stream);
	/* Ending COUNT and ending TYPE_INSTANCE.  */
	(*pos) += 2;
	print_subexp (exp, pos, stream, PREC_PREFIX);
	fputs_unfiltered (")", stream);
	return;
      }

      /* Default ops */

    default:
      op_str = "???";
      for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
	if (op_print_tab[tem].opcode == opcode)
	  {
	    op_str = op_print_tab[tem].string;
	    myprec = op_print_tab[tem].precedence;
	    assoc = op_print_tab[tem].right_assoc;
	    break;
	  }
      if (op_print_tab[tem].opcode != opcode)
	/* Not found; don't try to keep going because we don't know how
	   to interpret further elements.  For example, this happens
	   if opcode is OP_TYPE.  */
	error (_("Invalid expression"));
    }

  /* Note that PREC_BUILTIN will always emit parentheses.  */
  if ((int) myprec < (int) prec)
    fputs_filtered ("(", stream);
  if ((int) opcode > (int) BINOP_END)
    {
      if (assoc)
	{
	  /* Unary postfix operator.  */
	  print_subexp (exp, pos, stream, PREC_SUFFIX);
	  fputs_filtered (op_str, stream);
	}
      else
	{
	  /* Unary prefix operator.  */
	  fputs_filtered (op_str, stream);
	  if (myprec == PREC_BUILTIN_FUNCTION)
	    fputs_filtered ("(", stream);
	  print_subexp (exp, pos, stream, PREC_PREFIX);
	  if (myprec == PREC_BUILTIN_FUNCTION)
	    fputs_filtered (")", stream);
	}
    }
  else
    {
      /* Binary operator.  */
      /* Print left operand.
         If operator is right-associative,
         increment precedence for this operand.  */
      print_subexp (exp, pos, stream,
		    (enum precedence) ((int) myprec + assoc));
      /* Print the operator itself.  */
      if (assign_modify)
	fprintf_filtered (stream, " %s= ", op_str);
      else if (op_str[0] == ',')
	fprintf_filtered (stream, "%s ", op_str);
      else
	fprintf_filtered (stream, " %s ", op_str);
      /* Print right operand.
         If operator is left-associative,
         increment precedence for this operand.  */
      print_subexp (exp, pos, stream,
		    (enum precedence) ((int) myprec + !assoc));
    }

  if ((int) myprec < (int) prec)
    fputs_filtered (")", stream);
}
Example #8
0
static void
mi_on_resume (ptid_t ptid)
{
  struct thread_info *tp = NULL;

  if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
    tp = inferior_thread ();
  else
    tp = find_thread_ptid (ptid);

  /* Suppress output while calling an inferior function.  */
  if (tp->control.in_infcall)
    return;

  /* To cater for older frontends, emit ^running, but do it only once
     per each command.  We do it here, since at this point we know
     that the target was successfully resumed, and in non-async mode,
     we won't return back to MI interpreter code until the target
     is done running, so delaying the output of "^running" until then
     will make it impossible for frontend to know what's going on.

     In future (MI3), we'll be outputting "^done" here.  */
  if (!running_result_record_printed && mi_proceeded)
    {
      fprintf_unfiltered (raw_stdout, "%s^running\n",
			  current_token ? current_token : "");
    }

  if (PIDGET (ptid) == -1)
    fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
  else if (ptid_is_pid (ptid))
    {
      int count = 0;

      /* Backwards compatibility.  If there's only one inferior,
	 output "all", otherwise, output each resumed thread
	 individually.  */
      iterate_over_inferiors (mi_inferior_count, &count);

      if (count == 1)
	fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
      else
	iterate_over_threads (mi_output_running_pid, &ptid);
    }
  else
    {
      struct thread_info *ti = find_thread_ptid (ptid);

      gdb_assert (ti);
      fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
    }

  if (!running_result_record_printed && mi_proceeded)
    {
      running_result_record_printed = 1;
      /* This is what gdb used to do historically -- printing prompt even if
	 it cannot actually accept any input.  This will be surely removed
	 for MI3, and may be removed even earler.  */
      /* FIXME: review the use of target_is_async_p here -- is that
	 what we want? */
      if (!target_is_async_p ())
	fputs_unfiltered ("(gdb) \n", raw_stdout);
    }
  gdb_flush (raw_stdout);
}