コード例 #1
0
static enum string_repr_result
print_string_repr (PyObject *printer, const char *hint,
                   struct ui_file *stream, int recurse,
                   const struct value_print_options *options,
                   const struct language_defn *language,
                   struct gdbarch *gdbarch)
{
    struct value *replacement = NULL;
    PyObject *py_str = NULL;
    enum string_repr_result result = string_repr_ok;

    py_str = pretty_print_one_value (printer, &replacement);
    if (py_str)
    {
        struct cleanup *cleanup = make_cleanup_py_decref (py_str);

        if (py_str == Py_None)
            result = string_repr_none;
        else if (gdbpy_is_lazy_string (py_str))
        {
            CORE_ADDR addr;
            long length;
            struct type *type;
            char *encoding = NULL;
            struct value_print_options local_opts = *options;

            make_cleanup (free_current_contents, &encoding);
            gdbpy_extract_lazy_string (py_str, &addr, &type,
            &length, &encoding);

            local_opts.addressprint = 0;
            val_print_string (type, encoding, addr, (int) length,
            stream, &local_opts);
        }
        else
        {
            PyObject *string;

            string = python_string_to_target_python_string (py_str);
            if (string)
            {
                char *output;
                long length;
                struct type *type;

                make_cleanup_py_decref (string);
#ifdef IS_PY3K
                output = PyBytes_AS_STRING (string);
                length = PyBytes_GET_SIZE (string);
#else
                output = PyString_AsString (string);
                length = PyString_Size (string);
#endif
                type = builtin_type (gdbarch)->builtin_char;

                if (hint && !strcmp (hint, "string"))
                    LA_PRINT_STRING (stream, type, (gdb_byte *) output,
                                     length, NULL, 0, options);
                else
                    fputs_filtered (output, stream);
            }
            else
            {
                result = string_repr_error;
                print_stack_unless_memory_error (stream);
            }
        }

        do_cleanups (cleanup);
    }
    else if (replacement)
    {
        struct value_print_options opts = *options;

        opts.addressprint = 0;
        common_val_print (replacement, stream, recurse, &opts, language);
    }
    else
    {
        result = string_repr_error;
        print_stack_unless_memory_error (stream);
    }

    return result;
}
コード例 #2
0
struct compile_module *
compile_object_load (const char *object_file, const char *source_file,
		     enum compile_i_scope_types scope, void *scope_data)
{
  struct cleanup *cleanups, *cleanups_free_objfile;
  bfd *abfd;
  struct setup_sections_data setup_sections_data;
  CORE_ADDR addr, regs_addr, out_value_addr = 0;
  struct symbol *func_sym;
  struct type *func_type;
  struct bound_minimal_symbol bmsym;
  long storage_needed;
  asymbol **symbol_table, **symp;
  long number_of_symbols, missing_symbols;
  struct type *dptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
  unsigned dptr_type_len = TYPE_LENGTH (dptr_type);
  struct compile_module *retval;
  struct type *regs_type, *out_value_type = NULL;
  char *filename, **matching;
  struct objfile *objfile;
  int expect_parameters;
  struct type *expect_return_type;
  struct munmap_list *munmap_list_head = NULL;

  filename = tilde_expand (object_file);
  cleanups = make_cleanup (xfree, filename);

  abfd = gdb_bfd_open (filename, gnutarget, -1);
  if (abfd == NULL)
    error (_("\"%s\": could not open as compiled module: %s"),
          filename, bfd_errmsg (bfd_get_error ()));
  make_cleanup_bfd_unref (abfd);

  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
    error (_("\"%s\": not in loadable format: %s"),
          filename, gdb_bfd_errmsg (bfd_get_error (), matching));

  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0)
    error (_("\"%s\": not in object format."), filename);

  setup_sections_data.last_size = 0;
  setup_sections_data.last_section_first = abfd->sections;
  setup_sections_data.last_prot = -1;
  setup_sections_data.last_max_alignment = 1;
  setup_sections_data.munmap_list_headp = &munmap_list_head;
  make_cleanup (munmap_listp_free_cleanup, &munmap_list_head);
  bfd_map_over_sections (abfd, setup_sections, &setup_sections_data);
  setup_sections (abfd, NULL, &setup_sections_data);

  storage_needed = bfd_get_symtab_upper_bound (abfd);
  if (storage_needed < 0)
    error (_("Cannot read symbols of compiled module \"%s\": %s"),
          filename, bfd_errmsg (bfd_get_error ()));

  /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in
     "Reading symbols from ..." message for automatically generated file.  */
  objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL);
  cleanups_free_objfile = make_cleanup_free_objfile (objfile);

  func_sym = lookup_global_symbol_from_objfile (objfile,
						GCC_FE_WRAPPER_FUNCTION,
						VAR_DOMAIN).symbol;
  if (func_sym == NULL)
    error (_("Cannot find function \"%s\" in compiled module \"%s\"."),
	   GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile));
  func_type = SYMBOL_TYPE (func_sym);
  if (TYPE_CODE (func_type) != TYPE_CODE_FUNC)
    error (_("Invalid type code %d of function \"%s\" in compiled "
	     "module \"%s\"."),
	   TYPE_CODE (func_type), GCC_FE_WRAPPER_FUNCTION,
	   objfile_name (objfile));

  switch (scope)
    {
    case COMPILE_I_SIMPLE_SCOPE:
      expect_parameters = 1;
      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
      break;
    case COMPILE_I_RAW_SCOPE:
      expect_parameters = 0;
      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
      break;
    case COMPILE_I_PRINT_ADDRESS_SCOPE:
    case COMPILE_I_PRINT_VALUE_SCOPE:
      expect_parameters = 2;
      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
      break;
    default:
      internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope);
    }
  if (TYPE_NFIELDS (func_type) != expect_parameters)
    error (_("Invalid %d parameters of function \"%s\" in compiled "
	     "module \"%s\"."),
	   TYPE_NFIELDS (func_type), GCC_FE_WRAPPER_FUNCTION,
	   objfile_name (objfile));
  if (!types_deeply_equal (expect_return_type, TYPE_TARGET_TYPE (func_type)))
    error (_("Invalid return type of function \"%s\" in compiled "
	    "module \"%s\"."),
	  GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile));

  /* The memory may be later needed
     by bfd_generic_get_relocated_section_contents
     called from default_symfile_relocate.  */
  symbol_table = obstack_alloc (&objfile->objfile_obstack, storage_needed);
  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
  if (number_of_symbols < 0)
    error (_("Cannot parse symbols of compiled module \"%s\": %s"),
          filename, bfd_errmsg (bfd_get_error ()));

  missing_symbols = 0;
  for (symp = symbol_table; symp < symbol_table + number_of_symbols; symp++)
    {
      asymbol *sym = *symp;

      if (sym->flags != 0)
	continue;
      sym->flags = BSF_GLOBAL;
      sym->section = bfd_abs_section_ptr;
      if (strcmp (sym->name, "_GLOBAL_OFFSET_TABLE_") == 0)
	{
	  if (compile_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"ELF symbol \"%s\" relocated to zero\n",
				sym->name);

	  /* It seems to be a GCC bug, with -mcmodel=large there should be no
	     need for _GLOBAL_OFFSET_TABLE_.  Together with -fPIE the data
	     remain PC-relative even with _GLOBAL_OFFSET_TABLE_ as zero.  */
	  sym->value = 0;
	  continue;
	}
      bmsym = lookup_minimal_symbol (sym->name, NULL, NULL);
      switch (bmsym.minsym == NULL
	      ? mst_unknown : MSYMBOL_TYPE (bmsym.minsym))
	{
	case mst_text:
	  sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym);
	  if (compile_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"ELF mst_text symbol \"%s\" relocated to %s\n",
				sym->name,
				paddress (target_gdbarch (), sym->value));
	  break;
	case mst_text_gnu_ifunc:
	  sym->value = gnu_ifunc_resolve_addr (target_gdbarch (),
					       BMSYMBOL_VALUE_ADDRESS (bmsym));
	  if (compile_debug)
	    fprintf_unfiltered (gdb_stdlog,
				"ELF mst_text_gnu_ifunc symbol \"%s\" "
				"relocated to %s\n",
				sym->name,
				paddress (target_gdbarch (), sym->value));
	  break;
	default:
	  warning (_("Could not find symbol \"%s\" "
		     "for compiled module \"%s\"."),
		   sym->name, filename);
	  missing_symbols++;
	}
    }
  if (missing_symbols)
    error (_("%ld symbols were missing, cannot continue."), missing_symbols);

  bfd_map_over_sections (abfd, copy_sections, symbol_table);

  regs_type = get_regs_type (func_sym, objfile);
  if (regs_type == NULL)
    regs_addr = 0;
  else
    {
      /* Use read-only non-executable memory protection.  */
      regs_addr = gdbarch_infcall_mmap (target_gdbarch (),
					TYPE_LENGTH (regs_type),
					GDB_MMAP_PROT_READ);
      gdb_assert (regs_addr != 0);
      munmap_list_add (&munmap_list_head, regs_addr, TYPE_LENGTH (regs_type));
      if (compile_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "allocated %s bytes at %s for registers\n",
			    paddress (target_gdbarch (),
				      TYPE_LENGTH (regs_type)),
			    paddress (target_gdbarch (), regs_addr));
      store_regs (regs_type, regs_addr);
    }

  if (scope == COMPILE_I_PRINT_ADDRESS_SCOPE
      || scope == COMPILE_I_PRINT_VALUE_SCOPE)
    {
      out_value_type = get_out_value_type (func_sym, objfile, scope);
      if (out_value_type == NULL)
	{
	  do_cleanups (cleanups);
	  return NULL;
	}
      check_typedef (out_value_type);
      out_value_addr = gdbarch_infcall_mmap (target_gdbarch (),
					     TYPE_LENGTH (out_value_type),
					     (GDB_MMAP_PROT_READ
					      | GDB_MMAP_PROT_WRITE));
      gdb_assert (out_value_addr != 0);
      munmap_list_add (&munmap_list_head, out_value_addr,
		       TYPE_LENGTH (out_value_type));
      if (compile_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "allocated %s bytes at %s for printed value\n",
			    paddress (target_gdbarch (),
				      TYPE_LENGTH (out_value_type)),
			    paddress (target_gdbarch (), out_value_addr));
    }

  discard_cleanups (cleanups_free_objfile);

  retval = xmalloc (sizeof (*retval));
  retval->objfile = objfile;
  retval->source_file = xstrdup (source_file);
  retval->func_sym = func_sym;
  retval->regs_addr = regs_addr;
  retval->scope = scope;
  retval->scope_data = scope_data;
  retval->out_value_type = out_value_type;
  retval->out_value_addr = out_value_addr;

  /* CLEANUPS will free MUNMAP_LIST_HEAD.  */
  retval->munmap_list_head = munmap_list_head;
  munmap_list_head = NULL;

  do_cleanups (cleanups);

  return retval;
}
コード例 #3
0
ファイル: tilegx-tdep.c プロジェクト: nds32/binutils
static CORE_ADDR
tilegx_push_dummy_call (struct gdbarch *gdbarch,
			struct value *function,
			struct regcache *regcache,
			CORE_ADDR bp_addr, int nargs,
			struct value **args,
			CORE_ADDR sp, int struct_return,
			CORE_ADDR struct_addr)
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  CORE_ADDR stack_dest = sp;
  int argreg = TILEGX_R0_REGNUM;
  int i, j;
  int typelen, slacklen, alignlen;
  static const gdb_byte four_zero_words[16] = { 0 };

  /* If struct_return is 1, then the struct return address will
     consume one argument-passing register.  */
  if (struct_return)
    regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);

  /* Arguments are passed in R0 - R9, and as soon as an argument
     will not fit completely in the remaining registers, then it,
     and all remaining arguments, are put on the stack.  */
  for (i = 0; i < nargs && argreg <= TILEGX_R9_REGNUM; i++)
    {
      const gdb_byte *val;
      typelen = TYPE_LENGTH (value_enclosing_type (args[i]));

      if (typelen > (TILEGX_R9_REGNUM - argreg + 1) * tilegx_reg_size)
	break;

      /* Put argument into registers wordwise.	*/
      val = value_contents (args[i]);
      for (j = 0; j < typelen; j += tilegx_reg_size)
	{
	  /* ISSUE: Why special handling for "typelen = 4x + 1"?
	     I don't ever see "typelen" values except 4 and 8.	*/
	  int n = (typelen - j == 1) ? 1 : tilegx_reg_size;
	  ULONGEST w = extract_unsigned_integer (val + j, n, byte_order);

	  regcache_cooked_write_unsigned (regcache, argreg++, w);
	}
    }

  /* Align SP.  */
  stack_dest = tilegx_frame_align (gdbarch, stack_dest);

  /* Loop backwards through remaining arguments and push them on
     the stack, word aligned.  */
  for (j = nargs - 1; j >= i; j--)
    {
      gdb_byte *val;
      struct cleanup *back_to;
      const gdb_byte *contents = value_contents (args[j]);

      typelen = TYPE_LENGTH (value_enclosing_type (args[j]));
      slacklen = align_up (typelen, 8) - typelen;
      val = xmalloc (typelen + slacklen);
      back_to = make_cleanup (xfree, val);
      memcpy (val, contents, typelen);
      memset (val + typelen, 0, slacklen);

      /* Now write data to the stack.  The stack grows downwards.  */
      stack_dest -= typelen + slacklen;
      write_memory (stack_dest, val, typelen + slacklen);
      do_cleanups (back_to);
    }

  /* Add 16 bytes for linkage space to the stack.  */
  stack_dest = stack_dest - 16;
  write_memory (stack_dest, four_zero_words, 16);

  /* Update stack pointer.  */
  regcache_cooked_write_unsigned (regcache, TILEGX_SP_REGNUM, stack_dest);

  /* Set the return address register to point to the entry point of
     the program, where a breakpoint lies in wait.  */
  regcache_cooked_write_unsigned (regcache, TILEGX_LR_REGNUM, bp_addr);

  return stack_dest;
}
コード例 #4
0
ファイル: disasm.c プロジェクト: ajinkya93/netbsd-src
static int
dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
	    struct disassemble_info * di,
	    CORE_ADDR low, CORE_ADDR high,
	    int how_many, int flags, struct ui_file *stb)
{
  int num_displayed = 0;
  CORE_ADDR pc;

  /* parts of the symbolic representation of the address */
  int unmapped;
  int offset;
  int line;
  struct cleanup *ui_out_chain;

  for (pc = low; pc < high;)
    {
      char *filename = NULL;
      char *name = NULL;

      QUIT;
      if (how_many >= 0)
	{
	  if (num_displayed >= how_many)
	    break;
	  else
	    num_displayed++;
	}
      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);

      if ((flags & DISASSEMBLY_OMIT_PC) == 0)
	ui_out_text (uiout, pc_prefix (pc));
      ui_out_field_core_addr (uiout, "address", gdbarch, pc);

      if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
				   &line, &unmapped))
	{
	  /* We don't care now about line, filename and
	     unmapped. But we might in the future.  */
	  ui_out_text (uiout, " <");
	  if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
	    ui_out_field_string (uiout, "func-name", name);
	  ui_out_text (uiout, "+");
	  ui_out_field_int (uiout, "offset", offset);
	  ui_out_text (uiout, ">:\t");
	}
      else
	ui_out_text (uiout, ":\t");

      if (filename != NULL)
	xfree (filename);
      if (name != NULL)
	xfree (name);

      ui_file_rewind (stb);
      if (flags & DISASSEMBLY_RAW_INSN)
        {
          CORE_ADDR old_pc = pc;
          bfd_byte data;
          int status;
          const char *spacer = "";

          /* Build the opcodes using a temporary stream so we can
             write them out in a single go for the MI.  */
          struct ui_file *opcode_stream = mem_fileopen ();
          struct cleanup *cleanups =
            make_cleanup_ui_file_delete (opcode_stream);

          pc += gdbarch_print_insn (gdbarch, pc, di);
          for (;old_pc < pc; old_pc++)
            {
              status = (*di->read_memory_func) (old_pc, &data, 1, di);
              if (status != 0)
                (*di->memory_error_func) (status, old_pc, di);
              fprintf_filtered (opcode_stream, "%s%02x",
                                spacer, (unsigned) data);
              spacer = " ";
            }
          ui_out_field_stream (uiout, "opcodes", opcode_stream);
          ui_out_text (uiout, "\t");

          do_cleanups (cleanups);
        }
      else
        pc += gdbarch_print_insn (gdbarch, pc, di);
      ui_out_field_stream (uiout, "inst", stb);
      ui_file_rewind (stb);
      do_cleanups (ui_out_chain);
      ui_out_text (uiout, "\n");
    }
  return num_displayed;
}
コード例 #5
0
static int
captured_main (void *data)
{
  struct captured_main_args *context = data;
  int argc = context->argc;
  char **argv = context->argv;
  int count;
  static int quiet = 0;
  static int batch = 0;
  static int set_args = 0;

  /* Pointers to various arguments from command line.  */
  char *symarg = NULL;
  char *execarg = NULL;
  char *corearg = NULL;
  char *cdarg = NULL;
  char *ttyarg = NULL;

  /* These are static so that we can take their address in an initializer.  */
  static int print_help;
  static int print_version;

  /* Pointers to all arguments of --command option.  */
  char **cmdarg;
  /* Allocated size of cmdarg.  */
  int cmdsize;
  /* Number of elements of cmdarg used.  */
  int ncmd;

  /* Indices of all arguments of --directory option.  */
  char **dirarg;
  /* Allocated size.  */
  int dirsize;
  /* Number of elements used.  */
  int ndir;

  struct stat homebuf, cwdbuf;
  char *homedir, *homeinit;

  int i;

  long time_at_startup = get_run_time ();

#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
  setlocale (LC_MESSAGES, "");
#endif
#if defined (HAVE_SETLOCALE)
  setlocale (LC_CTYPE, "");
#endif
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  /* This needs to happen before the first use of malloc.  */
  init_malloc (NULL);

#ifdef HAVE_SBRK
  lim_at_start = (char *) sbrk (0);
#endif

#if defined (ALIGN_STACK_ON_STARTUP)
  i = (int) &count & 0x3;
  if (i != 0)
    alloca (4 - i);
#endif

  cmdsize = 1;
  cmdarg = (char **) xmalloc (cmdsize * sizeof (*cmdarg));
  ncmd = 0;
  dirsize = 1;
  dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
  ndir = 0;

  quit_flag = 0;
  line = (char *) xmalloc (linesize);
  line[0] = '\0';		/* Terminate saved (now empty) cmd line */
  instream = stdin;

  getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
  current_directory = gdb_dirbuf;

  gdb_stdout = stdio_fileopen (stdout);
  gdb_stderr = stdio_fileopen (stderr);
  gdb_stdlog = gdb_stderr;	/* for moment */
  gdb_stdtarg = gdb_stderr;	/* for moment */
  gdb_stdin = stdio_fileopen (stdin);
  gdb_stdtargerr = gdb_stderr;	/* for moment */
  gdb_stdtargin = gdb_stdin;	/* for moment */

  /* initialize error() */
  error_init ();

  /* Set the sysroot path.  */
#ifdef TARGET_SYSTEM_ROOT_RELOCATABLE
  gdb_sysroot = make_relative_prefix (argv[0], BINDIR, TARGET_SYSTEM_ROOT);
  if (gdb_sysroot)
    {
      struct stat s;
      int res = 0;

      if (stat (gdb_sysroot, &s) == 0)
	if (S_ISDIR (s.st_mode))
	  res = 1;

      if (res == 0)
	{
	  xfree (gdb_sysroot);
	  gdb_sysroot = TARGET_SYSTEM_ROOT;
	}
    }
  else
    gdb_sysroot = TARGET_SYSTEM_ROOT;
#else
#if defined (TARGET_SYSTEM_ROOT)
  gdb_sysroot = TARGET_SYSTEM_ROOT;
#else
  gdb_sysroot = "";
#endif
#endif

  /* There will always be an interpreter.  Either the one passed into
     this captured main, or one specified by the user at start up, or
     the console.  Initialize the interpreter to the one requested by 
     the application.  */
  interpreter_p = xstrdup (context->interpreter_p);

  /* Parse arguments and options.  */
  {
    int c;
    /* When var field is 0, use flag field to record the equivalent
       short option (or arbitrary numbers starting at 10 for those
       with no equivalent).  */
    enum {
      OPT_SE = 10,
      OPT_CD,
      OPT_ANNOTATE,
      OPT_STATISTICS,
      OPT_TUI,
      OPT_NOWINDOWS,
      OPT_WINDOWS
    };
    static struct option long_options[] =
    {
#if defined(TUI)
      {"tui", no_argument, 0, OPT_TUI},
#endif
      {"xdb", no_argument, &xdb_commands, 1},
      {"dbx", no_argument, &dbx_commands, 1},
      {"readnow", no_argument, &readnow_symbol_files, 1},
      {"r", no_argument, &readnow_symbol_files, 1},
      {"quiet", no_argument, &quiet, 1},
      {"q", no_argument, &quiet, 1},
      {"silent", no_argument, &quiet, 1},
      {"nx", no_argument, &inhibit_gdbinit, 1},
      {"n", no_argument, &inhibit_gdbinit, 1},
      {"batch", no_argument, &batch, 1},
      {"epoch", no_argument, &epoch_interface, 1},

    /* This is a synonym for "--annotate=1".  --annotate is now preferred,
       but keep this here for a long time because people will be running
       emacses which use --fullname.  */
      {"fullname", no_argument, 0, 'f'},
      {"f", no_argument, 0, 'f'},

      {"annotate", required_argument, 0, OPT_ANNOTATE},
      {"help", no_argument, &print_help, 1},
      {"se", required_argument, 0, OPT_SE},
      {"symbols", required_argument, 0, 's'},
      {"s", required_argument, 0, 's'},
      {"exec", required_argument, 0, 'e'},
      {"e", required_argument, 0, 'e'},
      {"core", required_argument, 0, 'c'},
      {"c", required_argument, 0, 'c'},
      {"pid", required_argument, 0, 'p'},
      {"p", required_argument, 0, 'p'},
      {"command", required_argument, 0, 'x'},
      {"version", no_argument, &print_version, 1},
      {"x", required_argument, 0, 'x'},
#ifdef GDBTK
      {"tclcommand", required_argument, 0, 'z'},
      {"enable-external-editor", no_argument, 0, 'y'},
      {"editor-command", required_argument, 0, 'w'},
#endif
      {"ui", required_argument, 0, 'i'},
      {"interpreter", required_argument, 0, 'i'},
      {"i", required_argument, 0, 'i'},
      {"directory", required_argument, 0, 'd'},
      {"d", required_argument, 0, 'd'},
      {"cd", required_argument, 0, OPT_CD},
      {"tty", required_argument, 0, 't'},
      {"baud", required_argument, 0, 'b'},
      {"b", required_argument, 0, 'b'},
      {"nw", no_argument, NULL, OPT_NOWINDOWS},
      {"nowindows", no_argument, NULL, OPT_NOWINDOWS},
      {"w", no_argument, NULL, OPT_WINDOWS},
      {"windows", no_argument, NULL, OPT_WINDOWS},
      {"statistics", no_argument, 0, OPT_STATISTICS},
      {"write", no_argument, &write_files, 1},
      {"args", no_argument, &set_args, 1},
      {0, no_argument, 0, 0}
    };

    while (1)
      {
	int option_index;

	c = getopt_long_only (argc, argv, "",
			      long_options, &option_index);
	if (c == EOF || set_args)
	  break;

	/* Long option that takes an argument.  */
	if (c == 0 && long_options[option_index].flag == 0)
	  c = long_options[option_index].val;

	switch (c)
	  {
	  case 0:
	    /* Long option that just sets a flag.  */
	    break;
	  case OPT_SE:
	    symarg = optarg;
	    execarg = optarg;
	    break;
	  case OPT_CD:
	    cdarg = optarg;
	    break;
	  case OPT_ANNOTATE:
	    /* FIXME: what if the syntax is wrong (e.g. not digits)?  */
	    annotation_level = atoi (optarg);
	    break;
	  case OPT_STATISTICS:
	    /* Enable the display of both time and space usage.  */
	    display_time = 1;
	    display_space = 1;
	    break;
	  case OPT_TUI:
	    /* --tui is equivalent to -i=tui.  */
	    xfree (interpreter_p);
	    interpreter_p = xstrdup ("tui");
	    break;
	  case OPT_WINDOWS:
	    /* FIXME: cagney/2003-03-01: Not sure if this option is
               actually useful, and if it is, what it should do.  */
	    use_windows = 1;
	    break;
	  case OPT_NOWINDOWS:
	    /* -nw is equivalent to -i=console.  */
	    xfree (interpreter_p);
	    interpreter_p = xstrdup (INTERP_CONSOLE);
	    use_windows = 0;
	    break;
	  case 'f':
	    annotation_level = 1;
/* We have probably been invoked from emacs.  Disable window interface.  */
	    use_windows = 0;
	    break;
	  case 's':
	    symarg = optarg;
	    break;
	  case 'e':
	    execarg = optarg;
	    break;
	  case 'c':
	    corearg = optarg;
	    break;
	  case 'p':
	    /* "corearg" is shared by "--core" and "--pid" */
	    corearg = optarg;
	    break;
	  case 'x':
	    cmdarg[ncmd++] = optarg;
	    if (ncmd >= cmdsize)
	      {
		cmdsize *= 2;
		cmdarg = (char **) xrealloc ((char *) cmdarg,
					     cmdsize * sizeof (*cmdarg));
	      }
	    break;
#ifdef GDBTK
	  case 'z':
	    {
extern int gdbtk_test (char *);
	      if (!gdbtk_test (optarg))
		{
		  fprintf_unfiltered (gdb_stderr, _("%s: unable to load tclcommand file \"%s\""),
				      argv[0], optarg);
		  exit (1);
		}
	      break;
	    }
	  case 'y':
	    /* Backwards compatibility only.  */
	    break;
	  case 'w':
	    {
	      external_editor_command = xstrdup (optarg);
	      break;
	    }
#endif /* GDBTK */
	  case 'i':
	    xfree (interpreter_p);
	    interpreter_p = xstrdup (optarg);
	    break;
	  case 'd':
	    dirarg[ndir++] = optarg;
	    if (ndir >= dirsize)
	      {
		dirsize *= 2;
		dirarg = (char **) xrealloc ((char *) dirarg,
					     dirsize * sizeof (*dirarg));
	      }
	    break;
	  case 't':
	    ttyarg = optarg;
	    break;
	  case 'q':
	    quiet = 1;
	    break;
	  case 'b':
	    {
	      int i;
	      char *p;

	      i = strtol (optarg, &p, 0);
	      if (i == 0 && p == optarg)

		/* Don't use *_filtered or warning() (which relies on
		   current_target) until after initialize_all_files(). */

		fprintf_unfiltered
		  (gdb_stderr,
		   _("warning: could not set baud rate to `%s'.\n"), optarg);
	      else
		baud_rate = i;
	    }
            break;
	  case 'l':
	    {
	      int i;
	      char *p;

	      i = strtol (optarg, &p, 0);
	      if (i == 0 && p == optarg)

		/* Don't use *_filtered or warning() (which relies on
		   current_target) until after initialize_all_files(). */

		fprintf_unfiltered
		  (gdb_stderr,
		 _("warning: could not set timeout limit to `%s'.\n"), optarg);
	      else
		remote_timeout = i;
	    }
	    break;

	  case '?':
	    fprintf_unfiltered (gdb_stderr,
			_("Use `%s --help' for a complete list of options.\n"),
				argv[0]);
	    exit (1);
	  }
      }

    /* If --help or --version, disable window interface.  */
    if (print_help || print_version)
      {
	use_windows = 0;
      }

    if (set_args)
      {
	/* The remaining options are the command-line options for the
	   inferior.  The first one is the sym/exec file, and the rest
	   are arguments.  */
	if (optind >= argc)
	  {
	    fprintf_unfiltered (gdb_stderr,
				_("%s: `--args' specified but no program specified\n"),
				argv[0]);
	    exit (1);
	  }
	symarg = argv[optind];
	execarg = argv[optind];
	++optind;
	set_inferior_args_vector (argc - optind, &argv[optind]);
      }
    else
      {
	/* OK, that's all the options.  The other arguments are filenames.  */
	count = 0;
	for (; optind < argc; optind++)
	  switch (++count)
	    {
	    case 1:
	      symarg = argv[optind];
	      execarg = argv[optind];
	      break;
	    case 2:
	      /* The documentation says this can be a "ProcID" as well. 
	         We will try it as both a corefile and a pid.  */
	      corearg = argv[optind];
	      break;
	    case 3:
	      fprintf_unfiltered (gdb_stderr,
				  _("Excess command line arguments ignored. (%s%s)\n"),
				  argv[optind], (optind == argc - 1) ? "" : " ...");
	      break;
	    }
      }
    if (batch)
      quiet = 1;
  }

  /* Initialize all files.  Give the interpreter a chance to take
     control of the console via the deprecated_init_ui_hook().  */
  gdb_init (argv[0]);

  /* Do these (and anything which might call wrap_here or *_filtered)
     after initialize_all_files() but before the interpreter has been
     installed.  Otherwize the help/version messages will be eaten by
     the interpreter's output handler.  */

  if (print_version)
    {
      print_gdb_version (gdb_stdout);
      wrap_here ("");
      printf_filtered ("\n");
      exit (0);
    }

  if (print_help)
    {
      print_gdb_help (gdb_stdout);
      fputs_unfiltered ("\n", gdb_stdout);
      exit (0);
    }

  /* FIXME: cagney/2003-02-03: The big hack (part 1 of 2) that lets
     GDB retain the old MI1 interpreter startup behavior.  Output the
     copyright message before the interpreter is installed.  That way
     it isn't encapsulated in MI output.  */
  if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0)
    {
      /* Print all the junk at the top, with trailing "..." if we are about
         to read a symbol file (possibly slowly).  */
      print_gdb_version (gdb_stdout);
      if (symarg)
	printf_filtered ("..");
      wrap_here ("");
      gdb_flush (gdb_stdout);	/* Force to screen during slow operations */
    }


  /* Install the default UI.  All the interpreters should have had a
     look at things by now.  Initialize the default interpreter. */

  {
    /* Find it.  */
    struct interp *interp = interp_lookup (interpreter_p);
    if (interp == NULL)
      error ("Interpreter `%s' unrecognized", interpreter_p);
    /* Install it.  */
    if (!interp_set (interp))
      {
        fprintf_unfiltered (gdb_stderr,
			    "Interpreter `%s' failed to initialize.\n",
                            interpreter_p);
        exit (1);
      }
  }

  /* FIXME: cagney/2003-02-03: The big hack (part 2 of 2) that lets
     GDB retain the old MI1 interpreter startup behavior.  Output the
     copyright message after the interpreter is installed when it is
     any sane interpreter.  */
  if (!quiet && !current_interp_named_p (INTERP_MI1))
    {
      /* Print all the junk at the top, with trailing "..." if we are about
         to read a symbol file (possibly slowly).  */
      print_gdb_version (gdb_stdout);
      if (symarg)
	printf_filtered ("..");
      wrap_here ("");
      gdb_flush (gdb_stdout);	/* Force to screen during slow operations */
    }

  error_pre_print = "\n\n";
  quit_pre_print = error_pre_print;

  /* We may get more than one warning, don't double space all of them... */
  warning_pre_print = _("\nwarning: ");

  /* Read and execute $HOME/.gdbinit file, if it exists.  This is done
     *before* all the command line arguments are processed; it sets
     global parameters, which are independent of what file you are
     debugging or what directory you are in.  */
  homedir = getenv ("HOME");
  if (homedir)
    {
      homeinit = (char *) alloca (strlen (homedir) +
				  strlen (gdbinit) + 10);
      strcpy (homeinit, homedir);
      strcat (homeinit, "/");
      strcat (homeinit, gdbinit);

      if (!inhibit_gdbinit)
	{
	  catch_command_errors (source_command, homeinit, 0, RETURN_MASK_ALL);
	}

      /* Do stats; no need to do them elsewhere since we'll only
         need them if homedir is set.  Make sure that they are
         zero in case one of them fails (this guarantees that they
         won't match if either exists).  */

      memset (&homebuf, 0, sizeof (struct stat));
      memset (&cwdbuf, 0, sizeof (struct stat));

      stat (homeinit, &homebuf);
      stat (gdbinit, &cwdbuf);	/* We'll only need this if
				   homedir was set.  */
    }

  /* Now perform all the actions indicated by the arguments.  */
  if (cdarg != NULL)
    {
      catch_command_errors (cd_command, cdarg, 0, RETURN_MASK_ALL);
    }

  for (i = 0; i < ndir; i++)
    catch_command_errors (directory_command, dirarg[i], 0, RETURN_MASK_ALL);
  xfree (dirarg);

  if (execarg != NULL
      && symarg != NULL
      && strcmp (execarg, symarg) == 0)
    {
      /* The exec file and the symbol-file are the same.  If we can't
         open it, better only print one error message.
         catch_command_errors returns non-zero on success! */
      if (catch_command_errors (exec_file_attach, execarg, !batch, RETURN_MASK_ALL))
	catch_command_errors (symbol_file_add_main, symarg, 0, RETURN_MASK_ALL);
    }
  else
    {
      if (execarg != NULL)
	catch_command_errors (exec_file_attach, execarg, !batch, RETURN_MASK_ALL);
      if (symarg != NULL)
	catch_command_errors (symbol_file_add_main, symarg, 0, RETURN_MASK_ALL);
    }

  /* After the symbol file has been read, print a newline to get us
     beyond the copyright line...  But errors should still set off
     the error message with a (single) blank line.  */
  if (!quiet)
    printf_filtered ("\n");
  error_pre_print = "\n";
  quit_pre_print = error_pre_print;
  warning_pre_print = _("\nwarning: ");

  if (corearg != NULL)
    {
      /* corearg may be either a corefile or a pid.
	 If its first character is a digit, try attach first
	 and then corefile.  Otherwise try corefile first. */

      if (isdigit (corearg[0]))
	{
	  if (catch_command_errors (attach_command, corearg, 
				    !batch, RETURN_MASK_ALL) == 0)
	    catch_command_errors (core_file_command, corearg, 
				  !batch, RETURN_MASK_ALL);
	}
      else /* Can't be a pid, better be a corefile. */
	catch_command_errors (core_file_command, corearg, 
			      !batch, RETURN_MASK_ALL);
    }

  if (ttyarg != NULL)
    catch_command_errors (tty_command, ttyarg, !batch, RETURN_MASK_ALL);

  /* Error messages should no longer be distinguished with extra output. */
  error_pre_print = NULL;
  quit_pre_print = NULL;
  warning_pre_print = _("warning: ");

  /* Read the .gdbinit file in the current directory, *if* it isn't
     the same as the $HOME/.gdbinit file (it should exist, also).  */

  if (!homedir
      || memcmp ((char *) &homebuf, (char *) &cwdbuf, sizeof (struct stat)))
    if (!inhibit_gdbinit)
      {
	catch_command_errors (source_command, gdbinit, 0, RETURN_MASK_ALL);
      }

  for (i = 0; i < ncmd; i++)
    {
#if 0
      /* NOTE: cagney/1999-11-03: SET_TOP_LEVEL() was a macro that
         expanded into a call to setjmp().  */
      if (!SET_TOP_LEVEL ()) /* NB: This is #if 0'd out */
	{
	  /* NOTE: I am commenting this out, because it is not clear
	     where this feature is used. It is very old and
	     undocumented. ezannoni: 1999-05-04 */
#if 0
	  if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0')
	    read_command_file (stdin);
	  else
#endif
	    source_command (cmdarg[i], !batch);
	  do_cleanups (ALL_CLEANUPS);
	}
#endif
      catch_command_errors (source_command, cmdarg[i], !batch, RETURN_MASK_ALL);
    }
  xfree (cmdarg);

  /* Read in the old history after all the command files have been read. */
  init_history ();

  if (batch)
    {
      if (attach_flag)
	/* Either there was a problem executing the command in the
	   batch file aborted early, or the batch file forgot to do an
	   explicit detach.  Explicitly detach the inferior ensuring
	   that there are no zombies.  */
	target_detach (NULL, 0);
      
      /* We have hit the end of the batch file.  */
      exit (0);
    }

  /* Do any host- or target-specific hacks.  This is used for i960 targets
     to force the user to set a nindy target and spec its parameters.  */

#ifdef BEFORE_MAIN_LOOP_HOOK
  BEFORE_MAIN_LOOP_HOOK;
#endif

  /* Show time and/or space usage.  */

  if (display_time)
    {
      long init_time = get_run_time () - time_at_startup;

      printf_unfiltered (_("Startup time: %ld.%06ld\n"),
			 init_time / 1000000, init_time % 1000000);
    }

  if (display_space)
    {
#ifdef HAVE_SBRK
      extern char **environ;
      char *lim = (char *) sbrk (0);

      printf_unfiltered (_("Startup size: data size %ld\n"),
			 (long) (lim - (char *) &environ));
#endif
    }

#if 0
  /* FIXME: cagney/1999-11-06: The original main loop was like: */
  while (1)
    {
      if (!SET_TOP_LEVEL ())
	{
	  do_cleanups (ALL_CLEANUPS);	/* Do complete cleanup */
	  /* GUIs generally have their own command loop, mainloop, or whatever.
	     This is a good place to gain control because many error
	     conditions will end up here via longjmp(). */
	  if (deprecated_command_loop_hook)
	    deprecated_command_loop_hook ();
	  else
	    deprecated_command_loop ();
	  quit_command ((char *) 0, instream == stdin);
	}
    }
  /* NOTE: If the command_loop() returned normally, the loop would
     attempt to exit by calling the function quit_command().  That
     function would either call exit() or throw an error returning
     control to SET_TOP_LEVEL. */
  /* NOTE: The function do_cleanups() was called once each time round
     the loop.  The usefulness of the call isn't clear.  If an error
     was thrown, everything would have already been cleaned up.  If
     command_loop() returned normally and quit_command() was called,
     either exit() or error() (again cleaning up) would be called. */
#endif
  /* NOTE: cagney/1999-11-07: There is probably no reason for not
     moving this loop and the code found in captured_command_loop()
     into the command_loop() proper.  The main thing holding back that
     change - SET_TOP_LEVEL() - has been eliminated. */
  while (1)
    {
      catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL);
    }
  /* No exit -- exit is through quit_command.  */
}
コード例 #6
0
ファイル: mi-cmd-break.c プロジェクト: rmbq/binutils-gdb
static void
mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
{
  char *address = NULL;
  int hardware = 0;
  int temp_p = 0;
  int thread = -1;
  int ignore_count = 0;
  char *condition = NULL;
  int pending = 0;
  int enabled = 1;
  int tracepoint = 0;
  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
  enum bptype type_wanted;
  struct event_location *location;
  struct breakpoint_ops *ops;
  int is_explicit = 0;
  struct explicit_location explicit_loc;
  char *extra_string = NULL;

  enum opt
    {
      HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
      IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
      TRACEPOINT_OPT,
      EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
      EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
    };
  static const struct mi_opt opts[] =
  {
    {"h", HARDWARE_OPT, 0},
    {"t", TEMP_OPT, 0},
    {"c", CONDITION_OPT, 1},
    {"i", IGNORE_COUNT_OPT, 1},
    {"p", THREAD_OPT, 1},
    {"f", PENDING_OPT, 0},
    {"d", DISABLE_OPT, 0},
    {"a", TRACEPOINT_OPT, 0},
    {"-source" , EXPLICIT_SOURCE_OPT, 1},
    {"-function", EXPLICIT_FUNC_OPT, 1},
    {"-label", EXPLICIT_LABEL_OPT, 1},
    {"-line", EXPLICIT_LINE_OPT, 1},
    { 0, 0, 0 }
  };

  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
     to denote the end of the option list. */
  int oind = 0;
  char *oarg;

  initialize_explicit_location (&explicit_loc);

  while (1)
    {
      int opt = mi_getopt ("-break-insert", argc, argv,
			   opts, &oind, &oarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case TEMP_OPT:
	  temp_p = 1;
	  break;
	case HARDWARE_OPT:
	  hardware = 1;
	  break;
	case CONDITION_OPT:
	  condition = oarg;
	  break;
	case IGNORE_COUNT_OPT:
	  ignore_count = atol (oarg);
	  break;
	case THREAD_OPT:
	  thread = atol (oarg);
	  break;
	case PENDING_OPT:
	  pending = 1;
	  break;
	case DISABLE_OPT:
	  enabled = 0;
	  break;
	case TRACEPOINT_OPT:
	  tracepoint = 1;
	  break;
	case EXPLICIT_SOURCE_OPT:
	  is_explicit = 1;
	  explicit_loc.source_filename = oarg;
	  break;
	case EXPLICIT_FUNC_OPT:
	  is_explicit = 1;
	  explicit_loc.function_name = oarg;
	  break;
	case EXPLICIT_LABEL_OPT:
	  is_explicit = 1;
	  explicit_loc.label_name = oarg;
	  break;
	case EXPLICIT_LINE_OPT:
	  is_explicit = 1;
	  explicit_loc.line_offset = linespec_parse_line_offset (oarg);
	  break;
	}
    }

  if (oind >= argc && !is_explicit)
    error (_("-%s-insert: Missing <location>"),
	   dprintf ? "dprintf" : "break");
  if (dprintf)
    {
      int format_num = is_explicit ? oind : oind + 1;

      if (hardware || tracepoint)
	error (_("-dprintf-insert: does not support -h or -a"));
      if (format_num >= argc)
	error (_("-dprintf-insert: Missing <format>"));

      extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
      make_cleanup (xfree, extra_string);
      address = argv[oind];
    }
  else
    {
      if (is_explicit)
	{
	  if (oind < argc)
	    error (_("-break-insert: Garbage following explicit location"));
	}
      else
	{
	  if (oind < argc - 1)
	    error (_("-break-insert: Garbage following <location>"));
	  address = argv[oind];
	}
    }

  /* Now we have what we need, let's insert the breakpoint!  */
  setup_breakpoint_reporting ();

  if (tracepoint)
    {
      /* Note that to request a fast tracepoint, the client uses the
	 "hardware" flag, although there's nothing of hardware related to
	 fast tracepoints -- one can implement slow tracepoints with
	 hardware breakpoints, but fast tracepoints are always software.
	 "fast" is a misnomer, actually, "jump" would be more appropriate.
	 A simulator or an emulator could conceivably implement fast
	 regular non-jump based tracepoints.  */
      type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
      ops = &tracepoint_breakpoint_ops;
    }
  else if (dprintf)
    {
      type_wanted = bp_dprintf;
      ops = &dprintf_breakpoint_ops;
    }
  else
    {
      type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
      ops = &bkpt_breakpoint_ops;
    }

  if (is_explicit)
    {
      /* Error check -- we must have one of the other
	 parameters specified.  */
      if (explicit_loc.source_filename != NULL
	  && explicit_loc.function_name == NULL
	  && explicit_loc.label_name == NULL
	  && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
	error (_("-%s-insert: --source option requires --function, --label,"
		 " or --line"), dprintf ? "dprintf" : "break");

      location = new_explicit_location (&explicit_loc);
    }
  else
    {
      location = string_to_event_location (&address, current_language);
      if (*address)
	{
	  delete_event_location (location);
	  error (_("Garbage '%s' at end of location"), address);
	}
    }

  make_cleanup_delete_event_location (location);

  create_breakpoint (get_current_arch (), location, condition, thread,
		     extra_string,
		     0 /* condition and thread are valid.  */,
		     temp_p, type_wanted,
		     ignore_count,
		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
		     ops, 0, enabled, 0, 0);
  do_cleanups (back_to);
}
コード例 #7
0
ファイル: exec.c プロジェクト: davearrama/gdb
void
exec_file_attach (char *filename, int from_tty)
{
  /* Remove any previous exec file.  */
  unpush_target (&exec_ops);

  /* Now open and digest the file the user requested, if any.  */

  if (!filename)
    {
      if (from_tty)
        printf_unfiltered (_("No executable file now.\n"));

      set_gdbarch_from_file (NULL);
    }
  else
    {
      struct cleanup *cleanups;
      char *scratch_pathname;
      int scratch_chan;

      scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
		   write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
			    &scratch_pathname);
#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
      if (scratch_chan < 0)
	{
	  char *exename = alloca (strlen (filename) + 5);
	  strcat (strcpy (exename, filename), ".exe");
	  scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, exename,
	     write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
	     &scratch_pathname);
	}
#endif
      if (scratch_chan < 0)
	perror_with_name (filename);
      exec_bfd = bfd_fopen (scratch_pathname, gnutarget,
			    write_files ? FOPEN_RUB : FOPEN_RB,
			    scratch_chan);

      if (!exec_bfd)
	{
	  close (scratch_chan);
	  error (_("\"%s\": could not open as an executable file: %s"),
		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
	}

      /* At this point, scratch_pathname and exec_bfd->name both point to the
         same malloc'd string.  However exec_close() will attempt to free it
         via the exec_bfd->name pointer, so we need to make another copy and
         leave exec_bfd as the new owner of the original copy. */
      scratch_pathname = xstrdup (scratch_pathname);
      cleanups = make_cleanup (xfree, scratch_pathname);

      if (!bfd_check_format (exec_bfd, bfd_object))
	{
	  /* Make sure to close exec_bfd, or else "run" might try to use
	     it.  */
	  exec_close (0);
	  error (_("\"%s\": not in executable format: %s"),
		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
	}

      /* FIXME - This should only be run for RS6000, but the ifdef is a poor
         way to accomplish.  */
#ifdef DEPRECATED_IBM6000_TARGET
      /* Setup initial vmap. */

      map_vmap (exec_bfd, 0);
      if (vmap == NULL)
	{
	  /* Make sure to close exec_bfd, or else "run" might try to use
	     it.  */
	  exec_close (0);
	  error (_("\"%s\": can't find the file sections: %s"),
		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
	}
#endif /* DEPRECATED_IBM6000_TARGET */

      if (build_section_table (exec_bfd, &exec_ops.to_sections,
			       &exec_ops.to_sections_end))
	{
	  /* Make sure to close exec_bfd, or else "run" might try to use
	     it.  */
	  exec_close (0);
	  error (_("\"%s\": can't find the file sections: %s"),
		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
	}

      exec_bfd_mtime = bfd_get_mtime (exec_bfd);

      validate_files ();

      set_gdbarch_from_file (exec_bfd);

      push_target (&exec_ops);

      /* Tell display code (if any) about the changed file name.  */
      if (deprecated_exec_file_display_hook)
	(*deprecated_exec_file_display_hook) (filename);

      do_cleanups (cleanups);
    }
  bfd_cache_close_all ();
  observer_notify_executable_changed ();
}
コード例 #8
0
ファイル: coff-pe-read.c プロジェクト: 0mp/freebsd
void
read_pe_exported_syms (struct objfile *objfile)
{
  bfd *dll = objfile->obfd;
  unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
  unsigned long export_rva, export_size, nsections, secptr, expptr;
  unsigned long exp_funcbase;
  unsigned char *expdata, *erva;
  unsigned long name_rvas, ordinals, nexp, ordbase;
  char *dll_name;

  /* Array elements are for text, data and bss in that order
     Initialization with start_rva > end_rva guarantees that
     unused sections won't be matched. */
  struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE]
    = { {0, 1, 0, mst_text},
  {0, 1, 0, mst_data},
  {0, 1, 0, mst_bss}
  };

  struct cleanup *back_to = 0;

  char const *target = bfd_get_target (objfile->obfd);

  if ((strcmp (target, "pe-i386") != 0) && (strcmp (target, "pei-i386") != 0))
    {
      /* This is not an i386 format file. Abort now, because the code
         is untested on anything else. *FIXME* test on further
         architectures and loosen or remove this test. */
      return;
    }

  /* Get pe_header, optional header and numbers of export entries.  */
  pe_header_offset = pe_get32 (dll, 0x3c);
  opthdr_ofs = pe_header_offset + 4 + 20;
  num_entries = pe_get32 (dll, opthdr_ofs + 92);

  if (num_entries < 1)		/* No exports.  */
    {
      return;
    }

  export_rva = pe_get32 (dll, opthdr_ofs + 96);
  export_size = pe_get32 (dll, opthdr_ofs + 100);
  nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
  secptr = (pe_header_offset + 4 + 20 +
	    pe_get16 (dll, pe_header_offset + 4 + 16));
  expptr = 0;

  /* Get the rva and size of the export section.  */
  for (i = 0; i < nsections; i++)
    {
      char sname[8];
      unsigned long secptr1 = secptr + 40 * i;
      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
      unsigned long fptr = pe_get32 (dll, secptr1 + 20);

      bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
      bfd_bread (sname, (bfd_size_type) 8, dll);

      if (vaddr <= export_rva && vaddr + vsize > export_rva)
	{
	  expptr = fptr + (export_rva - vaddr);
	  if (export_rva + export_size > vaddr + vsize)
	    export_size = vsize - (export_rva - vaddr);
	  break;
	}
    }

  if (export_size == 0)
    {
      /* Empty export table. */
      return;
    }

  /* Scan sections and store the base and size of the relevant sections. */
  for (i = 0; i < nsections; i++)
    {
      unsigned long secptr1 = secptr + 40 * i;
      unsigned long vsize = pe_get32 (dll, secptr1 + 8);
      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
      unsigned long flags = pe_get32 (dll, secptr1 + 36);
      char sec_name[9];
      int sectix;

      sec_name[8] = '\0';
      bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
      bfd_bread (sec_name, (bfd_size_type) 8, dll);

      sectix = read_pe_section_index (sec_name);

      if (sectix != PE_SECTION_INDEX_INVALID)
	{
	  section_data[sectix].rva_start = vaddr;
	  section_data[sectix].rva_end = vaddr + vsize;
	}
    }

  expdata = (unsigned char *) xmalloc (export_size);
  back_to = make_cleanup (xfree, expdata);

  bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
  bfd_bread (expdata, (bfd_size_type) export_size, dll);
  erva = expdata - export_rva;

  nexp = pe_as32 (expdata + 24);
  name_rvas = pe_as32 (expdata + 32);
  ordinals = pe_as32 (expdata + 36);
  ordbase = pe_as32 (expdata + 16);
  exp_funcbase = pe_as32 (expdata + 28);

  /* Use internal dll name instead of full pathname. */
  dll_name = pe_as32 (expdata + 12) + erva;

  bfd_map_over_sections (dll, get_section_vmas, section_data);

  /* Adjust the vma_offsets in case this PE got relocated. This
     assumes that *all* sections share the same relocation offset
     as the text section. */
  for (i = 0; i < PE_SECTION_TABLE_SIZE; i++)
    {
      section_data[i].vma_offset
	+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
    }

  printf_filtered ("Minimal symbols from %s...", dll_name);
  wrap_here ("");

  /* Truncate name at first dot. Should maybe also convert to all
     lower case for convenience on Windows. */
  read_pe_truncate_name (dll_name);

  /* Iterate through the list of symbols.  */
  for (i = 0; i < nexp; i++)
    {
      /* Pointer to the names vector.  */
      unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);

      /* Pointer to the function address vector.  */
      unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);

      /* Find this symbol's section in our own array. */
      int sectix = 0;

      for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix)
	{
	  if ((func_rva >= section_data[sectix].rva_start)
	      && (func_rva < section_data[sectix].rva_end))
	    {
	      add_pe_exported_sym (erva + name_rva,
				   func_rva,
				   section_data + sectix, dll_name, objfile);
	      break;
	    }
	}
    }

  /* discard expdata. */
  do_cleanups (back_to);
}
コード例 #9
0
ファイル: mi-main.c プロジェクト: debrouxl/tiemu
enum mi_cmd_result
mi_execute_async_cli_command (char *mi, char *args, int from_tty)
{
  struct cleanup *old_cleanups;
  char *run;
  char *async_args;

  if (target_can_async_p ())
    {
      async_args = (char *) xmalloc (strlen (args) + 2);
      make_exec_cleanup (free, async_args);
      strcpy (async_args, args);
      strcat (async_args, "&");
      run = xstrprintf ("%s %s", mi, async_args);
      make_exec_cleanup (free, run);
      add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
      old_cleanups = NULL;
    }
  else
    {
      run = xstrprintf ("%s %s", mi, args);
      old_cleanups = make_cleanup (xfree, run);
    }

  if (!target_can_async_p ())
    {
      /* NOTE: For synchronous targets asynchronous behavour is faked by
         printing out the GDB prompt before we even try to execute the
         command. */
      if (last_async_command)
	fputs_unfiltered (last_async_command, raw_stdout);
      fputs_unfiltered ("^running\n", raw_stdout);
      fputs_unfiltered ("(gdb) \n", raw_stdout);
      gdb_flush (raw_stdout);
    }
  else
    {
      /* FIXME: cagney/1999-11-29: Printing this message before
         calling execute_command is wrong.  It should only be printed
         once gdb has confirmed that it really has managed to send a
         run command to the target. */
      if (last_async_command)
	fputs_unfiltered (last_async_command, raw_stdout);
      fputs_unfiltered ("^running\n", raw_stdout);
    }

  execute_command ( /*ui */ run, 0 /*from_tty */ );

  if (!target_can_async_p ())
    {
      /* Do this before doing any printing.  It would appear that some
         print code leaves garbage around in the buffer. */
      do_cleanups (old_cleanups);
      /* If the target was doing the operation synchronously we fake
         the stopped message. */
      if (last_async_command)
	fputs_unfiltered (last_async_command, raw_stdout);
      fputs_unfiltered ("*stopped", raw_stdout);
      mi_out_put (uiout, raw_stdout);
      mi_out_rewind (uiout);
      fputs_unfiltered ("\n", raw_stdout);
      return MI_CMD_QUIET;
    }
  return MI_CMD_DONE;
}
コード例 #10
0
ファイル: disasm.c プロジェクト: dougmencken/apple-gdb-1824
int
find_pc_offset(CORE_ADDR start, CORE_ADDR *result, int offset,
               int funclimit, int peeklimit)
{
  CORE_ADDR low = INVALID_ADDRESS;
  CORE_ADDR high = INVALID_ADDRESS;
  CORE_ADDR cur;
  CORE_ADDR constrained;

  int length;

  struct disassemble_info di = gdb_disassemble_info_null(current_gdbarch);
  CORE_ADDR *addrs = NULL;
  unsigned int index;
  struct cleanup *cleanup = NULL;

  *result = INVALID_ADDRESS;
  cur = start;

  /* If we are constraining the address to stay in the same function,
     we need to be able to find its boundaries. */

  if (funclimit)
    {
      if (find_pc_partial_function_no_inlined(start, NULL, &low, &high) == 0)
	{
	  /* We were unable to find the start of the function. */
	  return -1;
	}
    }

  /* If the architecture has fixed-sized instructions, just use simple
     arithmetic. */

  length = gdbarch_instruction_length(current_gdbarch);
  if (length > 0)
    {
      cur = (start + (length * offset));

      /* Constrain to be within the function limits if appropriate. */
      if (funclimit && (cur > high))
	constrained = high;
      else if (funclimit && (cur < low))
	constrained = low;
      else
	constrained = cur;

      /* Return 1 if we constrained the address; 0 otherwise. */
      *result = constrained;
      return (constrained != cur);
    }

  /* From here, we must assume variable-sized instructions. */

  if ((! funclimit) && (offset < 0))
    {
      /* FIXME: We don't support seeking backwards past the beginning
	 of a function. */
      return -1;
    }

  /* If we have a positive offset, start seeking forward until we are
     either done, or reach the end of the function. */

  cur = start;
  while (offset > 0)
    {
      cur += TARGET_PRINT_INSN(cur, &di);
      offset--;

      if (funclimit && (cur > high))
	{
	  /* We went past the end of the function without ever
	     reaching the purportedly final instruction. */
	  return -1;
	}

      if (funclimit && (cur == high))
	{
	  /* We reached the end of the function.  Return 1 if we had
	     to constrain the address; 0 otherwise. */
	  *result = cur;
	  return (offset > 0);
	}
    }

  if (offset == 0)
    {
      *result = cur;
      return 0;
    }

  /* From here out we can assume we are doing a negative offset. */

  gdb_assert(low <= start);
  gdb_assert(offset < 0);

  /* A sanity check:  If we've stepped into some area of memory where
     gdb doesn't have symbols and the GUI requests we disassemble from $pc,
     gdb can come up with very large LOW-HIGH regions of memory to disassemble
     through.  As a sanity check, if this function starts four pages before
     the given $pc and we're in MI mode (so we have a GUI that may be
     requesting nonsensical things), shortcircuit this operation.  */

  if (((off_t)(start - low) > -offset) && ((start - low) > 16384)
      && ui_out_is_mi_like_p(uiout))
    {
      *result = start;
      return 1;
    }

  /* There's no point searching for more instructions slots than there
     are bytes.  If we were given a PEEKLIMIT of -1, or a PEEKLIMIT
     higher than we need, set it to the number of bytes from the start
     of the function. */

  if ((peeklimit < 0) || ((CORE_ADDR)peeklimit > (start - low)))
    peeklimit = (int)(start - low);

  /* If PEEKLIMIT is less than (start - low), we can still attempt the
     search --- maybe enough of the instruction stream will be
     multi-byte that we'll find our address regardless. */

  addrs = (CORE_ADDR *)xmalloc(peeklimit * sizeof(CORE_ADDR));
  cleanup = make_cleanup(xfree, addrs);

  /* We can assume that we are constrained to the current function at
     this point (see the comment above). */

  gdb_assert(funclimit);

  cur = low;
  index = 0;

  /* Seek forward until we either reach our starting point, or reach
     PEEKLIMIT. */

  for (;;)
    {
      if (cur >= start)
	break;
      if (index >= (unsigned int)peeklimit)
	break;

      gdb_assert((int)index < peeklimit);
      addrs[index++] = cur;
      cur += TARGET_PRINT_INSN(cur, &di);
    }

  if (cur == start)
    {
      /* We were able to seek all the way forward to the start address. */

      gdb_assert(funclimit);
      gdb_assert(offset < 0);

      if ((off_t)index < -offset)
	{
	  /* We weren't able to go far enough back; return the earliest
             instruction of the function.  */
	  *result = low;
	  do_cleanups(cleanup);
	  return 1;
	}
      else
	{
	  *result = addrs[index + offset];
	  do_cleanups(cleanup);
	  return 0;
	}
    }

  if (cur > start)
    {
      /* We seeked forward right past the start address, without ever
	 hitting it. */
      do_cleanups(cleanup);
      return -1;
    }

  if (index >= (unsigned int)peeklimit)
    {
      /* We went past PEEKLIMIT instructions, and hence, weren't able
	 to complete the backwards seek.  */
      do_cleanups(cleanup);
      return -1;
    }

  internal_error(__FILE__, __LINE__, "should never have reached here");
  do_cleanups(cleanup);
  return -1;
}
コード例 #11
0
void
mi_cmd_break_insert (char *command, char **argv, int argc)
{
  char *address = NULL;
  int hardware = 0;
  int temp_p = 0;
  int thread = -1;
  int ignore_count = 0;
  char *condition = NULL;
  int pending = 0;
  int enabled = 1;
  int tracepoint = 0;
  struct cleanup *back_to;
  enum bptype type_wanted;
  struct breakpoint_ops *ops;

  enum opt
    {
      HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
      IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
      TRACEPOINT_OPT,
    };
  static const struct mi_opt opts[] =
  {
    {"h", HARDWARE_OPT, 0},
    {"t", TEMP_OPT, 0},
    {"c", CONDITION_OPT, 1},
    {"i", IGNORE_COUNT_OPT, 1},
    {"p", THREAD_OPT, 1},
    {"f", PENDING_OPT, 0},
    {"d", DISABLE_OPT, 0},
    {"a", TRACEPOINT_OPT, 0},
    { 0, 0, 0 }
  };

  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
     to denote the end of the option list. */
  int oind = 0;
  char *oarg;

  while (1)
    {
      int opt = mi_getopt ("-break-insert", argc, argv,
			   opts, &oind, &oarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case TEMP_OPT:
	  temp_p = 1;
	  break;
	case HARDWARE_OPT:
	  hardware = 1;
	  break;
	case CONDITION_OPT:
	  condition = oarg;
	  break;
	case IGNORE_COUNT_OPT:
	  ignore_count = atol (oarg);
	  break;
	case THREAD_OPT:
	  thread = atol (oarg);
	  break;
	case PENDING_OPT:
	  pending = 1;
	  break;
	case DISABLE_OPT:
	  enabled = 0;
	  break;
	case TRACEPOINT_OPT:
	  tracepoint = 1;
	  break;
	}
    }

  if (oind >= argc)
    error (_("-break-insert: Missing <location>"));
  if (oind < argc - 1)
    error (_("-break-insert: Garbage following <location>"));
  address = argv[oind];

  /* Now we have what we need, let's insert the breakpoint!  */
  back_to = setup_breakpoint_reporting ();

  /* Note that to request a fast tracepoint, the client uses the
     "hardware" flag, although there's nothing of hardware related to
     fast tracepoints -- one can implement slow tracepoints with
     hardware breakpoints, but fast tracepoints are always software.
     "fast" is a misnomer, actually, "jump" would be more appropriate.
     A simulator or an emulator could conceivably implement fast
     regular non-jump based tracepoints.  */
  type_wanted = (tracepoint
		 ? (hardware ? bp_fast_tracepoint : bp_tracepoint)
		 : (hardware ? bp_hardware_breakpoint : bp_breakpoint));
  ops = tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops;

  create_breakpoint (get_current_arch (), address, condition, thread,
		     NULL,
		     0 /* condition and thread are valid.  */,
		     temp_p, type_wanted,
		     ignore_count,
		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
		     ops, 0, enabled, 0, 0);
  do_cleanups (back_to);

}
コード例 #12
0
ファイル: py-inferior.c プロジェクト: tkgunji/RCU2_soft
/* Implementation of gdb.read_memory (address, length).
   Returns a Python buffer object with LENGTH bytes of the inferior's
   memory at ADDRESS.  Both arguments are integers.  */
static PyObject *
infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
{
    int error = 0;
    CORE_ADDR addr, length;
    void *buffer = NULL;
    membuf_object *membuf_obj;
    PyObject *addr_obj, *length_obj;
    struct cleanup *cleanups;
    volatile struct gdb_exception except;
    static char *keywords[] = { "address", "length", NULL };

    if (! PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
                                       &addr_obj, &length_obj))
        return NULL;

    cleanups = make_cleanup (null_cleanup, NULL);

    TRY_CATCH (except, RETURN_MASK_ALL)
    {
        if (!get_addr_from_python (addr_obj, &addr)
                || !get_addr_from_python (length_obj, &length))
        {
            error = 1;
            break;
        }

        buffer = xmalloc (length);
        make_cleanup (xfree, buffer);

        read_memory (addr, buffer, length);
    }
    if (except.reason < 0)
    {
        do_cleanups (cleanups);
        GDB_PY_HANDLE_EXCEPTION (except);
    }

    if (error)
    {
        do_cleanups (cleanups);
        return NULL;
    }

    membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
    if (membuf_obj == NULL)
    {
        PyErr_SetString (PyExc_MemoryError,
                         _("Could not allocate memory buffer object."));
        do_cleanups (cleanups);
        return NULL;
    }

    discard_cleanups (cleanups);

    membuf_obj->buffer = buffer;
    membuf_obj->addr = addr;
    membuf_obj->length = length;

    return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
                                         Py_END_OF_BUFFER);
}
コード例 #13
0
enum ext_lang_rc
gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang,
                                struct type *type, const gdb_byte *valaddr,
                                int embedded_offset, CORE_ADDR address,
                                struct ui_file *stream, int recurse,
                                const struct value *val,
                                const struct value_print_options *options,
                                const struct language_defn *language)
{
    struct gdbarch *gdbarch = get_type_arch (type);
    PyObject *printer = NULL;
    PyObject *val_obj = NULL;
    struct value *value;
    char *hint = NULL;
    struct cleanup *cleanups;
    enum ext_lang_rc result = EXT_LANG_RC_NOP;
    enum string_repr_result print_result;

    /* No pretty-printer support for unavailable values.  */
    if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
        return EXT_LANG_RC_NOP;

    if (!gdb_python_initialized)
        return EXT_LANG_RC_NOP;

    cleanups = ensure_python_env (gdbarch, language);

    /* Instantiate the printer.  */
    if (valaddr)
        valaddr += embedded_offset;
    value = value_from_contents_and_address (type, valaddr,
    address + embedded_offset);

    set_value_component_location (value, val);
    /* set_value_component_location resets the address, so we may
       need to set it again.  */
    if (VALUE_LVAL (value) != lval_internalvar
    && VALUE_LVAL (value) != lval_internalvar_component
    && VALUE_LVAL (value) != lval_computed)
        set_value_address (value, address + embedded_offset);

    val_obj = value_to_value_object (value);
    if (! val_obj)
    {
        result = EXT_LANG_RC_ERROR;
        goto done;
    }

    /* Find the constructor.  */
    printer = find_pretty_printer (val_obj);
    Py_DECREF (val_obj);

    if (printer == NULL)
    {
        result = EXT_LANG_RC_ERROR;
        goto done;
    }

    make_cleanup_py_decref (printer);
    if (printer == Py_None)
    {
        result = EXT_LANG_RC_NOP;
        goto done;
    }

    /* If we are printing a map, we want some special formatting.  */
    hint = gdbpy_get_display_hint (printer);
    make_cleanup (free_current_contents, &hint);

    /* Print the section */
    print_result = print_string_repr (printer, hint, stream, recurse,
    options, language, gdbarch);
    if (print_result != string_repr_error)
        print_children (printer, hint, stream, recurse, options, language,
        print_result == string_repr_none);

    result = EXT_LANG_RC_OK;

done:
    if (PyErr_Occurred ())
        print_stack_unless_memory_error (stream);
    do_cleanups (cleanups);
    return result;
}
コード例 #14
0
/* Helper for gdbpy_apply_val_pretty_printer that formats children of the
   printer, if any exist.  If is_py_none is true, then nothing has
   been printed by to_string, and format output accordingly. */
static void
print_children (PyObject *printer, const char *hint,
                struct ui_file *stream, int recurse,
                const struct value_print_options *options,
                const struct language_defn *language,
                int is_py_none)
{
    int is_map, is_array, done_flag, pretty;
    unsigned int i;
    PyObject *children, *iter;
#ifndef IS_PY3K
    PyObject *frame;
#endif
    struct cleanup *cleanups;

    if (! PyObject_HasAttr (printer, gdbpy_children_cst))
        return;

    /* If we are printing a map or an array, we want some special
       formatting.  */
    is_map = hint && ! strcmp (hint, "map");
    is_array = hint && ! strcmp (hint, "array");

    children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst,
                                           NULL);
    if (! children)
    {
        print_stack_unless_memory_error (stream);
        return;
    }

    cleanups = make_cleanup_py_decref (children);

    iter = PyObject_GetIter (children);
    if (!iter)
    {
        print_stack_unless_memory_error (stream);
        goto done;
    }
    make_cleanup_py_decref (iter);

    /* Use the prettyformat_arrays option if we are printing an array,
       and the pretty option otherwise.  */
    if (is_array)
        pretty = options->prettyformat_arrays;
    else
    {
        if (options->prettyformat == Val_prettyformat)
            pretty = 1;
        else
            pretty = options->prettyformat_structs;
    }

    /* Manufacture a dummy Python frame to work around Python 2.4 bug,
       where it insists on having a non-NULL tstate->frame when
       a generator is called.  */
#ifndef IS_PY3K
    frame = push_dummy_python_frame ();
    if (!frame)
    {
        gdbpy_print_stack ();
        goto done;
    }
    make_cleanup_py_decref (frame);
#endif

    done_flag = 0;
    for (i = 0; i < options->print_max; ++i)
    {
        PyObject *py_v, *item = PyIter_Next (iter);
        const char *name;
        struct cleanup *inner_cleanup;

        if (! item)
        {
            if (PyErr_Occurred ())
                print_stack_unless_memory_error (stream);
            /* Set a flag so we can know whether we printed all the
               available elements.  */
            else
                done_flag = 1;
            break;
        }

        if (! PyTuple_Check (item) || PyTuple_Size (item) != 2)
        {
            PyErr_SetString (PyExc_TypeError,
                             _("Result of children iterator not a tuple"
                               " of two elements."));
            gdbpy_print_stack ();
            Py_DECREF (item);
            continue;
        }
        if (! PyArg_ParseTuple (item, "sO", &name, &py_v))
        {
            /* The user won't necessarily get a stack trace here, so provide
               more context.  */
            if (gdbpy_print_python_errors_p ())
                fprintf_unfiltered (gdb_stderr,
                                    _("Bad result from children iterator.\n"));
            gdbpy_print_stack ();
            Py_DECREF (item);
            continue;
        }
        inner_cleanup = make_cleanup_py_decref (item);

        /* Print initial "{".  For other elements, there are three
        cases:
         1. Maps.  Print a "," after each value element.
         2. Arrays.  Always print a ",".
         3. Other.  Always print a ",".  */
        if (i == 0)
        {
            if (is_py_none)
                fputs_filtered ("{", stream);
            else
                fputs_filtered (" = {", stream);
        }

        else if (! is_map || i % 2 == 0)
            fputs_filtered (pretty ? "," : ", ", stream);

        /* In summary mode, we just want to print "= {...}" if there is
        a value.  */
        if (options->summary)
        {
            /* This increment tricks the post-loop logic to print what
               we want.  */
            ++i;
            /* Likewise.  */
            pretty = 0;
            break;
        }

        if (! is_map || i % 2 == 0)
        {
            if (pretty)
            {
                fputs_filtered ("\n", stream);
                print_spaces_filtered (2 + 2 * recurse, stream);
            }
            else
                wrap_here (n_spaces (2 + 2 *recurse));
        }

        if (is_map && i % 2 == 0)
            fputs_filtered ("[", stream);
        else if (is_array)
        {
            /* We print the index, not whatever the child method
               returned as the name.  */
            if (options->print_array_indexes)
                fprintf_filtered (stream, "[%d] = ", i);
        }
        else if (! is_map)
        {
            fputs_filtered (name, stream);
            fputs_filtered (" = ", stream);
        }

        if (gdbpy_is_lazy_string (py_v))
        {
            CORE_ADDR addr;
            struct type *type;
            long length;
            char *encoding = NULL;
            struct value_print_options local_opts = *options;

            make_cleanup (free_current_contents, &encoding);
            gdbpy_extract_lazy_string (py_v, &addr, &type, &length, &encoding);

            local_opts.addressprint = 0;
            val_print_string (type, encoding, addr, (int) length, stream,
                              &local_opts);
        }
        else if (gdbpy_is_string (py_v))
        {
            char *output;

            output = python_string_to_host_string (py_v);
            if (!output)
                gdbpy_print_stack ();
            else
            {
                fputs_filtered (output, stream);
                xfree (output);
            }
        }
        else
        {
            struct value *value = convert_value_from_python (py_v);

            if (value == NULL)
            {
                gdbpy_print_stack ();
                error (_("Error while executing Python code."));
            }
            else
                common_val_print (value, stream, recurse + 1, options, language);
        }

        if (is_map && i % 2 == 0)
            fputs_filtered ("] = ", stream);

        do_cleanups (inner_cleanup);
    }

    if (i)
    {
        if (!done_flag)
        {
            if (pretty)
            {
                fputs_filtered ("\n", stream);
                print_spaces_filtered (2 + 2 * recurse, stream);
            }
            fputs_filtered ("...", stream);
        }
        if (pretty)
        {
            fputs_filtered ("\n", stream);
            print_spaces_filtered (2 * recurse, stream);
        }
        fputs_filtered ("}", stream);
    }

done:
    do_cleanups (cleanups);
}
コード例 #15
0
static void
rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
                     enum rx_frame_type frame_type,
		     struct rx_prologue *result)
{
  CORE_ADDR pc, next_pc;
  int rn;
  pv_t reg[RX_NUM_REGS];
  struct pv_area *stack;
  struct cleanup *back_to;
  CORE_ADDR after_last_frame_setup_insn = start_pc;

  memset (result, 0, sizeof (*result));

  result->frame_type = frame_type;

  for (rn = 0; rn < RX_NUM_REGS; rn++)
    {
      reg[rn] = pv_register (rn, 0);
      result->reg_offset[rn] = 1;
    }

  stack = make_pv_area (RX_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
  back_to = make_cleanup_free_pv_area (stack);

  if (frame_type == RX_FRAME_TYPE_FAST_INTERRUPT)
    {
      /* This code won't do anything useful at present, but this is
         what happens for fast interrupts.  */
      reg[RX_BPSW_REGNUM] = reg[RX_PSW_REGNUM];
      reg[RX_BPC_REGNUM] = reg[RX_PC_REGNUM];
    }
  else
    {
      /* When an exception occurs, the PSW is saved to the interrupt stack
         first.  */
      if (frame_type == RX_FRAME_TYPE_EXCEPTION)
	{
	  reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
	  pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[RX_PSW_REGNUM]);
	}

      /* The call instruction (or an exception/interrupt) has saved the return
          address on the stack.  */
      reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
      pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[RX_PC_REGNUM]);

    }


  pc = start_pc;
  while (pc < limit_pc)
    {
      int bytes_read;
      struct rx_get_opcode_byte_handle opcode_handle;
      RX_Opcode_Decoded opc;

      opcode_handle.pc = pc;
      bytes_read = rx_decode_opcode (pc, &opc, rx_get_opcode_byte,
				     &opcode_handle);
      next_pc = pc + bytes_read;

      if (opc.id == RXO_pushm	/* pushm r1, r2 */
	  && opc.op[1].type == RX_Operand_Register
	  && opc.op[2].type == RX_Operand_Register)
	{
	  int r1, r2;
	  int r;

	  r1 = opc.op[1].reg;
	  r2 = opc.op[2].reg;
	  for (r = r2; r >= r1; r--)
	    {
	      reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
	      pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[r]);
	    }
	  after_last_frame_setup_insn = next_pc;
	}
      else if (opc.id == RXO_mov	/* mov.l rdst, rsrc */
	       && opc.op[0].type == RX_Operand_Register
	       && opc.op[1].type == RX_Operand_Register
	       && opc.size == RX_Long)
	{
	  int rdst, rsrc;

	  rdst = opc.op[0].reg;
	  rsrc = opc.op[1].reg;
	  reg[rdst] = reg[rsrc];
	  if (rdst == RX_FP_REGNUM && rsrc == RX_SP_REGNUM)
	    after_last_frame_setup_insn = next_pc;
	}
      else if (opc.id == RXO_mov	/* mov.l rsrc, [-SP] */
	       && opc.op[0].type == RX_Operand_Predec
	       && opc.op[0].reg == RX_SP_REGNUM
	       && opc.op[1].type == RX_Operand_Register
	       && opc.size == RX_Long)
	{
	  int rsrc;

	  rsrc = opc.op[1].reg;
	  reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
	  pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[rsrc]);
	  after_last_frame_setup_insn = next_pc;
	}
      else if (opc.id == RXO_add	/* add #const, rsrc, rdst */
	       && opc.op[0].type == RX_Operand_Register
	       && opc.op[1].type == RX_Operand_Immediate
	       && opc.op[2].type == RX_Operand_Register)
	{
	  int rdst = opc.op[0].reg;
	  int addend = opc.op[1].addend;
	  int rsrc = opc.op[2].reg;
	  reg[rdst] = pv_add_constant (reg[rsrc], addend);
	  /* Negative adjustments to the stack pointer or frame pointer
	     are (most likely) part of the prologue.  */
	  if ((rdst == RX_SP_REGNUM || rdst == RX_FP_REGNUM) && addend < 0)
	    after_last_frame_setup_insn = next_pc;
	}
      else if (opc.id == RXO_mov
	       && opc.op[0].type == RX_Operand_Indirect
	       && opc.op[1].type == RX_Operand_Register
	       && opc.size == RX_Long
	       && (opc.op[0].reg == RX_SP_REGNUM
		   || opc.op[0].reg == RX_FP_REGNUM)
	       && (RX_R1_REGNUM <= opc.op[1].reg
		   && opc.op[1].reg <= RX_R4_REGNUM))
	{
	  /* This moves an argument register to the stack.  Don't
	     record it, but allow it to be a part of the prologue.  */
	}
      else if (opc.id == RXO_branch
	       && opc.op[0].type == RX_Operand_Immediate
	       && next_pc < opc.op[0].addend)
	{
	  /* When a loop appears as the first statement of a function
	     body, gcc 4.x will use a BRA instruction to branch to the
	     loop condition checking code.  This BRA instruction is
	     marked as part of the prologue.  We therefore set next_pc
	     to this branch target and also stop the prologue scan.
	     The instructions at and beyond the branch target should
	     no longer be associated with the prologue.

	     Note that we only consider forward branches here.  We
	     presume that a forward branch is being used to skip over
	     a loop body.

	     A backwards branch is covered by the default case below.
	     If we were to encounter a backwards branch, that would
	     most likely mean that we've scanned through a loop body.
	     We definitely want to stop the prologue scan when this
	     happens and that is precisely what is done by the default
	     case below.  */

	  after_last_frame_setup_insn = opc.op[0].addend;
	  break;		/* Scan no further if we hit this case.  */
	}
      else
	{
	  /* Terminate the prologue scan.  */
	  break;
	}

      pc = next_pc;
    }

  /* Is the frame size (offset, really) a known constant?  */
  if (pv_is_register (reg[RX_SP_REGNUM], RX_SP_REGNUM))
    result->frame_size = reg[RX_SP_REGNUM].k;

  /* Was the frame pointer initialized?  */
  if (pv_is_register (reg[RX_FP_REGNUM], RX_SP_REGNUM))
    {
      result->has_frame_ptr = 1;
      result->frame_ptr_offset = reg[RX_FP_REGNUM].k;
    }

  /* Record where all the registers were saved.  */
  pv_area_scan (stack, check_for_saved, (void *) result);

  result->prologue_end = after_last_frame_setup_insn;

  do_cleanups (back_to);
}
コード例 #16
0
ファイル: mi-main.c プロジェクト: debrouxl/tiemu
void
mi_load_progress (const char *section_name,
		  unsigned long sent_so_far,
		  unsigned long total_section,
		  unsigned long total_sent,
		  unsigned long grand_total)
{
  struct timeval time_now, delta, update_threshold;
  static struct timeval last_update;
  static char *previous_sect_name = NULL;
  int new_section;
  struct ui_out *saved_uiout;

  /* This function is called through deprecated_show_load_progress
     which means uiout may not be correct.  Fix it for the duration
     of this function.  */
  saved_uiout = uiout;

  if (current_interp_named_p (INTERP_MI))
    uiout = mi_out_new (2);
  else if (current_interp_named_p (INTERP_MI1))
    uiout = mi_out_new (1);
  else
    return;

  update_threshold.tv_sec = 0;
  update_threshold.tv_usec = 500000;
  gettimeofday (&time_now, NULL);

  delta.tv_usec = time_now.tv_usec - last_update.tv_usec;
  delta.tv_sec = time_now.tv_sec - last_update.tv_sec;

  if (delta.tv_usec < 0)
    {
      delta.tv_sec -= 1;
      delta.tv_usec += 1000000;
    }

  new_section = (previous_sect_name ?
		 strcmp (previous_sect_name, section_name) : 1);
  if (new_section)
    {
      struct cleanup *cleanup_tuple;
      xfree (previous_sect_name);
      previous_sect_name = xstrdup (section_name);

      if (last_async_command)
	fputs_unfiltered (last_async_command, raw_stdout);
      fputs_unfiltered ("+download", raw_stdout);
      cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
      ui_out_field_string (uiout, "section", section_name);
      ui_out_field_int (uiout, "section-size", total_section);
      ui_out_field_int (uiout, "total-size", grand_total);
      do_cleanups (cleanup_tuple);
      mi_out_put (uiout, raw_stdout);
      fputs_unfiltered ("\n", raw_stdout);
      gdb_flush (raw_stdout);
    }

  if (delta.tv_sec >= update_threshold.tv_sec &&
      delta.tv_usec >= update_threshold.tv_usec)
    {
      struct cleanup *cleanup_tuple;
      last_update.tv_sec = time_now.tv_sec;
      last_update.tv_usec = time_now.tv_usec;
      if (last_async_command)
	fputs_unfiltered (last_async_command, raw_stdout);
      fputs_unfiltered ("+download", raw_stdout);
      cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
      ui_out_field_string (uiout, "section", section_name);
      ui_out_field_int (uiout, "section-sent", sent_so_far);
      ui_out_field_int (uiout, "section-size", total_section);
      ui_out_field_int (uiout, "total-sent", total_sent);
      ui_out_field_int (uiout, "total-size", grand_total);
      do_cleanups (cleanup_tuple);
      mi_out_put (uiout, raw_stdout);
      fputs_unfiltered ("\n", raw_stdout);
      gdb_flush (raw_stdout);
    }

  xfree (uiout);
  uiout = saved_uiout;
}
コード例 #17
0
ファイル: p-valprint.c プロジェクト: peterdocter/cuda-gdb
static void
pascal_object_print_value (struct type *type, const gdb_byte *valaddr,
                           int offset,
                           CORE_ADDR address, struct ui_file *stream,
                           int recurse,
                           const struct value *val,
                           const struct value_print_options *options,
                           struct type **dont_print_vb)
{
    struct type **last_dont_print
        = (struct type **) obstack_next_free (&dont_print_vb_obstack);
    struct obstack tmp_obstack = dont_print_vb_obstack;
    int i, n_baseclasses = TYPE_N_BASECLASSES (type);

    if (dont_print_vb == 0)
    {
        /* If we're at top level, carve out a completely fresh
           chunk of the obstack and use that until this particular
           invocation returns.  */
        /* Bump up the high-water mark.  Now alpha is omega.  */
        obstack_finish (&dont_print_vb_obstack);
    }

    for (i = 0; i < n_baseclasses; i++)
    {
        int boffset = 0;
        struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
        const char *basename = type_name_no_tag (baseclass);
        const gdb_byte *base_valaddr = NULL;
        int thisoffset;
        volatile struct gdb_exception ex;
        int skip = 0;

        if (BASETYPE_VIA_VIRTUAL (type, i))
        {
            struct type **first_dont_print
                = (struct type **) obstack_base (&dont_print_vb_obstack);

            int j = (struct type **) obstack_next_free (&dont_print_vb_obstack)
                    - first_dont_print;

            while (--j >= 0)
                if (baseclass == first_dont_print[j])
                    goto flush_it;

            obstack_ptr_grow (&dont_print_vb_obstack, baseclass);
        }

        thisoffset = offset;

        TRY_CATCH (ex, RETURN_MASK_ERROR)
        {
            boffset = baseclass_offset (type, i, valaddr, offset, address, val);
        }
        if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
            skip = -1;
        else if (ex.reason < 0)
            skip = 1;
        else
        {
            skip = 0;

            /* The virtual base class pointer might have been clobbered by the
               user program. Make sure that it still points to a valid memory
               location.  */

            if (boffset < 0 || boffset >= TYPE_LENGTH (type))
            {
                gdb_byte *buf;
                struct cleanup *back_to;

                buf = xmalloc (TYPE_LENGTH (baseclass));
                back_to = make_cleanup (xfree, buf);

                base_valaddr = buf;
                if (target_read_memory (address + boffset, buf,
                                        TYPE_LENGTH (baseclass)) != 0)
                    skip = 1;
                address = address + boffset;
                thisoffset = 0;
                boffset = 0;
                do_cleanups (back_to);
            }
            else
                base_valaddr = valaddr;
        }

        if (options->pretty)
        {
            fprintf_filtered (stream, "\n");
            print_spaces_filtered (2 * recurse, stream);
        }
        fputs_filtered ("<", stream);
        /* Not sure what the best notation is in the case where there is no
           baseclass name.  */

        fputs_filtered (basename ? basename : "", stream);
        fputs_filtered ("> = ", stream);

        if (skip < 0)
            val_print_unavailable (stream);
        else if (skip > 0)
            val_print_invalid_address (stream);
        else
            pascal_object_print_value_fields (baseclass, base_valaddr,
                                              thisoffset + boffset, address,
                                              stream, recurse, val, options,
                                              (struct type **) obstack_base (&dont_print_vb_obstack),
                                              0);
        fputs_filtered (", ", stream);

flush_it:
        ;
    }
コード例 #18
0
ファイル: mi-main.c プロジェクト: debrouxl/tiemu
enum mi_cmd_result
mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
{
  int regnum, numregs, changed;
  int i;
  struct cleanup *cleanup;

  /* Note that the test for a valid register must include checking the
     REGISTER_NAME because NUM_REGS may be allocated for the union of
     the register sets within a family of related processors.  In this
     case, some entries of REGISTER_NAME will change depending upon
     the particular processor being debugged.  */

  numregs = NUM_REGS + NUM_PSEUDO_REGS;

  cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");

  if (argc == 0)		/* No args, just do all the regs */
    {
      for (regnum = 0;
	   regnum < numregs;
	   regnum++)
	{
	  if (REGISTER_NAME (regnum) == NULL
	      || *(REGISTER_NAME (regnum)) == '\0')
	    continue;
	  changed = register_changed_p (regnum);
	  if (changed < 0)
	    {
	      do_cleanups (cleanup);
	      mi_error_message = xstrprintf ("mi_cmd_data_list_changed_registers: Unable to read register contents.");
	      return MI_CMD_ERROR;
	    }
	  else if (changed)
	    ui_out_field_int (uiout, NULL, regnum);
	}
    }

  /* Else, list of register #s, just do listed regs */
  for (i = 0; i < argc; i++)
    {
      regnum = atoi (argv[i]);

      if (regnum >= 0
	  && regnum < numregs
	  && REGISTER_NAME (regnum) != NULL
	  && *REGISTER_NAME (regnum) != '\000')
	{
	  changed = register_changed_p (regnum);
	  if (changed < 0)
	    {
	      do_cleanups (cleanup);
	      mi_error_message = xstrprintf ("mi_cmd_data_list_register_change: Unable to read register contents.");
	      return MI_CMD_ERROR;
	    }
	  else if (changed)
	    ui_out_field_int (uiout, NULL, regnum);
	}
      else
	{
	  do_cleanups (cleanup);
	  mi_error_message = xstrprintf ("bad register number");
	  return MI_CMD_ERROR;
	}
    }
  do_cleanups (cleanup);
  return MI_CMD_DONE;
}
コード例 #19
0
ファイル: c-typeprint.c プロジェクト: nds32/binutils
void
c_type_print_base (struct type *type, struct ui_file *stream,
		   int show, int level, const struct type_print_options *flags)
{
  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;

  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);
      print_name_maybe_canonical (TYPE_NAME (type), flags, 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, flags);
      break;

    case TYPE_CODE_STRUCT:
    case TYPE_CODE_UNION:
      {
	struct type_print_options local_flags = *flags;
	struct type_print_options semi_local_flags = *flags;
	struct cleanup *local_cleanups = make_cleanup (null_cleanup, NULL);

	local_flags.local_typedefs = NULL;
	semi_local_flags.local_typedefs = NULL;

	if (!flags->raw)
	  {
	    if (flags->local_typedefs)
	      local_flags.local_typedefs
		= copy_typedef_hash (flags->local_typedefs);
	    else
	      local_flags.local_typedefs = create_typedef_hash ();

	    make_cleanup_free_typedef_hash (local_flags.local_typedefs);
	  }

	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))
	  {
	    /* When printing the tag name, we are still effectively
	       printing in the outer context, hence the use of FLAGS
	       here.  */
	    print_name_maybe_canonical (TYPE_TAG_NAME (type), flags, stream);
	    if (show > 0)
	      fputs_filtered (" ", stream);
	  }

	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;

	    c_type_print_template_args (&local_flags, type, stream);

	    /* Add in template parameters when printing derivation info.  */
	    add_template_parameters (local_flags.local_typedefs, type);
	    cp_type_print_derivation_info (stream, type, &local_flags);

	    /* This holds just the global typedefs and the template
	       parameters.  */
	    semi_local_flags.local_typedefs
	      = copy_typedef_hash (local_flags.local_typedefs);
	    if (semi_local_flags.local_typedefs)
	      make_cleanup_free_typedef_hash (semi_local_flags.local_typedefs);

	    /* Now add in the local typedefs.  */
	    recursively_update_typedef_hash (local_flags.local_typedefs, 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,
			      &local_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 blank line
	     between them.  Make sure to count only method that we
	     will display; artificial methods will be hidden.  */
	  len = TYPE_NFN_FIELDS (type);
	  if (!flags->print_methods)
	    len = 0;
	  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 =
		    TYPE_FN_FIELD_CONSTRUCTOR (f, j)
		    || 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))
		    {
		      c_print_type (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
				    "", stream, -1, 0,
				    &local_flags);
		      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 =
		    gdb_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, &local_flags);
			}
		      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 && flags->print_typedefs)
	    {
	      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 ");

		    /* We want to print typedefs with substitutions
		       from the template parameters or globally-known
		       typedefs but not local typedefs.  */
		    c_print_type (target,
				  TYPE_TYPEDEF_FIELD_NAME (type, i),
				  stream, show - 1, level + 4,
				  &semi_local_flags);
		    fprintf_filtered (stream, ";\n");
		  }
	      }

	    fprintfi_filtered (level, stream, "}");
	  }

	do_cleanups (local_cleanups);
      }
      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))
	{
	  print_name_maybe_canonical (TYPE_TAG_NAME (type), flags, 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);
	  print_name_maybe_canonical (TYPE_NAME (type), flags, 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;
    }
}
コード例 #20
0
ファイル: mi-main.c プロジェクト: debrouxl/tiemu
/* Return a list of register number and value pairs. The valid
   arguments expected are: a letter indicating the format in which to
   display the registers contents. This can be one of: x (hexadecimal), d
   (decimal), N (natural), t (binary), o (octal), r (raw).  After the
   format argumetn there can be a sequence of numbers, indicating which
   registers to fetch the content of. If the format is the only argument,
   a list of all the registers with their values is returned. */
enum mi_cmd_result
mi_cmd_data_list_register_values (char *command, char **argv, int argc)
{
  int regnum, numregs, format, result;
  int i;
  struct cleanup *list_cleanup, *tuple_cleanup;

  /* Note that the test for a valid register must include checking the
     REGISTER_NAME because NUM_REGS may be allocated for the union of
     the register sets within a family of related processors.  In this
     case, some entries of REGISTER_NAME will change depending upon
     the particular processor being debugged.  */

  numregs = NUM_REGS + NUM_PSEUDO_REGS;

  if (argc == 0)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_list_register_values: Usage: -data-list-register-values <format> [<regnum1>...<regnumN>]");
      return MI_CMD_ERROR;
    }

  format = (int) argv[0][0];

  list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values");

  if (argc == 1)		/* No args, beside the format: do all the regs */
    {
      for (regnum = 0;
	   regnum < numregs;
	   regnum++)
	{
	  if (REGISTER_NAME (regnum) == NULL
	      || *(REGISTER_NAME (regnum)) == '\0')
	    continue;
	  tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
	  ui_out_field_int (uiout, "number", regnum);
	  result = get_register (regnum, format);
	  if (result == -1)
	    {
	      do_cleanups (list_cleanup);
	      return MI_CMD_ERROR;
	    }
	  do_cleanups (tuple_cleanup);
	}
    }

  /* Else, list of register #s, just do listed regs */
  for (i = 1; i < argc; i++)
    {
      regnum = atoi (argv[i]);

      if (regnum >= 0
	  && regnum < numregs
	  && REGISTER_NAME (regnum) != NULL
	  && *REGISTER_NAME (regnum) != '\000')
	{
	  tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
	  ui_out_field_int (uiout, "number", regnum);
	  result = get_register (regnum, format);
	  if (result == -1)
	    {
	      do_cleanups (list_cleanup);
	      return MI_CMD_ERROR;
	    }
	  do_cleanups (tuple_cleanup);
	}
      else
	{
	  do_cleanups (list_cleanup);
	  mi_error_message = xstrprintf ("bad register number");
	  return MI_CMD_ERROR;
	}
    }
  do_cleanups (list_cleanup);
  return MI_CMD_DONE;
}
コード例 #21
0
ファイル: disasm.c プロジェクト: ajinkya93/netbsd-src
static void
do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
			      struct disassemble_info *di, int nlines,
			      struct linetable_entry *le,
			      CORE_ADDR low, CORE_ADDR high,
			      struct symtab *symtab,
			      int how_many, int flags, struct ui_file *stb)
{
  int newlines = 0;
  struct dis_line_entry *mle;
  struct symtab_and_line sal;
  int i;
  int out_of_order = 0;
  int next_line = 0;
  int num_displayed = 0;
  enum print_source_lines_flags psl_flags = 0;
  struct cleanup *ui_out_chain;
  struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
  struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);

  if (flags & DISASSEMBLY_FILENAME)
    psl_flags |= PRINT_SOURCE_LINES_FILENAME;

  mle = (struct dis_line_entry *) alloca (nlines
					  * sizeof (struct dis_line_entry));

  /* Copy linetable entries for this function into our data
     structure, creating end_pc's and setting out_of_order as
     appropriate.  */

  /* First, skip all the preceding functions.  */

  for (i = 0; i < nlines - 1 && le[i].pc < low; i++);

  /* Now, copy all entries before the end of this function.  */

  for (; i < nlines - 1 && le[i].pc < high; i++)
    {
      if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
	continue;		/* Ignore duplicates.  */

      /* Skip any end-of-function markers.  */
      if (le[i].line == 0)
	continue;

      mle[newlines].line = le[i].line;
      if (le[i].line > le[i + 1].line)
	out_of_order = 1;
      mle[newlines].start_pc = le[i].pc;
      mle[newlines].end_pc = le[i + 1].pc;
      newlines++;
    }

  /* If we're on the last line, and it's part of the function,
     then we need to get the end pc in a special way.  */

  if (i == nlines - 1 && le[i].pc < high)
    {
      mle[newlines].line = le[i].line;
      mle[newlines].start_pc = le[i].pc;
      sal = find_pc_line (le[i].pc, 0);
      mle[newlines].end_pc = sal.end;
      newlines++;
    }

  /* Now, sort mle by line #s (and, then by addresses within
     lines).  */

  if (out_of_order)
    qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);

  /* Now, for each line entry, emit the specified lines (unless
     they have been emitted before), followed by the assembly code
     for that line.  */

  ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");

  for (i = 0; i < newlines; i++)
    {
      /* Print out everything from next_line to the current line.  */
      if (mle[i].line >= next_line)
	{
	  if (next_line != 0)
	    {
	      /* Just one line to print.  */
	      if (next_line == mle[i].line)
		{
		  ui_out_tuple_chain
		    = make_cleanup_ui_out_tuple_begin_end (uiout,
							   "src_and_asm_line");
		  print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
		}
	      else
		{
		  /* Several source lines w/o asm instructions associated.  */
		  for (; next_line < mle[i].line; next_line++)
		    {
		      struct cleanup *ui_out_list_chain_line;
		      struct cleanup *ui_out_tuple_chain_line;
		      
		      ui_out_tuple_chain_line
			= make_cleanup_ui_out_tuple_begin_end (uiout,
							       "src_and_asm_line");
		      print_source_lines (symtab, next_line, next_line + 1,
					  psl_flags);
		      ui_out_list_chain_line
			= make_cleanup_ui_out_list_begin_end (uiout,
							      "line_asm_insn");
		      do_cleanups (ui_out_list_chain_line);
		      do_cleanups (ui_out_tuple_chain_line);
		    }
		  /* Print the last line and leave list open for
		     asm instructions to be added.  */
		  ui_out_tuple_chain
		    = make_cleanup_ui_out_tuple_begin_end (uiout,
							   "src_and_asm_line");
		  print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
		}
	    }
	  else
	    {
	      ui_out_tuple_chain
		= make_cleanup_ui_out_tuple_begin_end (uiout,
						       "src_and_asm_line");
	      print_source_lines (symtab, mle[i].line, mle[i].line + 1, psl_flags);
	    }

	  next_line = mle[i].line + 1;
	  ui_out_list_chain
	    = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
	}

      num_displayed += dump_insns (gdbarch, uiout, di,
				   mle[i].start_pc, mle[i].end_pc,
				   how_many, flags, stb);

      /* When we've reached the end of the mle array, or we've seen the last
         assembly range for this source line, close out the list/tuple.  */
      if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
	{
	  do_cleanups (ui_out_list_chain);
	  do_cleanups (ui_out_tuple_chain);
	  ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
	  ui_out_list_chain = make_cleanup (null_cleanup, 0);
	  ui_out_text (uiout, "\n");
	}
      if (how_many >= 0 && num_displayed >= how_many)
	break;
    }
  do_cleanups (ui_out_chain);
}
コード例 #22
0
ファイル: mi-main.c プロジェクト: debrouxl/tiemu
/* Write given values into registers. The registers and values are
   given as pairs. The corresponding MI command is 
   -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]*/
enum mi_cmd_result
mi_cmd_data_write_register_values (char *command, char **argv, int argc)
{
  int regnum;
  int i;
  int numregs;
  LONGEST value;
  char format;

  /* Note that the test for a valid register must include checking the
     REGISTER_NAME because NUM_REGS may be allocated for the union of
     the register sets within a family of related processors.  In this
     case, some entries of REGISTER_NAME will change depending upon
     the particular processor being debugged.  */

  numregs = NUM_REGS + NUM_PSEUDO_REGS;

  if (argc == 0)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: Usage: -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]");
      return MI_CMD_ERROR;
    }

  format = (int) argv[0][0];

  if (!target_has_registers)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: No registers.");
      return MI_CMD_ERROR;
    }

  if (!(argc - 1))
    {
      mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: No regs and values specified.");
      return MI_CMD_ERROR;
    }

  if ((argc - 1) % 2)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: Regs and vals are not in pairs.");
      return MI_CMD_ERROR;
    }

  for (i = 1; i < argc; i = i + 2)
    {
      regnum = atoi (argv[i]);

      if (regnum >= 0
	  && regnum < numregs
	  && REGISTER_NAME (regnum) != NULL
	  && *REGISTER_NAME (regnum) != '\000')
	{
	  void *buffer;
	  struct cleanup *old_chain;

	  /* Get the value as a number */
	  value = parse_and_eval_address (argv[i + 1]);
	  /* Get the value into an array */
	  buffer = xmalloc (DEPRECATED_REGISTER_SIZE);
	  old_chain = make_cleanup (xfree, buffer);
	  store_signed_integer (buffer, DEPRECATED_REGISTER_SIZE, value);
	  /* Write it down */
	  deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (regnum), buffer, register_size (current_gdbarch, regnum));
	  /* Free the buffer.  */
	  do_cleanups (old_chain);
	}
      else
	{
	  mi_error_message = xstrprintf ("bad register number");
	  return MI_CMD_ERROR;
	}
    }
  return MI_CMD_DONE;
}
コード例 #23
0
ファイル: event-top.c プロジェクト: T-J-Teru/gdb
void
display_gdb_prompt (char *new_prompt)
{
  char *actual_gdb_prompt = NULL;
  struct cleanup *old_chain;

  annotate_display_prompt ();

  /* Reset the nesting depth used when trace-commands is set.  */
  reset_command_nest_depth ();

  /* Each interpreter has its own rules on displaying the command
     prompt.  */
  if (!current_interp_display_prompt_p ())
    return;

  old_chain = make_cleanup (free_current_contents, &actual_gdb_prompt);

  /* Do not call the python hook on an explicit prompt change as
     passed to this function, as this forms a secondary/local prompt,
     IE, displayed but not set.  */
  if (! new_prompt)
    {
      if (sync_execution)
	{
	  /* This is to trick readline into not trying to display the
	     prompt.  Even though we display the prompt using this
	     function, readline still tries to do its own display if
	     we don't call rl_callback_handler_install and
	     rl_callback_handler_remove (which readline detects
	     because a global variable is not set).  If readline did
	     that, it could mess up gdb signal handlers for SIGINT.
	     Readline assumes that between calls to rl_set_signals and
	     rl_clear_signals gdb doesn't do anything with the signal
	     handlers.  Well, that's not the case, because when the
	     target executes we change the SIGINT signal handler.  If
	     we allowed readline to display the prompt, the signal
	     handler change would happen exactly between the calls to
	     the above two functions.  Calling
	     rl_callback_handler_remove(), does the job.  */

	  rl_callback_handler_remove ();
	  do_cleanups (old_chain);
	  return;
	}
      else
	{
	  /* Display the top level prompt.  */
	  actual_gdb_prompt = top_level_prompt ();
	}
    }
  else
    actual_gdb_prompt = xstrdup (new_prompt);

  if (async_command_editing_p)
    {
      rl_callback_handler_remove ();
      rl_callback_handler_install (actual_gdb_prompt, input_handler);
    }
  /* new_prompt at this point can be the top of the stack or the one
     passed in.  It can't be NULL.  */
  else
    {
      /* Don't use a _filtered function here.  It causes the assumed
         character position to be off, since the newline we read from
         the user is not accounted for.  */
      fputs_unfiltered (actual_gdb_prompt, gdb_stdout);
      gdb_flush (gdb_stdout);
    }

  do_cleanups (old_chain);
}
コード例 #24
0
ファイル: mi-main.c プロジェクト: debrouxl/tiemu
enum mi_cmd_result
mi_cmd_data_read_memory (char *command, char **argv, int argc)
{
  struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
  CORE_ADDR addr;
  long total_bytes;
  long nr_cols;
  long nr_rows;
  char word_format;
  struct type *word_type;
  long word_size;
  char word_asize;
  char aschar;
  gdb_byte *mbuf;
  int nr_bytes;
  long offset = 0;
  int optind = 0;
  char *optarg;
  enum opt
    {
      OFFSET_OPT
    };
  static struct mi_opt opts[] =
  {
    {"o", OFFSET_OPT, 1},
    0
  };

  while (1)
    {
      int opt = mi_getopt ("mi_cmd_data_read_memory", argc, argv, opts,
			   &optind, &optarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case OFFSET_OPT:
	  offset = atol (optarg);
	  break;
	}
    }
  argv += optind;
  argc -= optind;

  if (argc < 5 || argc > 6)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_read_memory: Usage: ADDR WORD-FORMAT WORD-SIZE NR-ROWS NR-COLS [ASCHAR].");
      return MI_CMD_ERROR;
    }

  /* Extract all the arguments. */

  /* Start address of the memory dump. */
  addr = parse_and_eval_address (argv[0]) + offset;
  /* The format character to use when displaying a memory word. See
     the ``x'' command. */
  word_format = argv[1][0];
  /* The size of the memory word. */
  word_size = atol (argv[2]);
  switch (word_size)
    {
    case 1:
      word_type = builtin_type_int8;
      word_asize = 'b';
      break;
    case 2:
      word_type = builtin_type_int16;
      word_asize = 'h';
      break;
    case 4:
      word_type = builtin_type_int32;
      word_asize = 'w';
      break;
    case 8:
      word_type = builtin_type_int64;
      word_asize = 'g';
      break;
    default:
      word_type = builtin_type_int8;
      word_asize = 'b';
    }
  /* The number of rows */
  nr_rows = atol (argv[3]);
  if (nr_rows <= 0)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_read_memory: invalid number of rows.");
      return MI_CMD_ERROR;
    }
  /* number of bytes per row. */
  nr_cols = atol (argv[4]);
  if (nr_cols <= 0)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_read_memory: invalid number of columns.");
      return MI_CMD_ERROR;
    }
  /* The un-printable character when printing ascii. */
  if (argc == 6)
    aschar = *argv[5];
  else
    aschar = 0;

  /* create a buffer and read it in. */
  total_bytes = word_size * nr_rows * nr_cols;
  mbuf = xcalloc (total_bytes, 1);
  make_cleanup (xfree, mbuf);

  nr_bytes = target_read (&current_target, TARGET_OBJECT_MEMORY, NULL,
			  mbuf, addr, total_bytes);
  if (nr_bytes <= 0)
    {
      do_cleanups (cleanups);
      mi_error_message = xstrdup ("Unable to read memory.");
      return MI_CMD_ERROR;
    }

  /* output the header information. */
  ui_out_field_core_addr (uiout, "addr", addr);
  ui_out_field_int (uiout, "nr-bytes", nr_bytes);
  ui_out_field_int (uiout, "total-bytes", total_bytes);
  ui_out_field_core_addr (uiout, "next-row", addr + word_size * nr_cols);
  ui_out_field_core_addr (uiout, "prev-row", addr - word_size * nr_cols);
  ui_out_field_core_addr (uiout, "next-page", addr + total_bytes);
  ui_out_field_core_addr (uiout, "prev-page", addr - total_bytes);

  /* Build the result as a two dimentional table. */
  {
    struct ui_stream *stream = ui_out_stream_new (uiout);
    struct cleanup *cleanup_list_memory;
    int row;
    int row_byte;
    cleanup_list_memory = make_cleanup_ui_out_list_begin_end (uiout, "memory");
    for (row = 0, row_byte = 0;
	 row < nr_rows;
	 row++, row_byte += nr_cols * word_size)
      {
	int col;
	int col_byte;
	struct cleanup *cleanup_tuple;
	struct cleanup *cleanup_list_data;
	cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
	ui_out_field_core_addr (uiout, "addr", addr + row_byte);
	/* ui_out_field_core_addr_symbolic (uiout, "saddr", addr + row_byte); */
	cleanup_list_data = make_cleanup_ui_out_list_begin_end (uiout, "data");
	for (col = 0, col_byte = row_byte;
	     col < nr_cols;
	     col++, col_byte += word_size)
	  {
	    if (col_byte + word_size > nr_bytes)
	      {
		ui_out_field_string (uiout, NULL, "N/A");
	      }
	    else
	      {
		ui_file_rewind (stream->stream);
		print_scalar_formatted (mbuf + col_byte, word_type, word_format,
					word_asize, stream->stream);
		ui_out_field_stream (uiout, NULL, stream);
	      }
	  }
	do_cleanups (cleanup_list_data);
	if (aschar)
	  {
	    int byte;
	    ui_file_rewind (stream->stream);
	    for (byte = row_byte; byte < row_byte + word_size * nr_cols; byte++)
	      {
		if (byte >= nr_bytes)
		  {
		    fputc_unfiltered ('X', stream->stream);
		  }
		else if (mbuf[byte] < 32 || mbuf[byte] > 126)
		  {
		    fputc_unfiltered (aschar, stream->stream);
		  }
		else
		  fputc_unfiltered (mbuf[byte], stream->stream);
	      }
	    ui_out_field_stream (uiout, "ascii", stream);
	  }
	do_cleanups (cleanup_tuple);
      }
    ui_out_stream_delete (stream);
    do_cleanups (cleanup_list_memory);
  }
  do_cleanups (cleanups);
  return MI_CMD_DONE;
}
コード例 #25
0
static void
copy_sections (bfd *abfd, asection *sect, void *data)
{
  asymbol **symbol_table = data;
  bfd_byte *sect_data, *sect_data_got;
  struct cleanup *cleanups;
  struct bfd_link_info link_info;
  struct bfd_link_order link_order;
  CORE_ADDR inferior_addr;
  struct link_hash_table_cleanup_data cleanup_data;

  if ((bfd_get_section_flags (abfd, sect) & (SEC_ALLOC | SEC_LOAD))
      != (SEC_ALLOC | SEC_LOAD))
    return;

  if (bfd_get_section_size (sect) == 0)
    return;

  /* Mostly a copy of bfd_simple_get_relocated_section_contents which GDB
     cannot use as it does not report relocations to undefined symbols.  */
  memset (&link_info, 0, sizeof (link_info));
  link_info.output_bfd = abfd;
  link_info.input_bfds = abfd;
  link_info.input_bfds_tail = &abfd->link.next;

  cleanup_data.abfd = abfd;
  cleanup_data.link_next = abfd->link.next;

  abfd->link.next = NULL;
  link_info.hash = bfd_link_hash_table_create (abfd);

  cleanups = make_cleanup (link_hash_table_free, &cleanup_data);
  link_info.callbacks = &link_callbacks;

  memset (&link_order, 0, sizeof (link_order));
  link_order.next = NULL;
  link_order.type = bfd_indirect_link_order;
  link_order.offset = 0;
  link_order.size = bfd_get_section_size (sect);
  link_order.u.indirect.section = sect;

  sect_data = xmalloc (bfd_get_section_size (sect));
  make_cleanup (xfree, sect_data);

  sect_data_got = bfd_get_relocated_section_contents (abfd, &link_info,
						      &link_order, sect_data,
						      FALSE, symbol_table);

  if (sect_data_got == NULL)
    error (_("Cannot map compiled module \"%s\" section \"%s\": %s"),
	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
	   bfd_errmsg (bfd_get_error ()));
  gdb_assert (sect_data_got == sect_data);

  inferior_addr = bfd_get_section_vma (abfd, sect);
  if (0 != target_write_memory (inferior_addr, sect_data,
				bfd_get_section_size (sect)))
    error (_("Cannot write compiled module \"%s\" section \"%s\" "
	     "to inferior memory range %s-%s."),
	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
	   paddress (target_gdbarch (), inferior_addr),
	   paddress (target_gdbarch (),
		     inferior_addr + bfd_get_section_size (sect)));

  do_cleanups (cleanups);
}
コード例 #26
0
ファイル: mi-main.c プロジェクト: debrouxl/tiemu
/* DATA-MEMORY-WRITE:

   COLUMN_OFFSET: optional argument. Must be preceeded by '-o'. The
   offset from the beginning of the memory grid row where the cell to
   be written is.
   ADDR: start address of the row in the memory grid where the memory
   cell is, if OFFSET_COLUMN is specified. Otherwise, the address of
   the location to write to.
   FORMAT: a char indicating format for the ``word''. See 
   the ``x'' command.
   WORD_SIZE: size of each ``word''; 1,2,4, or 8 bytes
   VALUE: value to be written into the memory address.

   Writes VALUE into ADDR + (COLUMN_OFFSET * WORD_SIZE).

   Prints nothing. */
enum mi_cmd_result
mi_cmd_data_write_memory (char *command, char **argv, int argc)
{
  CORE_ADDR addr;
  char word_format;
  long word_size;
  /* FIXME: ezannoni 2000-02-17 LONGEST could possibly not be big
     enough when using a compiler other than GCC. */
  LONGEST value;
  void *buffer;
  struct cleanup *old_chain;
  long offset = 0;
  int optind = 0;
  char *optarg;
  enum opt
    {
      OFFSET_OPT
    };
  static struct mi_opt opts[] =
  {
    {"o", OFFSET_OPT, 1},
    0
  };

  while (1)
    {
      int opt = mi_getopt ("mi_cmd_data_write_memory", argc, argv, opts,
			   &optind, &optarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case OFFSET_OPT:
	  offset = atol (optarg);
	  break;
	}
    }
  argv += optind;
  argc -= optind;

  if (argc != 4)
    {
      mi_error_message = xstrprintf ("mi_cmd_data_write_memory: Usage: [-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE.");
      return MI_CMD_ERROR;
    }

  /* Extract all the arguments. */
  /* Start address of the memory dump. */
  addr = parse_and_eval_address (argv[0]);
  /* The format character to use when displaying a memory word. See
     the ``x'' command. */
  word_format = argv[1][0];
  /* The size of the memory word. */
  word_size = atol (argv[2]);

  /* Calculate the real address of the write destination. */
  addr += (offset * word_size);

  /* Get the value as a number */
  value = parse_and_eval_address (argv[3]);
  /* Get the value into an array */
  buffer = xmalloc (word_size);
  old_chain = make_cleanup (xfree, buffer);
  store_signed_integer (buffer, word_size, value);
  /* Write it down to memory */
  write_memory (addr, buffer, word_size);
  /* Free the buffer.  */
  do_cleanups (old_chain);

  return MI_CMD_DONE;
}
コード例 #27
0
ファイル: py-function.c プロジェクト: Cookfeces/binutils-gdb
static struct value *
fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
	   void *cookie, int argc, struct value **argv)
{
  struct value *value = NULL;
  /* 'result' must be set to NULL, this initially indicates whether
     the function was called, or not.  */
  PyObject *result = NULL;
  PyObject *callable, *args;
  struct cleanup *cleanup;

  cleanup = ensure_python_env (gdbarch, language);

  args = convert_values_to_python (argc, argv);
  /* convert_values_to_python can return NULL on error.  If we
     encounter this, do not call the function, but allow the Python ->
     error code conversion below to deal with the Python exception.
     Note, that this is different if the function simply does not
     have arguments.  */

  if (args)
    {
      callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke");
      if (! callable)
	{
	  Py_DECREF (args);
	  error (_("No method named 'invoke' in object."));
	}

      result = PyObject_Call (callable, args, NULL);
      Py_DECREF (callable);
      Py_DECREF (args);
    }

  if (!result)
    {
      PyObject *ptype, *pvalue, *ptraceback;
      char *msg;

      PyErr_Fetch (&ptype, &pvalue, &ptraceback);

      /* Try to fetch an error message contained within ptype, pvalue.
	 When fetching the error message we need to make our own copy,
	 we no longer own ptype, pvalue after the call to PyErr_Restore.  */

      msg = gdbpy_exception_to_string (ptype, pvalue);
      make_cleanup (xfree, msg);

      if (msg == NULL)
	{
	  /* An error occurred computing the string representation of the
	     error message.  This is rare, but we should inform the user.  */

	  printf_filtered (_("An error occurred in a Python "
			     "convenience function\n"
			     "and then another occurred computing the "
			     "error message.\n"));
	  gdbpy_print_stack ();
	}

      /* Don't print the stack for gdb.GdbError exceptions.
	 It is generally used to flag user errors.

	 We also don't want to print "Error occurred in Python command"
	 for user errors.  However, a missing message for gdb.GdbError
	 exceptions is arguably a bug, so we flag it as such.  */

      if (!PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc)
	  || msg == NULL || *msg == '\0')
	{
	  PyErr_Restore (ptype, pvalue, ptraceback);
	  gdbpy_print_stack ();
	  if (msg != NULL && *msg != '\0')
	    error (_("Error occurred in Python convenience function: %s"),
		   msg);
	  else
	    error (_("Error occurred in Python convenience function."));
	}
      else
	{
	  Py_XDECREF (ptype);
	  Py_XDECREF (pvalue);
	  Py_XDECREF (ptraceback);
	  error ("%s", msg);
	}
    }

  value = convert_value_from_python (result);
  if (value == NULL)
    {
      Py_DECREF (result);
      gdbpy_print_stack ();
      error (_("Error while executing Python code."));
    }

  Py_DECREF (result);
  do_cleanups (cleanup);

  return value;
}
コード例 #28
0
static ps_err_e
rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr,
	   char *buf, int size)
{
  struct cleanup *old_chain;

  old_chain = save_inferior_ptid ();

  if (is_thread (inferior_ptid) ||	/* A thread */
      !target_thread_alive (inferior_ptid))	/* An lwp, but not alive */
    inferior_ptid = procfs_first_available ();	/* Find any live lwp.  */
  /* Note: don't need to call switch_to_thread; we're just reading memory.  */

#if defined (__sparcv9)
  /* For Sparc64 cross Sparc32, make sure the address has not been
     accidentally sign-extended (or whatever) to beyond 32 bits.  */
  if (bfd_get_arch_size (exec_bfd) == 32)
    addr &= 0xffffffff;
#endif

  while (size > 0)
    {
      int cc;

      /* FIXME: passing 0 as attrib argument.  */
      if (target_has_execution)
	cc = procfs_ops.to_xfer_memory (addr, buf, size,
					dowrite, 0, &procfs_ops);
      else
	cc = orig_core_ops.to_xfer_memory (addr, buf, size,
					   dowrite, 0, &core_ops);

      if (cc < 0)
	{
	  if (dowrite == 0)
	    print_sys_errmsg ("rw_common (): read", errno);
	  else
	    print_sys_errmsg ("rw_common (): write", errno);

	  do_cleanups (old_chain);

	  return PS_ERR;
	}
      else if (cc == 0)
	{
	  if (dowrite == 0)
	    warning ("rw_common (): unable to read at addr 0x%lx",
		     (long) addr);
	  else
	    warning ("rw_common (): unable to write at addr 0x%lx",
		     (long) addr);

	  do_cleanups (old_chain);

	  return PS_ERR;
	}

      size -= cc;
      buf += cc;
    }

  do_cleanups (old_chain);

  return PS_OK;
}
コード例 #29
0
ファイル: c-lang.c プロジェクト: ChrisG0x20/gdb
struct value *
evaluate_subexp_c (struct type *expect_type, struct expression *exp,
		   int *pos, enum noside noside)
{
  enum exp_opcode op = exp->elts[*pos].opcode;

  switch (op)
    {
    case OP_STRING:
      {
	int oplen, limit;
	struct type *type;
	struct obstack output;
	struct cleanup *cleanup;
	struct value *result;
	enum c_string_type dest_type;
	const char *dest_charset;
	int satisfy_expected = 0;

	obstack_init (&output);
	cleanup = make_cleanup_obstack_free (&output);

	++*pos;
	oplen = longest_to_int (exp->elts[*pos].longconst);

	++*pos;
	limit = *pos + BYTES_TO_EXP_ELEM (oplen + 1);
	dest_type
	  = (enum c_string_type) longest_to_int (exp->elts[*pos].longconst);
	switch (dest_type & ~C_CHAR)
	  {
	  case C_STRING:
	    type = language_string_char_type (exp->language_defn,
					      exp->gdbarch);
	    break;
	  case C_WIDE_STRING:
	    type = lookup_typename (exp->language_defn, exp->gdbarch,
				    "wchar_t", NULL, 0);
	    break;
	  case C_STRING_16:
	    type = lookup_typename (exp->language_defn, exp->gdbarch,
				    "char16_t", NULL, 0);
	    break;
	  case C_STRING_32:
	    type = lookup_typename (exp->language_defn, exp->gdbarch,
				    "char32_t", NULL, 0);
	    break;
	  default:
	    internal_error (__FILE__, __LINE__, _("unhandled c_string_type"));
	  }

	/* Ensure TYPE_LENGTH is valid for TYPE.  */
	check_typedef (type);

	/* If the caller expects an array of some integral type,
	   satisfy them.  If something odder is expected, rely on the
	   caller to cast.  */
	if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_ARRAY)
	  {
	    struct type *element_type
	      = check_typedef (TYPE_TARGET_TYPE (expect_type));

	    if (TYPE_CODE (element_type) == TYPE_CODE_INT
		|| TYPE_CODE (element_type) == TYPE_CODE_CHAR)
	      {
		type = element_type;
		satisfy_expected = 1;
	      }
	  }

	dest_charset = charset_for_string_type (dest_type, exp->gdbarch);

	++*pos;
	while (*pos < limit)
	  {
	    int len;

	    len = longest_to_int (exp->elts[*pos].longconst);

	    ++*pos;
	    if (noside != EVAL_SKIP)
	      parse_one_string (&output, &exp->elts[*pos].string, len,
				dest_charset, type);
	    *pos += BYTES_TO_EXP_ELEM (len);
	  }

	/* Skip the trailing length and opcode.  */
	*pos += 2;

	if (noside == EVAL_SKIP)
	  {
	    /* Return a dummy value of the appropriate type.  */
	    if (expect_type != NULL)
	      result = allocate_value (expect_type);
	    else if ((dest_type & C_CHAR) != 0)
	      result = allocate_value (type);
	    else
	      result = value_cstring ("", 0, type);
	    do_cleanups (cleanup);
	    return result;
	  }

	if ((dest_type & C_CHAR) != 0)
	  {
	    LONGEST value;

	    if (obstack_object_size (&output) != TYPE_LENGTH (type))
	      error (_("Could not convert character "
		       "constant to target character set"));
	    value = unpack_long (type, (gdb_byte *) obstack_base (&output));
	    result = value_from_longest (type, value);
	  }
	else
	  {
	    int i;

	    /* Write the terminating character.  */
	    for (i = 0; i < TYPE_LENGTH (type); ++i)
	      obstack_1grow (&output, 0);

	    if (satisfy_expected)
	      {
		LONGEST low_bound, high_bound;
		int element_size = TYPE_LENGTH (type);

		if (get_discrete_bounds (TYPE_INDEX_TYPE (expect_type),
					 &low_bound, &high_bound) < 0)
		  {
		    low_bound = 0;
		    high_bound = (TYPE_LENGTH (expect_type) / element_size) - 1;
		  }
		if (obstack_object_size (&output) / element_size
		    > (high_bound - low_bound + 1))
		  error (_("Too many array elements"));

		result = allocate_value (expect_type);
		memcpy (value_contents_raw (result), obstack_base (&output),
			obstack_object_size (&output));
	      }
	    else
	      result = value_cstring (obstack_base (&output),
				      obstack_object_size (&output),
				      type);
	  }
	do_cleanups (cleanup);
	return result;
      }
      break;

    default:
      break;
    }
  return evaluate_subexp_standard (expect_type, exp, pos, noside);
}
コード例 #30
0
/* Expand a call to a macro named ID, whose definition is DEF.  Append
   its expansion to DEST.  SRC is the input text following the ID
   token.  We are currently rescanning the expansions of the macros
   named in NO_LOOP; don't re-expand them.  Use LOOKUP_FUNC and
   LOOKUP_BATON to find definitions for any nested macro references.  

   Return 1 if we decided to expand it, zero otherwise.  (If it's a
   function-like macro name that isn't followed by an argument list,
   we don't expand it.)  If we return zero, leave SRC unchanged.  */
static int
expand (const char *id,
        struct macro_definition *def, 
        struct macro_buffer *dest,
        struct macro_buffer *src,
        struct macro_name_list *no_loop,
        macro_lookup_ftype *lookup_func,
        void *lookup_baton)
{
  struct macro_name_list new_no_loop;

  /* Create a new node to be added to the front of the no-expand list.
     This list is appropriate for re-scanning replacement lists, but
     it is *not* appropriate for scanning macro arguments; invocations
     of the macro whose arguments we are gathering *do* get expanded
     there.  */
  new_no_loop.name = id;
  new_no_loop.next = no_loop;

  /* What kind of macro are we expanding?  */
  if (def->kind == macro_object_like)
    {
      struct macro_buffer replacement_list;

      init_shared_buffer (&replacement_list, (char *) def->replacement,
                          strlen (def->replacement));

      scan (dest, &replacement_list, &new_no_loop, lookup_func, lookup_baton);
      return 1;
    }
  else if (def->kind == macro_function_like)
    {
      struct cleanup *back_to = make_cleanup (null_cleanup, 0);
      int argc;
      struct macro_buffer *argv = NULL;
      struct macro_buffer substituted;
      struct macro_buffer substituted_src;

      if (def->argc >= 1
          && strcmp (def->argv[def->argc - 1], "...") == 0)
        error ("Varargs macros not implemented yet.");

      make_cleanup (free_current_contents, &argv);
      argv = gather_arguments (id, src, &argc);

      /* If we couldn't find any argument list, then we don't expand
         this macro.  */
      if (! argv)
        {
          do_cleanups (back_to);
          return 0;
        }

      /* Check that we're passing an acceptable number of arguments for
         this macro.  */
      if (argc != def->argc)
        {
          /* Remember that a sequence of tokens like "foo()" is a
             valid invocation of a macro expecting either zero or one
             arguments.  */
          if (! (argc == 1
                 && argv[0].len == 0
                 && def->argc == 0))
            error ("Wrong number of arguments to macro `%s' "
                   "(expected %d, got %d).",
                   id, def->argc, argc);
        }

      /* Note that we don't expand macro invocations in the arguments
         yet --- we let subst_args take care of that.  Parameters that
         appear as operands of the stringifying operator "#" or the
         splicing operator "##" don't get macro references expanded,
         so we can't really tell whether it's appropriate to macro-
         expand an argument until we see how it's being used.  */
      init_buffer (&substituted, 0);
      make_cleanup (cleanup_macro_buffer, &substituted);
      substitute_args (&substituted, def, argc, argv, no_loop,
                       lookup_func, lookup_baton);

      /* Now `substituted' is the macro's replacement list, with all
         argument values substituted into it properly.  Re-scan it for
         macro references, but don't expand invocations of this macro.

         We create a new buffer, `substituted_src', which points into
         `substituted', and scan that.  We can't scan `substituted'
         itself, since the tokenization process moves the buffer's
         text pointer around, and we still need to be able to find
         `substituted's original text buffer after scanning it so we
         can free it.  */
      init_shared_buffer (&substituted_src, substituted.text, substituted.len);
      scan (dest, &substituted_src, &new_no_loop, lookup_func, lookup_baton);

      do_cleanups (back_to);

      return 1;
    }
  else
    internal_error (__FILE__, __LINE__, "bad macro definition kind");
}