* Makefile.in (SFILES): Add target-memory.c.
(COMMON_OBS): Add target-memory.o. * memattr.c (lookup_mem_region): Adjust handling for the top of memory. Improve comments. * remote.c (packet_check_result): New function, split out from packet_ok. Recognize "E." as an error prefix. (packet_ok): Use it. (remote_write_bytes_aux): New function, renamed from remote_write_bytes. Take packet header, packet format, and length flag as arguments. (remote_write_bytes): Rewrite to use remote_write_bytes_aux. (remote_send_printf, restore_remote_timeout) (remote_flash_timeout, remote_flash_erase, remote_flash_write) (remote_flash_done): New. (remote_xfer_partial): Handle flash writes. (init_remote_ops, init_remote_async_ops): Set to_flash_erase and to_flash_done. * symfile.c (struct load_section_data): Include a pointer to the cumulative stats and a request queue. Move most members to other types. (struct load_progress_data, struct load_progress_section_data): New types. (load_progress): Handle a NULL baton and zero bytes. Update for type changes. (load_section_callback): Create memory write requests instead of writing to memory. Don't print the progress message here. (clear_memory_write_data): New function. (generic_load): Use target_write_memory_blocks. * target-memory.c: New file. * target.c (update_current_target): Mention new uninherited methods. (memory_xfer_partial): Issue an error for flash writes. (target_flash_erase, target_flash_done): New functions. (target_write_with_progress): Call the progress callback at the start also. * target.h (enum target_object): Add TARGET_OBJECT_FLASH. (target_write_with_progress): Update comment. (struct target_ops): Add to_flash_erase and to_flash_done. (target_flash_erase, target_flash_done, struct memory_write_request) (memory_write_request_s, enum flash_preserve_mode) (target_write_memory_blocks): New, including a vector type for memory_write_request_s.
This commit is contained in:
parent
fd79eceebf
commit
a76d924dff
8 changed files with 968 additions and 111 deletions
125
gdb/symfile.c
125
gdb/symfile.c
|
@ -1537,11 +1537,23 @@ add_section_size_callback (bfd *abfd, asection *asec, void *data)
|
|||
/* Opaque data for load_section_callback. */
|
||||
struct load_section_data {
|
||||
unsigned long load_offset;
|
||||
struct load_progress_data *progress_data;
|
||||
VEC(memory_write_request_s) *requests;
|
||||
};
|
||||
|
||||
/* Opaque data for load_progress. */
|
||||
struct load_progress_data {
|
||||
/* Cumulative data. */
|
||||
unsigned long write_count;
|
||||
unsigned long data_count;
|
||||
bfd_size_type total_size;
|
||||
};
|
||||
|
||||
/* Per-section data for load_progress. */
|
||||
/* Opaque data for load_progress for a single section. */
|
||||
struct load_progress_section_data {
|
||||
struct load_progress_data *cumulative;
|
||||
|
||||
/* Per-section data. */
|
||||
const char *section_name;
|
||||
ULONGEST section_sent;
|
||||
ULONGEST section_size;
|
||||
|
@ -1549,12 +1561,30 @@ struct load_section_data {
|
|||
gdb_byte *buffer;
|
||||
};
|
||||
|
||||
/* Target write callback routine for load_section_callback. */
|
||||
/* Target write callback routine for progress reporting. */
|
||||
|
||||
static void
|
||||
load_progress (ULONGEST bytes, void *untyped_arg)
|
||||
{
|
||||
struct load_section_data *args = untyped_arg;
|
||||
struct load_progress_section_data *args = untyped_arg;
|
||||
struct load_progress_data *totals;
|
||||
|
||||
if (args == NULL)
|
||||
/* Writing padding data. No easy way to get at the cumulative
|
||||
stats, so just ignore this. */
|
||||
return;
|
||||
|
||||
totals = args->cumulative;
|
||||
|
||||
if (bytes == 0 && args->section_sent == 0)
|
||||
{
|
||||
/* The write is just starting. Let the user know we've started
|
||||
this section. */
|
||||
ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
|
||||
args->section_name, paddr_nz (args->section_size),
|
||||
paddr_nz (args->lma));
|
||||
return;
|
||||
}
|
||||
|
||||
if (validate_download)
|
||||
{
|
||||
|
@ -1576,10 +1606,10 @@ load_progress (ULONGEST bytes, void *untyped_arg)
|
|||
paddr (args->lma));
|
||||
do_cleanups (verify_cleanups);
|
||||
}
|
||||
args->data_count += bytes;
|
||||
totals->data_count += bytes;
|
||||
args->lma += bytes;
|
||||
args->buffer += bytes;
|
||||
args->write_count += 1;
|
||||
totals->write_count += 1;
|
||||
args->section_sent += bytes;
|
||||
if (quit_flag
|
||||
|| (deprecated_ui_load_progress_hook != NULL
|
||||
|
@ -1591,8 +1621,8 @@ load_progress (ULONGEST bytes, void *untyped_arg)
|
|||
deprecated_show_load_progress (args->section_name,
|
||||
args->section_sent,
|
||||
args->section_size,
|
||||
args->data_count,
|
||||
args->total_size);
|
||||
totals->data_count,
|
||||
totals->total_size);
|
||||
}
|
||||
|
||||
/* Callback service function for generic_load (bfd_map_over_sections). */
|
||||
|
@ -1600,12 +1630,12 @@ load_progress (ULONGEST bytes, void *untyped_arg)
|
|||
static void
|
||||
load_section_callback (bfd *abfd, asection *asec, void *data)
|
||||
{
|
||||
struct memory_write_request *new_request;
|
||||
struct load_section_data *args = data;
|
||||
struct load_progress_section_data *section_data;
|
||||
bfd_size_type size = bfd_get_section_size (asec);
|
||||
gdb_byte *buffer;
|
||||
struct cleanup *old_chain;
|
||||
const char *sect_name = bfd_get_section_name (abfd, asec);
|
||||
LONGEST transferred;
|
||||
|
||||
if ((bfd_get_section_flags (abfd, asec) & SEC_LOAD) == 0)
|
||||
return;
|
||||
|
@ -1613,49 +1643,63 @@ load_section_callback (bfd *abfd, asection *asec, void *data)
|
|||
if (size == 0)
|
||||
return;
|
||||
|
||||
buffer = xmalloc (size);
|
||||
old_chain = make_cleanup (xfree, buffer);
|
||||
new_request = VEC_safe_push (memory_write_request_s,
|
||||
args->requests, NULL);
|
||||
memset (new_request, 0, sizeof (struct memory_write_request));
|
||||
section_data = xcalloc (1, sizeof (struct load_progress_section_data));
|
||||
new_request->begin = bfd_section_lma (abfd, asec) + args->load_offset;
|
||||
new_request->end = new_request->begin + size; /* FIXME Should size be in instead? */
|
||||
new_request->data = xmalloc (size);
|
||||
new_request->baton = section_data;
|
||||
|
||||
args->section_name = sect_name;
|
||||
args->section_sent = 0;
|
||||
args->section_size = size;
|
||||
args->lma = bfd_section_lma (abfd, asec) + args->load_offset;
|
||||
args->buffer = buffer;
|
||||
buffer = new_request->data;
|
||||
|
||||
/* Is this really necessary? I guess it gives the user something
|
||||
to look at during a long download. */
|
||||
ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
|
||||
sect_name, paddr_nz (size), paddr_nz (args->lma));
|
||||
section_data->cumulative = args->progress_data;
|
||||
section_data->section_name = sect_name;
|
||||
section_data->section_size = size;
|
||||
section_data->lma = new_request->begin;
|
||||
section_data->buffer = buffer;
|
||||
|
||||
bfd_get_section_contents (abfd, asec, buffer, 0, size);
|
||||
}
|
||||
|
||||
transferred = target_write_with_progress (¤t_target,
|
||||
TARGET_OBJECT_MEMORY,
|
||||
NULL, buffer, args->lma,
|
||||
size, load_progress, args);
|
||||
if (transferred < size)
|
||||
error (_("Memory access error while loading section %s."),
|
||||
sect_name);
|
||||
/* Clean up an entire memory request vector, including load
|
||||
data and progress records. */
|
||||
|
||||
do_cleanups (old_chain);
|
||||
static void
|
||||
clear_memory_write_data (void *arg)
|
||||
{
|
||||
VEC(memory_write_request_s) **vec_p = arg;
|
||||
VEC(memory_write_request_s) *vec = *vec_p;
|
||||
int i;
|
||||
struct memory_write_request *mr;
|
||||
|
||||
for (i = 0; VEC_iterate (memory_write_request_s, vec, i, mr); ++i)
|
||||
{
|
||||
xfree (mr->data);
|
||||
xfree (mr->baton);
|
||||
}
|
||||
VEC_free (memory_write_request_s, vec);
|
||||
}
|
||||
|
||||
void
|
||||
generic_load (char *args, int from_tty)
|
||||
{
|
||||
asection *s;
|
||||
bfd *loadfile_bfd;
|
||||
struct timeval start_time, end_time;
|
||||
char *filename;
|
||||
struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
|
||||
struct load_section_data cbdata;
|
||||
struct load_progress_data total_progress;
|
||||
|
||||
CORE_ADDR entry;
|
||||
char **argv;
|
||||
|
||||
cbdata.load_offset = 0; /* Offset to add to vma for each section. */
|
||||
cbdata.write_count = 0; /* Number of writes needed. */
|
||||
cbdata.data_count = 0; /* Number of bytes written to target memory. */
|
||||
cbdata.total_size = 0; /* Total size of all bfd sectors. */
|
||||
memset (&cbdata, 0, sizeof (cbdata));
|
||||
memset (&total_progress, 0, sizeof (total_progress));
|
||||
cbdata.progress_data = &total_progress;
|
||||
|
||||
make_cleanup (clear_memory_write_data, &cbdata.requests);
|
||||
|
||||
argv = buildargv (args);
|
||||
|
||||
|
@ -1702,11 +1746,15 @@ generic_load (char *args, int from_tty)
|
|||
}
|
||||
|
||||
bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
|
||||
(void *) &cbdata.total_size);
|
||||
(void *) &total_progress.total_size);
|
||||
|
||||
bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
|
||||
|
||||
gettimeofday (&start_time, NULL);
|
||||
|
||||
bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
|
||||
if (target_write_memory_blocks (cbdata.requests, flash_discard,
|
||||
load_progress) != 0)
|
||||
error (_("Load failed"));
|
||||
|
||||
gettimeofday (&end_time, NULL);
|
||||
|
||||
|
@ -1714,7 +1762,7 @@ generic_load (char *args, int from_tty)
|
|||
ui_out_text (uiout, "Start address ");
|
||||
ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry));
|
||||
ui_out_text (uiout, ", load size ");
|
||||
ui_out_field_fmt (uiout, "load-size", "%lu", cbdata.data_count);
|
||||
ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count);
|
||||
ui_out_text (uiout, "\n");
|
||||
/* We were doing this in remote-mips.c, I suspect it is right
|
||||
for other targets too. */
|
||||
|
@ -1726,8 +1774,9 @@ generic_load (char *args, int from_tty)
|
|||
file is loaded in. Some targets do (e.g., remote-vx.c) but
|
||||
others don't (or didn't - perhaps they have all been deleted). */
|
||||
|
||||
print_transfer_performance (gdb_stdout, cbdata.data_count,
|
||||
cbdata.write_count, &start_time, &end_time);
|
||||
print_transfer_performance (gdb_stdout, total_progress.data_count,
|
||||
total_progress.write_count,
|
||||
&start_time, &end_time);
|
||||
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue