Index: objfiles.c =================================================================== RCS file: /cvs/src/src/gdb/objfiles.c,v retrieving revision 1.85 diff -u -p -u -r1.85 objfiles.c --- objfiles.c 14 Jul 2009 14:55:06 -0000 1.85 +++ objfiles.c 17 Jul 2009 00:21:13 -0000 @@ -64,6 +64,18 @@ struct objfile *current_objfile; /* For struct objfile *symfile_objfile; /* Main symbol table loaded from */ struct objfile *rt_common_objfile; /* For runtime common symbols */ +struct address_to_obj_section +{ + CORE_ADDR addr; + CORE_ADDR endaddr; + struct obj_section *section; +}; + +/* Records whether any objfiles appeared or disappeared since we last updated + address to obj section map. */ + +static int objfiles_updated_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. */ @@ -94,6 +106,7 @@ add_to_objfile_sections (struct bfd *abf obstack_grow (&objfile->objfile_obstack, (char *) §ion, sizeof (section)); objfile->sections_end = (struct obj_section *) (((size_t) objfile->sections_end) + 1); + objfiles_updated_p += 1; /* Rebuild section map next time we need it. */ } /* Builds a section table for OBJFILE. @@ -394,6 +407,7 @@ unlink_objfile (struct objfile *objfile) void free_objfile (struct objfile *objfile) { + objfiles_updated_p += 1; /* Rebuild section map next time we need it. */ if (objfile->separate_debug_objfile) { free_objfile (objfile->separate_debug_objfile); @@ -757,22 +771,121 @@ have_minimal_symbols (void) return 0; } +/* Qsort comparison function. */ +static int +section_map_compare (const void *a, const void *b) +{ + const struct address_to_obj_section *aa = + (const struct address_to_obj_section *) a; + const struct address_to_obj_section *bb = + (const struct address_to_obj_section *) b; + + if (aa->addr < bb->addr) + { + gdb_assert (aa->endaddr <= bb->addr); + return -1; + } + else if (aa->addr > bb->addr) + { + gdb_assert (aa->addr >= bb->endaddr); + return 1; + } + /* This can happen for separate debug-info files. */ + gdb_assert (aa->endaddr == bb->endaddr); + + return 0; +} + +/* Update PMAP, PMAP_SIZE with non-TLS sections from all objfiles. */ + +static void +update_section_map (struct address_to_obj_section **pmap, + int *pmap_size) +{ + int map_size, idx; + struct obj_section *s; + struct objfile *objfile; + struct address_to_obj_section *map; + + gdb_assert (objfiles_updated_p != 0); + + map = *pmap; + xfree (map); + +#define insert_p(objf, sec) \ + ((bfd_get_section_flags ((objf)->obfd, (sec)->the_bfd_section) \ + & SEC_THREAD_LOCAL) == 0) + + map_size = 0; + ALL_OBJSECTIONS (objfile, s) + if (insert_p (objfile, s)) + map_size += 1; + + map = xmalloc (map_size * sizeof (*map)); + + idx = 0; + ALL_OBJSECTIONS (objfile, s) + if (insert_p (objfile, s)) + { + map[idx].section = s; + map[idx].addr = obj_section_addr (s); + map[idx].endaddr = obj_section_endaddr (s); + idx += 1; + } + +#undef insert_p + + qsort (map, map_size, sizeof (*map), section_map_compare); + + *pmap = map; + *pmap_size = map_size; +} + +/* Bsearch comparison function. */ + +int +find_pc_section_cmp (const void *key, const void *elt) +{ + CORE_ADDR pc = *(CORE_ADDR *) key; + const struct address_to_obj_section *entry = + (const struct address_to_obj_section *) elt; + + if (pc < entry->addr) + return -1; + if (pc < entry->endaddr) + return 0; + return 1; +} + /* Returns a section whose range includes PC or NULL if none found. */ struct obj_section * find_pc_section (CORE_ADDR pc) { + static struct address_to_obj_section *sections; + static int num_sections; + struct obj_section *s; - struct objfile *objfile; + struct address_to_obj_section *aos; /* Check for mapped overlay section first. */ s = find_pc_mapped_section (pc); if (s) return s; - ALL_OBJSECTIONS (objfile, s) - if (obj_section_addr (s) <= pc && pc < obj_section_endaddr (s)) - return s; + if (objfiles_updated_p != 0) + { + update_section_map (§ions, &num_sections); + + /* Don't need updates to section map until objfiles are added + or removed. */ + objfiles_updated_p = 0; + } + + aos = bsearch (&pc, sections, num_sections, sizeof (*sections), + find_pc_section_cmp); + if (aos) + return aos->section; return NULL; }