/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998
- Free Software Foundation, Inc.
+ Copyright 1990-1996, 1998, 2000 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
This file is part of GDB.
} while (0)
#endif
-int (*ui_load_progress_hook) PARAMS ((char *, unsigned long));
+int (*ui_load_progress_hook) (const char *section, unsigned long num);
+void (*show_load_progress) (const char *section,
+ unsigned long section_sent,
+ unsigned long section_size,
+ unsigned long total_sent,
+ unsigned long total_size);
void (*pre_add_symbol_hook) PARAMS ((char *));
void (*post_add_symbol_hook) PARAMS ((void));
+void (*target_new_objfile_hook) PARAMS ((struct objfile *));
/* Global variables owned by this file */
int readnow_symbol_files; /* Read full symbols immediately */
"Empty symbol table found for `%s'", 0, 0
};
+struct complaint unknown_option_complaint =
+{
+ "Unknown option `%s' ignored", 0, 0
+};
+
/* External variables and functions referenced. */
extern int info_verbose;
for the objectfile OBJFILE and stuffs ADDR into all of the offsets. */
void
-default_symfile_offsets (objfile, addr)
+default_symfile_offsets (objfile, addrs)
struct objfile *objfile;
- CORE_ADDR addr;
+ struct section_addr_info *addrs;
{
int i;
obstack_alloc (&objfile->psymbol_obstack, SIZEOF_SECTION_OFFSETS);
memset (objfile->section_offsets, 0, SIZEOF_SECTION_OFFSETS);
- for (i = 0; i < SECT_OFF_MAX; i++)
- ANOFFSET (objfile->section_offsets, i) = addr;
+ /* If user explicitly specified values for data and bss, set them here. */
+
+ if (addrs->text_addr)
+ ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT) = addrs->text_addr;
+ if (addrs->data_addr)
+ ANOFFSET (objfile->section_offsets, SECT_OFF_DATA) = addrs->data_addr;
+ if (addrs->bss_addr)
+ ANOFFSET (objfile->section_offsets, SECT_OFF_BSS) = addrs->bss_addr;
+
+ /* Now calculate offsets for other sections. */
+ for (i = 0; i < MAX_SECTIONS && addrs->other[i].name; i++)
+ {
+ struct other_sections *osp ;
+
+ osp = &addrs->other[i] ;
+ if (addrs->other[i].addr == 0)
+ continue;
+#if 0
+ if (strcmp (".text", osp->name) == 0)
+ SECT_OFF_TEXT = osp->sectindex ;
+ else if (strcmp (".data", osp->name) == 0)
+ SECT_OFF_DATA = osp->sectindex ;
+ else if (strcmp (".bss", osp->name) == 0)
+ SECT_OFF_BSS = osp->sectindex ;
+#endif
+ /* Record all sections in offsets */
+ ANOFFSET (objfile->section_offsets, osp->sectindex) = osp->addr;
+ }
}
the symbol reading (and complaints can be more terse about it). */
void
-syms_from_objfile (objfile, addr, mainline, verbo)
+syms_from_objfile (objfile, addrs, mainline, verbo)
struct objfile *objfile;
- CORE_ADDR addr;
+ struct section_addr_info *addrs;
int mainline;
int verbo;
{
struct section_offsets *section_offsets;
- asection *lowest_sect;
+ asection *lower_sect;
+ asection *sect;
+ CORE_ADDR lower_offset;
+ struct section_addr_info local_addr;
struct cleanup *old_chain;
+ int i;
+
+ /* If ADDRS is NULL, initialize the local section_addr_info struct and
+ point ADDRS to it. We now establish the convention that an addr of
+ zero means no load address was specified. */
+
+ if (addrs == NULL)
+ {
+ memset (&local_addr, 0, sizeof (local_addr));
+ addrs = &local_addr;
+ }
init_entry_point_info (objfile);
find_sym_fns (objfile);
happens for the PA64 port. */
if (mainline)
{
- addr = 0; /* No offset from objfile addresses. */
+ /* No offset from objfile addresses. */
+ addrs -> text_addr = 0;
+ addrs -> data_addr = 0;
+ addrs -> bss_addr = 0;
}
else
{
- lowest_sect = bfd_get_section_by_name (objfile->obfd, ".text");
- if (lowest_sect == NULL)
+ /* Find lowest loadable section to be used as starting point for
+ continguous sections. FIXME!! won't work without call to find
+ .text first, but this assumes text is lowest section. */
+ lower_sect = bfd_get_section_by_name (objfile->obfd, ".text");
+ if (lower_sect == NULL)
bfd_map_over_sections (objfile->obfd, find_lowest_section,
- (PTR) &lowest_sect);
-
- if (lowest_sect == NULL)
+ (PTR) &lower_sect);
+ if (lower_sect == NULL)
warning ("no loadable sections found in added symbol-file %s",
objfile->name);
-
- if (lowest_sect)
- addr -= bfd_section_vma (objfile->obfd, lowest_sect);
+ else if ((bfd_get_section_flags (objfile->obfd, lower_sect) & SEC_CODE)
+ == 0)
+ warning ("Lowest section in %s is %s at %s",
+ objfile->name,
+ bfd_section_name (objfile->obfd, lower_sect),
+ paddr (bfd_section_vma (objfile->obfd, lower_sect)));
+ if (lower_sect != NULL)
+ lower_offset = bfd_section_vma (objfile->obfd, lower_sect);
+ else
+ lower_offset = 0;
+
+ /* Calculate offsets for the loadable sections.
+ FIXME! Sections must be in order of increasing loadable section
+ so that contiguous sections can use the lower-offset!!!
+
+ Adjust offsets if the segments are not contiguous.
+ If the section is contiguous, its offset should be set to
+ the offset of the highest loadable section lower than it
+ (the loadable section directly below it in memory).
+ this_offset = lower_offset = lower_addr - lower_orig_addr */
+
+ /* FIXME: These sections will not need special treatment because ALL
+ sections are in the other sections table */
+
+ if (addrs->text_addr != 0)
+ {
+ sect = bfd_get_section_by_name (objfile->obfd, ".text");
+ if (sect)
+ {
+ addrs->text_addr -= bfd_section_vma (objfile->obfd, sect);
+ lower_offset = addrs->text_addr;
+ }
+ }
+ else
+ /* ??? who's below me? */
+ addrs->text_addr = lower_offset;
+
+ if (addrs->data_addr != 0)
+ {
+ sect = bfd_get_section_by_name (objfile->obfd, ".data");
+ if (sect)
+ {
+ addrs->data_addr -= bfd_section_vma (objfile->obfd, sect);
+ lower_offset = addrs->data_addr;
+ }
+ }
+ else
+ addrs->data_addr = lower_offset;
+
+ if (addrs->bss_addr != 0)
+ {
+ sect = bfd_get_section_by_name (objfile->obfd, ".bss");
+ if (sect)
+ {
+ addrs->bss_addr -= bfd_section_vma (objfile->obfd, sect);
+ lower_offset = addrs->bss_addr;
+ }
+ }
+ else
+ addrs->bss_addr = lower_offset;
+
+ /* Now calculate offsets for other sections. */
+ for (i=0 ; i < MAX_SECTIONS && addrs->other[i].name; i++)
+ {
+
+ if (addrs->other[i].addr != 0)
+ {
+ sect=bfd_get_section_by_name(objfile->obfd, addrs->other[i].name);
+ if (sect)
+ {
+ addrs->other[i].addr -= bfd_section_vma (objfile->obfd, sect);
+ lower_offset = addrs->other[i].addr;
+ addrs->other[i].sectindex = sect->index ;
+ }
+ else
+ {
+ warning ("section %s not found in %s", addrs->other[i].name,
+ objfile->name);
+ addrs->other[i].addr = 0;
+ }
+ }
+ else
+ addrs->other[i].addr = lower_offset;
+ }
}
/* Initialize symbol reading routines for this objfile, allow complaints to
(*objfile->sf->sym_init) (objfile);
clear_complaints (1, verbo);
- (*objfile->sf->sym_offsets) (objfile, addr);
+ (*objfile->sf->sym_offsets) (objfile, addrs);
#ifndef IBM6000_TARGET
/* This is a SVR4/SunOS specific hack, I think. In any event, it
These should probably all be collapsed into some target
independent form of shared library support. FIXME. */
- if (addr)
+ if (addrs)
{
struct obj_section *s;
+ /* Map section offsets in "addr" back to the object's
+ sections by comparing the section names with bfd's
+ section names. Then adjust the section address by
+ the offset. */ /* for gdb/13815 */
+
ALL_OBJFILE_OSECTIONS (objfile, s)
{
+ CORE_ADDR s_addr = 0;
+ int i;
+
+ if (strcmp (s->the_bfd_section->name, ".text") == 0)
+ s_addr = addrs->text_addr;
+ else if (strcmp (s->the_bfd_section->name, ".data") == 0)
+ s_addr = addrs->data_addr;
+ else if (strcmp (s->the_bfd_section->name, ".bss") == 0)
+ s_addr = addrs->bss_addr;
+ else
+ for (i = 0; !s_addr && addrs->other[i].name; i++)
+ if (strcmp (s->the_bfd_section->name, addrs->other[i].name) == 0)
+ s_addr = addrs->other[i].addr; /* end added for gdb/13815 */
+
s->addr -= s->offset;
- s->addr += addr;
+ s->addr += s_addr;
s->endaddr -= s->offset;
- s->endaddr += addr;
- s->offset += addr;
+ s->endaddr += s_addr;
+ s->offset += s_addr;
}
}
#endif /* not IBM6000_TARGET */
as dynamically loaded code. If !mainline, ADDR is the address
where the text segment was loaded.
- USER_LOADED is TRUE if the add-symbol-file command was how this
- symbol file came to be processed.
-
- IS_SOLIB is TRUE if this symbol file represents a solib, as discovered
- by the target's implementation of the solib package.
-
Upon success, returns a pointer to the objfile that was added.
Upon failure, jumps back to command level (never returns). */
struct objfile *
-symbol_file_add (name, from_tty, addr, mainline, mapped, readnow, user_loaded, is_solib)
+symbol_file_add (name, from_tty, addrs, mainline, flags)
char *name;
int from_tty;
- CORE_ADDR addr;
+ struct section_addr_info *addrs;
int mainline;
- int mapped;
- int readnow;
- int user_loaded;
- int is_solib;
+ int flags;
{
struct objfile *objfile;
struct partial_symtab *psymtab;
&& !query ("Load new symbol table from \"%s\"? ", name))
error ("Not confirmed.");
- objfile = allocate_objfile (abfd, mapped, user_loaded, is_solib);
+ objfile = allocate_objfile (abfd, flags);
/* If the objfile uses a mapped symbol file, and we have a psymtab for
it, then skip reading any symbols at this time. */
gdb_flush (gdb_stdout);
}
}
- syms_from_objfile (objfile, addr, mainline, from_tty);
+ syms_from_objfile (objfile, addrs, mainline, from_tty);
}
/* We now have at least a partial symbol table. Check to see if the
the gdb startup command line or on a per symbol file basis. Expand
all partial symbol tables for this objfile if so. */
- if (readnow || readnow_symbol_files)
+ if ((flags & OBJF_READNOW) || readnow_symbol_files)
{
if (from_tty || info_verbose)
{
new_symfile_objfile (objfile, mainline, from_tty);
- target_new_objfile (objfile);
+ if (target_new_objfile_hook)
+ target_new_objfile_hook (objfile);
return (objfile);
}
char *name = NULL;
CORE_ADDR text_relocation = 0; /* text_relocation */
struct cleanup *cleanups;
- int mapped = 0;
- int readnow = 0;
+ int flags = OBJF_USERLOADED;
dont_repeat ();
{
if (STREQ (*argv, "-mapped"))
{
- mapped = 1;
+ flags |= OBJF_MAPPED;
}
else if (STREQ (*argv, "-readnow"))
{
- readnow = 1;
+ flags |= OBJF_READNOW;
}
else if (**argv == '-')
{
return;
else if (text_relocation == (CORE_ADDR) -1)
{
- symbol_file_add (name, from_tty, (CORE_ADDR) 0,
- 1, mapped, readnow, 1, 0);
+ symbol_file_add (name, from_tty, NULL, 1, flags);
#ifdef HPUXHPPA
RESET_HP_UX_GLOBALS ();
#endif
}
else
- symbol_file_add (name, from_tty, (CORE_ADDR) text_relocation,
- 0, mapped, readnow, 1, 0);
+ {
+ struct section_addr_info section_addrs;
+ memset (§ion_addrs, 0, sizeof (section_addrs));
+ section_addrs.text_addr = (CORE_ADDR) text_relocation;
+ symbol_file_add (name, from_tty, §ion_addrs, 0, flags);
+ }
/* Getting new symbols may change our opinion about what is
frameless. */
to worry about finding it, and (b) On VMS, fork() is very slow and so
we don't want to run a subprocess. On the other hand, I'm not sure how
performance compares. */
-#define GENERIC_LOAD_CHUNK 256
-#define VALIDATE_DOWNLOAD 0
+
+static int download_write_size = 512;
+static int validate_download = 0;
+
void
-generic_load (filename, from_tty)
- char *filename;
- int from_tty;
+generic_load (char *args, int from_tty)
{
- struct cleanup *old_cleanups;
asection *s;
bfd *loadfile_bfd;
time_t start_time, end_time; /* Start and end times of download */
unsigned long data_count = 0; /* Number of bytes transferred to memory */
- int n;
- unsigned long load_offset = 0; /* offset to add to vma for each section */
- char buf[GENERIC_LOAD_CHUNK + 8];
-#if VALIDATE_DOWNLOAD
- char verify_buffer[GENERIC_LOAD_CHUNK + 8];
-#endif
-
- /* enable user to specify address for downloading as 2nd arg to load */
- n = sscanf (filename, "%s 0x%lx", buf, &load_offset);
- if (n > 1)
- filename = buf;
+ unsigned long write_count = 0; /* Number of writes needed. */
+ unsigned long load_offset; /* offset to add to vma for each section */
+ char *filename;
+ struct cleanup *old_cleanups;
+ char *offptr;
+ CORE_ADDR total_size = 0;
+ CORE_ADDR total_sent = 0;
+
+ /* Parse the input argument - the user can specify a load offset as
+ a second argument. */
+ filename = xmalloc (strlen (args) + 1);
+ old_cleanups = make_cleanup (free, filename);
+ strcpy (filename, args);
+ offptr = strchr (filename, ' ');
+ if (offptr != NULL)
+ {
+ char *endptr;
+ load_offset = strtoul (offptr, &endptr, 0);
+ if (offptr == endptr)
+ error ("Invalid download offset:%s\n", offptr);
+ *offptr = '\0';
+ }
else
load_offset = 0;
+ /* Open the file for loading. */
loadfile_bfd = bfd_openr (filename, gnutarget);
if (loadfile_bfd == NULL)
{
perror_with_name (filename);
return;
}
+
/* FIXME: should be checking for errors from bfd_close (for one thing,
on error it does not free all the storage associated with the
bfd). */
- old_cleanups = make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd);
+ make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd);
if (!bfd_check_format (loadfile_bfd, bfd_object))
{
bfd_errmsg (bfd_get_error ()));
}
+ for (s = loadfile_bfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ total_size += bfd_get_section_size_before_reloc (s);
+
start_time = time (NULL);
for (s = loadfile_bfd->sections; s; s = s->next)
{
if (s->flags & SEC_LOAD)
{
- bfd_size_type size;
-
- size = bfd_get_section_size_before_reloc (s);
+ CORE_ADDR size = bfd_get_section_size_before_reloc (s);
if (size > 0)
{
char *buffer;
struct cleanup *old_chain;
- bfd_vma lma;
- unsigned long l = size;
+ CORE_ADDR lma = s->lma + load_offset;
+ CORE_ADDR block_size;
int err;
- char *sect;
- unsigned long sent;
- unsigned long len;
+ const char *sect_name = bfd_get_section_name (loadfile_bfd, s);
+ CORE_ADDR sent;
- l = l > GENERIC_LOAD_CHUNK ? GENERIC_LOAD_CHUNK : l;
+ 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 (free, buffer);
- lma = s->lma;
- lma += load_offset;
-
/* Is this really necessary? I guess it gives the user something
to look at during a long download. */
- printf_filtered ("Loading section %s, size 0x%lx lma ",
- bfd_get_section_name (loadfile_bfd, s),
- (unsigned long) size);
- print_address_numeric (lma, 1, gdb_stdout);
- printf_filtered ("\n");
+#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);
- sect = (char *) bfd_get_section_name (loadfile_bfd, s);
sent = 0;
do
{
- len = (size - sent) < l ? (size - sent) : l;
- sent += len;
- err = target_write_memory (lma, buffer, len);
- if (ui_load_progress_hook)
- if (ui_load_progress_hook (sect, sent))
- error ("Canceled the download");
-#if VALIDATE_DOWNLOAD
- /* Broken memories and broken monitors manifest themselves
- here when bring new computers to life.
- This doubles already slow downloads.
- */
+ CORE_ADDR len;
+ CORE_ADDR 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;
- {
- target_read_memory (lma, verify_buffer, len);
- if (0 != bcmp (buffer, verify_buffer, len))
- error ("Download verify failed at %08x",
- (unsigned long) lma);
- }
-
-#endif
+ 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 (free, 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;
- } /* od */
- while (err == 0 && sent < size);
+ write_count += 1;
+ sent += len;
+ total_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, total_sent, total_size);
+ }
+ while (sent < size);
if (err != 0)
- error ("Memory access error while loading section %s.",
- bfd_get_section_name (loadfile_bfd, s));
+ error ("Memory access error while loading section %s.", sect_name);
do_cleanups (old_chain);
}
end_time = time (NULL);
{
- unsigned long entry;
+ CORE_ADDR entry;
entry = bfd_get_start_address (loadfile_bfd);
- printf_filtered ("Start address 0x%lx , load size %ld\n", entry, data_count);
+#ifdef UI_OUT
+ 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", "%ld" , data_count);
+ ui_out_text (uiout, "\n");
+
+#else
+ fprintf_unfiltered (gdb_stdout,
+ "Start address 0x%s , load size %ld\n",
+ paddr_nz (entry), data_count);
+#endif
/* We were doing this in remote-mips.c, I suspect it is right
for other targets too. */
write_pc (entry);
loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c
does. */
- report_transfer_performance (data_count, start_time, end_time);
+ print_transfer_performance (gdb_stdout, data_count, write_count,
+ end_time - start_time);
do_cleanups (old_cleanups);
}
/* Report how fast the transfer went. */
+/* DEPRECATED: cagney/1999-10-18: report_transfer_performance is being
+ replaced by print_transfer_performance (with a very different
+ function signature). */
+
void
report_transfer_performance (data_count, start_time, end_time)
unsigned long data_count;
time_t start_time, end_time;
{
- printf_filtered ("Transfer rate: ");
- if (end_time != start_time)
- printf_filtered ("%ld bits/sec",
- (data_count * 8) / (end_time - start_time));
+ print_transfer_performance (gdb_stdout, data_count, end_time - start_time, 0);
+}
+
+void
+print_transfer_performance (struct ui_file *stream,
+ unsigned long data_count,
+ unsigned long write_count,
+ unsigned long time_count)
+{
+#ifdef UI_OUT
+ ui_out_text (uiout, "Transfer rate: ");
+ if (time_count > 0)
+ {
+ ui_out_field_fmt (uiout, "transfer-rate", "%ld",
+ (data_count * 8) / time_count);
+ ui_out_text (uiout, " bits/sec");
+ }
else
- printf_filtered ("%ld bits in <1 sec", (data_count * 8));
- printf_filtered (".\n");
+ {
+ ui_out_field_fmt (uiout, "transferred-bits", "%ld", (data_count * 8));
+ ui_out_text (uiout, " bits in <1 sec");
+ }
+ if (write_count > 0)
+ {
+ ui_out_text (uiout, ", ");
+ ui_out_field_fmt (uiout, "write-rate", "%ld", data_count / write_count);
+ ui_out_text (uiout, " bytes/write");
+ }
+ ui_out_text (uiout, ".\n");
+#else
+ fprintf_unfiltered (stream, "Transfer rate: ");
+ if (time_count > 0)
+ fprintf_unfiltered (stream, "%ld bits/sec", (data_count * 8) / time_count);
+ else
+ fprintf_unfiltered (stream, "%ld bits in <1 sec", (data_count * 8));
+ if (write_count > 0)
+ fprintf_unfiltered (stream, ", %ld bytes/write", data_count / write_count);
+ fprintf_unfiltered (stream, ".\n");
+#endif
}
/* This function allows the addition of incrementally linked object files.
{
char *name = NULL;
CORE_ADDR text_addr;
+ int flags = OBJF_USERLOADED;
char *arg;
- int readnow = 0;
- int mapped = 0;
+ int expecting_option = 0;
+ int option_index = 0;
+ int argcnt = 0;
+ int sec_num = 0;
+ int i;
+ struct
+ {
+ enum { OPT_SECTION } type;
+ char *name;
+ char *value;
+ } opt[SECT_OFF_MAX];
+ struct section_addr_info section_addrs;
dont_repeat ();
/* Make a copy of the string that we can safely write into. */
- args = strdup (args);
+ args = xstrdup (args);
make_cleanup (free, args);
+ /* Ensure section_addrs is initialized */
+ memset (§ion_addrs, 0, sizeof (section_addrs));
+
/* Pick off any -option args and the file name. */
- while ((*args != '\000') && (name == NULL))
+ while (*args != '\000')
{
while (isspace (*args))
{
}
if (*arg != '-')
{
- name = arg;
+ if (expecting_option)
+ {
+ opt[option_index++].value = arg;
+ expecting_option = 0;
+ }
+ else
+ {
+ switch (argcnt)
+ {
+ case 0:
+ name = arg;
+ break;
+ case 1:
+ opt[option_index].type = OPT_SECTION;
+ opt[option_index].name = ".text";
+ opt[option_index++].value = arg;
+ break;
+ case 2:
+ opt[option_index].type = OPT_SECTION;
+ opt[option_index].name = ".data";
+ opt[option_index++].value = arg;
+ break;
+ case 3:
+ opt[option_index].type = OPT_SECTION;
+ opt[option_index].name = ".bss";
+ opt[option_index++].value = arg;
+ break;
+ default:
+ warning ("Too many arguments entered; see \"help add-symbol-file\" for command syntax.");
+ }
+ argcnt++;
+ }
}
else if (STREQ (arg, "-mapped"))
{
- mapped = 1;
+ flags |= OBJF_MAPPED;
}
else if (STREQ (arg, "-readnow"))
{
- readnow = 1;
- }
- else
- {
- error ("unknown option `%s'", arg);
+ flags |= OBJF_READNOW;
}
+ else if (STREQN (arg, "-T", 2))
+ {
+ if (option_index >= SECT_OFF_MAX)
+ {
+ warning ("Number of options exceeds maximum allowed.");
+ }
+ else
+ {
+ expecting_option = 1;
+ opt[option_index].type = OPT_SECTION;
+ opt[option_index].name = arg + 2;
+ }
+ }
+ else
+ {
+ error ("Unknown option `%s'", arg);
+ }
}
- /* After picking off any options and the file name, args should be
- left pointing at the remainder of the command line, which should
- be the address expression to evaluate. */
-
if (name == NULL)
{
error ("add-symbol-file takes a file name");
name = tilde_expand (name);
make_cleanup (free, name);
- if (*args != '\000')
+ if (option_index > 0)
{
- text_addr = parse_and_eval_address (args);
+ /* Print the prompt for the query below.
+ We have to split this up into 3 print statements because
+ local_hex_string returns a local static string. */
+
+ printf_filtered ("add symbol table from file \"%s\" at\n", name);
+ for (i = 0; i < option_index; i++)
+ {
+ switch (opt[i].type)
+ {
+ case OPT_SECTION:
+ {
+ CORE_ADDR addr;
+ char *val = opt[i].value;
+ char *sec = opt[i].name;
+
+ val = opt[i].value;
+ if (val[0] == '0' && val[1] == 'x')
+ addr = strtoul (val+2, NULL, 16);
+ else
+ addr = strtoul (val, NULL, 10);
+
+ if (strcmp (sec, ".text") == 0)
+ section_addrs.text_addr = addr;
+ else if (strcmp (sec, ".data") == 0)
+ section_addrs.data_addr = addr;
+ else if (strcmp (sec, ".bss") == 0)
+ section_addrs.bss_addr = addr;
+ /* Add the section to the others even if it is a
+ text data or bss section. This is redundent but
+ eventually, none will be given special treatment */
+ {
+ section_addrs.other[sec_num].name = xstrdup (sec);
+ make_cleanup (free, section_addrs.other[sec_num].name);
+ section_addrs.other[sec_num++].addr = addr;
+ printf_filtered ("\t%s_addr = %s\n",
+ sec,
+ local_hex_string ((unsigned long)addr));
+ }
+
+ /* The object's sections are initialized when a
+ call is made to build_objfile_section_table (objfile).
+ This happens in reread_symbols.
+ At this point, we don't know what file type this is,
+ so we can't determine what section names are valid. */
+ }
+ break;
+ default:
+ complain (&unknown_option_complaint, opt[i].name);
+ }
+ }
+ /* Eventually, these hard coded names will be obsolete */
+ /* All the addresses will be on the others section */
}
else
{
- target_link (name, &text_addr);
+ CORE_ADDR text_addr;
+ target_link (name, &text_addr);
if (text_addr == (CORE_ADDR) -1)
- error ("Don't know how to get text start location for this file");
- }
-
- /* FIXME-32x64: Assumes text_addr fits in a long. */
- if ((from_tty)
- && (!query ("add symbol table from file \"%s\" at text_addr = %s?\n",
- name, local_hex_string ((unsigned long) text_addr))))
+ error("Don't know how to get text start location for this file");
+ section_addrs.text_addr = text_addr;
+ section_addrs.data_addr = 0;
+ section_addrs.bss_addr = 0;
+ printf_filtered("add symbol table from file \"%s\" at text_addr = %s?\n",
+ name, local_hex_string ((unsigned long)text_addr));
+ }
+ if (from_tty && (!query ("%s", "")))
error ("Not confirmed.");
- symbol_file_add (name, from_tty, text_addr, 0, mapped, readnow,
- 1, /* user_loaded */
- 0); /* We'll guess it's ! is_solib */
+ symbol_file_add (name, from_tty, §ion_addrs, 0, flags);
/* Getting new symbols may change our opinion about what is
frameless. */
sizeof (objfile->static_psymbols));
/* Free the obstacks for non-reusable objfiles */
- obstack_free (&objfile->psymbol_cache.cache, 0);
- memset (&objfile->psymbol_cache, 0,
- sizeof (objfile->psymbol_cache));
+ free_bcache (&objfile->psymbol_cache);
obstack_free (&objfile->psymbol_obstack, 0);
obstack_free (&objfile->symbol_obstack, 0);
obstack_free (&objfile->type_obstack, 0);
current_source_symtab = 0;
current_source_line = 0;
clear_pc_function_cache ();
- target_new_objfile (NULL);
+ if (target_new_objfile_hook)
+ target_new_objfile_hook (NULL);
}
/* clear_symtab_users_once:
c->completer = filename_completer;
c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command,
- "Usage: add-symbol-file FILE ADDR\n\
+ "Usage: add-symbol-file FILE ADDR [DATA_ADDR [BSS_ADDR]]\n\
+or: add-symbol-file FILE -T<SECT> <SECT_ADDR> -T<SECT> <SECT_ADDR> ...\n\
Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\
-ADDR is the starting address of the file's text.",
+ADDR is the starting address of the file's text.\n\
+The optional arguments, DATA_ADDR and BSS_ADDR, should be specified\n\
+if the data and bss segments are not contiguous with the text.\n\
+For complicated cases, SECT is a section name to be loaded at SECT_ADDR.",
&cmdlist);
c->completer = filename_completer;
add_info ("extensions", info_ext_lang_command,
"All filename extensions associated with a source language.");
+
+ add_show_from_set
+ (add_set_cmd ("download-write-size", class_obscure,
+ var_integer, (char *) &download_write_size,
+ "Set the write size used when downloading a program.\n"
+ "Only used when downloading a program onto a remote\n"
+ "target. Specify zero, or a negative value, to disable\n"
+ "blocked writes. The actual size of each transfer is also\n"
+ "limited by the size of the target packet and the memory\n"
+ "cache.\n",
+ &setlist),
+ &showlist);
}