2002-01-15 Michael Snyder <msnyder@redhat.com>
* symfile.c (generic_load): Use bfd_map_over_sections method instead of manipulating bfd structure members directly. (add_section_size_callback): New function, bfd sections callback used by generic_load. (load_sections_callback): New function, bfd sections callback used by generic_load.
This commit is contained in:
parent
08cf96df0e
commit
e4f9b4d584
|
@ -1,3 +1,12 @@
|
||||||
|
2002-01-15 Michael Snyder <msnyder@redhat.com>
|
||||||
|
|
||||||
|
* symfile.c (generic_load): Use bfd_map_over_sections method
|
||||||
|
instead of manipulating bfd structure members directly.
|
||||||
|
(add_section_size_callback): New function, bfd sections callback
|
||||||
|
used by generic_load.
|
||||||
|
(load_sections_callback): New function, bfd sections callback
|
||||||
|
used by generic_load.
|
||||||
|
|
||||||
2002-01-15 Elena Zannoni <ezannoni@redhat.com>
|
2002-01-15 Elena Zannoni <ezannoni@redhat.com>
|
||||||
|
|
||||||
[Based on work by Jim Blandy]
|
[Based on work by Jim Blandy]
|
||||||
|
|
265
gdb/symfile.c
265
gdb/symfile.c
|
@ -1174,19 +1174,139 @@ load_command (char *arg, int from_tty)
|
||||||
static int download_write_size = 512;
|
static int download_write_size = 512;
|
||||||
static int validate_download = 0;
|
static int validate_download = 0;
|
||||||
|
|
||||||
|
/* Callback service function for generic_load (bfd_map_over_sections). */
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_section_size_callback (bfd *abfd, asection *asec, void *data)
|
||||||
|
{
|
||||||
|
bfd_size_type *sum = data;
|
||||||
|
|
||||||
|
*sum += bfd_get_section_size_before_reloc (asec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Opaque data for load_section_callback. */
|
||||||
|
struct load_section_data {
|
||||||
|
unsigned long load_offset;
|
||||||
|
unsigned long write_count;
|
||||||
|
unsigned long data_count;
|
||||||
|
bfd_size_type total_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Callback service function for generic_load (bfd_map_over_sections). */
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_section_callback (bfd *abfd, asection *asec, void *data)
|
||||||
|
{
|
||||||
|
struct load_section_data *args = data;
|
||||||
|
|
||||||
|
if (bfd_get_section_flags (abfd, asec) & SEC_LOAD)
|
||||||
|
{
|
||||||
|
bfd_size_type size = bfd_get_section_size_before_reloc (asec);
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
char *buffer;
|
||||||
|
struct cleanup *old_chain;
|
||||||
|
CORE_ADDR lma = bfd_section_lma (abfd, asec) + args->load_offset;
|
||||||
|
bfd_size_type block_size;
|
||||||
|
int err;
|
||||||
|
const char *sect_name = bfd_get_section_name (abfd, asec);
|
||||||
|
bfd_size_type sent;
|
||||||
|
|
||||||
|
if (download_write_size > 0 && size > download_write_size)
|
||||||
|
block_size = download_write_size;
|
||||||
|
else
|
||||||
|
block_size = size;
|
||||||
|
|
||||||
|
buffer = xmalloc (size);
|
||||||
|
old_chain = make_cleanup (xfree, buffer);
|
||||||
|
|
||||||
|
/* Is this really necessary? I guess it gives the user something
|
||||||
|
to look at during a long download. */
|
||||||
|
#ifdef UI_OUT
|
||||||
|
ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
|
||||||
|
sect_name, paddr_nz (size), paddr_nz (lma));
|
||||||
|
#else
|
||||||
|
fprintf_unfiltered (gdb_stdout,
|
||||||
|
"Loading section %s, size 0x%s lma 0x%s\n",
|
||||||
|
sect_name, paddr_nz (size), paddr_nz (lma));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bfd_get_section_contents (abfd, asec, buffer, 0, size);
|
||||||
|
|
||||||
|
sent = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
bfd_size_type this_transfer = size - sent;
|
||||||
|
|
||||||
|
if (this_transfer >= block_size)
|
||||||
|
this_transfer = block_size;
|
||||||
|
len = target_write_memory_partial (lma, buffer,
|
||||||
|
this_transfer, &err);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
if (validate_download)
|
||||||
|
{
|
||||||
|
/* Broken memories and broken monitors manifest
|
||||||
|
themselves here when bring new computers to
|
||||||
|
life. This doubles already slow downloads. */
|
||||||
|
/* NOTE: cagney/1999-10-18: A more efficient
|
||||||
|
implementation might add a verify_memory()
|
||||||
|
method to the target vector and then use
|
||||||
|
that. remote.c could implement that method
|
||||||
|
using the ``qCRC'' packet. */
|
||||||
|
char *check = xmalloc (len);
|
||||||
|
struct cleanup *verify_cleanups =
|
||||||
|
make_cleanup (xfree, check);
|
||||||
|
|
||||||
|
if (target_read_memory (lma, check, len) != 0)
|
||||||
|
error ("Download verify read failed at 0x%s",
|
||||||
|
paddr (lma));
|
||||||
|
if (memcmp (buffer, check, len) != 0)
|
||||||
|
error ("Download verify compare failed at 0x%s",
|
||||||
|
paddr (lma));
|
||||||
|
do_cleanups (verify_cleanups);
|
||||||
|
}
|
||||||
|
args->data_count += len;
|
||||||
|
lma += len;
|
||||||
|
buffer += len;
|
||||||
|
args->write_count += 1;
|
||||||
|
sent += len;
|
||||||
|
if (quit_flag
|
||||||
|
|| (ui_load_progress_hook != NULL
|
||||||
|
&& ui_load_progress_hook (sect_name, sent)))
|
||||||
|
error ("Canceled the download");
|
||||||
|
|
||||||
|
if (show_load_progress != NULL)
|
||||||
|
show_load_progress (sect_name, sent, size,
|
||||||
|
args->data_count, args->total_size);
|
||||||
|
}
|
||||||
|
while (sent < size);
|
||||||
|
|
||||||
|
if (err != 0)
|
||||||
|
error ("Memory access error while loading section %s.", sect_name);
|
||||||
|
|
||||||
|
do_cleanups (old_chain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
generic_load (char *args, int from_tty)
|
generic_load (char *args, int from_tty)
|
||||||
{
|
{
|
||||||
asection *s;
|
asection *s;
|
||||||
bfd *loadfile_bfd;
|
bfd *loadfile_bfd;
|
||||||
time_t start_time, end_time; /* Start and end times of download */
|
time_t start_time, end_time; /* Start and end times of download */
|
||||||
unsigned long data_count = 0; /* Number of bytes transferred to memory */
|
|
||||||
unsigned long write_count = 0; /* Number of writes needed. */
|
|
||||||
unsigned long load_offset; /* offset to add to vma for each section */
|
|
||||||
char *filename;
|
char *filename;
|
||||||
struct cleanup *old_cleanups;
|
struct cleanup *old_cleanups;
|
||||||
char *offptr;
|
char *offptr;
|
||||||
bfd_size_type total_size = 0;
|
struct load_section_data cbdata;
|
||||||
|
CORE_ADDR entry;
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
/* Parse the input argument - the user can specify a load offset as
|
/* Parse the input argument - the user can specify a load offset as
|
||||||
a second argument. */
|
a second argument. */
|
||||||
|
@ -1198,13 +1318,13 @@ generic_load (char *args, int from_tty)
|
||||||
{
|
{
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
load_offset = strtoul (offptr, &endptr, 0);
|
cbdata.load_offset = strtoul (offptr, &endptr, 0);
|
||||||
if (offptr == endptr)
|
if (offptr == endptr)
|
||||||
error ("Invalid download offset:%s\n", offptr);
|
error ("Invalid download offset:%s\n", offptr);
|
||||||
*offptr = '\0';
|
*offptr = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
load_offset = 0;
|
cbdata.load_offset = 0;
|
||||||
|
|
||||||
/* Open the file for loading. */
|
/* Open the file for loading. */
|
||||||
loadfile_bfd = bfd_openr (filename, gnutarget);
|
loadfile_bfd = bfd_openr (filename, gnutarget);
|
||||||
|
@ -1225,129 +1345,30 @@ generic_load (char *args, int from_tty)
|
||||||
bfd_errmsg (bfd_get_error ()));
|
bfd_errmsg (bfd_get_error ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s = loadfile_bfd->sections; s; s = s->next)
|
bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
|
||||||
if (bfd_get_section_flags (loadfile_bfd, s) & SEC_LOAD)
|
(void *) &cbdata.total_size);
|
||||||
total_size += bfd_get_section_size_before_reloc (s);
|
|
||||||
|
|
||||||
start_time = time (NULL);
|
start_time = time (NULL);
|
||||||
|
|
||||||
for (s = loadfile_bfd->sections; s; s = s->next)
|
bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
|
||||||
{
|
|
||||||
if (s->flags & SEC_LOAD)
|
|
||||||
{
|
|
||||||
bfd_size_type size = bfd_get_section_size_before_reloc (s);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
struct cleanup *old_chain;
|
|
||||||
CORE_ADDR lma = bfd_section_lma (loadfile_bfd, s) + load_offset;
|
|
||||||
bfd_size_type block_size;
|
|
||||||
int err;
|
|
||||||
const char *sect_name = bfd_get_section_name (loadfile_bfd, s);
|
|
||||||
bfd_size_type sent;
|
|
||||||
|
|
||||||
if (download_write_size > 0 && size > download_write_size)
|
|
||||||
block_size = download_write_size;
|
|
||||||
else
|
|
||||||
block_size = size;
|
|
||||||
|
|
||||||
buffer = xmalloc (size);
|
|
||||||
old_chain = make_cleanup (xfree, buffer);
|
|
||||||
|
|
||||||
/* Is this really necessary? I guess it gives the user something
|
|
||||||
to look at during a long download. */
|
|
||||||
#ifdef UI_OUT
|
|
||||||
ui_out_message (uiout, 0,
|
|
||||||
"Loading section %s, size 0x%s lma 0x%s\n",
|
|
||||||
sect_name, paddr_nz (size), paddr_nz (lma));
|
|
||||||
#else
|
|
||||||
fprintf_unfiltered (gdb_stdout,
|
|
||||||
"Loading section %s, size 0x%s lma 0x%s\n",
|
|
||||||
sect_name, paddr_nz (size), paddr_nz (lma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
|
|
||||||
|
|
||||||
sent = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
bfd_size_type this_transfer = size - sent;
|
|
||||||
|
|
||||||
if (this_transfer >= block_size)
|
|
||||||
this_transfer = block_size;
|
|
||||||
len = target_write_memory_partial (lma, buffer,
|
|
||||||
this_transfer, &err);
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
if (validate_download)
|
|
||||||
{
|
|
||||||
/* Broken memories and broken monitors manifest
|
|
||||||
themselves here when bring new computers to
|
|
||||||
life. This doubles already slow downloads. */
|
|
||||||
/* NOTE: cagney/1999-10-18: A more efficient
|
|
||||||
implementation might add a verify_memory()
|
|
||||||
method to the target vector and then use
|
|
||||||
that. remote.c could implement that method
|
|
||||||
using the ``qCRC'' packet. */
|
|
||||||
char *check = xmalloc (len);
|
|
||||||
struct cleanup *verify_cleanups = make_cleanup (xfree,
|
|
||||||
check);
|
|
||||||
|
|
||||||
if (target_read_memory (lma, check, len) != 0)
|
|
||||||
error ("Download verify read failed at 0x%s",
|
|
||||||
paddr (lma));
|
|
||||||
if (memcmp (buffer, check, len) != 0)
|
|
||||||
error ("Download verify compare failed at 0x%s",
|
|
||||||
paddr (lma));
|
|
||||||
do_cleanups (verify_cleanups);
|
|
||||||
}
|
|
||||||
data_count += len;
|
|
||||||
lma += len;
|
|
||||||
buffer += len;
|
|
||||||
write_count += 1;
|
|
||||||
sent += len;
|
|
||||||
if (quit_flag
|
|
||||||
|| (ui_load_progress_hook != NULL
|
|
||||||
&& ui_load_progress_hook (sect_name, sent)))
|
|
||||||
error ("Canceled the download");
|
|
||||||
|
|
||||||
if (show_load_progress != NULL)
|
|
||||||
show_load_progress (sect_name, sent, size,
|
|
||||||
data_count, total_size);
|
|
||||||
}
|
|
||||||
while (sent < size);
|
|
||||||
|
|
||||||
if (err != 0)
|
|
||||||
error ("Memory access error while loading section %s.",
|
|
||||||
sect_name);
|
|
||||||
|
|
||||||
do_cleanups (old_chain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end_time = time (NULL);
|
end_time = time (NULL);
|
||||||
{
|
|
||||||
CORE_ADDR entry = bfd_get_start_address (loadfile_bfd);
|
|
||||||
|
|
||||||
|
entry = bfd_get_start_address (loadfile_bfd);
|
||||||
#ifdef UI_OUT
|
#ifdef UI_OUT
|
||||||
ui_out_text (uiout, "Start address ");
|
ui_out_text (uiout, "Start address ");
|
||||||
ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry));
|
ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry));
|
||||||
ui_out_text (uiout, ", load size ");
|
ui_out_text (uiout, ", load size ");
|
||||||
ui_out_field_fmt (uiout, "load-size", "%lu", data_count);
|
ui_out_field_fmt (uiout, "load-size", "%lu", cbdata.data_count);
|
||||||
ui_out_text (uiout, "\n");
|
ui_out_text (uiout, "\n");
|
||||||
|
|
||||||
#else
|
#else
|
||||||
fprintf_unfiltered (gdb_stdout,
|
fprintf_unfiltered (gdb_stdout,
|
||||||
"Start address 0x%s, load size %lu\n",
|
"Start address 0x%s, load size %lu\n",
|
||||||
paddr_nz (entry), data_count);
|
paddr_nz (entry), cbdata.data_count);
|
||||||
#endif
|
#endif
|
||||||
/* We were doing this in remote-mips.c, I suspect it is right
|
/* We were doing this in remote-mips.c, I suspect it is right
|
||||||
for other targets too. */
|
for other targets too. */
|
||||||
write_pc (entry);
|
write_pc (entry);
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: are we supposed to call symbol_file_add or not? According to
|
/* FIXME: are we supposed to call symbol_file_add or not? According to
|
||||||
a comment from remote-mips.c (where a call to symbol_file_add was
|
a comment from remote-mips.c (where a call to symbol_file_add was
|
||||||
|
@ -1355,8 +1376,8 @@ generic_load (char *args, int from_tty)
|
||||||
loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c
|
loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c
|
||||||
does. */
|
does. */
|
||||||
|
|
||||||
print_transfer_performance (gdb_stdout, data_count, write_count,
|
print_transfer_performance (gdb_stdout, cbdata.data_count,
|
||||||
end_time - start_time);
|
cbdata.write_count, end_time - start_time);
|
||||||
|
|
||||||
do_cleanups (old_cleanups);
|
do_cleanups (old_cleanups);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue