/* 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, 0, 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; }
void mi_cmd_stack_list_locals (char *command, char **argv, int argc) { struct frame_info *frame; int raw_arg = 0; enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; int skip_unavailable = 0; int i; if (argc > 1) { int i; enum opt { NO_FRAME_FILTERS, SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; while (1) { char *oarg; /* Don't parse 'print-values' as an option. */ int opt = mi_getopt ("-stack-list-locals", argc - 1, argv, opts, &oind, &oarg); if (opt < 0) break; switch ((enum opt) opt) { case NO_FRAME_FILTERS: raw_arg = oind; case SKIP_UNAVAILABLE: skip_unavailable = 1; break; } } } /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) error (_("-stack-list-locals: Usage: [--no-frame-filters] " "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); if (! raw_arg && frame_filters) { int flags = PRINT_LEVEL | PRINT_LOCALS; result = apply_frame_filter (frame, flags, print_value, current_uiout, 0, 0); } /* Run the inbuilt backtrace if there are no filters registered, or if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { list_args_or_locals (locals, print_value, frame, skip_unavailable); } }
void mi_cmd_var_evaluate_expression (char *command, char **argv, int argc) { struct ui_out *uiout = current_uiout; struct varobj *var; enum varobj_display_formats format; int formatFound; int oind; char *oarg; enum opt { OP_FORMAT }; static const struct mi_opt opts[] = { {"f", OP_FORMAT, 1}, { 0, 0, 0 } }; /* Parse arguments. */ format = FORMAT_NATURAL; formatFound = 0; oind = 0; while (1) { int opt = mi_getopt ("-var-evaluate-expression", argc, argv, opts, &oind, &oarg); if (opt < 0) break; switch ((enum opt) opt) { case OP_FORMAT: if (formatFound) error (_("Cannot specify format more than once")); format = mi_parse_format (oarg); formatFound = 1; break; } } if (oind >= argc) error (_("Usage: [-f FORMAT] NAME")); if (oind < argc - 1) error (_("Garbage at end of command")); /* Get varobj handle, if a valid var obj name was specified. */ var = varobj_get_handle (argv[oind]); if (formatFound) { char *val = varobj_get_formatted_value (var, format); ui_out_field_string (uiout, "value", val); xfree (val); } else { char *val = varobj_get_value (var); ui_out_field_string (uiout, "value", val); xfree (val); } }
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, 0, 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; }
/* The arguments to be passed on the command line and parsed here are: either: START-ADDRESS: address to start the disassembly at. END-ADDRESS: address to end the disassembly at. or: FILENAME: The name of the file where we want disassemble from. LINE: The line around which we want to disassemble. It will disassemble the function that contins that line. HOW_MANY: Number of disassembly lines to display. In mixed mode, it is the number of disassembly lines only, not counting the source lines. always required: MODE: 0 or 1 for disassembly only, or mixed source and disassembly, respectively. */ void mi_cmd_disassemble (char *command, char **argv, int argc) { CORE_ADDR start; int mixed_source_and_assembly; struct symtab *s; /* Which options have we processed ... */ int file_seen = 0; int line_seen = 0; int num_seen = 0; int start_seen = 0; int end_seen = 0; /* ... and their corresponding value. */ char *file_string = NULL; int line_num = -1; int how_many = -1; CORE_ADDR low = 0; CORE_ADDR high = 0; /* Options processing stuff. */ int optind = 0; char *optarg; enum opt { FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT }; static struct mi_opt opts[] = { {"f", FILE_OPT, 1}, {"l", LINE_OPT, 1}, {"n", NUM_OPT, 1}, {"s", START_OPT, 1}, {"e", END_OPT, 1}, { 0, 0, 0 } }; /* Get the options with their arguments. Keep track of what we encountered. */ while (1) { int opt = mi_getopt ("mi_cmd_disassemble", argc, argv, opts, &optind, &optarg); if (opt < 0) break; switch ((enum opt) opt) { case FILE_OPT: file_string = xstrdup (optarg); file_seen = 1; break; case LINE_OPT: line_num = atoi (optarg); line_seen = 1; break; case NUM_OPT: how_many = atoi (optarg); num_seen = 1; break; case START_OPT: low = parse_and_eval_address (optarg); start_seen = 1; break; case END_OPT: high = parse_and_eval_address (optarg); end_seen = 1; break; } } argv += optind; argc -= optind; /* Allow only filename + linenum (with how_many which is not required) OR start_addr + and_addr */ if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen) || (line_seen && file_seen && !num_seen && !start_seen && !end_seen) || (!line_seen && !file_seen && !num_seen && start_seen && end_seen))) error ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode."); if (argc != 1) error ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode."); mixed_source_and_assembly = atoi (argv[0]); if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1)) error (_("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.")); /* We must get the function beginning and end where line_num is contained. */ if (line_seen && file_seen) { s = lookup_symtab (file_string); if (s == NULL) error (_("mi_cmd_disassemble: Invalid filename.")); if (!find_line_pc (s, line_num, &start)) error (_("mi_cmd_disassemble: Invalid line number")); if (find_pc_partial_function (start, NULL, &low, &high) == 0) error (_("mi_cmd_disassemble: No function contains specified address")); } gdb_disassembly (uiout, file_string, line_num, mixed_source_and_assembly, how_many, low, high); }
void mi_cmd_stack_list_frames (char *command, char **argv, int argc) { int frame_low; int frame_high; int i; struct cleanup *cleanup_stack; struct frame_info *fi; enum py_bt_status result = PY_BT_ERROR; int raw_arg = 0; int oind = 0; enum opt { NO_FRAME_FILTERS }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, { 0, 0, 0 } }; /* Parse arguments. In this instance we are just looking for --no-frame-filters. */ while (1) { char *oarg; int opt = mi_getopt ("-stack-list-frames", argc, argv, opts, &oind, &oarg); if (opt < 0) break; switch ((enum opt) opt) { case NO_FRAME_FILTERS: raw_arg = oind; break; } } /* After the last option is parsed, there should either be low - high range, or no further arguments. */ if ((argc - oind != 0) && (argc - oind != 2)) error (_("-stack-list-frames: Usage: [--no-frame-filters] [FRAME_LOW FRAME_HIGH]")); /* If there is a range, set it. */ if (argc - oind == 2) { frame_low = atoi (argv[0 + oind]); frame_high = atoi (argv[1 + oind]); } else { /* Called with no arguments, it means we want the whole backtrace. */ frame_low = -1; frame_high = -1; } /* Let's position fi on the frame at which to start the display. Could be the innermost frame if the whole stack needs displaying, or if frame_low is 0. */ for (i = 0, fi = get_current_frame (); fi && i < frame_low; i++, fi = get_prev_frame (fi)); if (fi == NULL) error (_("-stack-list-frames: Not enough frames in stack.")); cleanup_stack = make_cleanup_ui_out_list_begin_end (current_uiout, "stack"); if (! raw_arg && frame_filters) { int flags = PRINT_LEVEL | PRINT_FRAME_INFO; int py_frame_low = frame_low; /* We cannot pass -1 to frame_low, as that would signify a relative backtrace from the tail of the stack. So, in the case of frame_low == -1, assign and increment it. */ if (py_frame_low == -1) py_frame_low++; result = apply_frame_filter (get_current_frame (), flags, NO_VALUES, current_uiout, py_frame_low, frame_high); } /* Run the inbuilt backtrace if there are no filters registered, or if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { /* Now let's print the frames up to frame_high, or until there are frames in the stack. */ for (; fi && (i <= frame_high || frame_high == -1); i++, fi = get_prev_frame (fi)) { QUIT; /* Print the location and the address always, even for level 0. If args is 0, don't print the arguments. */ print_frame_info (fi, 1, LOC_AND_ADDRESS, 0 /* args */ ); } } do_cleanups (cleanup_stack); }
/* Add zero or more directories to the front of the source path. */ enum mi_cmd_result mi_cmd_env_dir (char *command, char **argv, int argc) { int i; int optind = 0; int reset = 0; char *optarg; enum opt { RESET_OPT }; static struct mi_opt opts[] = { { "r", RESET_OPT, 0 }, { NULL, 0, 0 } }; dont_repeat(); if (mi_version(uiout) < 2) { for (i = argc - 1; i >= 0; --i) env_execute_cli_command ("dir", argv[i]); return MI_CMD_DONE; } /* Otherwise mi level is 2 or higher. */ while (1) { int opt = mi_getopt ("mi_cmd_env_dir", argc, argv, opts, &optind, &optarg); if (opt < 0) break; switch ((enum opt)opt) { case RESET_OPT: reset = 1; break; default: break; } } argv += optind; argc -= optind; if (reset) { /* Reset means setting to default path first. */ xfree (source_path); init_source_path (); } for (i = argc - 1; i >= 0; --i) env_mod_path (argv[i], &source_path); init_last_source_visited (); ui_out_field_string (uiout, "source-path", source_path); forget_cached_source_info (); return MI_CMD_DONE; }
/* Add one or more directories to start of executable search path. */ enum mi_cmd_result mi_cmd_env_path (char *command, char **argv, int argc) { char *exec_path; const char *env; int reset = 0; int optind = 0; int i; char *optarg; enum opt { RESET_OPT }; static struct mi_opt opts[] = { { "r", RESET_OPT, 0 }, { NULL, 0, 0 } }; dont_repeat(); if (mi_version(uiout) < 2) { for (i = (argc - 1); i >= 0; --i) env_execute_cli_command("path", argv[i]); return MI_CMD_DONE; } /* Otherwise the mi level is 2 or higher. */ while (1) { int opt = mi_getopt ("mi_cmd_env_path", argc, argv, opts, &optind, &optarg); if (opt < 0) break; switch ((enum opt)opt) { case RESET_OPT: reset = 1; break; default: break; } } argv += optind; argc -= optind; if (reset) { /* Reset implies resetting to original path first. */ exec_path = xstrdup (orig_path); } else { /* Otherwise, get current path to modify. */ env = get_in_environ (inferior_environ, path_var_name); /* Can be null if path is not set. */ if (!env) env = ""; exec_path = xstrdup (env); } for (i = argc - 1; i >= 0; --i) env_mod_path (argv[i], &exec_path); set_in_environ (inferior_environ, path_var_name, exec_path); xfree (exec_path); env = get_in_environ (inferior_environ, path_var_name); ui_out_field_string (uiout, "path", env); return MI_CMD_DONE; }
void mi_cmd_disassemble (char *command, char **argv, int argc) { struct gdbarch *gdbarch = get_current_arch (); struct ui_out *uiout = current_uiout; CORE_ADDR start; int mode, disasm_flags; struct symtab *s; /* Which options have we processed ... */ int file_seen = 0; int line_seen = 0; int num_seen = 0; int start_seen = 0; int end_seen = 0; /* ... and their corresponding value. */ char *file_string = NULL; int line_num = -1; int how_many = -1; CORE_ADDR low = 0; CORE_ADDR high = 0; struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); /* Options processing stuff. */ int oind = 0; char *oarg; enum opt { FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT }; static const struct mi_opt opts[] = { {"f", FILE_OPT, 1}, {"l", LINE_OPT, 1}, {"n", NUM_OPT, 1}, {"s", START_OPT, 1}, {"e", END_OPT, 1}, { 0, 0, 0 } }; /* Get the options with their arguments. Keep track of what we encountered. */ while (1) { int opt = mi_getopt ("-data-disassemble", argc, argv, opts, &oind, &oarg); if (opt < 0) break; switch ((enum opt) opt) { case FILE_OPT: file_string = xstrdup (oarg); file_seen = 1; make_cleanup (xfree, file_string); break; case LINE_OPT: line_num = atoi (oarg); line_seen = 1; break; case NUM_OPT: how_many = atoi (oarg); num_seen = 1; break; case START_OPT: low = parse_and_eval_address (oarg); start_seen = 1; break; case END_OPT: high = parse_and_eval_address (oarg); end_seen = 1; break; } } argv += oind; argc -= oind; /* Allow only filename + linenum (with how_many which is not required) OR start_addr + end_addr. */ if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen) || (line_seen && file_seen && !num_seen && !start_seen && !end_seen) || (!line_seen && !file_seen && !num_seen && start_seen && end_seen))) error (_("-data-disassemble: Usage: ( [-f filename -l linenum [-n " "howmany]] | [-s startaddr -e endaddr]) [--] mode.")); if (argc != 1) error (_("-data-disassemble: Usage: [-f filename -l linenum " "[-n howmany]] [-s startaddr -e endaddr] [--] mode.")); mode = atoi (argv[0]); if (mode < 0 || mode > 3) error (_("-data-disassemble: Mode argument must be 0, 1, 2, or 3.")); /* Convert the mode into a set of disassembly flags. */ disasm_flags = 0; if (mode & 0x1) disasm_flags |= DISASSEMBLY_SOURCE; if (mode & 0x2) disasm_flags |= DISASSEMBLY_RAW_INSN; /* We must get the function beginning and end where line_num is contained. */ if (line_seen && file_seen) { s = lookup_symtab (file_string); if (s == NULL) error (_("-data-disassemble: Invalid filename.")); if (!find_line_pc (s, line_num, &start)) error (_("-data-disassemble: Invalid line number")); if (find_pc_partial_function (start, NULL, &low, &high) == 0) error (_("-data-disassemble: " "No function contains specified address")); } gdb_disassembly (gdbarch, uiout, file_string, disasm_flags, how_many, low, high); do_cleanups (cleanups); }