This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] New commands, dump/restore memory<-->file
- From: Michael Snyder <msnyder at cygnus dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Tue, 26 Mar 2002 17:46:20 -0800
- Subject: [RFA] New commands, dump/restore memory<-->file
Hello,
Back in January, there was a discussion about adding commands that
would allow gdb to copy data from target memory to a file and back
again. Andrew and I have done an implementation of those commands,
and here it is for your approval.
The syntax looks like this:
dump <format> <filename> memory <start> <end>
dump <format> <filename> value <expression>
restore <filename> <offset> <start> <end>
Where <format> may be srec, ihex, tekhex, or binary (defaulting
to binary). Start and end may be numeric or symbolic.
Expression can be any expression that GDB can normally evaluate.
The restore command can copy a file back into target memory
for any running target. It can bias the copy by an offset,
and it can copy a subrange of the file (specified by start and
end, which are file-relative ie. before the offset is applied).
There is also an alternate form of the dump command called
append, which will append new data onto an existing file;
it only works with the binary file format at present.
New files are appended at the end of this diff.
2002-03-26 Michael Snyder <msnyder@redhat.com>
Andrew Cagney <cagney@redhat.com>
* cli/cli-dump.c: New file. Dump memory to file,
restore file to memory.
* Makefile.in: Add rules, dependencies for cli-dump.o.
2002-03-26 Michael Snyder <msnyder@redhat.com>
* gdb.base/default.exp: Add tests for dump, append, and restore.
* gdb.base/help.exp: Add tests for dump, append, and restore.
* gdb.base/dump.exp: New file, test dump, append and restore.
* gdb.base/dump.c: New file.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.165
diff -c -3 -p -r1.165 Makefile.in
*** Makefile.in 2002/03/24 00:40:35 1.165
--- Makefile.in 2002/03/27 01:39:55
*************** INTL_CFLAGS = -I$(INTL_DIR) -I$(INTL_SRC
*** 137,144 ****
--- 137,146 ----
# CLI sub directory definitons
#
SUBDIR_CLI_OBS = \
+ cli-dump.o \
cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o
SUBDIR_CLI_SRCS = \
+ cli/cli-dump.c \
cli/cli-decode.c cli/cli-script.c cli/cli-cmds.c cli/cli-setshow.c \
cli/cli-utils.c
SUBDIR_CLI_DEPS =
*************** c_lang_h = c-lang.h $(value_h)
*** 593,598 ****
--- 595,601 ----
call_cmds_h = call-cmds.h
cli_cmds_h = $(srcdir)/cli/cli-cmds.h
cli_decode_h = $(srcdir)/cli/cli-decode.h $(command_h)
+ cli_dump_h = $(srcdir)/cli/cli-dump.h
cli_out_h = cli-out.h
cli_script_h = $(srcdir)/cli/cli-script.h
cli_setshow_h = $(srcdir)/cli/cli-setshow.h
*************** wrapper.o: wrapper.c $(defs_h) $(frame_h
*** 2210,2224 ****
# Need to explicitly specify the compile rule as make will do nothing
# or try to compile the object file into the cli directory.
cli-decode.o: $(srcdir)/cli/cli-decode.c $(cli_decode_h) \
$(cli_cmds_h) $(defs_h) $(ui_out_h) \
$(symtab_h) gdb_regex.h
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-decode.c
! cli-cmds.o: $(srcdir)/cli/cli-cmds.c $(cli_cmds_h) $(cli_decode_h) \
! $(cli_script_h) $(cli_setshow_h) $(top_h) $(completer_h) \
! $(defs_h) $(target_h) gdb_wait.h gdb_regex.h $(ui_out_h)
! $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-cmds.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(cli_setshow_h) \
$(cli_decode_h) $(cli_cmds_h) $(defs_h) \
--- 2213,2231 ----
# Need to explicitly specify the compile rule as make will do nothing
# or try to compile the object file into the cli directory.
+ cli-cmds.o: $(srcdir)/cli/cli-cmds.c $(cli_cmds_h) $(cli_decode_h) \
+ $(cli_script_h) $(cli_setshow_h) $(top_h) $(completer_h) \
+ $(defs_h) $(target_h) gdb_wait.h gdb_regex.h $(ui_out_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-cmds.c
+
cli-decode.o: $(srcdir)/cli/cli-decode.c $(cli_decode_h) \
$(cli_cmds_h) $(defs_h) $(ui_out_h) \
$(symtab_h) gdb_regex.h
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-decode.c
! cli-dump.o: $(srcdir)/cli/cli-dump.c $(defs_h) $(gdb_string_h) $(command_h) \
! $(value_h) $(gdbcmd_h) $(completer_h) $(cli_dump_h)
! $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-dump.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(cli_setshow_h) \
$(cli_decode_h) $(cli_cmds_h) $(defs_h) \
Index: testsuite/gdb.base/help.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/help.exp,v
retrieving revision 1.8
diff -c -3 -p -r1.8 help.exp
*** help.exp 2002/03/26 05:10:26 1.8
--- help.exp 2002/03/27 01:43:12
*************** gdb_test "set height 400" "" "test set h
*** 38,43 ****
--- 38,57 ----
gdb_test "help add-symbol-file" "Usage: add-symbol-file FILE ADDR \\\[-s <SECT> <SECT_ADDR> -s <SECT> <SECT_ADDR> \.\.\.\\\]\[\r\n\]+Load the symbols from FILE, assuming FILE has been dynamically loaded\.\[\r\n\]+ADDR is the starting address of the file's text\.\[\r\n\]+The optional arguments are section-name section-address pairs and\[\r\n\]+should be specified if the data and bss segments are not contiguous\[\r\n\]+with the text\. SECT is a section name to be loaded at SECT_ADDR\." "help add-symbol-file"
# test help aliases
gdb_test "help aliases" "Aliases of other commands\.\[\r\n\]+List of commands\:.*\[\r\n\]+Type \"help\" followed by command name for full documentation\.\[\r\n\]+Command name abbreviations are allowed if unambiguous\." "help aliases"
+ # test help append
+ gdb_test "help append" \
+ "Append target code/data to a local file\.\[\r\n\]+List of append subcommands:.*"
+ gdb_test "help append binary" \
+ "Append target code/data to a raw binary file\.\[\r\n\]+List of append binary subcommands:.*"
+ gdb_test "help append memory" \
+ "Append contents of memory to a raw binary file\.\[\r\n\]+Arguments are FILE START STOP\. Writes the contents of memory within the\[\r\n\]+range \\\[START \.\. STOP\\) to the specifed FILE in raw target ordered bytes\."
+ gdb_test "help append value" \
+ "Append the value of an expression to a raw binary file\.\[\r\n\]+Arguments are FILE EXPRESSION\. Writes the value of EXPRESSION to\[\r\n\]+the specified FILE in raw target ordered bytes\."
+ gdb_test "help append binary memory" \
+ "Append contents of memory to a raw binary file\.\[\r\n\]+Arguments are FILE START STOP\. Writes the contents of memory within the\[\r\n\]+range \\\[START \.\. STOP\\) to the specifed FILE in raw target ordered bytes\."
+ gdb_test "help append binary value" \
+ "Append the value of an expression to a raw binary file\.\[\r\n\]+Arguments are FILE EXPRESSION\. Writes the value of EXPRESSION\[\r\n\]+to the specified FILE in raw target ordered bytes\."
+ # test help attach
gdb_test "help attach" "Attach to a process or file outside of GDB\.\[\r\n\]+This command attaches to another target, of the same type as your last\[\r\n\]+\"target\" command \\(\"info files\" will show your target stack\\)\.\[\r\n\]+The command may take as argument a process id or a device file\.\[\r\n\]+For a process id, you must have permission to send the process a signal,\[\r\n\]+and it must have the same effective uid as the debugger\.\[\r\n\]+When using \"attach\" with a process id, the debugger finds the\[\r\n\]+program running in the process, looking first in the current working\[\r\n\]+directory, or \\(if not found there\\) using the source file search path\[\r\n\]+\\(see the \"directory\" command\\)\. You can also use the \"file\" command\[\r\n\]+to specify the program, and to load its symbol table\." "help attach"
# test help breakpoint "b" abbreviation
gdb_test "help b" "Set breakpoint at specified line or function\.\[\r\n\]+Argument may be line number, function name, or \"\[*\]\" and an address\.\[\r\n\]+If line number is specified, break at start of code for that line\.\[\r\n\]+If function is specified, break at start of code for that function\.\[\r\n\]+If an address is specified, break at that exact address\.\[\r\n\]+With no arg, uses current execution address of selected stack frame\.\[\r\n\]+This is useful for breaking on return to a stack frame\.\[\r\n\]+Multiple breakpoints at one place are permitted, and useful if conditional\.\[\r\n\]+Do \"help breakpoints\" for info on other commands dealing with breakpoints\." "help breakpoint \"b\" abbreviation"
*************** gdb_test "help down-silently" "Same as t
*** 117,122 ****
--- 131,151 ----
# -re "Get fatal error; make debugger dump its core\."
#
# }
+ # test help dump
+ gdb_test "help dump" "Dump target code/data to a local file\.\[\r\n\]+List of dump subcommands:.*"
+ gdb_test "help dump binary" "Write target code/data to a raw binary file\.\[\r\n\]+List of dump binary subcommands:.*"
+ gdb_test "help dump ihex" "Write target code/data to an intel hex file\.\[\r\n\]+List of dump ihex subcommands:.*"
+ gdb_test "help dump srec" "Write target code/data to an srec file\.\[\r\n\]+List of dump srec subcommands:.*"
+ gdb_test "help dump tekhex" "Write target code/data to a tekhex file\.\[\r\n\]+List of dump tekhex subcommands:.*"
+ gdb_test "help dump value" "Write the value of an expression to a raw binary file\.\[\r\n\]+Arguments are FILE EXPRESSION\. Writes the value of EXPRESSION to\[\r\n\]+the specified FILE in raw target ordered bytes\."
+ gdb_test "help dump binary memory" "Write contents of memory to a raw binary file\.\[\r\n\]+Arguments are FILE START STOP\. Writes the contents of memory\[\r\n\]+within the range \\\[START \.\. STOP\\) to the specifed FILE in binary format\."
+ gdb_test "help dump binary value" "Write the value of an expression to a raw binary file\.\[\r\n\]+Arguments are FILE EXPRESSION\. Writes the value of EXPRESSION\[\r\n\]+to the specified FILE in raw target ordered bytes\." "help dump binary value"
+ gdb_test "help dump ihex memory" "Write contents of memory to an ihex file\.\[\r\n\]+Arguments are FILE START STOP\. Writes the contents of memory within\[\r\n\]+the range \\\[START \.\. STOP\\) to the specifed FILE in intel hex format\."
+ gdb_test "help dump ihex value" "Write the value of an expression to an ihex file\.\[\r\n\]+Arguments are FILE EXPRESSION\. Writes the value of EXPRESSION\[\r\n\]+to the specified FILE in intel hex format\."
+ gdb_test "help dump srec memory" "Write contents of memory to an srec file\.\[\r\n\]+Arguments are FILE START STOP\. Writes the contents of memory\[\r\n\]+within the range \\\[START \.\. STOP\\) to the specifed FILE in srec format\."
+ gdb_test "help dump srec value" "Write the value of an expression to an srec file\.\[\r\n\]+Arguments are FILE EXPRESSION\. Writes the value of EXPRESSION\[\r\n\]+to the specified FILE in srec format\."
+ gdb_test "help dump tekhex memory" "Write contents of memory to a tekhex file\.\[\r\n\]+Arguments are FILE START STOP\. Writes the contents of memory\[\r\n\]+within the range \\\[START \.\. STOP\\) to the specifed FILE in tekhex format\."
+ gdb_test "help dump tekhex value" "Write the value of an expression to a tekhex file\.\[\r\n\]+Arguments are FILE EXPRESSION\. Writes the value of EXPRESSION\[\r\n\]+to the specified FILE in tekhex format\."
# test help echo
gdb_test "help echo" "Print a constant string\. Give string as argument\.\[\r\n\]+C escape sequences may be used in the argument\.\[\r\n\]+No newline is added at the end of the argument;\[\r\n\]+use \"\\\\n\" if you want a newline to be printed\.\[\r\n\]+Since leading and trailing whitespace are ignored in command arguments,\[\r\n\]+if you want to print some you must use \"\\\\\" before leading whitespace\[\r\n\]+to be printed or after trailing whitespace\." "help echo"
# test help enable breakpoints delete
*************** gdb_test "help r" "Start debugged progra
*** 298,303 ****
--- 327,334 ----
gdb_test "help run" "Start debugged program\. You may specify arguments to give it\.\[\r\n\]+Args may include \"\\*\", or \"\\\[\.\.\.\\\]\"; they are expanded using \"sh\"\.\[\r\n\]+Input and output redirection with \">\", \"<\", or \">>\" are also allowed\.\[\r\n\]+With no arguments, uses arguments last specified \\(with \"run\" or \"set args\"\\)\.\[\r\n\]+To cancel previous arguments and run with no arguments,\[\r\n\]+use \"set args\" without arguments\." "help run"
# test help rbreak
gdb_test "help rbreak" "Set a breakpoint for all functions matching REGEXP\." "help rbreak"
+ # test help restore
+ gdb_test "help restore" "Restore the contents of FILE to target memory\.\[\r\n\]+Arguments are FILE OFFSET START END where all except FILE are optional\.\[\r\n\]+OFFSET will be added to the base address of the file \\(default zero\\)\.\[\r\n\]+If START and END are given, only the file contents within that range\[\r\n\]+\\(file relative\\) will be restored to target memory\."
# test help return
gdb_test "help return" "Make selected stack frame return to its caller\.\[\r\n\]+Control remains in the debugger, but when you continue\[\r\n\]+execution will resume in the frame above the one now selected\.\[\r\n\]+If an argument is given, it is an expression for the value to return\." "help return"
# test help reverse-search
Index: testsuite/gdb.base/default.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/default.exp,v
retrieving revision 1.8
diff -c -3 -p -r1.8 default.exp
*** default.exp 2002/03/23 00:05:29 1.8
--- default.exp 2002/03/27 01:43:12
*************** set timeout 60
*** 34,39 ****
--- 34,47 ----
gdb_test "add-symbol-file" "add-symbol-file takes a file name and an address" "add-symbol-file"
+ # test append
+ gdb_test "append" "\"append\" must be followed by a subcommand\.\[\r\n\]+List of append subcommands:.*"
+ gdb_test "append binary" "\"append binary\" must be followed by a subcommand\.\[\r\n\]+List of append binary subcommands:.*"
+ gdb_test "append memory" "Missing filename\."
+ gdb_test "append value" "Missing filename\."
+ gdb_test "append binary memory" "Missing filename\."
+ gdb_test "append binary value" "Missing filename\."
+
setup_xfail "mips-idt-*"
send_gdb "attach\n"
gdb_expect {
*************** gdb_test "document" "Argument required .
*** 191,196 ****
--- 199,220 ----
gdb_test "down" "No stack.*" "down"
#test down-silently
gdb_test "down-silently" "No stack." "down-silently"
+ # test dump
+ gdb_test "dump" "\"dump\" must be followed by a subcommand\.\[\r\n\]+List of dump subcommands:.*"
+ gdb_test "dump binary" "\"dump binary\" must be followed by a subcommand\.\[\r\n\]+List of dump binary subcommands:.*"
+ gdb_test "dump ihex" "\"dump ihex\" must be followed by a subcommand\.\[\r\n\]+List of dump ihex subcommands:.*"
+ gdb_test "dump memory" "Missing filename\."
+ gdb_test "dump srec" "\"dump srec\" must be followed by a subcommand\.\[\r\n\]+List of dump srec subcommands:.*"
+ gdb_test "dump tekhex" "\"dump tekhex\" must be followed by a subcommand\.\[\r\n\]+List of dump tekhex subcommands:.*"
+ gdb_test "dump value" "Missing filename\."
+ gdb_test "dump binary memory" "Missing filename\."
+ gdb_test "dump binary value" "Missing filename\."
+ gdb_test "dump ihex memory" "Missing filename\."
+ gdb_test "dump ihex value" "Missing filename\."
+ gdb_test "dump srec memory" "Missing filename\."
+ gdb_test "dump srec value" "Missing filename\."
+ gdb_test "dump tekhex memory" "Missing filename\."
+ gdb_test "dump tekhex value" "Missing filename\."
#test echo
gdb_test "echo" "" "echo"
#test enable breakpoints delete
*************** No program loaded.*$gdb_prompt $"\
*** 490,495 ****
--- 514,522 ----
#test rbreak
gdb_test "rbreak" "" "rbreak"
+
+ # test restore
+ gdb_test "restore" "You can't do that without a process to debug\."
#test return
# The middle case accomodated the OBSOLETE a29k, where doing the "ni"
File: cli/cli-dump.c
/* Dump-to-file commands, for GDB, the GNU debugger.
Copyright 2002 Free Software Foundation, Inc.
Contributed by Red Hat.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdb_string.h"
#include "cli/cli-decode.h"
#include "cli/cli-cmds.h"
#include "value.h"
#include "completer.h"
#include "cli/cli-dump.h"
#include "gdb_assert.h"
#include <ctype.h>
#include "target.h"
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
char *
skip_spaces (char *chp)
{
if (chp == NULL)
return NULL;
while (isspace (*chp))
chp++;
return chp;
}
char *
scan_expression_with_cleanup (char **cmd, const char *def)
{
if ((*cmd) == NULL || (**cmd) == '\0')
{
char *exp = xstrdup (def);
make_cleanup (xfree, exp);
return exp;
}
else
{
char *exp;
char *end;
end = (*cmd) + strcspn (*cmd, " \t");
exp = savestring ((*cmd), end - (*cmd));
make_cleanup (xfree, exp);
(*cmd) = skip_spaces (end);
return exp;
}
}
static void
do_fclose_cleanup (void *arg)
{
FILE *file = arg;
fclose (arg);
}
static struct cleanup *
make_cleanup_fclose (FILE *file)
{
return make_cleanup (do_fclose_cleanup, file);
}
char *
scan_filename_with_cleanup (char **cmd, const char *defname)
{
char *filename;
char *fullname;
/* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */
/* File. */
if ((*cmd) == NULL)
{
if (defname == NULL)
error ("Missing filename.");
filename = xstrdup (defname);
make_cleanup (xfree, filename);
}
else
{
/* FIXME: should parse a possibly quoted string. */
char *end;
(*cmd) = skip_spaces (*cmd);
end = *cmd + strcspn (*cmd, " \t");
filename = savestring ((*cmd), end - (*cmd));
make_cleanup (xfree, filename);
(*cmd) = skip_spaces (end);
}
gdb_assert (filename != NULL);
fullname = tilde_expand (filename);
make_cleanup (xfree, fullname);
return fullname;
}
FILE *
fopen_with_cleanup (char *filename, const char *mode)
{
FILE *file = fopen (filename, mode);
if (file == NULL)
perror_with_name (filename);
make_cleanup_fclose (file);
return file;
}
static bfd *
bfd_openr_with_cleanup (const char *filename, const char *target)
{
bfd *ibfd;
if ((ibfd = bfd_openr (filename, target)) == NULL)
error ("Failed to open %s: %s.", filename,
bfd_errmsg (bfd_get_error ()));
make_cleanup_bfd_close (ibfd);
if (!bfd_check_format (ibfd, bfd_object))
error ("'%s' is not a recognized file format.", filename);
return ibfd;
}
static bfd *
bfd_openw_with_cleanup (char *filename, const char *target, char *mode)
{
bfd *obfd;
if (*mode == 'w') /* Write: create new file */
{
if ((obfd = bfd_openw (filename, target)) == NULL)
error ("Failed to open %s: %s.", filename,
bfd_errmsg (bfd_get_error ()));
make_cleanup_bfd_close (obfd);
if (!bfd_set_format (obfd, bfd_object))
error ("bfd_openw_with_cleanup: %s.", bfd_errmsg (bfd_get_error ()));
}
else if (*mode == 'a') /* Append to existing file */
{ /* FIXME -- doesn't work... */
error ("bfd_openw does not work with append.");
}
else
error ("bfd_openw_with_cleanup: unknown mode %s.", mode);
return obfd;
}
struct cmd_list_element *dump_cmdlist;
struct cmd_list_element *append_cmdlist;
struct cmd_list_element *srec_cmdlist;
struct cmd_list_element *ihex_cmdlist;
struct cmd_list_element *tekhex_cmdlist;
struct cmd_list_element *binary_dump_cmdlist;
struct cmd_list_element *binary_append_cmdlist;
static void
dump_command (char *cmd, int from_tty)
{
printf_unfiltered ("\"dump\" must be followed by a subcommand.\n\n");
help_list (dump_cmdlist, "dump ", -1, gdb_stdout);
}
static void
append_command (char *cmd, int from_tty)
{
printf_unfiltered ("\"append\" must be followed by a subcommand.\n\n");
help_list (dump_cmdlist, "append ", -1, gdb_stdout);
}
static void
dump_binary_file (char *filename, char *mode,
char *buf, int len)
{
FILE *file;
int status;
file = fopen_with_cleanup (filename, mode);
status = fwrite (buf, len, 1, file);
if (status != 1)
perror_with_name (filename);
}
static void
dump_bfd_file (char *filename, char *mode,
char *target, CORE_ADDR vaddr,
char *buf, int len)
{
bfd *obfd;
asection *osection;
obfd = bfd_openw_with_cleanup (filename, target, mode);
osection = bfd_make_section_anyway (obfd, ".newsec");
bfd_set_section_size (obfd, osection, len);
bfd_set_section_vma (obfd, osection, vaddr);
bfd_set_section_alignment (obfd, osection, 0);
bfd_set_section_flags (obfd, osection, 0x203);
osection->entsize = 0;
bfd_set_section_contents (obfd, osection, buf, 0, len);
}
static void
dump_memory_to_file (char *cmd, char *mode, char *file_format)
{
struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
CORE_ADDR lo;
CORE_ADDR hi;
ULONGEST count;
char *filename;
void *buf;
char *lo_exp;
char *hi_exp;
int len;
/* Open the file. */
filename = scan_filename_with_cleanup (&cmd, NULL);
/* Find the low address. */
if (cmd == NULL || *cmd == '\0')
error ("Missing start address.");
lo_exp = cmd;
cmd += strcspn (cmd, " \t");
lo_exp = savestring (lo_exp, cmd - lo_exp);
make_cleanup (xfree, lo_exp);
cmd = skip_spaces (cmd);
/* Find the second address - rest of line. */
if (cmd == NULL || *cmd == '\0')
error ("Missing stop address.");
hi_exp = cmd;
lo = parse_and_eval_address (lo_exp);
hi = parse_and_eval_address (hi_exp);
if (hi <= lo)
error ("Invalid memory address range (start >= end).");
count = hi - lo;
/* FIXME: Should use read_memory_partial() and a magic blocking
value. */
buf = xmalloc (count);
make_cleanup (xfree, buf);
target_read_memory (lo, buf, count);
/* Have everything. Open/write the data. */
if (file_format == NULL || strcmp (file_format, "binary") == 0)
{
dump_binary_file (filename, mode, buf, count);
}
else
{
dump_bfd_file (filename, mode, file_format, lo, buf, count);
}
do_cleanups (old_cleanups);
}
static void
dump_memory_command (char *cmd, char *mode)
{
dump_memory_to_file (cmd, mode, "binary");
}
static void
dump_value_to_file (char *cmd, char *mode, char *file_format)
{
struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
struct value *val;
char *filename;
/* Open the file. */
filename = scan_filename_with_cleanup (&cmd, NULL);
/* Find the value. */
if (cmd == NULL || *cmd == '\0')
error ("No value to %s.", *mode == 'a' ? "append" : "dump");
val = parse_and_eval (cmd);
if (val == NULL)
error ("Invalid expression.");
/* Have everything. Open/write the data. */
if (file_format == NULL || strcmp (file_format, "binary") == 0)
{
dump_binary_file (filename, mode, VALUE_CONTENTS (val),
TYPE_LENGTH (VALUE_TYPE (val)));
}
else
{
CORE_ADDR vaddr;
if (VALUE_LVAL (val))
{
vaddr = VALUE_ADDRESS (val);
}
else
{
vaddr = 0;
warning ("value is not an lval: address assumed to be zero");
}
dump_bfd_file (filename, mode, file_format, vaddr,
VALUE_CONTENTS (val),
TYPE_LENGTH (VALUE_TYPE (val)));
}
do_cleanups (old_cleanups);
}
static void
dump_value_command (char *cmd, char *mode)
{
dump_value_to_file (cmd, mode, "binary");
}
static void
dump_filetype (char *cmd, char *mode, char *filetype)
{
char *suffix = cmd;
if (cmd == NULL || *cmd == '\0')
error ("Missing subcommand: try 'help %s %s'.",
mode[0] == 'a' ? "append" : "dump",
filetype);
suffix += strcspn (cmd, " \t");
if (suffix != cmd)
{
if (strncmp ("memory", cmd, suffix - cmd) == 0)
{
dump_memory_to_file (suffix, mode, filetype);
return;
}
else if (strncmp ("value", cmd, suffix - cmd) == 0)
{
dump_value_to_file (suffix, mode, filetype);
return;
}
}
error ("dump %s: unknown subcommand '%s' -- try 'value' or 'memory'.",
filetype, cmd);
}
static void
dump_srec_memory (char *args, int from_tty)
{
dump_memory_to_file (args, "w", "srec");
}
static void
dump_srec_value (char *args, int from_tty)
{
dump_value_to_file (args, "w", "srec");
}
static void
dump_ihex_memory (char *args, int from_tty)
{
dump_memory_to_file (args, "w", "ihex");
}
static void
dump_ihex_value (char *args, int from_tty)
{
dump_value_to_file (args, "w", "ihex");
}
static void
dump_tekhex_memory (char *args, int from_tty)
{
dump_memory_to_file (args, "w", "tekhex");
}
static void
dump_tekhex_value (char *args, int from_tty)
{
dump_value_to_file (args, "w", "tekhex");
}
static void
dump_binary_memory (char *args, int from_tty)
{
dump_memory_to_file (args, "w", "binary");
}
static void
dump_binary_value (char *args, int from_tty)
{
dump_value_to_file (args, "w", "binary");
}
static void
append_binary_memory (char *args, int from_tty)
{
dump_memory_to_file (args, "a", "binary");
}
static void
append_binary_value (char *args, int from_tty)
{
dump_value_to_file (args, "a", "binary");
}
struct dump_context
{
void (*func) (char *cmd, char *mode);
char *mode;
};
static void
call_dump_func (struct cmd_list_element *c, char *args, int from_tty)
{
struct dump_context *d = get_cmd_context (c);
d->func (args, d->mode);
}
void
add_dump_command (char *name, void (*func) (char *args, char *mode),
char *descr)
{
struct cmd_list_element *c;
struct dump_context *d;
c = add_cmd (name, class_files, NULL, descr, &dump_cmdlist);
c->completer = filename_completer;
d = XMALLOC (struct dump_context);
d->func = func;
d->mode = "w";
set_cmd_context (c, d);
c->func = call_dump_func;
c = add_cmd (name, class_files, NULL, descr, &append_cmdlist);
c->completer = filename_completer;
d = XMALLOC (struct dump_context);
d->func = func;
d->mode = "a";
set_cmd_context (c, d);
c->func = call_dump_func;
/* Replace "Dump " at start of docstring with "Append "
(borrowed from add_show_from_set). */
if ( c->doc[0] == 'W'
&& c->doc[1] == 'r'
&& c->doc[2] == 'i'
&& c->doc[3] == 't'
&& c->doc[4] == 'e'
&& c->doc[5] == ' ')
c->doc = concat ("Append ", c->doc + 6, NULL);
}
/* Opaque data for restore_section_callback. */
struct callback_data {
unsigned long load_offset;
CORE_ADDR load_start;
CORE_ADDR load_end;
};
/* Function: restore_section_callback.
Callback function for bfd_map_over_sections.
Selectively loads the sections into memory. */
static void
restore_section_callback (bfd *ibfd, asection *isec, void *args)
{
struct callback_data *data = args;
bfd_vma sec_start = bfd_section_vma (ibfd, isec);
bfd_size_type size = bfd_section_size (ibfd, isec);
bfd_vma sec_end = sec_start + size;
bfd_size_type sec_offset = 0;
bfd_size_type sec_load_count = size;
struct cleanup *old_chain;
char *buf;
int ret;
/* Ignore non-loadable sections, eg. from elf files. */
if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD))
return;
/* Does the section overlap with the desired restore range? */
if (sec_end <= data->load_start
|| (data->load_end > 0 && sec_start >= data->load_end))
{
/* No, no useable data in this section. */
printf_filtered ("skipping section %s...\n",
bfd_section_name (ibfd, isec));
return;
}
/* Compare section address range with user-requested
address range (if any). Compute where the actual
transfer should start and end. */
if (sec_start < data->load_start)
sec_offset = data->load_start - sec_start;
/* Size of a partial transfer: */
sec_load_count -= sec_offset;
if (data->load_end > 0 && sec_end > data->load_end)
sec_load_count -= sec_end - data->load_end;
/* Get the data. */
buf = xmalloc (size);
old_chain = make_cleanup (xfree, buf);
if (!bfd_get_section_contents (ibfd, isec, buf, 0, size))
error ("Failed to read bfd file %s: '%s'.", bfd_get_filename (ibfd),
bfd_errmsg (bfd_get_error ()));
printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
bfd_section_name (ibfd, isec),
(unsigned long) sec_start,
(unsigned long) sec_end);
if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0)
printf_filtered (" into memory (0x%lx to 0x%lx)\n",
(unsigned long) sec_start
+ sec_offset + data->load_offset,
(unsigned long) sec_start + sec_offset
+ data->load_offset + sec_load_count);
else
puts_filtered ("\n");
/* Write the data. */
ret = target_write_memory (sec_start + sec_offset + data->load_offset,
buf + sec_offset, sec_load_count);
if (ret != 0)
warning ("restore: memory write failed (%s).", safe_strerror (ret));
do_cleanups (old_chain);
return;
}
static void
restore_binary_file (char *filename, struct callback_data *data)
{
FILE *file = fopen_with_cleanup (filename, "r");
int status;
char *buf;
long len;
/* Get the file size for reading. */
if (fseek (file, 0, SEEK_END) == 0)
len = ftell (file);
else
perror_with_name (filename);
if (len <= data->load_start)
error ("Start address is greater than length of binary file %s.",
filename);
/* Chop off "len" if it exceeds the requested load_end addr. */
if (data->load_end != 0 && data->load_end < len)
len = data->load_end;
/* Chop off "len" if the requested load_start addr skips some bytes. */
if (data->load_start > 0)
len -= data->load_start;
printf_filtered
("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
filename,
(unsigned long) data->load_start + data->load_offset,
(unsigned long) data->load_start + data->load_offset + len);
/* Now set the file pos to the requested load start pos. */
if (fseek (file, data->load_start, SEEK_SET) != 0)
perror_with_name (filename);
/* Now allocate a buffer and read the file contents. */
buf = xmalloc (len);
make_cleanup (xfree, buf);
if (fread (buf, 1, len, file) != len)
perror_with_name (filename);
/* Now write the buffer into target memory. */
len = target_write_memory (data->load_start + data->load_offset, buf, len);
if (len != 0)
warning ("restore: memory write failed (%s).", safe_strerror (len));
return;
}
static void
restore_command (char *args, int from_tty)
{
char *filename;
struct callback_data data;
bfd *ibfd;
int binary_flag = 0;
if (!target_has_execution)
noprocess ();
data.load_offset = 0;
data.load_start = 0;
data.load_end = 0;
/* Parse the input arguments. First is filename (required). */
filename = scan_filename_with_cleanup (&args, NULL);
args = skip_spaces (args);
if (args != NULL && *args != '\0')
{
char *binary_string = "binary";
/* Look for optional "binary" flag. */
if (strncmp (args, binary_string, strlen (binary_string)) == 0)
{
binary_flag = 1;
args += strlen (binary_string);
args = skip_spaces (args);
}
/* Parse offset (optional). */
data.load_offset = strtoul (args, &args, 0);
args = skip_spaces (args);
if (args != NULL && *args != '\0')
{
/* Parse start address (optional). */
data.load_start = strtoul (args, &args, 0);
args = skip_spaces (args);
if (args != NULL && *args != '\0')
{
/* Parse end address (optional). */
data.load_end = strtoul (args, &args, 0);
if (data.load_end <= data.load_start)
error ("Start must be less than end.");
args = skip_spaces (args);
if (args != NULL && *args != '\0')
{
warning ("Junk at end of line: '%s'", args);
}
}
}
}
if (info_verbose)
printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
filename, (unsigned long) data.load_offset,
(unsigned long) data.load_start,
(unsigned long) data.load_end);
if (binary_flag)
{
restore_binary_file (filename, &data);
}
else
{
/* Open the file for loading. */
ibfd = bfd_openr_with_cleanup (filename, NULL);
/* Process the sections. */
bfd_map_over_sections (ibfd, restore_section_callback, &data);
}
return;
}
static void
srec_dump_command (char *cmd, int from_tty)
{
printf_unfiltered ("\"dump srec\" must be followed by a subcommand.\n");
help_list (srec_cmdlist, "dump srec ", -1, gdb_stdout);
}
static void
ihex_dump_command (char *cmd, int from_tty)
{
printf_unfiltered ("\"dump ihex\" must be followed by a subcommand.\n");
help_list (ihex_cmdlist, "dump ihex ", -1, gdb_stdout);
}
static void
tekhex_dump_command (char *cmd, int from_tty)
{
printf_unfiltered ("\"dump tekhex\" must be followed by a subcommand.\n");
help_list (tekhex_cmdlist, "dump tekhex ", -1, gdb_stdout);
}
static void
binary_dump_command (char *cmd, int from_tty)
{
printf_unfiltered ("\"dump binary\" must be followed by a subcommand.\n");
help_list (binary_dump_cmdlist, "dump binary ", -1, gdb_stdout);
}
static void
binary_append_command (char *cmd, int from_tty)
{
printf_unfiltered ("\"append binary\" must be followed by a subcommand.\n");
help_list (binary_append_cmdlist, "append binary ", -1, gdb_stdout);
}
void
_initialize_cli_dump (void)
{
struct cmd_list_element *c;
add_prefix_cmd ("dump", class_files, dump_command, "\
Dump target code/data to a local file.",
&dump_cmdlist, "dump ",
0/*allow-unknown*/,
&cmdlist);
add_prefix_cmd ("append", class_files, append_command, "\
Append target code/data to a local file.",
&append_cmdlist, "append ",
0/*allow-unknown*/,
&cmdlist);
add_dump_command ("memory", dump_memory_command, "\
Write contents of memory to a raw binary file.\n\
Arguments are FILE START STOP. Writes the contents of memory within the\n\
range [START .. STOP) to the specifed FILE in raw target ordered bytes.");
add_dump_command ("value", dump_value_command, "\
Write the value of an expression to a raw binary file.\n\
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
the specified FILE in raw target ordered bytes.");
add_prefix_cmd ("srec", class_files, srec_dump_command, "\
Write target code/data to an srec file.",
&srec_cmdlist, "dump srec ",
0 /*allow-unknown*/,
&dump_cmdlist);
add_prefix_cmd ("ihex", class_files, ihex_dump_command, "\
Write target code/data to an intel hex file.",
&ihex_cmdlist, "dump ihex ",
0 /*allow-unknown*/,
&dump_cmdlist);
add_prefix_cmd ("tekhex", class_files, tekhex_dump_command, "\
Write target code/data to a tekhex file.",
&tekhex_cmdlist, "dump tekhex ",
0 /*allow-unknown*/,
&dump_cmdlist);
add_prefix_cmd ("binary", class_files, binary_dump_command, "\
Write target code/data to a raw binary file.",
&binary_dump_cmdlist, "dump binary ",
0 /*allow-unknown*/,
&dump_cmdlist);
add_prefix_cmd ("binary", class_files, binary_append_command, "\
Append target code/data to a raw binary file.",
&binary_append_cmdlist, "append binary ",
0 /*allow-unknown*/,
&append_cmdlist);
add_cmd ("memory", class_files, dump_srec_memory, "\
Write contents of memory to an srec file.\n\
Arguments are FILE START STOP. Writes the contents of memory\n\
within the range [START .. STOP) to the specifed FILE in srec format.",
&srec_cmdlist);
add_cmd ("value", class_files, dump_srec_value, "\
Write the value of an expression to an srec file.\n\
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
to the specified FILE in srec format.",
&srec_cmdlist);
add_cmd ("memory", class_files, dump_ihex_memory, "\
Write contents of memory to an ihex file.\n\
Arguments are FILE START STOP. Writes the contents of memory within\n\
the range [START .. STOP) to the specifed FILE in intel hex format.",
&ihex_cmdlist);
add_cmd ("value", class_files, dump_ihex_value, "\
Write the value of an expression to an ihex file.\n\
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
to the specified FILE in intel hex format.",
&ihex_cmdlist);
add_cmd ("memory", class_files, dump_tekhex_memory, "\
Write contents of memory to a tekhex file.\n\
Arguments are FILE START STOP. Writes the contents of memory\n\
within the range [START .. STOP) to the specifed FILE in tekhex format.",
&tekhex_cmdlist);
add_cmd ("value", class_files, dump_tekhex_value, "\
Write the value of an expression to a tekhex file.\n\
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
to the specified FILE in tekhex format.",
&tekhex_cmdlist);
add_cmd ("memory", class_files, dump_binary_memory, "\
Write contents of memory to a raw binary file.\n\
Arguments are FILE START STOP. Writes the contents of memory\n\
within the range [START .. STOP) to the specifed FILE in binary format.",
&binary_dump_cmdlist);
add_cmd ("value", class_files, dump_binary_value, "\
Write the value of an expression to a raw binary file.\n\
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
to the specified FILE in raw target ordered bytes.",
&binary_dump_cmdlist);
add_cmd ("memory", class_files, append_binary_memory, "\
Append contents of memory to a raw binary file.\n\
Arguments are FILE START STOP. Writes the contents of memory within the\n\
range [START .. STOP) to the specifed FILE in raw target ordered bytes.",
&binary_append_cmdlist);
add_cmd ("value", class_files, append_binary_value, "\
Append the value of an expression to a raw binary file.\n\
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
to the specified FILE in raw target ordered bytes.",
&binary_append_cmdlist);
c = add_com ("restore", class_files, restore_command,
"Restore the contents of FILE to target memory.\n\
Arguments are FILE OFFSET START END where all except FILE are optional.\n\
OFFSET will be added to the base address of the file (default zero).\n\
If START and END are given, only the file contents within that range
(file relative) will be restored to target memory.");
c->completer = filename_completer;
}
File: testsuite/gdb.base/dump.exp
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Please email any bugs, comments, and/or additions to this file to:
# bug-gdb@prep.ai.mit.edu
# This file was written by Michael Snyder (msnyder@redhat.com)
# This is a test for the gdb command "dump".
if $tracelevel then {
strace $tracelevel
}
set prms_id 0
set bug_id 0
set testfile "dump"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
}
# Start with a fresh gdb.
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
# Clean up any stale output files from previous test runs
remote_exec build "rm -f intarr1.bin intarr1b.bin intarr1.ihex intarr1.srec intarr1.tekhex intarr2.bin intarr2b.bin intarr2.ihex intarr2.srec intarr2.tekhex intstr1.bin intstr1b.bin intstr1.ihex intstr1.srec intstr1.tekhex intstr2.bin intstr2b.bin intstr2.ihex intstr2.srec intstr2.tekhex"
# Test help (FIXME:)
# Run target program until data structs are initialized.
if { ! [ runto checkpoint1 ] } then {
gdb_suppress_entire_file "Program failed to run, so all tests in this file will automatically fail."
}
# Now generate some dump files.
proc make_dump_file { command msg } {
global gdb_prompt
send_gdb "${command}\n"
gdb_expect {
-re ".*\[Ee\]rror.*$gdb_prompt $" { fail $msg }
-re ".*\[Ww\]arning.*$gdb_prompt $" { fail $msg }
-re ".*\[Uu\]ndefined dump command.*$gdb_prompt $" { fail $msg }
-re "${command}\[\r\n\]+$gdb_prompt $" { pass $msg }
timeout { fail "$msg (timeout)" }
}
}
make_dump_file "dump val intarr1.bin intarray" \
"dump array as value, default"
make_dump_file "dump val intstr1.bin intstruct" \
"dump struct as value, default"
make_dump_file "dump bin val intarr1b.bin intarray" \
"dump array as value, binary"
make_dump_file "dump bin val intstr1b.bin intstruct" \
"dump struct as value, binary"
make_dump_file "dump srec val intarr1.srec intarray" \
"dump array as value, srec"
make_dump_file "dump srec val intstr1.srec intstruct" \
"dump struct as value, srec"
make_dump_file "dump ihex val intarr1.ihex intarray" \
"dump array as value, intel hex"
make_dump_file "dump ihex val intstr1.ihex intstruct" \
"dump struct as value, intel hex"
make_dump_file "dump tekhex val intarr1.tekhex intarray" \
"dump array as value, tekhex"
make_dump_file "dump tekhex val intstr1.tekhex intstruct" \
"dump struct as value, tekhex"
proc capture_value { expression } {
global gdb_prompt
global expect_out
set output_string ""
send_gdb "print ${expression}\n"
gdb_expect {
-re ".*\[\r\n\]+.\[0123456789\]+ = (\[^\r\n\]+).*$gdb_prompt $" {
set output_string $expect_out(1,string)
}
default {
fail "capture_value failed on $expression."
}
}
return $output_string
}
set array_start [capture_value "/x &intarray\[0\]"]
set array_end [capture_value "/x &intarray\[32\]"]
set struct_start [capture_value "/x &intstruct"]
set struct_end [capture_value "/x &intstruct + 1"]
set array_val [capture_value "intarray"]
set struct_val [capture_value "intstruct"]
make_dump_file "dump mem intarr2.bin $array_start $array_end" \
"dump array as memory, default"
make_dump_file "dump mem intstr2.bin $struct_start $struct_end" \
"dump struct as memory, default"
make_dump_file "dump bin mem intarr2b.bin $array_start $array_end" \
"dump array as memory, binary"
make_dump_file "dump bin mem intstr2b.bin $struct_start $struct_end" \
"dump struct as memory, binary"
make_dump_file "dump srec mem intarr2.srec $array_start $array_end" \
"dump array as memory, srec"
make_dump_file "dump srec mem intstr2.srec $struct_start $struct_end" \
"dump struct as memory, srec"
make_dump_file "dump ihex mem intarr2.ihex $array_start $array_end" \
"dump array as memory, ihex"
make_dump_file "dump ihex mem intstr2.ihex $struct_start $struct_end" \
"dump struct as memory, ihex"
make_dump_file "dump tekhex mem intarr2.tekhex $array_start $array_end" \
"dump array as memory, tekhex"
make_dump_file "dump tekhex mem intstr2.tekhex $struct_start $struct_end" \
"dump struct as memory, tekhex"
# Now start a fresh gdb session, and reload the saved value files.
gdb_exit
gdb_start
gdb_file_cmd ${binfile}
# Reload saved values one by one, and compare.
if { ![string compare $array_val [capture_value "intarray"]] } then {
fail "start with intarray un-initialized"
} else {
pass "start with intarray un-initialized"
}
if { ![string compare $struct_val [capture_value "intstruct"]] } then {
fail "start with intstruct un-initialized"
} else {
pass "start with intstruct un-initialized"
}
proc test_reload_saved_value { filename msg oldval newval } {
global gdb_prompt
gdb_file_cmd $filename
if { ![string compare $oldval [capture_value $newval]] } then {
pass $msg
} else {
fail $msg
}
}
proc test_restore_saved_value { restore_args msg oldval newval } {
global gdb_prompt
gdb_test "restore $restore_args" \
"Restoring .*" \
"Restore command, $msg"
if { ![string compare $oldval [capture_value $newval]] } then {
pass "Restored value, $msg"
} else {
fail "Restored value, $msg"
}
}
test_reload_saved_value "intarr1.srec" "reload array as value, srec" \
$array_val "intarray"
test_reload_saved_value "intstr1.srec" "reload struct as value, srec" \
$struct_val "intstruct"
test_reload_saved_value "intarr2.srec" "reload array as memory, srec" \
$array_val "intarray"
test_reload_saved_value "intstr2.srec" "reload struct as memory, srec" \
$struct_val "intstruct"
test_reload_saved_value "intarr1.ihex" "reload array as value, intel hex" \
$array_val "intarray"
test_reload_saved_value "intstr1.ihex" "reload struct as value, intel hex" \
$struct_val "intstruct"
test_reload_saved_value "intarr2.ihex" "reload array as memory, intel hex" \
$array_val "intarray"
test_reload_saved_value "intstr2.ihex" "reload struct as memory, intel hex" \
$struct_val "intstruct"
test_reload_saved_value "intarr1.tekhex" "reload array as value, tekhex" \
$array_val "intarray"
test_reload_saved_value "intstr1.tekhex" "reload struct as value, tekhex" \
$struct_val "intstruct"
test_reload_saved_value "intarr2.tekhex" "reload array as memory, tekhex" \
$array_val "intarray"
test_reload_saved_value "intstr2.tekhex" "reload struct as memory, tekhex" \
$struct_val "intstruct"
# Start a fresh gdb session
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
# Run to main.
if { ! [ runto main ] } then {
gdb_suppress_entire_file "Program failed to run, so remaining tests in this file will automatically fail."
}
if { ![string compare $array_val [capture_value "intarray"]] } then {
fail "start with intarray un-initialized, runto main"
} else {
pass "start with intarray un-initialized, runto main"
}
if { ![string compare $struct_val [capture_value "intstruct"]] } then {
fail "start with intstruct un-initialized, runto main"
} else {
pass "start with intstruct un-initialized, runto main"
}
test_restore_saved_value "intarr1.srec" "array as value, srec" \
$array_val "intarray"
test_restore_saved_value "intstr1.srec" "struct as value, srec" \
$struct_val "intstruct"
gdb_test "print zero_all ()" "void" "zero all 1"
test_restore_saved_value "intarr2.srec" "array as memory, srec" \
$array_val "intarray"
test_restore_saved_value "intstr2.srec" "struct as memory, srec" \
$struct_val "intstruct"
gdb_test "print zero_all ()" "void" "zero all 2"
test_restore_saved_value "intarr1.ihex" "array as value, ihex" \
$array_val "intarray"
test_restore_saved_value "intstr1.ihex" "struct as value, ihex" \
$struct_val "intstruct"
gdb_test "print zero_all ()" "void" "zero all 3"
test_restore_saved_value "intarr2.ihex" "array as memory, ihex" \
$array_val "intarray"
test_restore_saved_value "intstr2.ihex" "struct as memory, ihex" \
$struct_val "intstruct"
gdb_test "print zero_all ()" "void" "zero all 4"
test_restore_saved_value "intarr1.tekhex" "array as value, tekhex" \
$array_val "intarray"
test_restore_saved_value "intstr1.tekhex" "struct as value, tekhex" \
$struct_val "intstruct"
gdb_test "print zero_all ()" "void" "zero all 5"
test_restore_saved_value "intarr2.tekhex" "array as memory, tekhex" \
$array_val "intarray"
test_restore_saved_value "intstr2.tekhex" "struct as memory, tekhex" \
$struct_val "intstruct"
gdb_test "print zero_all ()" "void" "zero all 6"
test_restore_saved_value "intarr1.bin binary $array_start" \
"array as value, binary" \
$array_val "intarray"
test_restore_saved_value "intstr1.bin binary $struct_start" \
"struct as value, binary" \
$struct_val "intstruct"
gdb_test "print zero_all ()" "void" "zero all 7"
test_restore_saved_value "intarr2.bin binary $array_start" \
"array as memory, binary" \
$array_val "intarray"
test_restore_saved_value "intstr2.bin binary $struct_start" \
"struct as memory, binary" \
$struct_val "intstruct"
# test restore with offset.
set array2_start [capture_value "/x &intarray2\[0\]"]
set struct2_start [capture_value "/x &intstruct2"]
set array2_offset \
[capture_value "/x (char *) &intarray2 - (char *) &intarray"]
set struct2_offset \
[capture_value "/x (char *) &intstruct2 - (char *) &intstruct"]
gdb_test "print zero_all ()" "void" "zero all 8"
test_restore_saved_value "intarr1.srec $array2_offset" \
"array copy, srec" \
$array_val "intarray2"
test_restore_saved_value "intstr1.srec $struct2_offset" \
"struct copy, srec" \
$struct_val "intstruct2"
gdb_test "print zero_all ()" "void" "zero all 9"
test_restore_saved_value "intarr1.ihex $array2_offset" \
"array copy, ihex" \
$array_val "intarray2"
test_restore_saved_value "intstr1.ihex $struct2_offset" \
"struct copy, ihex" \
$struct_val "intstruct2"
gdb_test "print zero_all ()" "void" "zero all 10"
test_restore_saved_value "intarr1.tekhex $array2_offset" \
"array copy, tekhex" \
$array_val "intarray2"
test_restore_saved_value "intstr1.tekhex $struct2_offset" \
"struct copy, tekhex" \
$struct_val "intstruct2"
gdb_test "print zero_all ()" "void" "zero all 11"
test_restore_saved_value "intarr1.bin binary $array2_start" \
"array copy, binary" \
$array_val "intarray2"
test_restore_saved_value "intstr1.bin binary $struct2_start" \
"struct copy, binary" \
$struct_val "intstruct2"
#
# test restore with start/stop addresses.
#
# For this purpose, we will restore just the third element of the array,
# and check to see that adjacent elements are not modified.
#
# We will need the address and offset of the third and fourth elements.
#
set element3_start [capture_value "/x &intarray\[3\]"]
set element4_start [capture_value "/x &intarray\[4\]"]
set element3_offset \
[capture_value "/x (char *) &intarray\[3\] - (char *) &intarray\[0\]"]
set element4_offset \
[capture_value "/x (char *) &intarray\[4\] - (char *) &intarray\[0\]"]
gdb_test "print zero_all ()" "void" "zero all 12"
test_restore_saved_value "intarr1.srec 0 $element3_start $element4_start" \
"array partial, srec" \
[capture_value "4"] "intarray\[3\]"
gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 1"
gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 1"
gdb_test "print zero_all ()" "void" "zero all 13"
test_restore_saved_value "intarr1.ihex 0 $element3_start $element4_start" \
"array partial, ihex" \
[capture_value "4"] "intarray\[3\]"
gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 2"
gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 2"
gdb_test "print zero_all ()" "void" "zero all 14"
test_restore_saved_value "intarr1.tekhex 0 $element3_start $element4_start" \
"array partial, tekhex" \
[capture_value "4"] "intarray\[3\]"
gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 3"
gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 3"
gdb_test "print zero_all ()" "void" "zero all 15"
test_restore_saved_value \
"intarr1.bin binary $array_start $element3_offset $element4_offset" \
"array partial, binary" \
[capture_value "4"] "intarray\[3\]"
gdb_test "print intarray\[2\] == 0" " = 1" "element 2 not changed - 4"
gdb_test "print intarray\[4\] == 0" " = 1" "element 4 not changed - 4"
# clean up files
remote_exec build "rm -f intarr1.bin intarr1b.bin intarr1.ihex intarr1.srec intarr1.tekhex intarr2.bin intarr2b.bin intarr2.ihex intarr2.srec intarr2.tekhex intstr1.bin intstr1b.bin intstr1.ihex intstr1.srec intstr1.tekhex intstr2.bin intstr2b.bin intstr2.ihex intstr2.srec intstr2.tekhex"
File: testsuite/gdb.base/dump.c
#define ARRSIZE 32
int intarray[ARRSIZE], intarray2[ARRSIZE];
struct teststruct {
int a;
int b;
int c;
int d;
int e;
int f;
int g;
} intstruct, intstruct2;
void checkpoint1 ()
{
/* intarray and teststruct have been initialized. */
}
void
zero_all ()
{
memset ((char *) &intarray, 0, sizeof (intarray));
memset ((char *) &intarray2, 0, sizeof (intarray2));
memset ((char *) &intstruct, 0, sizeof (intstruct));
memset ((char *) &intstruct2, 0, sizeof (intstruct2));
}
main()
{
int i;
for (i = 0; i < ARRSIZE; i++)
intarray[i] = i+1;
intstruct.a = 12 * 1;
intstruct.b = 12 * 2;
intstruct.c = 12 * 3;
intstruct.d = 12 * 4;
intstruct.e = 12 * 5;
intstruct.f = 12 * 6;
intstruct.g = 12 * 7;
checkpoint1 ();
}