X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fobjfiles.c;h=9f779a47d88783e0cce61d7364a13ff276c925b0;hb=15d123c99f48b4b4620d87a0e9ee124de1a0659f;hp=92db65ef7c061f89f666f803108b6eec74323a2a;hpb=f1f2b5f40ef91b70acaa733f6f92f08de5efa29f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 92db65ef7c..9f779a47d8 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -1,7 +1,7 @@ /* GDB routines for manipulating objfiles. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc. + 2002, 2003, 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -51,6 +51,7 @@ #include "arch-utils.h" #include "exec.h" #include "observer.h" +#include "complaints.h" /* Prototypes for local functions */ @@ -60,16 +61,53 @@ static void objfile_free_data (struct objfile *objfile); /* Externally visible variables that are owned by this module. See declarations in objfile.h for more info. */ -struct objfile *object_files; /* Linked list of all objfiles */ struct objfile *current_objfile; /* For symbol file being read in */ -struct objfile *symfile_objfile; /* Main symbol table loaded from */ struct objfile *rt_common_objfile; /* For runtime common symbols */ +struct objfile_pspace_info +{ + int objfiles_changed_p; + struct obj_section **sections; + int num_sections; +}; + +/* Per-program-space data key. */ +static const struct program_space_data *objfiles_pspace_data; + +static void +objfiles_pspace_data_cleanup (struct program_space *pspace, void *arg) +{ + struct objfile_pspace_info *info; + + info = program_space_data (pspace, objfiles_pspace_data); + if (info != NULL) + { + xfree (info->sections); + xfree (info); + } +} + +/* Get the current svr4 data. If none is found yet, add it now. This + function always returns a valid object. */ + +static struct objfile_pspace_info * +get_objfile_pspace_data (struct program_space *pspace) +{ + struct objfile_pspace_info *info; + + info = program_space_data (pspace, objfiles_pspace_data); + if (info == NULL) + { + info = XZALLOC (struct objfile_pspace_info); + set_program_space_data (pspace, objfiles_pspace_data, info); + } + + return info; +} + /* Records whether any objfiles appeared or disappeared since we last updated address to obj section map. */ -static int objfiles_changed_p; - /* Locate all mappable sections of a BFD file. objfile_p_char is a char * to get it through bfd_map_over_sections; we cast it back to its proper type. */ @@ -156,24 +194,16 @@ build_objfile_section_table (struct objfile *objfile) struct objfile * allocate_objfile (bfd *abfd, int flags) { - struct objfile *objfile = NULL; - struct objfile *last_one = NULL; - - /* If we don't support mapped symbol files, didn't ask for the file to be - mapped, or failed to open the mapped file for some reason, then revert - back to an unmapped objfile. */ + struct objfile *objfile; - if (objfile == NULL) - { - objfile = (struct objfile *) xmalloc (sizeof (struct objfile)); - memset (objfile, 0, sizeof (struct objfile)); - objfile->psymbol_cache = bcache_xmalloc (); - objfile->macro_cache = bcache_xmalloc (); - /* We could use obstack_specify_allocation here instead, but - gdb_obstack.h specifies the alloc/dealloc functions. */ - obstack_init (&objfile->objfile_obstack); - terminate_minimal_symbol_table (objfile); - } + objfile = (struct objfile *) xzalloc (sizeof (struct objfile)); + objfile->psymbol_cache = bcache_xmalloc (); + objfile->macro_cache = bcache_xmalloc (); + objfile->filename_cache = bcache_xmalloc (); + /* We could use obstack_specify_allocation here instead, but + gdb_obstack.h specifies the alloc/dealloc functions. */ + obstack_init (&objfile->objfile_obstack); + terminate_minimal_symbol_table (objfile); objfile_alloc_data (objfile); @@ -181,7 +211,7 @@ allocate_objfile (bfd *abfd, int flags) that any data that is reference is saved in the per-objfile data region. */ - objfile->obfd = abfd; + objfile->obfd = gdb_bfd_ref (abfd); if (objfile->name != NULL) { xfree (objfile->name); @@ -207,6 +237,8 @@ allocate_objfile (bfd *abfd, int flags) objfile->name = xstrdup ("<>"); } + objfile->pspace = current_program_space; + /* Initialize the section indexes for this objfile, so that we can later detect if they are used w/o being properly assigned to. */ @@ -226,6 +258,8 @@ allocate_objfile (bfd *abfd, int flags) object_files = objfile; else { + struct objfile *last_one; + for (last_one = object_files; last_one->next; last_one = last_one->next); @@ -235,9 +269,10 @@ allocate_objfile (bfd *abfd, int flags) /* Save passed in flag bits. */ objfile->flags |= flags; - objfiles_changed_p = 1; /* Rebuild section map next time we need it. */ + /* Rebuild section map next time we need it. */ + get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1; - return (objfile); + return objfile; } /* Retrieve the gdbarch associated with OBJFILE. */ @@ -260,29 +295,34 @@ init_entry_point_info (struct objfile *objfile) /* Executable file -- record its entry point so we'll recognize the startup file because it contains the entry point. */ objfile->ei.entry_point = bfd_get_start_address (objfile->obfd); + objfile->ei.entry_point_p = 1; } else if (bfd_get_file_flags (objfile->obfd) & DYNAMIC && bfd_get_start_address (objfile->obfd) != 0) - /* Some shared libraries may have entry points set and be - runnable. There's no clear way to indicate this, so just check - for values other than zero. */ - objfile->ei.entry_point = bfd_get_start_address (objfile->obfd); + { + /* Some shared libraries may have entry points set and be + runnable. There's no clear way to indicate this, so just check + for values other than zero. */ + objfile->ei.entry_point = bfd_get_start_address (objfile->obfd); + objfile->ei.entry_point_p = 1; + } else { /* Examination of non-executable.o files. Short-circuit this stuff. */ - objfile->ei.entry_point = INVALID_ENTRY_POINT; + objfile->ei.entry_point_p = 0; } } -/* Get current entry point address. */ +/* If there is a valid and known entry point, function fills *ENTRY_P with it + and returns non-zero; otherwise it returns zero. */ -CORE_ADDR -entry_point_address (void) +int +entry_point_address_query (CORE_ADDR *entry_p) { struct gdbarch *gdbarch; CORE_ADDR entry_point; - if (symfile_objfile == NULL) + if (symfile_objfile == NULL || !symfile_objfile->ei.entry_point_p) return 0; gdbarch = get_objfile_arch (symfile_objfile); @@ -298,7 +338,21 @@ entry_point_address (void) symbol table. */ entry_point = gdbarch_addr_bits_remove (gdbarch, entry_point); - return entry_point; + *entry_p = entry_point; + return 1; +} + +/* Get current entry point address. Call error if it is not known. */ + +CORE_ADDR +entry_point_address (void) +{ + CORE_ADDR retval; + + if (!entry_point_address_query (&retval)) + error (_("Entry point address is not known.")); + + return retval; } /* Create the terminating entry of OBJFILE's minimal symbol table. @@ -324,6 +378,42 @@ terminate_minimal_symbol_table (struct objfile *objfile) } } +/* Iterator on PARENT and every separate debug objfile of PARENT. + The usage pattern is: + for (objfile = parent; + objfile; + objfile = objfile_separate_debug_iterate (parent, objfile)) + ... +*/ + +struct objfile * +objfile_separate_debug_iterate (const struct objfile *parent, + const struct objfile *objfile) +{ + struct objfile *res; + + res = objfile->separate_debug_objfile; + if (res) + return res; + + res = objfile->separate_debug_objfile_link; + if (res) + return res; + + /* Common case where there is no separate debug objfile. */ + if (objfile == parent) + return NULL; + + for (res = objfile->separate_debug_objfile_backlink; + res != parent; + res = res->separate_debug_objfile_backlink) + { + gdb_assert (res != NULL); + if (res->separate_debug_objfile_link) + return res->separate_debug_objfile_link; + } + return NULL; +} /* Put one object file before a specified on in the global list. This can be used to make sure an object file is destroyed before @@ -401,6 +491,41 @@ unlink_objfile (struct objfile *objfile) _("unlink_objfile: objfile already unlinked")); } +/* Add OBJFILE as a separate debug objfile of PARENT. */ + +void +add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent) +{ + gdb_assert (objfile && parent); + + /* Must not be already in a list. */ + gdb_assert (objfile->separate_debug_objfile_backlink == NULL); + gdb_assert (objfile->separate_debug_objfile_link == NULL); + + objfile->separate_debug_objfile_backlink = parent; + objfile->separate_debug_objfile_link = parent->separate_debug_objfile; + parent->separate_debug_objfile = objfile; + + /* Put the separate debug object before the normal one, this is so that + usage of the ALL_OBJFILES_SAFE macro will stay safe. */ + put_objfile_before (objfile, parent); +} + +/* Free all separate debug objfile of OBJFILE, but don't free OBJFILE + itself. */ + +void +free_objfile_separate_debug (struct objfile *objfile) +{ + struct objfile *child; + + for (child = objfile->separate_debug_objfile; child;) + { + struct objfile *next_child = child->separate_debug_objfile_link; + free_objfile (child); + child = next_child; + } +} /* Destroy an objfile and all the symtabs and psymtabs under it. Note that as much as possible is allocated on the objfile_obstack @@ -421,16 +546,38 @@ unlink_objfile (struct objfile *objfile) void free_objfile (struct objfile *objfile) { - if (objfile->separate_debug_objfile) - { - free_objfile (objfile->separate_debug_objfile); - } - + /* Free all separate debug objfiles. */ + free_objfile_separate_debug (objfile); + if (objfile->separate_debug_objfile_backlink) { /* We freed the separate debug file, make sure the base objfile doesn't reference it. */ - objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL; + struct objfile *child; + + child = objfile->separate_debug_objfile_backlink->separate_debug_objfile; + + if (child == objfile) + { + /* OBJFILE is the first child. */ + objfile->separate_debug_objfile_backlink->separate_debug_objfile = + objfile->separate_debug_objfile_link; + } + else + { + /* Find OBJFILE in the list. */ + while (1) + { + if (child->separate_debug_objfile_link == objfile) + { + child->separate_debug_objfile_link = + objfile->separate_debug_objfile_link; + break; + } + child = child->separate_debug_objfile_link; + gdb_assert (child); + } + } } /* Remove any references to this objfile in the global value @@ -458,8 +605,8 @@ free_objfile (struct objfile *objfile) unlink_objfile (objfile); - /* If we are going to free the runtime common objfile, mark it - as unallocated. */ + if (objfile == symfile_objfile) + symfile_objfile = NULL; if (objfile == rt_common_objfile) rt_common_objfile = NULL; @@ -508,12 +655,15 @@ free_objfile (struct objfile *objfile) /* Free the obstacks for non-reusable objfiles */ bcache_xfree (objfile->psymbol_cache); bcache_xfree (objfile->macro_cache); + bcache_xfree (objfile->filename_cache); if (objfile->demangled_names_hash) htab_delete (objfile->demangled_names_hash); obstack_free (&objfile->objfile_obstack, 0); + + /* Rebuild section map next time we need it. */ + get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1; + xfree (objfile); - objfile = NULL; - objfiles_changed_p = 1; /* Rebuild section map next time we need it. */ } static void @@ -623,6 +773,10 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) } } + if (objfile->psymtabs_addrmap) + addrmap_relocate (objfile->psymtabs_addrmap, + ANOFFSET (delta, SECT_OFF_TEXT (objfile))); + { struct partial_symtab *p; @@ -666,7 +820,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) to be out of order. */ msymbols_sort (objfile); - if (objfile->ei.entry_point != ~(CORE_ADDR) 0) + if (objfile->ei.entry_point_p) { /* Relocate ei.entry_point with its section offset, use SECT_OFF_TEXT only as a fallback. */ @@ -685,7 +839,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) } /* Rebuild section map next time we need it. */ - objfiles_changed_p = 1; + get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1; /* Update the table in exec_ops, used to read memory. */ ALL_OBJFILE_OSECTIONS (objfile, s) @@ -700,6 +854,37 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) breakpoint_re_set (); } +/* Return non-zero if OBJFILE has partial symbols. */ + +int +objfile_has_partial_symbols (struct objfile *objfile) +{ + return objfile->psymtabs != NULL; +} + +/* Return non-zero if OBJFILE has full symbols. */ + +int +objfile_has_full_symbols (struct objfile *objfile) +{ + return objfile->symtabs != NULL; +} + +/* Return non-zero if OBJFILE has full or partial symbols, either directly + or through a separate debug file. */ + +int +objfile_has_symbols (struct objfile *objfile) +{ + struct objfile *o; + + for (o = objfile; o; o = objfile_separate_debug_iterate (objfile, o)) + if (objfile_has_partial_symbols (o) || objfile_has_full_symbols (o)) + return 1; + return 0; +} + + /* Many places in gdb want to test just to see if we have any partial symbols available. This function returns zero if none are currently available, nonzero otherwise. */ @@ -711,10 +896,8 @@ have_partial_symbols (void) ALL_OBJFILES (ofp) { - if (ofp->psymtabs != NULL) - { - return 1; - } + if (objfile_has_partial_symbols (ofp)) + return 1; } return 0; } @@ -730,10 +913,8 @@ have_full_symbols (void) ALL_OBJFILES (ofp) { - if (ofp->symtabs != NULL) - { - return 1; - } + if (objfile_has_full_symbols (ofp)) + return 1; } return 0; } @@ -790,16 +971,72 @@ qsort_cmp (const void *a, const void *b) const CORE_ADDR sect2_addr = obj_section_addr (sect2); if (sect1_addr < sect2_addr) - { - gdb_assert (obj_section_endaddr (sect1) <= sect2_addr); - return -1; - } + return -1; else if (sect1_addr > sect2_addr) - { - gdb_assert (sect1_addr >= obj_section_endaddr (sect2)); - return 1; - } - + return 1; + else + { + /* Sections are at the same address. This could happen if + A) we have an objfile and a separate debuginfo. + B) we are confused, and have added sections without proper relocation, + or something like that. */ + + const struct objfile *const objfile1 = sect1->objfile; + const struct objfile *const objfile2 = sect2->objfile; + + if (objfile1->separate_debug_objfile == objfile2 + || objfile2->separate_debug_objfile == objfile1) + { + /* Case A. The ordering doesn't matter: separate debuginfo files + will be filtered out later. */ + + return 0; + } + + /* Case B. Maintain stable sort order, so bugs in GDB are easier to + triage. This section could be slow (since we iterate over all + objfiles in each call to qsort_cmp), but this shouldn't happen + very often (GDB is already in a confused state; one hopes this + doesn't happen at all). If you discover that significant time is + spent in the loops below, do 'set complaints 100' and examine the + resulting complaints. */ + + if (objfile1 == objfile2) + { + /* Both sections came from the same objfile. We are really confused. + Sort on sequence order of sections within the objfile. */ + + const struct obj_section *osect; + + ALL_OBJFILE_OSECTIONS (objfile1, osect) + if (osect == sect1) + return -1; + else if (osect == sect2) + return 1; + + /* We should have found one of the sections before getting here. */ + gdb_assert (0); + } + else + { + /* Sort on sequence number of the objfile in the chain. */ + + const struct objfile *objfile; + + ALL_OBJFILES (objfile) + if (objfile == objfile1) + return -1; + else if (objfile == objfile2) + return 1; + + /* We should have found one of the objfiles before getting here. */ + gdb_assert (0); + } + + } + + /* Unreachable. */ + gdb_assert (0); return 0; } @@ -823,69 +1060,186 @@ preferred_obj_section (struct obj_section *a, struct obj_section *b) return b; } -/* Update PMAP, PMAP_SIZE with non-TLS sections from all objfiles. */ +/* Return 1 if SECTION should be inserted into the section map. + We want to insert only non-overlay and non-TLS section. */ -static void -update_section_map (struct obj_section ***pmap, int *pmap_size) +static int +insert_section_p (const struct bfd *abfd, + const struct bfd_section *section) { - int map_size, i, j; - struct obj_section *s, **map; - struct objfile *objfile; + const bfd_vma lma = bfd_section_lma (abfd, section); - gdb_assert (objfiles_changed_p != 0); + if (lma != 0 && lma != bfd_section_vma (abfd, section) + && (bfd_get_file_flags (abfd) & BFD_IN_MEMORY) == 0) + /* This is an overlay section. IN_MEMORY check is needed to avoid + discarding sections from the "system supplied DSO" (aka vdso) + on some Linux systems (e.g. Fedora 11). */ + return 0; + if ((bfd_get_section_flags (abfd, section) & SEC_THREAD_LOCAL) != 0) + /* This is a TLS section. */ + return 0; - map = *pmap; - xfree (map); + return 1; +} -#define insert_p(objf, sec) \ - ((bfd_get_section_flags ((objf)->obfd, (sec)->the_bfd_section) \ - & SEC_THREAD_LOCAL) == 0) +/* Filter out overlapping sections where one section came from the real + objfile, and the other from a separate debuginfo file. + Return the size of table after redundant sections have been eliminated. */ - map_size = 0; - ALL_OBJSECTIONS (objfile, s) - if (insert_p (objfile, s)) - map_size += 1; +static int +filter_debuginfo_sections (struct obj_section **map, int map_size) +{ + int i, j; - map = xmalloc (map_size * sizeof (*map)); + for (i = 0, j = 0; i < map_size - 1; i++) + { + struct obj_section *const sect1 = map[i]; + struct obj_section *const sect2 = map[i + 1]; + const struct objfile *const objfile1 = sect1->objfile; + const struct objfile *const objfile2 = sect2->objfile; + const CORE_ADDR sect1_addr = obj_section_addr (sect1); + const CORE_ADDR sect2_addr = obj_section_addr (sect2); + + if (sect1_addr == sect2_addr + && (objfile1->separate_debug_objfile == objfile2 + || objfile2->separate_debug_objfile == objfile1)) + { + map[j++] = preferred_obj_section (sect1, sect2); + ++i; + } + else + map[j++] = sect1; + } - i = 0; - ALL_OBJSECTIONS (objfile, s) - if (insert_p (objfile, s)) - map[i++] = s; + if (i < map_size) + { + gdb_assert (i == map_size - 1); + map[j++] = map[i]; + } -#undef insert_p + /* The map should not have shrunk to less than half the original size. */ + gdb_assert (map_size / 2 <= j); - qsort (map, map_size, sizeof (*map), qsort_cmp); + return j; +} + +/* Filter out overlapping sections, issuing a warning if any are found. + Overlapping sections could really be overlay sections which we didn't + classify as such in insert_section_p, or we could be dealing with a + corrupt binary. */ + +static int +filter_overlapping_sections (struct obj_section **map, int map_size) +{ + int i, j; - /* With separate debuginfo files, we may have up to two (almost) - identical copies of some obj_sections in the map. - Filter out duplicates. */ - for (i = 0, j = 0; i < map_size; ++i) + for (i = 0, j = 0; i < map_size - 1; ) { - struct obj_section *sect1 = map[i]; - struct obj_section *sect2 = (i + 1 < map_size) ? map[i + 1] : NULL; + int k; - if (sect2 == NULL - || obj_section_addr (sect1) != obj_section_addr (sect2)) - map[j++] = sect1; - else + map[j++] = map[i]; + for (k = i + 1; k < map_size; k++) { - map[j++] = preferred_obj_section (sect1, sect2); - ++i; + struct obj_section *const sect1 = map[i]; + struct obj_section *const sect2 = map[k]; + const CORE_ADDR sect1_addr = obj_section_addr (sect1); + const CORE_ADDR sect2_addr = obj_section_addr (sect2); + const CORE_ADDR sect1_endaddr = obj_section_endaddr (sect1); + + gdb_assert (sect1_addr <= sect2_addr); + + if (sect1_endaddr <= sect2_addr) + break; + else + { + /* We have an overlap. Report it. */ + + struct objfile *const objf1 = sect1->objfile; + struct objfile *const objf2 = sect2->objfile; + + const struct bfd *const abfd1 = objf1->obfd; + const struct bfd *const abfd2 = objf2->obfd; + + const struct bfd_section *const bfds1 = sect1->the_bfd_section; + const struct bfd_section *const bfds2 = sect2->the_bfd_section; + + const CORE_ADDR sect2_endaddr = obj_section_endaddr (sect2); + + struct gdbarch *const gdbarch = get_objfile_arch (objf1); + + complaint (&symfile_complaints, + _("unexpected overlap between:\n" + " (A) section `%s' from `%s' [%s, %s)\n" + " (B) section `%s' from `%s' [%s, %s).\n" + "Will ignore section B"), + bfd_section_name (abfd1, bfds1), objf1->name, + paddress (gdbarch, sect1_addr), + paddress (gdbarch, sect1_endaddr), + bfd_section_name (abfd2, bfds2), objf2->name, + paddress (gdbarch, sect2_addr), + paddress (gdbarch, sect2_endaddr)); + } } + i = k; } - if (j < map_size) + if (i < map_size) { - /* Some duplicates were eliminated. - The new size shouldn't be less than half of the original. */ - gdb_assert (map_size / 2 <= j); - map_size = j; + gdb_assert (i == map_size - 1); + map[j++] = map[i]; + } + + return j; +} + + +/* Update PMAP, PMAP_SIZE with sections from all objfiles, excluding any + TLS, overlay and overlapping sections. */ + +static void +update_section_map (struct program_space *pspace, + struct obj_section ***pmap, int *pmap_size) +{ + int alloc_size, map_size, i; + struct obj_section *s, **map; + struct objfile *objfile; + + gdb_assert (get_objfile_pspace_data (pspace)->objfiles_changed_p != 0); + + map = *pmap; + xfree (map); - map = xrealloc (map, map_size * sizeof (*map)); /* Trim excess space. */ + alloc_size = 0; + ALL_PSPACE_OBJFILES (pspace, objfile) + ALL_OBJFILE_OSECTIONS (objfile, s) + if (insert_section_p (objfile->obfd, s->the_bfd_section)) + alloc_size += 1; + + /* This happens on detach/attach (e.g. in gdb.base/attach.exp). */ + if (alloc_size == 0) + { + *pmap = NULL; + *pmap_size = 0; + return; } + + map = xmalloc (alloc_size * sizeof (*map)); + + i = 0; + ALL_PSPACE_OBJFILES (pspace, objfile) + ALL_OBJFILE_OSECTIONS (objfile, s) + if (insert_section_p (objfile->obfd, s->the_bfd_section)) + map[i++] = s; + + qsort (map, alloc_size, sizeof (*map), qsort_cmp); + map_size = filter_debuginfo_sections(map, alloc_size); + map_size = filter_overlapping_sections(map, map_size); + + if (map_size < alloc_size) + /* Some sections were eliminated. Trim excess space. */ + map = xrealloc (map, map_size * sizeof (*map)); else - gdb_assert (j == map_size); + gdb_assert (alloc_size == map_size); *pmap = map; *pmap_size = map_size; @@ -911,9 +1265,7 @@ bsearch_cmp (const void *key, const void *elt) struct obj_section * find_pc_section (CORE_ADDR pc) { - static struct obj_section **sections; - static int num_sections; - + struct objfile_pspace_info *pspace_info; struct obj_section *s, **sp; /* Check for mapped overlay section first. */ @@ -921,17 +1273,31 @@ find_pc_section (CORE_ADDR pc) if (s) return s; - if (objfiles_changed_p != 0) + pspace_info = get_objfile_pspace_data (current_program_space); + if (pspace_info->objfiles_changed_p != 0) { - update_section_map (§ions, &num_sections); + update_section_map (current_program_space, + &pspace_info->sections, + &pspace_info->num_sections); + + /* Don't need updates to section map until objfiles are added, + removed or relocated. */ + pspace_info->objfiles_changed_p = 0; + } - /* Don't need updates to section map until objfiles are added - or removed. */ - objfiles_changed_p = 0; + /* The C standard (ISO/IEC 9899:TC2) requires the BASE argument to + bsearch be non-NULL. */ + if (pspace_info->sections == NULL) + { + gdb_assert (pspace_info->num_sections == 0); + return NULL; } - sp = (struct obj_section **) bsearch (&pc, sections, num_sections, - sizeof (*sections), bsearch_cmp); + sp = (struct obj_section **) bsearch (&pc, + pspace_info->sections, + pspace_info->num_sections, + sizeof (*pspace_info->sections), + bsearch_cmp); if (sp != NULL) return *sp; return NULL; @@ -963,7 +1329,8 @@ in_plt_section (CORE_ADDR pc, char *name) struct objfile_data { unsigned index; - void (*cleanup) (struct objfile *, void *); + void (*save) (struct objfile *, void *); + void (*free) (struct objfile *, void *); }; struct objfile_data_registration @@ -981,7 +1348,8 @@ struct objfile_data_registry static struct objfile_data_registry objfile_data_registry = { NULL, 0 }; const struct objfile_data * -register_objfile_data_with_cleanup (void (*cleanup) (struct objfile *, void *)) +register_objfile_data_with_cleanup (void (*save) (struct objfile *, void *), + void (*free) (struct objfile *, void *)) { struct objfile_data_registration **curr; @@ -993,7 +1361,8 @@ register_objfile_data_with_cleanup (void (*cleanup) (struct objfile *, void *)) (*curr)->next = NULL; (*curr)->data = XMALLOC (struct objfile_data); (*curr)->data->index = objfile_data_registry.num_registrations++; - (*curr)->data->cleanup = cleanup; + (*curr)->data->save = save; + (*curr)->data->free = free; return (*curr)->data; } @@ -1001,7 +1370,7 @@ register_objfile_data_with_cleanup (void (*cleanup) (struct objfile *, void *)) const struct objfile_data * register_objfile_data (void) { - return register_objfile_data_with_cleanup (NULL); + return register_objfile_data_with_cleanup (NULL, NULL); } static void @@ -1029,11 +1398,21 @@ clear_objfile_data (struct objfile *objfile) gdb_assert (objfile->data != NULL); + /* Process all the save handlers. */ + for (registration = objfile_data_registry.registrations, i = 0; i < objfile->num_data; registration = registration->next, i++) - if (objfile->data[i] != NULL && registration->data->cleanup) - registration->data->cleanup (objfile, objfile->data[i]); + if (objfile->data[i] != NULL && registration->data->save != NULL) + registration->data->save (objfile, objfile->data[i]); + + /* Now process all the free handlers. */ + + for (registration = objfile_data_registry.registrations, i = 0; + i < objfile->num_data; + registration = registration->next, i++) + if (objfile->data[i] != NULL && registration->data->free != NULL) + registration->data->free (objfile, objfile->data[i]); memset (objfile->data, 0, objfile->num_data * sizeof (void *)); } @@ -1059,10 +1438,30 @@ objfile_data (struct objfile *objfile, const struct objfile_data *data) void objfiles_changed (void) { - objfiles_changed_p = 1; /* Rebuild section map next time we need it. */ + /* Rebuild section map next time we need it. */ + get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1; } -/* Unreference and possibly close abfd. */ +/* Add reference to ABFD. Returns ABFD. */ +struct bfd * +gdb_bfd_ref (struct bfd *abfd) +{ + int *p_refcount = bfd_usrdata (abfd); + + if (p_refcount != NULL) + { + *p_refcount += 1; + return abfd; + } + + p_refcount = xmalloc (sizeof (*p_refcount)); + *p_refcount = 1; + bfd_usrdata (abfd) = p_refcount; + + return abfd; +} + +/* Unreference and possibly close ABFD. */ void gdb_bfd_unref (struct bfd *abfd) { @@ -1074,16 +1473,14 @@ gdb_bfd_unref (struct bfd *abfd) p_refcount = bfd_usrdata (abfd); - /* Valid range for p_refcount: NULL (single owner), or a pointer - to int counter, which has a value of 1 (single owner) or 2 (shared). */ - gdb_assert (p_refcount == NULL || *p_refcount == 1 || *p_refcount == 2); + /* Valid range for p_refcount: a pointer to int counter, which has a + value of 1 (single owner) or 2 (shared). */ + gdb_assert (*p_refcount == 1 || *p_refcount == 2); + + *p_refcount -= 1; + if (*p_refcount > 0) + return; - if (p_refcount != NULL) - { - *p_refcount -= 1; - if (*p_refcount > 0) - return; - } xfree (p_refcount); bfd_usrdata (abfd) = NULL; /* Paranoia. */ @@ -1093,3 +1490,13 @@ gdb_bfd_unref (struct bfd *abfd) name, bfd_errmsg (bfd_get_error ())); xfree (name); } + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_objfiles; + +void +_initialize_objfiles (void) +{ + objfiles_pspace_data + = register_program_space_data_with_cleanup (objfiles_pspace_data_cleanup); +}