コード例 #1
0
ファイル: auxv.c プロジェクト: simark/binutils-gdb
void
fprint_auxv_entry (struct ui_file *file, const char *name,
		   const char *description, enum auxv_format format,
		   CORE_ADDR type, CORE_ADDR val)
{
  fprintf_filtered (file, ("%-4s %-20s %-30s "),
		    plongest (type), name, description);
  switch (format)
    {
    case AUXV_FORMAT_DEC:
      fprintf_filtered (file, ("%s\n"), plongest (val));
      break;
    case AUXV_FORMAT_HEX:
      fprintf_filtered (file, ("%s\n"), paddress (target_gdbarch (), val));
      break;
    case AUXV_FORMAT_STR:
      {
	struct value_print_options opts;

	get_user_print_options (&opts);
	if (opts.addressprint)
	  fprintf_filtered (file, ("%s "), paddress (target_gdbarch (), val));
	val_print_string (builtin_type (target_gdbarch ())->builtin_char,
			  NULL, val, -1, file, &opts);
	fprintf_filtered (file, ("\n"));
      }
      break;
    }
}
コード例 #2
0
ファイル: m2-typeprint.c プロジェクト: neon12345/gdb
void
m2_enum (struct type *type, struct ui_file *stream, int show, int level)
{
  LONGEST lastval;
  int i, len;

  if (show < 0)
    {
      /* If we just printed a tag name, no need to print anything else.  */
      if (TYPE_TAG_NAME (type) == NULL)
	fprintf_filtered (stream, "(...)");
    }
  else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
    {
      fprintf_filtered (stream, "(");
      len = TYPE_NFIELDS (type);
      lastval = 0;
      for (i = 0; i < len; i++)
	{
	  QUIT;
	  if (i > 0)
	    fprintf_filtered (stream, ", ");
	  wrap_here ("    ");
	  fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
	  if (lastval != TYPE_FIELD_ENUMVAL (type, i))
	    {
	      fprintf_filtered (stream, " = %s",
				plongest (TYPE_FIELD_ENUMVAL (type, i)));
	      lastval = TYPE_FIELD_ENUMVAL (type, i);
	    }
	  lastval++;
	}
      fprintf_filtered (stream, ")");
    }
}
コード例 #3
0
ファイル: ada-typeprint.c プロジェクト: asdlei00/gdb
static void
print_enum_type (struct type *type, struct ui_file *stream)
{
    int len = TYPE_NFIELDS (type);
    int i;
    LONGEST lastval;

    fprintf_filtered (stream, "(");
    wrap_here (" ");

    lastval = 0;
    for (i = 0; i < len; i++)
    {
        QUIT;
        if (i)
            fprintf_filtered (stream, ", ");
        wrap_here ("    ");
        fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
        if (lastval != TYPE_FIELD_ENUMVAL (type, i))
        {
            fprintf_filtered (stream, " => %s",
                              plongest (TYPE_FIELD_ENUMVAL (type, i)));
            lastval = TYPE_FIELD_ENUMVAL (type, i);
        }
        lastval += 1;
    }
    fprintf_filtered (stream, ")");
}
コード例 #4
0
ファイル: utils.c プロジェクト: atgreen/binutils-gdb
char *
pfildes (gdb_fildes_t fd)
{
#if USE_WIN32API
  return phex_nz (fd, sizeof (gdb_fildes_t));
#else
  return plongest (fd);
#endif
}
コード例 #5
0
ファイル: gcore.c プロジェクト: atgreen/binutils-gdb
static int
gcore_create_callback (CORE_ADDR vaddr, unsigned long size, int read,
		       int write, int exec, int modified, void *data)
{
  bfd *obfd = data;
  asection *osec;
  flagword flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_LOAD;

  /* If the memory segment has no permissions set, ignore it, otherwise
     when we later try to access it for read/write, we'll get an error
     or jam the kernel.  */
  if (read == 0 && write == 0 && exec == 0 && modified == 0)
    {
      if (info_verbose)
        {
          fprintf_filtered (gdb_stdout, "Ignore segment, %s bytes at %s\n",
                            plongest (size), paddress (target_gdbarch (), vaddr));
        }

      return 0;
    }

  if (write == 0 && modified == 0 && !solib_keep_data_in_core (vaddr, size))
    {
      /* See if this region of memory lies inside a known file on disk.
	 If so, we can avoid copying its contents by clearing SEC_LOAD.  */
      struct objfile *objfile;
      struct obj_section *objsec;

      ALL_OBJSECTIONS (objfile, objsec)
	{
	  bfd *abfd = objfile->obfd;
	  asection *asec = objsec->the_bfd_section;
	  bfd_vma align = (bfd_vma) 1 << bfd_get_section_alignment (abfd,
								    asec);
	  bfd_vma start = obj_section_addr (objsec) & -align;
	  bfd_vma end = (obj_section_endaddr (objsec) + align - 1) & -align;

	  /* Match if either the entire memory region lies inside the
	     section (i.e. a mapping covering some pages of a large
	     segment) or the entire section lies inside the memory region
	     (i.e. a mapping covering multiple small sections).

	     This BFD was synthesized from reading target memory,
	     we don't want to omit that.  */
	  if (objfile->separate_debug_objfile_backlink == NULL
	      && ((vaddr >= start && vaddr + size <= end)
	          || (start >= vaddr && end <= vaddr + size))
	      && !(bfd_get_file_flags (abfd) & BFD_IN_MEMORY))
	    {
	      flags &= ~(SEC_LOAD | SEC_HAS_CONTENTS);
	      goto keep;	/* Break out of two nested for loops.  */
	    }
	}

    keep:;
    }
コード例 #6
0
ファイル: break-catch-sig.c プロジェクト: nds32/binutils
static const char *
signal_to_name_or_int (enum gdb_signal sig)
{
  const char *result = gdb_signal_to_name (sig);

  if (strcmp (result, "?") == 0)
    result = plongest (sig);

  return result;
}
コード例 #7
0
ファイル: mi-interp.c プロジェクト: ajinkya93/netbsd-src
static void
mi_tsv_created (const struct trace_state_variable *tsv)
{
  struct mi_interp *mi = top_level_interpreter_data ();

  target_terminal_ours ();

  fprintf_unfiltered (mi->event_channel, "tsv-created,"
		      "name=\"%s\",initial=\"%s\"\n",
		      tsv->name, plongest (tsv->initial_value));

  gdb_flush (mi->event_channel);
}
コード例 #8
0
ファイル: mi-interp.c プロジェクト: ajinkya93/netbsd-src
static void
mi_tsv_modified (const struct trace_state_variable *tsv)
{
  struct mi_interp *mi = top_level_interpreter_data ();
  struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());

  target_terminal_ours ();

  fprintf_unfiltered (mi->event_channel,
		      "tsv-modified");

  ui_out_redirect (mi_uiout, mi->event_channel);

  ui_out_field_string (mi_uiout, "name", tsv->name);
  ui_out_field_string (mi_uiout, "initial",
		       plongest (tsv->initial_value));
  if (tsv->value_known)
    ui_out_field_string (mi_uiout, "current", plongest (tsv->value));

  ui_out_redirect (mi_uiout, NULL);

  gdb_flush (mi->event_channel);
}
コード例 #9
0
ファイル: go-valprint.c プロジェクト: kraj/binutils-gdb
static void
print_go_string (struct type *type,
                 LONGEST embedded_offset, CORE_ADDR address,
                 struct ui_file *stream, int recurse,
                 struct value *val,
                 const struct value_print_options *options)
{
    struct gdbarch *gdbarch = get_type_arch (type);
    struct type *elt_ptr_type = TYPE_FIELD_TYPE (type, 0);
    struct type *elt_type = TYPE_TARGET_TYPE (elt_ptr_type);
    LONGEST length;
    /* TODO(dje): The encapsulation of what a pointer is belongs in value.c.
       I.e. If there's going to be unpack_pointer, there should be
       unpack_value_field_as_pointer.  Do this until we can get
       unpack_value_field_as_pointer.  */
    LONGEST addr;
    const gdb_byte *valaddr = value_contents_for_printing (val);


    if (! unpack_value_field_as_long (type, valaddr, embedded_offset, 0,
                                      val, &addr))
        error (_("Unable to read string address"));

    if (! unpack_value_field_as_long (type, valaddr, embedded_offset, 1,
                                      val, &length))
        error (_("Unable to read string length"));

    /* TODO(dje): Print address of struct or actual string?  */
    if (options->addressprint)
    {
        fputs_filtered (paddress (gdbarch, addr), stream);
        fputs_filtered (" ", stream);
    }

    if (length < 0)
    {
        fputs_filtered (_("<invalid length: "), stream);
        fputs_filtered (plongest (addr), stream);
        fputs_filtered (">", stream);
        return;
    }

    /* TODO(dje): Perhaps we should pass "UTF8" for ENCODING.
       The target encoding is a global switch.
       Either choice is problematic.  */
    val_print_string (elt_type, NULL, addr, length, stream, options);
}
コード例 #10
0
ファイル: aarch64-linux-tdep.c プロジェクト: ChrisG0x20/gdb
static int
aarch64_linux_syscall_record (struct regcache *regcache,
			      unsigned long svc_number)
{
  int ret = 0;
  enum gdb_syscall syscall_gdb;

  syscall_gdb =
    aarch64_canonicalize_syscall ((enum aarch64_syscall) svc_number);

  if (syscall_gdb < 0)
    {
      printf_unfiltered (_("Process record and replay target doesn't "
			   "support syscall number %s\n"),
			 plongest (svc_number));
      return -1;
    }

  if (syscall_gdb == gdb_sys_sigreturn
      || syscall_gdb == gdb_sys_rt_sigreturn)
   {
     if (aarch64_all_but_pc_registers_record (regcache))
       return -1;
     return 0;
   }

  ret = record_linux_system_call (syscall_gdb, regcache,
				  &aarch64_linux_record_tdep);
  if (ret != 0)
    return ret;

  /* Record the return value of the system call.  */
  if (record_full_arch_list_add_reg (regcache, AARCH64_X0_REGNUM))
    return -1;
  /* Record LR.  */
  if (record_full_arch_list_add_reg (regcache, AARCH64_LR_REGNUM))
    return -1;
  /* Record CPSR.  */
  if (record_full_arch_list_add_reg (regcache, AARCH64_CPSR_REGNUM))
    return -1;

  return 0;
}
コード例 #11
0
static int
i386_linux_intx80_sysenter_syscall_record (struct regcache *regcache)
{
  int ret;
  LONGEST syscall_native;
  enum gdb_syscall syscall_gdb;

  regcache_raw_read_signed (regcache, I386_EAX_REGNUM, &syscall_native);

  syscall_gdb = i386_canonicalize_syscall (syscall_native);

  if (syscall_gdb < 0)
    {
      printf_unfiltered (_("Process record and replay target doesn't "
                           "support syscall number %s\n"), 
			 plongest (syscall_native));
      return -1;
    }

  if (syscall_gdb == gdb_sys_sigreturn
      || syscall_gdb == gdb_sys_rt_sigreturn)
   {
     if (i386_all_but_ip_registers_record (regcache))
       return -1;
     return 0;
   }

  ret = record_linux_system_call (syscall_gdb, regcache,
				  &i386_linux_record_tdep);
  if (ret)
    return ret;

  /* Record the return value of the system call.  */
  if (record_arch_list_add_reg (regcache, I386_EAX_REGNUM))
    return -1;

  return 0;
}
コード例 #12
0
ファイル: p-typeprint.c プロジェクト: jon-turney/binutils-gdb
void
pascal_type_print_base (struct type *type, struct ui_file *stream, int show,
			int level, const struct type_print_options *flags)
{
  int i;
  int len;
  LONGEST lastval;
  enum
    {
      s_none, s_public, s_private, s_protected
    }
  section_type;

  QUIT;
  wrap_here ("    ");
  if (type == NULL)
    {
      fputs_filtered ("<type unknown>", stream);
      return;
    }

  /* void pointer */
  if ((TYPE_CODE (type) == TYPE_CODE_PTR)
      && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID))
    {
      fputs_filtered (TYPE_NAME (type) ? TYPE_NAME (type) : "pointer",
		      stream);
      return;
    }
  /* When SHOW is zero or less, and there is a valid type name, then always
     just print the type name directly from the type.  */

  if (show <= 0
      && TYPE_NAME (type) != NULL)
    {
      fputs_filtered (TYPE_NAME (type), stream);
      return;
    }

  type = check_typedef (type);

  switch (TYPE_CODE (type))
    {
    case TYPE_CODE_TYPEDEF:
    case TYPE_CODE_PTR:
    case TYPE_CODE_REF:
      /* case TYPE_CODE_FUNC:
         case TYPE_CODE_METHOD: */
      pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level,
			      flags);
      break;

    case TYPE_CODE_ARRAY:
      /* pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type),
	                                   stream, 0, 0);
         pascal_type_print_base (TYPE_TARGET_TYPE (type),
	                         stream, show, level);
         pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type),
	                                   stream, 0, 0, 0); */
      pascal_print_type (TYPE_TARGET_TYPE (type), NULL, stream, 0, 0, flags);
      break;

    case TYPE_CODE_FUNC:
    case TYPE_CODE_METHOD:
      /*
         pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
         only after args !!  */
      break;
    case TYPE_CODE_STRUCT:
      if (TYPE_NAME (type) != NULL)
	{
	  fputs_filtered (TYPE_NAME (type), stream);
	  fputs_filtered (" = ", stream);
	}
      if (HAVE_CPLUS_STRUCT (type))
	{
	  fprintf_filtered (stream, "class ");
	}
      else
	{
	  fprintf_filtered (stream, "record ");
	}
      goto struct_union;

    case TYPE_CODE_UNION:
      if (TYPE_NAME (type) != NULL)
	{
	  fputs_filtered (TYPE_NAME (type), stream);
	  fputs_filtered (" = ", stream);
	}
      fprintf_filtered (stream, "case <?> of ");

    struct_union:
      wrap_here ("    ");
      if (show < 0)
	{
	  /* If we just printed a tag name, no need to print anything else.  */
	  if (TYPE_NAME (type) == NULL)
	    fprintf_filtered (stream, "{...}");
	}
      else if (show > 0 || TYPE_NAME (type) == NULL)
	{
	  pascal_type_print_derivation_info (stream, type);

	  fprintf_filtered (stream, "\n");
	  if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
	    {
	      if (TYPE_STUB (type))
		fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
	      else
		fprintfi_filtered (level + 4, stream, "<no data fields>\n");
	    }

	  /* Start off with no specific section type, so we can print
	     one for the first field we find, and use that section type
	     thereafter until we find another type.  */

	  section_type = s_none;

	  /* If there is a base class for this type,
	     do not print the field that it occupies.  */

	  len = TYPE_NFIELDS (type);
	  for (i = TYPE_N_BASECLASSES (type); i < len; i++)
	    {
	      QUIT;
	      /* Don't print out virtual function table.  */
	      if ((startswith (TYPE_FIELD_NAME (type, i), "_vptr"))
		  && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
		continue;

	      /* If this is a pascal object or class we can print the
	         various section labels.  */

	      if (HAVE_CPLUS_STRUCT (type))
		{
		  if (TYPE_FIELD_PROTECTED (type, i))
		    {
		      if (section_type != s_protected)
			{
			  section_type = s_protected;
			  fprintfi_filtered (level + 2, stream,
					     "protected\n");
			}
		    }
		  else if (TYPE_FIELD_PRIVATE (type, i))
		    {
		      if (section_type != s_private)
			{
			  section_type = s_private;
			  fprintfi_filtered (level + 2, stream, "private\n");
			}
		    }
		  else
		    {
		      if (section_type != s_public)
			{
			  section_type = s_public;
			  fprintfi_filtered (level + 2, stream, "public\n");
			}
		    }
		}

	      print_spaces_filtered (level + 4, stream);
	      if (field_is_static (&TYPE_FIELD (type, i)))
		fprintf_filtered (stream, "static ");
	      pascal_print_type (TYPE_FIELD_TYPE (type, i),
				 TYPE_FIELD_NAME (type, i),
				 stream, show - 1, level + 4, flags);
	      if (!field_is_static (&TYPE_FIELD (type, i))
		  && TYPE_FIELD_PACKED (type, i))
		{
		  /* It is a bitfield.  This code does not attempt
		     to look at the bitpos and reconstruct filler,
		     unnamed fields.  This would lead to misleading
		     results if the compiler does not put out fields
		     for such things (I don't know what it does).  */
		  fprintf_filtered (stream, " : %d",
				    TYPE_FIELD_BITSIZE (type, i));
		}
	      fprintf_filtered (stream, ";\n");
	    }

	  /* If there are both fields and methods, put a space between.  */
	  len = TYPE_NFN_FIELDS (type);
	  if (len && section_type != s_none)
	    fprintf_filtered (stream, "\n");

	  /* Object pascal: print out the methods.  */

	  for (i = 0; i < len; i++)
	    {
	      struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
	      int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
	      const char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);

	      /* this is GNU C++ specific
	         how can we know constructor/destructor?
	         It might work for GNU pascal.  */
	      for (j = 0; j < len2; j++)
		{
		  const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);

		  int is_constructor = (startswith (physname, "__ct__"));
		  int is_destructor = (startswith (physname, "__dt__"));

		  QUIT;
		  if (TYPE_FN_FIELD_PROTECTED (f, j))
		    {
		      if (section_type != s_protected)
			{
			  section_type = s_protected;
			  fprintfi_filtered (level + 2, stream,
					     "protected\n");
			}
		    }
		  else if (TYPE_FN_FIELD_PRIVATE (f, j))
		    {
		      if (section_type != s_private)
			{
			  section_type = s_private;
			  fprintfi_filtered (level + 2, stream, "private\n");
			}
		    }
		  else
		    {
		      if (section_type != s_public)
			{
			  section_type = s_public;
			  fprintfi_filtered (level + 2, stream, "public\n");
			}
		    }

		  print_spaces_filtered (level + 4, stream);
		  if (TYPE_FN_FIELD_STATIC_P (f, j))
		    fprintf_filtered (stream, "static ");
		  if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
		    {
		      /* Keep GDB from crashing here.  */
		      fprintf_filtered (stream, "<undefined type> %s;\n",
					TYPE_FN_FIELD_PHYSNAME (f, j));
		      break;
		    }

		  if (is_constructor)
		    {
		      fprintf_filtered (stream, "constructor ");
		    }
		  else if (is_destructor)
		    {
		      fprintf_filtered (stream, "destructor  ");
		    }
		  else if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) != 0
			   && TYPE_CODE (TYPE_TARGET_TYPE (
				TYPE_FN_FIELD_TYPE (f, j))) != TYPE_CODE_VOID)
		    {
		      fprintf_filtered (stream, "function  ");
		    }
		  else
		    {
		      fprintf_filtered (stream, "procedure ");
		    }
		  /* This does not work, no idea why !!  */

		  pascal_type_print_method_args (physname,
						 method_name,
						 stream);

		  if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) != 0
		      && TYPE_CODE (TYPE_TARGET_TYPE (
			   TYPE_FN_FIELD_TYPE (f, j))) != TYPE_CODE_VOID)
		    {
		      fputs_filtered (" : ", stream);
		      type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
				  "", stream, -1);
		    }
		  if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
		    fprintf_filtered (stream, "; virtual");

		  fprintf_filtered (stream, ";\n");
		}
	    }
	  fprintfi_filtered (level, stream, "end");
	}
      break;

    case TYPE_CODE_ENUM:
      if (TYPE_NAME (type) != NULL)
	{
	  fputs_filtered (TYPE_NAME (type), stream);
	  if (show > 0)
	    fputs_filtered (" ", stream);
	}
      /* enum is just defined by
         type enume_name = (enum_member1,enum_member2,...)  */
      fprintf_filtered (stream, " = ");
      wrap_here ("    ");
      if (show < 0)
	{
	  /* If we just printed a tag name, no need to print anything else.  */
	  if (TYPE_NAME (type) == NULL)
	    fprintf_filtered (stream, "(...)");
	}
      else if (show > 0 || TYPE_NAME (type) == NULL)
	{
	  fprintf_filtered (stream, "(");
	  len = TYPE_NFIELDS (type);
	  lastval = 0;
	  for (i = 0; i < len; i++)
	    {
	      QUIT;
	      if (i)
		fprintf_filtered (stream, ", ");
	      wrap_here ("    ");
	      fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
	      if (lastval != TYPE_FIELD_ENUMVAL (type, i))
		{
		  fprintf_filtered (stream,
				    " := %s",
				    plongest (TYPE_FIELD_ENUMVAL (type, i)));
		  lastval = TYPE_FIELD_ENUMVAL (type, i);
		}
	      lastval++;
	    }
	  fprintf_filtered (stream, ")");
	}
      break;

    case TYPE_CODE_VOID:
      fprintf_filtered (stream, "void");
      break;

    case TYPE_CODE_UNDEF:
      fprintf_filtered (stream, "record <unknown>");
      break;

    case TYPE_CODE_ERROR:
      fprintf_filtered (stream, "%s", TYPE_ERROR_NAME (type));
      break;

      /* this probably does not work for enums.  */
    case TYPE_CODE_RANGE:
      {
	struct type *target = TYPE_TARGET_TYPE (type);

	print_type_scalar (target, TYPE_LOW_BOUND (type), stream);
	fputs_filtered ("..", stream);
	print_type_scalar (target, TYPE_HIGH_BOUND (type), stream);
      }
      break;

    case TYPE_CODE_SET:
      fputs_filtered ("set of ", stream);
      pascal_print_type (TYPE_INDEX_TYPE (type), "", stream,
			 show - 1, level, flags);
      break;

    case TYPE_CODE_STRING:
      fputs_filtered ("String", stream);
      break;

    default:
      /* Handle types not explicitly handled by the other cases,
         such as fundamental types.  For these, just print whatever
         the type name is, as recorded in the type itself.  If there
         is no type name, then complain.  */
      if (TYPE_NAME (type) != NULL)
	{
	  fputs_filtered (TYPE_NAME (type), stream);
	}
      else
	{
	  /* At least for dump_symtab, it is important that this not be
	     an error ().  */
	  fprintf_filtered (stream, "<invalid unnamed pascal type code %d>",
			    TYPE_CODE (type));
	}
      break;
    }
}
コード例 #13
0
void
c_type_print_base (struct type *type, struct ui_file *stream,
		   int show, int level)
{
  int i;
  int len, real_len;
  enum
    {
      s_none, s_public, s_private, s_protected
    }
  section_type;
  int need_access_label = 0;
  int j, len2;

  QUIT;

  wrap_here ("    ");
  if (type == NULL)
    {
      fputs_filtered (_("<type unknown>"), stream);
      return;
    }

  /* When SHOW is zero or less, and there is a valid type name, then
     always just print the type name directly from the type.  */
  /* If we have "typedef struct foo {. . .} bar;" do we want to print
     it as "struct foo" or as "bar"?  Pick the latter, because C++
     folk tend to expect things like "class5 *foo" rather than "struct
     class5 *foo".  */

  if (show <= 0
      && TYPE_NAME (type) != NULL)
    {
      c_type_print_modifier (type, stream, 0, 1);
      fputs_filtered (TYPE_NAME (type), stream);
      return;
    }

  CHECK_TYPEDEF (type);

  switch (TYPE_CODE (type))
    {
    case TYPE_CODE_TYPEDEF:
      /* If we get here, the typedef doesn't have a name, and we
	 couldn't resolve TYPE_TARGET_TYPE.  Not much we can do.  */
      gdb_assert (TYPE_NAME (type) == NULL);
      gdb_assert (TYPE_TARGET_TYPE (type) == NULL);
      fprintf_filtered (stream, _("<unnamed typedef>"));
      break;

    case TYPE_CODE_ARRAY:
    case TYPE_CODE_PTR:
    case TYPE_CODE_MEMBERPTR:
    case TYPE_CODE_REF:
    case TYPE_CODE_FUNC:
    case TYPE_CODE_METHOD:
    case TYPE_CODE_METHODPTR:
      c_type_print_base (TYPE_TARGET_TYPE (type),
			 stream, show, level);
      break;

    case TYPE_CODE_STRUCT:
    case TYPE_CODE_UNION:
      c_type_print_modifier (type, stream, 0, 1);
      if (TYPE_CODE (type) == TYPE_CODE_UNION)
	fprintf_filtered (stream, "union ");
      else if (TYPE_DECLARED_CLASS (type))
	fprintf_filtered (stream, "class ");
      else
	fprintf_filtered (stream, "struct ");

      /* Print the tag if it exists.  The HP aCC compiler emits a
         spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed
         enum}" tag for unnamed struct/union/enum's, which we don't
         want to print.  */
      if (TYPE_TAG_NAME (type) != NULL
	  && strncmp (TYPE_TAG_NAME (type), "{unnamed", 8))
	{
	  fputs_filtered (TYPE_TAG_NAME (type), stream);
	  if (show > 0)
	    fputs_filtered (" ", stream);
	}
      wrap_here ("    ");
      if (show < 0)
	{
	  /* If we just printed a tag name, no need to print anything
	     else.  */
	  if (TYPE_TAG_NAME (type) == NULL)
	    fprintf_filtered (stream, "{...}");
	}
      else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
	{
	  struct type *basetype;
	  int vptr_fieldno;

	  cp_type_print_derivation_info (stream, type);

	  fprintf_filtered (stream, "{\n");
	  if (TYPE_NFIELDS (type) == 0 && TYPE_NFN_FIELDS (type) == 0
	      && TYPE_TYPEDEF_FIELD_COUNT (type) == 0)
	    {
	      if (TYPE_STUB (type))
		fprintfi_filtered (level + 4, stream,
				   _("<incomplete type>\n"));
	      else
		fprintfi_filtered (level + 4, stream,
				   _("<no data fields>\n"));
	    }

	  /* Start off with no specific section type, so we can print
	     one for the first field we find, and use that section type
	     thereafter until we find another type.  */

	  section_type = s_none;

	  /* For a class, if all members are private, there's no need
	     for a "private:" label; similarly, for a struct or union
	     masquerading as a class, if all members are public, there's
	     no need for a "public:" label.  */

	  if (TYPE_DECLARED_CLASS (type))
	    {
	      QUIT;
	      len = TYPE_NFIELDS (type);
	      for (i = TYPE_N_BASECLASSES (type); i < len; i++)
		if (!TYPE_FIELD_PRIVATE (type, i))
		  {
		    need_access_label = 1;
		    break;
		  }
	      QUIT;
	      if (!need_access_label)
		{
		  len2 = TYPE_NFN_FIELDS (type);
		  for (j = 0; j < len2; j++)
		    {
		      len = TYPE_FN_FIELDLIST_LENGTH (type, j);
		      for (i = 0; i < len; i++)
			if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
									j), i))
			  {
			    need_access_label = 1;
			    break;
			  }
		      if (need_access_label)
			break;
		    }
		}
	    }
	  else
	    {
	      QUIT;
	      len = TYPE_NFIELDS (type);
	      for (i = TYPE_N_BASECLASSES (type); i < len; i++)
		if (TYPE_FIELD_PRIVATE (type, i)
		    || TYPE_FIELD_PROTECTED (type, i))
		  {
		    need_access_label = 1;
		    break;
		  }
	      QUIT;
	      if (!need_access_label)
		{
		  len2 = TYPE_NFN_FIELDS (type);
		  for (j = 0; j < len2; j++)
		    {
		      QUIT;
		      len = TYPE_FN_FIELDLIST_LENGTH (type, j);
		      for (i = 0; i < len; i++)
			if (TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type,
									 j), i)
			    || TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
									  j),
						      i))
			  {
			    need_access_label = 1;
			    break;
			  }
		      if (need_access_label)
			break;
		    }
		}
	    }

	  /* If there is a base class for this type,
	     do not print the field that it occupies.  */

	  len = TYPE_NFIELDS (type);
	  vptr_fieldno = get_vptr_fieldno (type, &basetype);
	  for (i = TYPE_N_BASECLASSES (type); i < len; i++)
	    {
	      QUIT;

	      /* If we have a virtual table pointer, omit it.  Even if
		 virtual table pointers are not specifically marked in
		 the debug info, they should be artificial.  */
	      if ((i == vptr_fieldno && type == basetype)
		  || TYPE_FIELD_ARTIFICIAL (type, i))
		continue;

	      if (need_access_label)
		{
		  if (TYPE_FIELD_PROTECTED (type, i))
		    {
		      if (section_type != s_protected)
			{
			  section_type = s_protected;
			  fprintfi_filtered (level + 2, stream,
					     "protected:\n");
			}
		    }
		  else if (TYPE_FIELD_PRIVATE (type, i))
		    {
		      if (section_type != s_private)
			{
			  section_type = s_private;
			  fprintfi_filtered (level + 2, stream,
					     "private:\n");
			}
		    }
		  else
		    {
		      if (section_type != s_public)
			{
			  section_type = s_public;
			  fprintfi_filtered (level + 2, stream,
					     "public:\n");
			}
		    }
		}

	      print_spaces_filtered (level + 4, stream);
	      if (field_is_static (&TYPE_FIELD (type, i)))
		fprintf_filtered (stream, "static ");
	      c_print_type (TYPE_FIELD_TYPE (type, i),
			    TYPE_FIELD_NAME (type, i),
			    stream, show - 1, level + 4);
	      if (!field_is_static (&TYPE_FIELD (type, i))
		  && TYPE_FIELD_PACKED (type, i))
		{
		  /* It is a bitfield.  This code does not attempt
		     to look at the bitpos and reconstruct filler,
		     unnamed fields.  This would lead to misleading
		     results if the compiler does not put out fields
		     for such things (I don't know what it does).  */
		  fprintf_filtered (stream, " : %d",
				    TYPE_FIELD_BITSIZE (type, i));
		}
	      fprintf_filtered (stream, ";\n");
	    }

	  /* If there are both fields and methods, put a blank line
	     between them.  Make sure to count only method that we
	     will display; artificial methods will be hidden.  */
	  len = TYPE_NFN_FIELDS (type);
	  real_len = 0;
	  for (i = 0; i < len; i++)
	    {
	      struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
	      int len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
	      int j;

	      for (j = 0; j < len2; j++)
		if (!TYPE_FN_FIELD_ARTIFICIAL (f, j))
		  real_len++;
	    }
	  if (real_len > 0 && section_type != s_none)
	    fprintf_filtered (stream, "\n");

	  /* C++: print out the methods.  */
	  for (i = 0; i < len; i++)
	    {
	      struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
	      int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
	      const char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);
	      const char *name = type_name_no_tag (type);
	      int is_constructor = name && strcmp (method_name,
						   name) == 0;

	      for (j = 0; j < len2; j++)
		{
		  const char *mangled_name;
		  char *demangled_name;
		  struct cleanup *inner_cleanup;
		  const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
		  int is_full_physname_constructor =
		    is_constructor_name (physname) 
		    || is_destructor_name (physname)
		    || method_name[0] == '~';

		  /* Do not print out artificial methods.  */
		  if (TYPE_FN_FIELD_ARTIFICIAL (f, j))
		    continue;

		  inner_cleanup = make_cleanup (null_cleanup, NULL);

		  QUIT;
		  if (TYPE_FN_FIELD_PROTECTED (f, j))
		    {
		      if (section_type != s_protected)
			{
			  section_type = s_protected;
			  fprintfi_filtered (level + 2, stream,
					     "protected:\n");
			}
		    }
		  else if (TYPE_FN_FIELD_PRIVATE (f, j))
		    {
		      if (section_type != s_private)
			{
			  section_type = s_private;
			  fprintfi_filtered (level + 2, stream,
					     "private:\n");
			}
		    }
		  else
		    {
		      if (section_type != s_public)
			{
			  section_type = s_public;
			  fprintfi_filtered (level + 2, stream,
					     "public:\n");
			}
		    }

		  print_spaces_filtered (level + 4, stream);
		  if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
		    fprintf_filtered (stream, "virtual ");
		  else if (TYPE_FN_FIELD_STATIC_P (f, j))
		    fprintf_filtered (stream, "static ");
		  if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
		    {
		      /* Keep GDB from crashing here.  */
		      fprintf_filtered (stream,
					_("<undefined type> %s;\n"),
					TYPE_FN_FIELD_PHYSNAME (f, j));
		      break;
		    }
		  else if (!is_constructor	/* Constructors don't
						   have declared
						   types.  */
			   && !is_full_physname_constructor  /* " " */
			   && !is_type_conversion_operator (type, i, j))
		    {
		      type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
				  "", stream, -1);
		      fputs_filtered (" ", stream);
		    }
		  if (TYPE_FN_FIELD_STUB (f, j))
		    {
		      char *tem;

		      /* Build something we can demangle.  */
		      tem = gdb_mangle_name (type, i, j);
		      make_cleanup (xfree, tem);
		      mangled_name = tem;
		    }
		  else
		    mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j);

		  demangled_name =
		    cplus_demangle (mangled_name,
				    DMGL_ANSI | DMGL_PARAMS);
		  if (demangled_name == NULL)
		    {
		      /* In some cases (for instance with the HP
		         demangling), if a function has more than 10
		         arguments, the demangling will fail.
		         Let's try to reconstruct the function
		         signature from the symbol information.  */
		      if (!TYPE_FN_FIELD_STUB (f, j))
			{
			  int staticp = TYPE_FN_FIELD_STATIC_P (f, j);
			  struct type *mtype = TYPE_FN_FIELD_TYPE (f, j);

			  cp_type_print_method_args (mtype,
						     "",
						     method_name,
						     staticp,
						     stream);
			}
		      else
			fprintf_filtered (stream,
					  _("<badly mangled name '%s'>"),
					  mangled_name);
		    }
		  else
		    {
		      char *p;
		      char *demangled_no_class
			= remove_qualifiers (demangled_name);

		      /* Get rid of the `static' appended by the
			 demangler.  */
		      p = strstr (demangled_no_class, " static");
		      if (p != NULL)
			{
			  int length = p - demangled_no_class;
			  char *demangled_no_static;

			  demangled_no_static
			    = (char *) xmalloc (length + 1);
			  strncpy (demangled_no_static,
				   demangled_no_class, length);
			  *(demangled_no_static + length) = '\0';
			  fputs_filtered (demangled_no_static, stream);
			  xfree (demangled_no_static);
			}
		      else
			fputs_filtered (demangled_no_class, stream);
		      xfree (demangled_name);
		    }

		  do_cleanups (inner_cleanup);

		  fprintf_filtered (stream, ";\n");
		}
	    }

	  /* Print typedefs defined in this class.  */

	  if (TYPE_TYPEDEF_FIELD_COUNT (type) != 0)
	    {
	      if (TYPE_NFIELDS (type) != 0 || TYPE_NFN_FIELDS (type) != 0)
		fprintf_filtered (stream, "\n");

	      for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); i++)
		{
		  struct type *target = TYPE_TYPEDEF_FIELD_TYPE (type, i);

		  /* Dereference the typedef declaration itself.  */
		  gdb_assert (TYPE_CODE (target) == TYPE_CODE_TYPEDEF);
		  target = TYPE_TARGET_TYPE (target);

		  print_spaces_filtered (level + 4, stream);
		  fprintf_filtered (stream, "typedef ");
		  c_print_type (target, TYPE_TYPEDEF_FIELD_NAME (type, i),
				stream, show - 1, level + 4);
		  fprintf_filtered (stream, ";\n");
		}
	    }

	  fprintfi_filtered (level, stream, "}");

	  if (TYPE_LOCALTYPE_PTR (type) && show >= 0)
	    fprintfi_filtered (level,
			       stream, _(" (Local at %s:%d)\n"),
			       TYPE_LOCALTYPE_FILE (type),
			       TYPE_LOCALTYPE_LINE (type));
	}
      break;

    case TYPE_CODE_ENUM:
      c_type_print_modifier (type, stream, 0, 1);
      fprintf_filtered (stream, "enum ");
      /* Print the tag name if it exists.
         The aCC compiler emits a spurious 
         "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}"
         tag for unnamed struct/union/enum's, which we don't
         want to print.  */
      if (TYPE_TAG_NAME (type) != NULL
	  && strncmp (TYPE_TAG_NAME (type), "{unnamed", 8))
	{
	  fputs_filtered (TYPE_TAG_NAME (type), stream);
	  if (show > 0)
	    fputs_filtered (" ", stream);
	}

      wrap_here ("    ");
      if (show < 0)
	{
	  /* If we just printed a tag name, no need to print anything
	     else.  */
	  if (TYPE_TAG_NAME (type) == NULL)
	    fprintf_filtered (stream, "{...}");
	}
      else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
	{
	  LONGEST lastval = 0;

	  fprintf_filtered (stream, "{");
	  len = TYPE_NFIELDS (type);
	  for (i = 0; i < len; i++)
	    {
	      QUIT;
	      if (i)
		fprintf_filtered (stream, ", ");
	      wrap_here ("    ");
	      fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
	      if (lastval != TYPE_FIELD_ENUMVAL (type, i))
		{
		  fprintf_filtered (stream, " = %s",
				    plongest (TYPE_FIELD_ENUMVAL (type, i)));
		  lastval = TYPE_FIELD_ENUMVAL (type, i);
		}
	      lastval++;
	    }
	  fprintf_filtered (stream, "}");
	}
      break;

    case TYPE_CODE_VOID:
      fprintf_filtered (stream, "void");
      break;

    case TYPE_CODE_UNDEF:
      fprintf_filtered (stream, _("struct <unknown>"));
      break;

    case TYPE_CODE_ERROR:
      fprintf_filtered (stream, "%s", TYPE_ERROR_NAME (type));
      break;

    case TYPE_CODE_RANGE:
      /* This should not occur.  */
      fprintf_filtered (stream, _("<range type>"));
      break;

    case TYPE_CODE_NAMESPACE:
      fputs_filtered ("namespace ", stream);
      fputs_filtered (TYPE_TAG_NAME (type), stream);
      break;

    default:
      /* Handle types not explicitly handled by the other cases, such
         as fundamental types.  For these, just print whatever the
         type name is, as recorded in the type itself.  If there is no
         type name, then complain.  */
      if (TYPE_NAME (type) != NULL)
	{
	  c_type_print_modifier (type, stream, 0, 1);
	  fputs_filtered (TYPE_NAME (type), stream);
	}
      else
	{
	  /* At least for dump_symtab, it is important that this not
	     be an error ().  */
	  fprintf_filtered (stream, _("<invalid type code %d>"),
			    TYPE_CODE (type));
	}
      break;
    }
}
コード例 #14
0
void
c_type_print_varspec_suffix (struct type *type,
			     struct ui_file *stream,
			     int show, int passed_a_ptr,
			     int demangled_args)
{
  if (type == 0)
    return;

  if (TYPE_NAME (type) && show <= 0)
    return;

  QUIT;

  switch (TYPE_CODE (type))
    {
    case TYPE_CODE_ARRAY:
      {
	LONGEST low_bound, high_bound;
	int is_vector = TYPE_VECTOR (type);

	if (passed_a_ptr)
	  fprintf_filtered (stream, ")");

	fprintf_filtered (stream, (is_vector ?
				   "__attribute__ ((vector_size(" : "["));
	if (get_array_bounds (type, &low_bound, &high_bound))
	  fprintf_filtered (stream, "%s", 
			    plongest (high_bound - low_bound + 1));
	fprintf_filtered (stream, (is_vector ? ")))" : "]"));

	c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream,
				     show, 0, 0);
      }
      break;

    case TYPE_CODE_MEMBERPTR:
      c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream,
				   show, 0, 0);
      break;

    case TYPE_CODE_METHODPTR:
      fprintf_filtered (stream, ")");
      c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream,
				   show, 0, 0);
      break;

    case TYPE_CODE_PTR:
    case TYPE_CODE_REF:
      c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream,
				   show, 1, 0);
      break;

    case TYPE_CODE_METHOD:
    case TYPE_CODE_FUNC:
      if (passed_a_ptr)
	fprintf_filtered (stream, ")");
      if (!demangled_args)
	c_type_print_args (type, stream, 0, current_language->la_language);
      c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream,
				   show, passed_a_ptr, 0);
      break;

    case TYPE_CODE_TYPEDEF:
      c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream,
				   show, passed_a_ptr, 0);
      break;

    case TYPE_CODE_UNDEF:
    case TYPE_CODE_STRUCT:
    case TYPE_CODE_UNION:
    case TYPE_CODE_ENUM:
    case TYPE_CODE_INT:
    case TYPE_CODE_FLT:
    case TYPE_CODE_VOID:
    case TYPE_CODE_ERROR:
    case TYPE_CODE_CHAR:
    case TYPE_CODE_BOOL:
    case TYPE_CODE_SET:
    case TYPE_CODE_RANGE:
    case TYPE_CODE_STRING:
    case TYPE_CODE_COMPLEX:
    case TYPE_CODE_NAMESPACE:
    case TYPE_CODE_DECFLOAT:
      /* These types do not need a suffix.  They are listed so that
         gcc -Wall will report types that may not have been
         considered.  */
      break;
    default:
      error (_("type not handled in c_type_print_varspec_suffix()"));
      break;
    }
}
コード例 #15
0
void
pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
				  int show, int passed_a_ptr)
{
  if (type == 0)
    return;

  if (TYPE_NAME (type) && show <= 0)
    return;

  QUIT;

  switch (TYPE_CODE (type))
    {
    case TYPE_CODE_PTR:
      fprintf_filtered (stream, "^");
      pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
      break;			/* Pointer should be handled normally
				   in pascal.  */

    case TYPE_CODE_METHOD:
      if (passed_a_ptr)
	fprintf_filtered (stream, "(");
      if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
	{
	  fprintf_filtered (stream, "function  ");
	}
      else
	{
	  fprintf_filtered (stream, "procedure ");
	}

      if (passed_a_ptr)
	{
	  fprintf_filtered (stream, " ");
	  pascal_type_print_base (TYPE_DOMAIN_TYPE (type),
				  stream, 0, passed_a_ptr);
	  fprintf_filtered (stream, "::");
	}
      break;

    case TYPE_CODE_REF:
      pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
      fprintf_filtered (stream, "&");
      break;

    case TYPE_CODE_FUNC:
      if (passed_a_ptr)
	fprintf_filtered (stream, "(");

      if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
	{
	  fprintf_filtered (stream, "function  ");
	}
      else
	{
	  fprintf_filtered (stream, "procedure ");
	}

      break;

    case TYPE_CODE_ARRAY:
      if (passed_a_ptr)
	fprintf_filtered (stream, "(");
      fprintf_filtered (stream, "array ");
      if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0
	&& !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
	fprintf_filtered (stream, "[%s..%s] ",
			  plongest (TYPE_ARRAY_LOWER_BOUND_VALUE (type)),
			  plongest (TYPE_ARRAY_UPPER_BOUND_VALUE (type)));
      fprintf_filtered (stream, "of ");
      break;

    case TYPE_CODE_UNDEF:
    case TYPE_CODE_STRUCT:
    case TYPE_CODE_UNION:
    case TYPE_CODE_ENUM:
    case TYPE_CODE_INT:
    case TYPE_CODE_FLT:
    case TYPE_CODE_VOID:
    case TYPE_CODE_ERROR:
    case TYPE_CODE_CHAR:
    case TYPE_CODE_BOOL:
    case TYPE_CODE_SET:
    case TYPE_CODE_RANGE:
    case TYPE_CODE_STRING:
    case TYPE_CODE_BITSTRING:
    case TYPE_CODE_COMPLEX:
    case TYPE_CODE_TYPEDEF:
      /* These types need no prefix.  They are listed here so that
         gcc -Wall will reveal any types that haven't been handled.  */
      break;
    default:
      error (_("type not handled in pascal_type_print_varspec_prefix()"));
      break;
    }
}
コード例 #16
0
ファイル: somread.c プロジェクト: mstorsjo/binutils-gdb
static void
som_symtab_read (bfd *abfd, struct objfile *objfile,
		 struct section_offsets *section_offsets)
{
  struct cleanup *cleanup;
  struct gdbarch *gdbarch = get_objfile_arch (objfile);
  unsigned int number_of_symbols;
  int val, dynamic;
  char *stringtab;
  asection *shlib_info;
  struct som_external_symbol_dictionary_record *buf, *bufp, *endbufp;
  char *symname;
  CONST int symsize = sizeof (struct som_external_symbol_dictionary_record);


#define text_offset ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile))
#define data_offset ANOFFSET (section_offsets, SECT_OFF_DATA (objfile))

  number_of_symbols = bfd_get_symcount (abfd);

  /* Allocate a buffer to read in the debug info.
     We avoid using alloca because the memory size could be so large
     that we could hit the stack size limit.  */
  buf = xmalloc (symsize * number_of_symbols);
  cleanup = make_cleanup (xfree, buf);
  bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
  val = bfd_bread (buf, symsize * number_of_symbols, abfd);
  if (val != symsize * number_of_symbols)
    error (_("Couldn't read symbol dictionary!"));

  /* Allocate a buffer to read in the som stringtab section of
     the debugging info.  Again, we avoid using alloca because
     the data could be so large that we could potentially hit
     the stack size limitat.  */
  stringtab = xmalloc (obj_som_stringtab_size (abfd));
  make_cleanup (xfree, stringtab);
  bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
  val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd);
  if (val != obj_som_stringtab_size (abfd))
    error (_("Can't read in HP string table."));

  /* We need to determine if objfile is a dynamic executable (so we
     can do the right thing for ST_ENTRY vs ST_CODE symbols).

     There's nothing in the header which easily allows us to do
     this.

     This code used to rely upon the existence of a $SHLIB_INFO$
     section to make this determination.  HP claims that it is
     more accurate to check for a nonzero text offset, but they
     have not provided any information about why that test is
     more accurate.  */
  dynamic = (text_offset != 0);

  endbufp = buf + number_of_symbols;
  for (bufp = buf; bufp < endbufp; ++bufp)
    {
      enum minimal_symbol_type ms_type;
      unsigned int flags = bfd_getb32 (bufp->flags);
      unsigned int symbol_type
	= (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
      unsigned int symbol_scope
	= (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK;
      CORE_ADDR symbol_value = bfd_getb32 (bufp->symbol_value);
      asection *section = NULL;

      QUIT;

      /* Compute the section.  */
      switch (symbol_scope)
	{
	case SS_EXTERNAL:
	  if (symbol_type != ST_STORAGE)
	    section = bfd_und_section_ptr;
	  else
	    section = bfd_com_section_ptr;
	  break;

	case SS_UNSAT:
	  if (symbol_type != ST_STORAGE)
	    section = bfd_und_section_ptr;
	  else
	    section = bfd_com_section_ptr;
	  break;

	case SS_UNIVERSAL:
	  section = bfd_section_from_som_symbol (abfd, bufp);
	  break;

	case SS_LOCAL:
	  section = bfd_section_from_som_symbol (abfd, bufp);
	  break;
	}

      switch (symbol_scope)
	{
	case SS_UNIVERSAL:
	case SS_EXTERNAL:
	  switch (symbol_type)
	    {
	    case ST_SYM_EXT:
	    case ST_ARG_EXT:
	      continue;

	    case ST_CODE:
	    case ST_PRI_PROG:
	    case ST_SEC_PROG:
	    case ST_MILLICODE:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_ENTRY:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      /* For a dynamic executable, ST_ENTRY symbols are
	         the stubs, while the ST_CODE symbol is the real
	         function.  */
	      if (dynamic)
		ms_type = mst_solib_trampoline;
	      else
		ms_type = mst_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_STUB:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_solib_trampoline;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_DATA:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      symbol_value += data_offset;
	      ms_type = mst_data;
	      break;
	    default:
	      continue;
	    }
	  break;

#if 0
	  /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!).  */
	case SS_GLOBAL:
#endif
	case SS_LOCAL:
	  switch (symbol_type)
	    {
	    case ST_SYM_EXT:
	    case ST_ARG_EXT:
	      continue;

	    case ST_CODE:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_file_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);

	    check_strange_names:
	      /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
	         label prefixes for stabs, constant data, etc.  So we need
	         only filter out L$ symbols which are left in due to
	         limitations in how GAS generates SOM relocations.

	         When linking in the HPUX C-library the HP linker has
	         the nasty habit of placing section symbols from the literal
	         subspaces in the middle of the program's text.  Filter
	         those out as best we can.  Check for first and last character
	         being '$'.

	         And finally, the newer HP compilers emit crud like $PIC_foo$N
	         in some circumstance (PIC code I guess).  It's also claimed
	         that they emit D$ symbols too.  What stupidity.  */
	      if ((symname[0] == 'L' && symname[1] == '$')
	      || (symname[0] == '$' && symname[strlen (symname) - 1] == '$')
		  || (symname[0] == 'D' && symname[1] == '$')
		  || (strncmp (symname, "L0\001", 3) == 0)
		  || (strncmp (symname, "$PIC", 4) == 0))
		continue;
	      break;

	    case ST_PRI_PROG:
	    case ST_SEC_PROG:
	    case ST_MILLICODE:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_file_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_ENTRY:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      /* SS_LOCAL symbols in a shared library do not have
		 export stubs, so we do not have to worry about
		 using mst_file_text vs mst_solib_trampoline here like
		 we do for SS_UNIVERSAL and SS_EXTERNAL symbols above.  */
	      ms_type = mst_file_text;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;

	    case ST_STUB:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      ms_type = mst_solib_trampoline;
	      symbol_value += text_offset;
	      symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value);
	      break;


	    case ST_DATA:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      symbol_value += data_offset;
	      ms_type = mst_file_data;
	      goto check_strange_names;

	    default:
	      continue;
	    }
	  break;

	  /* This can happen for common symbols when -E is passed to the
	     final link.  No idea _why_ that would make the linker force
	     common symbols to have an SS_UNSAT scope, but it does.

	     This also happens for weak symbols, but their type is
	     ST_DATA.  */
	case SS_UNSAT:
	  switch (symbol_type)
	    {
	    case ST_STORAGE:
	    case ST_DATA:
	      symname = bfd_getb32 (bufp->name) + stringtab;
	      symbol_value += data_offset;
	      ms_type = mst_data;
	      break;

	    default:
	      continue;
	    }
	  break;

	default:
	  continue;
	}

      if (bfd_getb32 (bufp->name) > obj_som_stringtab_size (abfd))
	error (_("Invalid symbol data; bad HP string table offset: %s"),
	       plongest (bfd_getb32 (bufp->name)));

      if (bfd_is_const_section (section))
	{
	  struct obj_section *iter;

	  ALL_OBJFILE_OSECTIONS (objfile, iter)
	    {
	      if (bfd_is_const_section (iter->the_bfd_section))
		continue;

	      if (obj_section_addr (iter) <= symbol_value
		  && symbol_value < obj_section_endaddr (iter))
		{
		  section = iter->the_bfd_section;
		  break;
		}
	    }
	}

      prim_record_minimal_symbol_and_info (symname, symbol_value, ms_type,
					   gdb_bfd_section_index (objfile->obfd,
								  section),
					   objfile);
    }

  do_cleanups (cleanup);
}
コード例 #17
0
ファイル: expprint.c プロジェクト: 5kg/gdb
int
dump_subexp_body_standard (struct expression *exp, 
			   struct ui_file *stream, int elt)
{
  int opcode = exp->elts[elt++].opcode;

  switch (opcode)
    {
    case TERNOP_COND:
    case TERNOP_SLICE:
      elt = dump_subexp (exp, stream, elt);
      /* FALL THROUGH */
    case BINOP_ADD:
    case BINOP_SUB:
    case BINOP_MUL:
    case BINOP_DIV:
    case BINOP_REM:
    case BINOP_MOD:
    case BINOP_LSH:
    case BINOP_RSH:
    case BINOP_LOGICAL_AND:
    case BINOP_LOGICAL_OR:
    case BINOP_BITWISE_AND:
    case BINOP_BITWISE_IOR:
    case BINOP_BITWISE_XOR:
    case BINOP_EQUAL:
    case BINOP_NOTEQUAL:
    case BINOP_LESS:
    case BINOP_GTR:
    case BINOP_LEQ:
    case BINOP_GEQ:
    case BINOP_REPEAT:
    case BINOP_ASSIGN:
    case BINOP_COMMA:
    case BINOP_SUBSCRIPT:
    case BINOP_EXP:
    case BINOP_MIN:
    case BINOP_MAX:
    case BINOP_INTDIV:
    case BINOP_ASSIGN_MODIFY:
    case BINOP_VAL:
    case BINOP_CONCAT:
    case BINOP_IN:
    case BINOP_RANGE:
    case BINOP_END:
    case STRUCTOP_MEMBER:
    case STRUCTOP_MPTR:
      elt = dump_subexp (exp, stream, elt);
      /* FALL THROUGH */
    case UNOP_NEG:
    case UNOP_LOGICAL_NOT:
    case UNOP_COMPLEMENT:
    case UNOP_IND:
    case UNOP_ADDR:
    case UNOP_PREINCREMENT:
    case UNOP_POSTINCREMENT:
    case UNOP_PREDECREMENT:
    case UNOP_POSTDECREMENT:
    case UNOP_SIZEOF:
    case UNOP_PLUS:
    case UNOP_CAP:
    case UNOP_CHR:
    case UNOP_ORD:
    case UNOP_ABS:
    case UNOP_FLOAT:
    case UNOP_HIGH:
    case UNOP_MAX:
    case UNOP_MIN:
    case UNOP_ODD:
    case UNOP_TRUNC:
      elt = dump_subexp (exp, stream, elt);
      break;
    case OP_LONG:
      fprintf_filtered (stream, "Type @");
      gdb_print_host_address (exp->elts[elt].type, stream);
      fprintf_filtered (stream, " (");
      type_print (exp->elts[elt].type, NULL, stream, 0);
      fprintf_filtered (stream, "), value %ld (0x%lx)",
			(long) exp->elts[elt + 1].longconst,
			(long) exp->elts[elt + 1].longconst);
      elt += 3;
      break;
    case OP_DOUBLE:
      fprintf_filtered (stream, "Type @");
      gdb_print_host_address (exp->elts[elt].type, stream);
      fprintf_filtered (stream, " (");
      type_print (exp->elts[elt].type, NULL, stream, 0);
      fprintf_filtered (stream, "), value %g",
			(double) exp->elts[elt + 1].doubleconst);
      elt += 3;
      break;
    case OP_VAR_VALUE:
      fprintf_filtered (stream, "Block @");
      gdb_print_host_address (exp->elts[elt].block, stream);
      fprintf_filtered (stream, ", symbol @");
      gdb_print_host_address (exp->elts[elt + 1].symbol, stream);
      fprintf_filtered (stream, " (%s)",
			SYMBOL_PRINT_NAME (exp->elts[elt + 1].symbol));
      elt += 3;
      break;
    case OP_VAR_ENTRY_VALUE:
      fprintf_filtered (stream, "Entry value of symbol @");
      gdb_print_host_address (exp->elts[elt].symbol, stream);
      fprintf_filtered (stream, " (%s)",
			SYMBOL_PRINT_NAME (exp->elts[elt].symbol));
      elt += 2;
      break;
    case OP_LAST:
      fprintf_filtered (stream, "History element %ld",
			(long) exp->elts[elt].longconst);
      elt += 2;
      break;
    case OP_REGISTER:
      fprintf_filtered (stream, "Register $%s", &exp->elts[elt + 1].string);
      elt += 3 + BYTES_TO_EXP_ELEM (exp->elts[elt].longconst + 1);
      break;
    case OP_INTERNALVAR:
      fprintf_filtered (stream, "Internal var @");
      gdb_print_host_address (exp->elts[elt].internalvar, stream);
      fprintf_filtered (stream, " (%s)",
			internalvar_name (exp->elts[elt].internalvar));
      elt += 2;
      break;
    case OP_FUNCALL:
      {
	int i, nargs;

	nargs = longest_to_int (exp->elts[elt].longconst);

	fprintf_filtered (stream, "Number of args: %d", nargs);
	elt += 2;

	for (i = 1; i <= nargs + 1; i++)
	  elt = dump_subexp (exp, stream, elt);
      }
      break;
    case OP_ARRAY:
      {
	int lower, upper;
	int i;

	lower = longest_to_int (exp->elts[elt].longconst);
	upper = longest_to_int (exp->elts[elt + 1].longconst);

	fprintf_filtered (stream, "Bounds [%d:%d]", lower, upper);
	elt += 3;

	for (i = 1; i <= upper - lower + 1; i++)
	  elt = dump_subexp (exp, stream, elt);
      }
      break;
    case UNOP_DYNAMIC_CAST:
    case UNOP_REINTERPRET_CAST:
    case UNOP_CAST_TYPE:
    case UNOP_MEMVAL_TYPE:
      fprintf_filtered (stream, " (");
      elt = dump_subexp (exp, stream, elt);
      fprintf_filtered (stream, ")");
      elt = dump_subexp (exp, stream, elt);
      break;
    case UNOP_MEMVAL:
    case UNOP_CAST:
      fprintf_filtered (stream, "Type @");
      gdb_print_host_address (exp->elts[elt].type, stream);
      fprintf_filtered (stream, " (");
      type_print (exp->elts[elt].type, NULL, stream, 0);
      fprintf_filtered (stream, ")");
      elt = dump_subexp (exp, stream, elt + 2);
      break;
    case UNOP_MEMVAL_TLS:
      fprintf_filtered (stream, "TLS type @");
      gdb_print_host_address (exp->elts[elt + 1].type, stream);
      fprintf_filtered (stream, " (__thread /* \"%s\" */ ",
                        (exp->elts[elt].objfile == NULL ? "(null)"
			 : exp->elts[elt].objfile->name));
      type_print (exp->elts[elt + 1].type, NULL, stream, 0);
      fprintf_filtered (stream, ")");
      elt = dump_subexp (exp, stream, elt + 3);
      break;
    case OP_TYPE:
      fprintf_filtered (stream, "Type @");
      gdb_print_host_address (exp->elts[elt].type, stream);
      fprintf_filtered (stream, " (");
      type_print (exp->elts[elt].type, NULL, stream, 0);
      fprintf_filtered (stream, ")");
      elt += 2;
      break;
    case OP_TYPEOF:
    case OP_DECLTYPE:
      fprintf_filtered (stream, "Typeof (");
      elt = dump_subexp (exp, stream, elt);
      fprintf_filtered (stream, ")");
      break;
    case OP_TYPEID:
      fprintf_filtered (stream, "typeid (");
      elt = dump_subexp (exp, stream, elt);
      fprintf_filtered (stream, ")");
      break;
    case STRUCTOP_STRUCT:
    case STRUCTOP_PTR:
      {
	char *elem_name;
	int len;

	len = longest_to_int (exp->elts[elt].longconst);
	elem_name = &exp->elts[elt + 1].string;

	fprintf_filtered (stream, "Element name: `%.*s'", len, elem_name);
	elt = dump_subexp (exp, stream, elt + 3 + BYTES_TO_EXP_ELEM (len + 1));
      }
      break;
    case OP_SCOPE:
      {
	char *elem_name;
	int len;

	fprintf_filtered (stream, "Type @");
	gdb_print_host_address (exp->elts[elt].type, stream);
	fprintf_filtered (stream, " (");
	type_print (exp->elts[elt].type, NULL, stream, 0);
	fprintf_filtered (stream, ") ");

	len = longest_to_int (exp->elts[elt + 1].longconst);
	elem_name = &exp->elts[elt + 2].string;

	fprintf_filtered (stream, "Field name: `%.*s'", len, elem_name);
	elt += 4 + BYTES_TO_EXP_ELEM (len + 1);
      }
      break;
    case TYPE_INSTANCE:
      {
	LONGEST len;

	len = exp->elts[elt++].longconst;
	fprintf_filtered (stream, "%s TypeInstance: ", plongest (len));
	while (len-- > 0)
	  {
	    fprintf_filtered (stream, "Type @");
	    gdb_print_host_address (exp->elts[elt].type, stream);
	    fprintf_filtered (stream, " (");
	    type_print (exp->elts[elt].type, NULL, stream, 0);
	    fprintf_filtered (stream, ")");
	    elt++;
	    if (len > 0)
	      fputs_filtered (", ", stream);
	  }
	/* Ending LEN and ending TYPE_INSTANCE.  */
	elt += 2;
	elt = dump_subexp (exp, stream, elt);
      }
      break;
    default:
    case OP_NULL:
    case MULTI_SUBSCRIPT:
    case OP_F77_UNDETERMINED_ARGLIST:
    case OP_COMPLEX:
    case OP_STRING:
    case OP_BOOL:
    case OP_M2_STRING:
    case OP_THIS:
    case OP_NAME:
      fprintf_filtered (stream, "Unknown format");
    }

  return elt;
}
コード例 #18
0
ファイル: auxv.c プロジェクト: Claruarius/stblinux-2.6.37
/* Print the contents of the target's AUXV on the specified file.  */
int
fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
{
  CORE_ADDR type, val;
  gdb_byte *data;
  LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL,
				   &data);
  gdb_byte *ptr = data;
  int ents = 0;

  if (len <= 0)
    return len;

  while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
    {
      const char *name = "???";
      const char *description = "";
      enum { dec, hex, str } flavor = hex;

      switch (type)
	{
#define TAG(tag, text, kind) \
	case tag: name = #tag; description = text; flavor = kind; break
	  TAG (AT_NULL, _("End of vector"), hex);
	  TAG (AT_IGNORE, _("Entry should be ignored"), hex);
	  TAG (AT_EXECFD, _("File descriptor of program"), dec);
	  TAG (AT_PHDR, _("Program headers for program"), hex);
	  TAG (AT_PHENT, _("Size of program header entry"), dec);
	  TAG (AT_PHNUM, _("Number of program headers"), dec);
	  TAG (AT_PAGESZ, _("System page size"), dec);
	  TAG (AT_BASE, _("Base address of interpreter"), hex);
	  TAG (AT_FLAGS, _("Flags"), hex);
	  TAG (AT_ENTRY, _("Entry point of program"), hex);
	  TAG (AT_NOTELF, _("Program is not ELF"), dec);
	  TAG (AT_UID, _("Real user ID"), dec);
	  TAG (AT_EUID, _("Effective user ID"), dec);
	  TAG (AT_GID, _("Real group ID"), dec);
	  TAG (AT_EGID, _("Effective group ID"), dec);
	  TAG (AT_CLKTCK, _("Frequency of times()"), dec);
	  TAG (AT_PLATFORM, _("String identifying platform"), str);
	  TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex);
	  TAG (AT_FPUCW, _("Used FPU control word"), dec);
	  TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec);
	  TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec);
	  TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec);
	  TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
	  TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
	  TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
	  TAG (AT_EXECFN, _("File name of executable"), str);
	  TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
	  TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
	  TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex);
	  TAG (AT_SUN_UID, _("Effective user ID"), dec);
	  TAG (AT_SUN_RUID, _("Real user ID"), dec);
	  TAG (AT_SUN_GID, _("Effective group ID"), dec);
	  TAG (AT_SUN_RGID, _("Real group ID"), dec);
	  TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex);
	  TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex);
	  TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str);
	  TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec);
	  TAG (AT_SUN_PLATFORM, _("Platform name string"), str);
	  TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex);
	  TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec);
	  TAG (AT_SUN_CPU, _("CPU name string"), str);
	  TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex);
	  TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec);
	  TAG (AT_SUN_EXECNAME,
	       _("Canonicalized file name given to execve"), str);
	  TAG (AT_SUN_MMU, _("String for name of MMU module"), str);
	  TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex);
	  TAG (AT_SUN_AUXFLAGS,
	       _("AF_SUN_ flags passed from the kernel"), hex);
	}

      fprintf_filtered (file, "%-4s %-20s %-30s ",
			plongest (type), name, description);
      switch (flavor)
	{
	case dec:
	  fprintf_filtered (file, "%s\n", plongest (val));
	  break;
	case hex:
	  fprintf_filtered (file, "%s\n", paddress (target_gdbarch, val));
	  break;
	case str:
	  {
	    struct value_print_options opts;

	    get_user_print_options (&opts);
	    if (opts.addressprint)
	      fprintf_filtered (file, "%s", paddress (target_gdbarch, val));
	    val_print_string (builtin_type (target_gdbarch)->builtin_char,
			      NULL, val, -1, file, &opts);
	    fprintf_filtered (file, "\n");
	  }
	  break;
	}
      ++ents;
      if (type == AT_NULL)
	break;
    }

  xfree (data);

  return ents;
}
コード例 #19
0
void
do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
{
  /* A flag to indicate the option is changed or not.  */
  int option_changed = 0;

  gdb_assert (c->type == set_cmd);

  switch (c->var_type)
    {
    case var_string:
      {
	char *newobj;
	const char *p;
	char *q;
	int ch;

	if (arg == NULL)
	  arg = "";
	newobj = (char *) xmalloc (strlen (arg) + 2);
	p = arg;
	q = newobj;
	while ((ch = *p++) != '\000')
	  {
	    if (ch == '\\')
	      {
		/* \ at end of argument is used after spaces
		   so they won't be lost.  */
		/* This is obsolete now that we no longer strip
		   trailing whitespace and actually, the backslash
		   didn't get here in my test, readline or
		   something did something funky with a backslash
		   right before a newline.  */
		if (*p == 0)
		  break;
		ch = parse_escape (get_current_arch (), &p);
		if (ch == 0)
		  break;	/* C loses */
		else if (ch > 0)
		  *q++ = ch;
	      }
	    else
	      *q++ = ch;
	  }
#if 0
	if (*(p - 1) != '\\')
	  *q++ = ' ';
#endif
	*q++ = '\0';
	newobj = (char *) xrealloc (newobj, q - newobj);

	if (*(char **) c->var == NULL
	    || strcmp (*(char **) c->var, newobj) != 0)
	  {
	    xfree (*(char **) c->var);
	    *(char **) c->var = newobj;

	    option_changed = 1;
	  }
	else
	  xfree (newobj);
      }
      break;
    case var_string_noescape:
      if (arg == NULL)
	arg = "";

      if (*(char **) c->var == NULL || strcmp (*(char **) c->var, arg) != 0)
	{
	  xfree (*(char **) c->var);
	  *(char **) c->var = xstrdup (arg);

	  option_changed = 1;
	}
      break;
    case var_filename:
      if (arg == NULL)
	error_no_arg (_("filename to set it to."));
      /* FALLTHROUGH */
    case var_optional_filename:
      {
	char *val = NULL;

	if (arg != NULL)
	  {
	    /* Clear trailing whitespace of filename.  */
	    const char *ptr = arg + strlen (arg) - 1;
	    char *copy;

	    while (ptr >= arg && (*ptr == ' ' || *ptr == '\t'))
	      ptr--;
	    copy = xstrndup (arg, ptr + 1 - arg);

	    val = tilde_expand (copy);
	    xfree (copy);
	  }
	else
	  val = xstrdup ("");

	if (*(char **) c->var == NULL
	    || strcmp (*(char **) c->var, val) != 0)
	  {
	    xfree (*(char **) c->var);
	    *(char **) c->var = val;

	    option_changed = 1;
	  }
	else
	  xfree (val);
      }
      break;
    case var_boolean:
      {
	int val = parse_cli_boolean_value (arg);

	if (val < 0)
	  error (_("\"on\" or \"off\" expected."));
	if (val != *(int *) c->var)
	  {
	    *(int *) c->var = val;

	    option_changed = 1;
	  }
      }
      break;
    case var_auto_boolean:
      {
	enum auto_boolean val = parse_auto_binary_operation (arg);

	if (*(enum auto_boolean *) c->var != val)
	  {
	    *(enum auto_boolean *) c->var = val;

	    option_changed = 1;
	  }
      }
      break;
    case var_uinteger:
    case var_zuinteger:
      {
	LONGEST val;

	if (arg == NULL)
	  {
	    if (c->var_type == var_uinteger)
	      error_no_arg (_("integer to set it to, or \"unlimited\"."));
	    else
	      error_no_arg (_("integer to set it to."));
	  }

	if (c->var_type == var_uinteger && is_unlimited_literal (arg))
	  val = 0;
	else
	  val = parse_and_eval_long (arg);

	if (c->var_type == var_uinteger && val == 0)
	  val = UINT_MAX;
	else if (val < 0
		 /* For var_uinteger, don't let the user set the value
		    to UINT_MAX directly, as that exposes an
		    implementation detail to the user interface.  */
		 || (c->var_type == var_uinteger && val >= UINT_MAX)
		 || (c->var_type == var_zuinteger && val > UINT_MAX))
	  error (_("integer %s out of range"), plongest (val));

	if (*(unsigned int *) c->var != val)
	  {
	    *(unsigned int *) c->var = val;

	    option_changed = 1;
	  }
      }
      break;
    case var_integer:
    case var_zinteger:
      {
	LONGEST val;

	if (arg == NULL)
	  {
	    if (c->var_type == var_integer)
	      error_no_arg (_("integer to set it to, or \"unlimited\"."));
	    else
	      error_no_arg (_("integer to set it to."));
	  }

	if (c->var_type == var_integer && is_unlimited_literal (arg))
	  val = 0;
	else
	  val = parse_and_eval_long (arg);

	if (val == 0 && c->var_type == var_integer)
	  val = INT_MAX;
	else if (val < INT_MIN
		 /* For var_integer, don't let the user set the value
		    to INT_MAX directly, as that exposes an
		    implementation detail to the user interface.  */
		 || (c->var_type == var_integer && val >= INT_MAX)
		 || (c->var_type == var_zinteger && val > INT_MAX))
	  error (_("integer %s out of range"), plongest (val));

	if (*(int *) c->var != val)
	  {
	    *(int *) c->var = val;

	    option_changed = 1;
	  }
	break;
      }
    case var_enum:
      {
	int i;
	int len;
	int nmatches;
	const char *match = NULL;
	char *p;

	/* If no argument was supplied, print an informative error
	   message.  */
	if (arg == NULL)
	  {
	    char *msg;
	    int msg_len = 0;

	    for (i = 0; c->enums[i]; i++)
	      msg_len += strlen (c->enums[i]) + 2;

	    msg = xmalloc (msg_len);
	    *msg = '\0';
	    make_cleanup (xfree, msg);

	    for (i = 0; c->enums[i]; i++)
	      {
		if (i != 0)
		  strcat (msg, ", ");
		strcat (msg, c->enums[i]);
	      }
	    error (_("Requires an argument. Valid arguments are %s."), 
		   msg);
	  }

	p = strchr (arg, ' ');

	if (p)
	  len = p - arg;
	else
	  len = strlen (arg);

	nmatches = 0;
	for (i = 0; c->enums[i]; i++)
	  if (strncmp (arg, c->enums[i], len) == 0)
	    {
	      if (c->enums[i][len] == '\0')
		{
		  match = c->enums[i];
		  nmatches = 1;
		  break; /* Exact match.  */
		}
	      else
		{
		  match = c->enums[i];
		  nmatches++;
		}
	    }

	if (nmatches <= 0)
	  error (_("Undefined item: \"%s\"."), arg);

	if (nmatches > 1)
	  error (_("Ambiguous item \"%s\"."), arg);

	if (*(const char **) c->var != match)
	  {
	    *(const char **) c->var = match;

	    option_changed = 1;
	  }
      }
      break;
    case var_zuinteger_unlimited:
      {
	LONGEST val;

	if (arg == NULL)
	  error_no_arg (_("integer to set it to, or \"unlimited\"."));

	if (is_unlimited_literal (arg))
	  val = -1;
	else
	  val = parse_and_eval_long (arg);

	if (val > INT_MAX)
	  error (_("integer %s out of range"), plongest (val));
	else if (val < -1)
	  error (_("only -1 is allowed to set as unlimited"));

	if (*(int *) c->var != val)
	  {
	    *(int *) c->var = val;
	    option_changed = 1;
	  }
      }
      break;
    default:
      error (_("gdb internal error: bad var_type in do_setshow_command"));
    }
  c->func (c, NULL, from_tty);

  if (notify_command_param_changed_p (option_changed, c))
    {
      char *name, *cp;
      struct cmd_list_element **cmds;
      struct cmd_list_element *p;
      int i;
      int length = 0;

      /* Compute the whole multi-word command options.  If user types command
	 'set foo bar baz on', c->name is 'baz', and GDB can't pass "bar" to
	 command option change notification, because it is confusing.  We can
	 trace back through field 'prefix' to compute the whole options,
	 and pass "foo bar baz" to notification.  */

      for (i = 0, p = c; p != NULL; i++)
	{
	  length += strlen (p->name);
	  length++;

	  p = p->prefix;
	}
      cp = name = (char *) xmalloc (length);
      cmds = XNEWVEC (struct cmd_list_element *, i);

      /* Track back through filed 'prefix' and cache them in CMDS.  */
      for (i = 0, p = c; p != NULL; i++)
	{
	  cmds[i] = p;
	  p = p->prefix;
	}

      /* Don't trigger any observer notification if prefixlist is not
	 setlist.  */
      i--;
      if (cmds[i]->prefixlist != &setlist)
	{
	  xfree (cmds);
	  xfree (name);

	  return;
	}
      /* Traverse them in the reversed order, and copy their names into
	 NAME.  */
      for (i--; i >= 0; i--)
	{
	  memcpy (cp, cmds[i]->name, strlen (cmds[i]->name));
	  cp += strlen (cmds[i]->name);

	  if (i != 0)
	    {
	      cp[0] = ' ';
	      cp++;
	    }
	}
      cp[0] = 0;

      xfree (cmds);

      switch (c->var_type)
	{
	case var_string:
	case var_string_noescape:
	case var_filename:
	case var_optional_filename:
	case var_enum:
	  observer_notify_command_param_changed (name, *(char **) c->var);
	  break;
	case var_boolean:
	  {
	    char *opt = *(int *) c->var ? "on" : "off";

	    observer_notify_command_param_changed (name, opt);
	  }
	  break;
	case var_auto_boolean:
	  {
	    const char *s = auto_boolean_enums[*(enum auto_boolean *) c->var];

	    observer_notify_command_param_changed (name, s);
	  }
	  break;
	case var_uinteger:
	case var_zuinteger:
	  {
	    char s[64];

	    xsnprintf (s, sizeof s, "%u", *(unsigned int *) c->var);
	    observer_notify_command_param_changed (name, s);
	  }
	  break;
	case var_integer:
	case var_zinteger:
	case var_zuinteger_unlimited:
	  {
	    char s[64];

	    xsnprintf (s, sizeof s, "%d", *(int *) c->var);
	    observer_notify_command_param_changed (name, s);
	  }
	  break;
	}
      xfree (name);
    }
}