#include <time.h>
#include <sys/time.h>
+#include "psymtab.h"
int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num);
void (*deprecated_show_load_progress) (const char *section,
int auto_solib_limit;
\f
-/* This compares two partial symbols by names, using strcmp_iw_ordered
- for the comparison. */
-
-static int
-compare_psymbols (const void *s1p, const void *s2p)
-{
- struct partial_symbol *const *s1 = s1p;
- struct partial_symbol *const *s2 = s2p;
-
- return strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*s1),
- SYMBOL_SEARCH_NAME (*s2));
-}
-
-void
-sort_pst_symbols (struct partial_symtab *pst)
-{
- /* Sort the global list; don't sort the static list */
-
- qsort (pst->objfile->global_psymbols.list + pst->globals_offset,
- pst->n_global_syms, sizeof (struct partial_symbol *),
- compare_psymbols);
-}
-
/* Make a null terminated copy of the string at PTR with SIZE characters in
the obstack pointed to by OBSTACKP . Returns the address of the copy.
Note that the string at PTR does not have to be null terminated, I.E. it
return val;
}
-/* True if we are nested inside psymtab_to_symtab. */
+/* True if we are reading a symbol table. */
int currently_reading_symtab = 0;
currently_reading_symtab--;
}
-/* Get the symbol table that corresponds to a partial_symtab.
- This is fast after the first time you do it. In fact, there
- is an even faster macro PSYMTAB_TO_SYMTAB that does the fast
- case inline. */
-
-struct symtab *
-psymtab_to_symtab (struct partial_symtab *pst)
+/* Increment currently_reading_symtab and return a cleanup that can be
+ used to decrement it. */
+struct cleanup *
+increment_reading_symtab (void)
{
- /* If it's been looked up before, return it. */
- if (pst->symtab)
- return pst->symtab;
-
- /* If it has not yet been read in, read it. */
- if (!pst->readin)
- {
- struct cleanup *back_to = make_cleanup (decrement_reading_symtab, NULL);
- currently_reading_symtab++;
- (*pst->read_symtab) (pst);
- do_cleanups (back_to);
- }
-
- return pst->symtab;
+ ++currently_reading_symtab;
+ return make_cleanup (decrement_reading_symtab, NULL);
}
/* Remember the lowest-addressed loadable section we've seen.
{
asection **lowest = (asection **) obj;
- if (0 == (bfd_get_section_flags (abfd, sect) & SEC_LOAD))
+ if (0 == (bfd_get_section_flags (abfd, sect) & (SEC_ALLOC | SEC_LOAD)))
return;
if (!*lowest)
*lowest = sect; /* First loadable section */
return sap;
}
-/* Create a section_addr_info from section offsets in OBJFILE. */
+/* Create a section_addr_info from section offsets in ABFD. */
-struct section_addr_info *
-build_section_addr_info_from_objfile (const struct objfile *objfile)
+static struct section_addr_info *
+build_section_addr_info_from_bfd (bfd *abfd)
{
struct section_addr_info *sap;
int i;
struct bfd_section *sec;
- int addr_bit = gdbarch_addr_bit (objfile->gdbarch);
- CORE_ADDR mask = CORE_ADDR_MAX;
- if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
- mask = ((CORE_ADDR) 1 << addr_bit) - 1;
-
- sap = alloc_section_addr_info (objfile->num_sections);
- for (i = 0, sec = objfile->obfd->sections; sec != NULL; sec = sec->next)
- if (bfd_get_section_flags (objfile->obfd, sec) & (SEC_ALLOC | SEC_LOAD))
+ sap = alloc_section_addr_info (bfd_count_sections (abfd));
+ for (i = 0, sec = abfd->sections; sec != NULL; sec = sec->next)
+ if (bfd_get_section_flags (abfd, sec) & (SEC_ALLOC | SEC_LOAD))
{
- sap->other[i].addr = (bfd_get_section_vma (objfile->obfd, sec)
- + objfile->section_offsets->offsets[i]) & mask;
- sap->other[i].name = xstrdup (bfd_get_section_name (objfile->obfd,
- sec));
+ sap->other[i].addr = bfd_get_section_vma (abfd, sec);
+ sap->other[i].name = xstrdup (bfd_get_section_name (abfd, sec));
sap->other[i].sectindex = sec->index;
i++;
}
return sap;
}
+/* Create a section_addr_info from section offsets in OBJFILE. */
+
+struct section_addr_info *
+build_section_addr_info_from_objfile (const struct objfile *objfile)
+{
+ struct section_addr_info *sap;
+ int i;
+
+ /* Before reread_symbols gets rewritten it is not safe to call:
+ gdb_assert (objfile->num_sections == bfd_count_sections (objfile->obfd));
+ */
+ sap = build_section_addr_info_from_bfd (objfile->obfd);
+ for (i = 0; i < sap->num_sections && sap->other[i].name; i++)
+ {
+ int sectindex = sap->other[i].sectindex;
+
+ sap->other[i].addr += objfile->section_offsets->offsets[sectindex];
+ }
+ return sap;
+}
/* Free all memory allocated by build_section_addr_info_from_section_table. */
}
}
+/* qsort comparator for addrs_section_sort. Sort entries in ascending order by
+ their (name, sectindex) pair. sectindex makes the sort by name stable. */
+
+static int
+addrs_section_compar (const void *ap, const void *bp)
+{
+ const struct other_sections *a = *((struct other_sections **) ap);
+ const struct other_sections *b = *((struct other_sections **) bp);
+ int retval, a_idx, b_idx;
+
+ retval = strcmp (a->name, b->name);
+ if (retval)
+ return retval;
+
+ /* SECTINDEX is undefined iff ADDR is zero. */
+ a_idx = a->addr == 0 ? 0 : a->sectindex;
+ b_idx = b->addr == 0 ? 0 : b->sectindex;
+ return a_idx - b_idx;
+}
+
+/* Provide sorted array of pointers to sections of ADDRS. The array is
+ terminated by NULL. Caller is responsible to call xfree for it. */
+
+static struct other_sections **
+addrs_section_sort (struct section_addr_info *addrs)
+{
+ struct other_sections **array;
+ int i;
+
+ /* `+ 1' for the NULL terminator. */
+ array = xmalloc (sizeof (*array) * (addrs->num_sections + 1));
+ for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++)
+ array[i] = &addrs->other[i];
+ array[i] = NULL;
+
+ qsort (array, i, sizeof (*array), addrs_section_compar);
+
+ return array;
+}
+
/* Relativize absolute addresses in ADDRS into offsets based on ABFD. Fill-in
- also SECTINDEXes there. */
+ also SECTINDEXes specific to ABFD there. This function can be used to
+ rebase ADDRS to start referencing different BFD than before. */
void
addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
{
asection *lower_sect;
- asection *sect;
CORE_ADDR lower_offset;
int i;
+ struct cleanup *my_cleanup;
+ struct section_addr_info *abfd_addrs;
+ struct other_sections **addrs_sorted, **abfd_addrs_sorted;
+ struct other_sections **addrs_to_abfd_addrs;
/* Find lowest loadable section to be used as starting point for
continguous sections. */
else
lower_offset = bfd_section_vma (bfd_get_filename (abfd), lower_sect);
+ /* Create ADDRS_TO_ABFD_ADDRS array to map the sections in ADDRS to sections
+ in ABFD. Section names are not unique - there can be multiple sections of
+ the same name. Also the sections of the same name do not have to be
+ adjacent to each other. Some sections may be present only in one of the
+ files. Even sections present in both files do not have to be in the same
+ order.
+
+ Use stable sort by name for the sections in both files. Then linearly
+ scan both lists matching as most of the entries as possible. */
+
+ addrs_sorted = addrs_section_sort (addrs);
+ my_cleanup = make_cleanup (xfree, addrs_sorted);
+
+ abfd_addrs = build_section_addr_info_from_bfd (abfd);
+ make_cleanup_free_section_addr_info (abfd_addrs);
+ abfd_addrs_sorted = addrs_section_sort (abfd_addrs);
+ make_cleanup (xfree, abfd_addrs_sorted);
+
+ /* Now create ADDRS_TO_ABFD_ADDRS from ADDRS_SORTED and ABFD_ADDRS_SORTED. */
+
+ addrs_to_abfd_addrs = xzalloc (sizeof (*addrs_to_abfd_addrs)
+ * addrs->num_sections);
+ make_cleanup (xfree, addrs_to_abfd_addrs);
+
+ while (*addrs_sorted)
+ {
+ const char *sect_name = (*addrs_sorted)->name;
+
+ while (*abfd_addrs_sorted
+ && strcmp ((*abfd_addrs_sorted)->name, sect_name) < 0)
+ abfd_addrs_sorted++;
+
+ if (*abfd_addrs_sorted
+ && strcmp ((*abfd_addrs_sorted)->name, sect_name) == 0)
+ {
+ int index_in_addrs;
+
+ /* Make the found item directly addressable from ADDRS. */
+ index_in_addrs = *addrs_sorted - addrs->other;
+ gdb_assert (addrs_to_abfd_addrs[index_in_addrs] == NULL);
+ addrs_to_abfd_addrs[index_in_addrs] = *abfd_addrs_sorted;
+
+ /* Never use the same ABFD entry twice. */
+ abfd_addrs_sorted++;
+ }
+
+ addrs_sorted++;
+ }
+
/* 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!!!
for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++)
{
- if (addrs->other[i].addr != 0)
+ const char *sect_name = addrs->other[i].name;
+ struct other_sections *sect = addrs_to_abfd_addrs[i];
+
+ if (sect)
{
- sect = bfd_get_section_by_name (abfd, addrs->other[i].name);
- if (sect)
+ /* This is the index used by BFD. */
+ addrs->other[i].sectindex = sect->sectindex;
+
+ if (addrs->other[i].addr != 0)
{
- addrs->other[i].addr -= bfd_section_vma (abfd, sect);
+ addrs->other[i].addr -= sect->addr;
lower_offset = addrs->other[i].addr;
- /* This is the index used by BFD. */
- addrs->other[i].sectindex = sect->index;
}
else
- {
- warning (_("section %s not found in %s"), addrs->other[i].name,
- bfd_get_filename (abfd));
- addrs->other[i].addr = 0;
- }
+ addrs->other[i].addr = lower_offset;
}
else
- addrs->other[i].addr = lower_offset;
+ {
+ /* This section does not exist in ABFD, which is normally
+ unexpected and we want to issue a warning.
+
+ However, the ELF prelinker does create a few sections which are
+ marked in the main executable as loadable (they are loaded in
+ memory from the DYNAMIC segment) and yet are not present in
+ separate debug info files. This is fine, and should not cause
+ a warning. Shared libraries contain just the section
+ ".gnu.liblist" but it is not marked as loadable there. There is
+ no other way to identify them than by their name as the sections
+ created by prelink have no special flags. */
+
+ if (!(strcmp (sect_name, ".gnu.liblist") == 0
+ || strcmp (sect_name, ".gnu.conflict") == 0
+ || strcmp (sect_name, ".dynbss") == 0
+ || strcmp (sect_name, ".sdynbss") == 0))
+ warning (_("section %s not found in %s"), sect_name,
+ bfd_get_filename (abfd));
+
+ addrs->other[i].addr = 0;
+
+ /* SECTINDEX is invalid if ADDR is zero. */
+ }
}
+
+ do_cleanups (my_cleanup);
}
/* Parse the user's idea of an offset for dynamic linking, into our idea
int flags)
{
struct objfile *objfile;
- struct partial_symtab *psymtab;
struct cleanup *my_cleanups;
const char *name = bfd_get_filename (abfd);
const int from_tty = add_flags & SYMFILE_VERBOSE;
gdb_flush (gdb_stdout);
}
- for (psymtab = objfile->psymtabs;
- psymtab != NULL;
- psymtab = psymtab->next)
- {
- psymtab_to_symtab (psymtab);
- }
+ if (objfile->sf)
+ objfile->sf->qf->expand_all_symtabs (objfile);
}
if ((from_tty || info_verbose)
void
set_initial_language (void)
{
- struct partial_symtab *pst;
+ char *filename;
enum language lang = language_unknown;
- pst = find_main_psymtab ();
- if (pst != NULL)
- {
- if (pst->filename != NULL)
- lang = deduce_language_from_filename (pst->filename);
-
- if (lang == language_unknown)
- {
- /* Make C the default language */
- lang = language_c;
- }
+ filename = find_main_filename ();
+ if (filename != NULL)
+ lang = deduce_language_from_filename (filename);
- set_language (lang);
- expected_language = current_language; /* Don't warn the user. */
+ if (lang == language_unknown)
+ {
+ /* Make C the default language */
+ lang = language_c;
}
+
+ set_language (lang);
+ expected_language = current_language; /* Don't warn the user. */
}
/* If NAME is a remote name open the file using remote protocol, otherwise
for other targets too. */
regcache_write_pc (get_current_regcache (), entry);
+ /* Reset breakpoints, now that we have changed the load image. For
+ instance, breakpoints may have been set (or reset, by
+ post_create_inferior) while connected to the target but before we
+ loaded the program. In that case, the prologue analyzer could
+ have read instructions from the target to find the right
+ breakpoint locations. Loading has changed the contents of that
+ memory. */
+
+ breakpoint_re_set ();
+
/* 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 commented out), making the call confuses GDB if more than one
return (symtab);
}
-
-struct partial_symtab *
-allocate_psymtab (const char *filename, struct objfile *objfile)
-{
- struct partial_symtab *psymtab;
-
- if (objfile->free_psymtabs)
- {
- psymtab = objfile->free_psymtabs;
- objfile->free_psymtabs = psymtab->next;
- }
- else
- psymtab = (struct partial_symtab *)
- obstack_alloc (&objfile->objfile_obstack,
- sizeof (struct partial_symtab));
-
- memset (psymtab, 0, sizeof (struct partial_symtab));
- psymtab->filename = (char *) bcache (filename, strlen (filename) + 1,
- objfile->filename_cache);
- psymtab->symtab = NULL;
-
- /* Prepend it to the psymtab list for the objfile it belongs to.
- Psymtabs are searched in most recent inserted -> least recent
- inserted order. */
-
- psymtab->objfile = objfile;
- psymtab->next = objfile->psymtabs;
- objfile->psymtabs = psymtab;
-#if 0
- {
- struct partial_symtab **prev_pst;
- psymtab->objfile = objfile;
- psymtab->next = NULL;
- prev_pst = &(objfile->psymtabs);
- while ((*prev_pst) != NULL)
- prev_pst = &((*prev_pst)->next);
- (*prev_pst) = psymtab;
- }
-#endif
-
- return (psymtab);
-}
-
-void
-discard_psymtab (struct partial_symtab *pst)
-{
- struct partial_symtab **prev_pst;
-
- /* From dbxread.c:
- Empty psymtabs happen as a result of header files which don't
- have any symbols in them. There can be a lot of them. But this
- check is wrong, in that a psymtab with N_SLINE entries but
- nothing else is not empty, but we don't realize that. Fixing
- that without slowing things down might be tricky. */
-
- /* First, snip it out of the psymtab chain */
-
- prev_pst = &(pst->objfile->psymtabs);
- while ((*prev_pst) != pst)
- prev_pst = &((*prev_pst)->next);
- (*prev_pst) = pst->next;
-
- /* Next, put it on a free list for recycling */
-
- pst->next = pst->objfile->free_psymtabs;
- pst->objfile->free_psymtabs = pst;
-}
\f
/* Reset all data structures in gdb which may contain references to symbol
clear_symtab_users ();
}
\f
-/* Allocate and partially fill a partial symtab. It will be
- completely filled at the end of the symbol list.
-
- FILENAME is the name of the symbol-file we are reading from. */
-
-struct partial_symtab *
-start_psymtab_common (struct objfile *objfile,
- struct section_offsets *section_offsets,
- const char *filename,
- CORE_ADDR textlow, struct partial_symbol **global_syms,
- struct partial_symbol **static_syms)
-{
- struct partial_symtab *psymtab;
-
- psymtab = allocate_psymtab (filename, objfile);
- psymtab->section_offsets = section_offsets;
- psymtab->textlow = textlow;
- psymtab->texthigh = psymtab->textlow; /* default */
- psymtab->globals_offset = global_syms - objfile->global_psymbols.list;
- psymtab->statics_offset = static_syms - objfile->static_psymbols.list;
- return (psymtab);
-}
-\f
-/* Helper function, initialises partial symbol structure and stashes
- it into objfile's bcache. Note that our caching mechanism will
- use all fields of struct partial_symbol to determine hash value of the
- structure. In other words, having two symbols with the same name but
- different domain (or address) is possible and correct. */
-
-static const struct partial_symbol *
-add_psymbol_to_bcache (char *name, int namelength, int copy_name,
- domain_enum domain,
- enum address_class class,
- long val, /* Value as a long */
- CORE_ADDR coreaddr, /* Value as a CORE_ADDR */
- enum language language, struct objfile *objfile,
- int *added)
-{
- /* psymbol is static so that there will be no uninitialized gaps in the
- structure which might contain random data, causing cache misses in
- bcache. */
- static struct partial_symbol psymbol;
-
- /* However, we must ensure that the entire 'value' field has been
- zeroed before assigning to it, because an assignment may not
- write the entire field. */
- memset (&psymbol.ginfo.value, 0, sizeof (psymbol.ginfo.value));
- /* val and coreaddr are mutually exclusive, one of them *will* be zero */
- if (val != 0)
- {
- SYMBOL_VALUE (&psymbol) = val;
- }
- else
- {
- SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
- }
- SYMBOL_SECTION (&psymbol) = 0;
- SYMBOL_LANGUAGE (&psymbol) = language;
- PSYMBOL_DOMAIN (&psymbol) = domain;
- PSYMBOL_CLASS (&psymbol) = class;
-
- SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
-
- /* Stash the partial symbol away in the cache */
- return bcache_full (&psymbol, sizeof (struct partial_symbol),
- objfile->psymbol_cache, added);
-}
-
-/* Helper function, adds partial symbol to the given partial symbol
- list. */
-
-static void
-append_psymbol_to_list (struct psymbol_allocation_list *list,
- const struct partial_symbol *psym,
- struct objfile *objfile)
-{
- if (list->next >= list->list + list->size)
- extend_psymbol_list (list, objfile);
- *list->next++ = (struct partial_symbol *) psym;
- OBJSTAT (objfile, n_psyms++);
-}
-
-/* Add a symbol with a long value to a psymtab.
- Since one arg is a struct, we pass in a ptr and deref it (sigh).
- Return the partial symbol that has been added. */
-
-/* NOTE: carlton/2003-09-11: The reason why we return the partial
- symbol is so that callers can get access to the symbol's demangled
- name, which they don't have any cheap way to determine otherwise.
- (Currenly, dwarf2read.c is the only file who uses that information,
- though it's possible that other readers might in the future.)
- Elena wasn't thrilled about that, and I don't blame her, but we
- couldn't come up with a better way to get that information. If
- it's needed in other situations, we could consider breaking up
- SYMBOL_SET_NAMES to provide access to the demangled name lookup
- cache. */
-
-const struct partial_symbol *
-add_psymbol_to_list (char *name, int namelength, int copy_name,
- domain_enum domain,
- enum address_class class,
- struct psymbol_allocation_list *list,
- long val, /* Value as a long */
- CORE_ADDR coreaddr, /* Value as a CORE_ADDR */
- enum language language, struct objfile *objfile)
-{
- const struct partial_symbol *psym;
-
- int added;
-
- /* Stash the partial symbol away in the cache */
- psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
- val, coreaddr, language, objfile, &added);
-
- /* Do not duplicate global partial symbols. */
- if (list == &objfile->global_psymbols
- && !added)
- return psym;
-
- /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
- append_psymbol_to_list (list, psym, objfile);
- return psym;
-}
-
-/* Initialize storage for partial symbols. */
-
-void
-init_psymbol_list (struct objfile *objfile, int total_symbols)
-{
- /* Free any previously allocated psymbol lists. */
-
- if (objfile->global_psymbols.list)
- {
- xfree (objfile->global_psymbols.list);
- }
- if (objfile->static_psymbols.list)
- {
- xfree (objfile->static_psymbols.list);
- }
-
- /* Current best guess is that approximately a twentieth
- of the total symbols (in a debugging file) are global or static
- oriented symbols */
-
- objfile->global_psymbols.size = total_symbols / 10;
- objfile->static_psymbols.size = total_symbols / 10;
-
- if (objfile->global_psymbols.size > 0)
- {
- objfile->global_psymbols.next =
- objfile->global_psymbols.list = (struct partial_symbol **)
- xmalloc ((objfile->global_psymbols.size
- * sizeof (struct partial_symbol *)));
- }
- if (objfile->static_psymbols.size > 0)
- {
- objfile->static_psymbols.next =
- objfile->static_psymbols.list = (struct partial_symbol **)
- xmalloc ((objfile->static_psymbols.size
- * sizeof (struct partial_symbol *)));
- }
-}
-
/* OVERLAYS:
The following code implements an abstraction for debugging overlay sections.
/* It doesn't make sense to call this function unless you have some
segment base addresses. */
- gdb_assert (segment_bases > 0);
+ gdb_assert (num_segment_bases > 0);
/* If we do not have segment mappings for the object file, we
can not relocate it by segments. */