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; }
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; }
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; }
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; }
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. */ }
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); }
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 (); }
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); }
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; }
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; }
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); }
/* 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); }
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; }
/* 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); }
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); }
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; }
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: ; }
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; }
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; } }
/* 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; }
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); }
/* 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; }
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); }
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 (¤t_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; }
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); }
/* 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; }
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; }
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; }
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); }
/* 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"); }