📄 mi-main.c
字号:
} else { do_cleanups (list_cleanup); mi_error_message = xstrprintf ("bad register number"); return MI_CMD_ERROR; } } do_cleanups (list_cleanup); return MI_CMD_DONE;}/* Output one register's contents in the desired format. */static intget_register (int regnum, int format){ char buffer[MAX_REGISTER_SIZE]; int optim; int realnum; CORE_ADDR addr; enum lval_type lval; static struct ui_stream *stb = NULL; stb = ui_out_stream_new (uiout); if (format == 'N') format = 0; frame_register (deprecated_selected_frame, regnum, &optim, &lval, &addr, &realnum, buffer); if (optim) { mi_error_message = xstrprintf ("Optimized out"); return -1; } if (format == 'r') { int j; char *ptr, buf[1024]; strcpy (buf, "0x"); ptr = buf + 2; for (j = 0; j < register_size (current_gdbarch, regnum); j++) { int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j : register_size (current_gdbarch, regnum) - 1 - j; sprintf (ptr, "%02x", (unsigned char) buffer[idx]); ptr += 2; } ui_out_field_string (uiout, "value", buf); /*fputs_filtered (buf, gdb_stdout); */ } else { val_print (register_type (current_gdbarch, regnum), buffer, 0, 0, stb->stream, format, 1, 0, Val_pretty_default); ui_out_field_stream (uiout, "value", stb); ui_out_stream_delete (stb); } return 1;}/* 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_resultmi_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;}#if 0/*This is commented out because we decided it was not useful. I leave it, just in case. ezannoni:1999-12-08 *//* Assign a value to a variable. The expression argument must be in the form A=2 or "A = 2" (I.e. if there are spaces it needs to be quoted. */enum mi_cmd_resultmi_cmd_data_assign (char *command, char **argv, int argc){ struct expression *expr; struct cleanup *old_chain; if (argc != 1) { mi_error_message = xstrprintf ("mi_cmd_data_assign: Usage: -data-assign expression"); return MI_CMD_ERROR; } /* NOTE what follows is a clone of set_command(). FIXME: ezannoni 01-12-1999: Need to decide what to do with this for libgdb purposes. */ expr = parse_expression (argv[0]); old_chain = make_cleanup (free_current_contents, &expr); evaluate_expression (expr); do_cleanups (old_chain); return MI_CMD_DONE;}#endif/* Evaluate the value of the argument. The argument is an expression. If the expression contains spaces it needs to be included in double quotes. */enum mi_cmd_resultmi_cmd_data_evaluate_expression (char *command, char **argv, int argc){ struct expression *expr; struct cleanup *old_chain = NULL; struct value *val; struct ui_stream *stb = NULL; stb = ui_out_stream_new (uiout); if (argc != 1) { mi_error_message = xstrprintf ("mi_cmd_data_evaluate_expression: Usage: -data-evaluate-expression expression"); return MI_CMD_ERROR; } expr = parse_expression (argv[0]); old_chain = make_cleanup (free_current_contents, &expr); val = evaluate_expression (expr); /* Print the result of the expression evaluation. */ val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val), stb->stream, 0, 0, 0, 0); ui_out_field_stream (uiout, "value", stb); ui_out_stream_delete (stb); do_cleanups (old_chain); return MI_CMD_DONE;}enum mi_cmd_resultmi_cmd_target_download (char *args, int from_tty){ char *run; struct cleanup *old_cleanups = NULL; run = xstrprintf ("load %s", args); old_cleanups = make_cleanup (xfree, run); execute_command (run, from_tty); do_cleanups (old_cleanups); return MI_CMD_DONE;}/* Connect to the remote target. */enum mi_cmd_resultmi_cmd_target_select (char *args, int from_tty){ char *run; struct cleanup *old_cleanups = NULL; run = xstrprintf ("target %s", args); old_cleanups = make_cleanup (xfree, run); /* target-select is always synchronous. once the call has returned we know that we are connected. */ /* NOTE: At present all targets that are connected are also (implicitly) talking to a halted target. In the future this may change. */ execute_command (run, from_tty); do_cleanups (old_cleanups); /* Issue the completion message here. */ if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("^connected", raw_stdout); mi_out_put (uiout, raw_stdout); mi_out_rewind (uiout); fputs_unfiltered ("\n", raw_stdout); do_exec_cleanups (ALL_CLEANUPS); return MI_CMD_QUIET;}/* DATA-MEMORY-READ: ADDR: start address of data to be dumped. WORD-FORMAT: a char indicating format for the ``word''. See the ``x'' command. WORD-SIZE: size of each ``word''; 1,2,4, or 8 bytes NR_ROW: Number of rows. NR_COL: The number of colums (words per row). ASCHAR: (OPTIONAL) Append an ascii character dump to each row. Use ASCHAR for unprintable characters. Reads SIZE*NR_ROW*NR_COL bytes starting at ADDR from memory and displayes them. Returns: {addr="...",rowN={wordN="..." ,... [,ascii="..."]}, ...} Returns: The number of bytes read is SIZE*ROW*COL. */enum mi_cmd_resultmi_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; char *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 = 0; while (nr_bytes < total_bytes) { int error; long num = target_read_memory_partial (addr + nr_bytes, mbuf + nr_bytes, total_bytes - nr_bytes, &error); if (num <= 0) break; nr_bytes += num; } /* 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;}/* 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_resultmi_cmd_data_write_memory (char *command, char **argv, int argc){ CORE_ADDR addr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -