X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsymfile.c;h=5e554fed56e55f6cd49314b4c0fe44a720763ef6;hb=7f6ef0c0b8517b25e34e9f5c1208afefef50aec9;hp=4523b4b98bc74f1379fe9e9fe06e6cddf9210c83;hpb=2711e4564f4ab411bdf2cedff3fb92abadd630b8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/symfile.c b/gdb/symfile.c index 4523b4b98b..5e554fed56 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1,7 +1,7 @@ /* Generic symbol file reading for the GNU debugger, GDB. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -10,7 +10,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -19,9 +19,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "bfdlink.h" @@ -53,6 +51,8 @@ #include "exec.h" #include "parser-defs.h" #include "varobj.h" +#include "elf-bfd.h" +#include "solib.h" #include #include @@ -71,7 +71,6 @@ void (*deprecated_show_load_progress) (const char *section, unsigned long total_size); void (*deprecated_pre_add_symbol_hook) (const char *); void (*deprecated_post_add_symbol_hook) (void); -void (*deprecated_target_new_objfile_hook) (struct objfile *); static void clear_symtab_users_cleanup (void *ignore); @@ -89,8 +88,6 @@ static int simple_read_overlay_region_table (void); static void simple_free_overlay_region_table (void); #endif -static void set_initial_language (void); - static void load_command (char *, int); static void symbol_file_add_main_1 (char *args, int from_tty, int flags); @@ -107,7 +104,7 @@ bfd *symfile_bfd_open (char *); int get_section_index (struct objfile *, char *); -static void find_sym_fns (struct objfile *); +static struct sym_fns *find_sym_fns (bfd *); static void decrement_reading_symtab (void *); @@ -147,6 +144,8 @@ static char *find_separate_debug_file (struct objfile *objfile); static void init_filename_language_table (void); +static void symfile_find_segment_sections (struct objfile *objfile); + void _initialize_symfile (void); /* List of all available sym_fns. On gdb startup, each object file reader @@ -431,12 +430,19 @@ init_objfile_sect_indices (struct objfile *objfile) /* This is where things get really weird... We MUST have valid indices for the various sect_index_* members or gdb will abort. So if for example, there is no ".text" section, we have to - accomodate that. Except when explicitly adding symbol files at - some address, section_offsets contains nothing but zeros, so it - doesn't matter which slot in section_offsets the individual - sect_index_* members index into. So if they are all zero, it is - safe to just point all the currently uninitialized indices to the - first slot. */ + accomodate that. First, check for a file with the standard + one or two segments. */ + + symfile_find_segment_sections (objfile); + + /* Except when explicitly adding symbol files at some address, + section_offsets contains nothing but zeros, so it doesn't matter + which slot in section_offsets the individual sect_index_* members + index into. So if they are all zero, it is safe to just point + all the currently uninitialized indices to the first slot. But + beware: if this is the main executable, it may be relocated + later, e.g. by the remote qOffsets packet, and then this will + be wrong! That's why we try segments first. */ for (i = 0; i < objfile->num_sections; i++) { @@ -640,6 +646,70 @@ default_symfile_offsets (struct objfile *objfile, } +/* Divide the file into segments, which are individual relocatable units. + This is the default version of the sym_fns.sym_segments function for + symbol readers that do not have an explicit representation of segments. + It assumes that object files do not have segments, and fully linked + files have a single segment. */ + +struct symfile_segment_data * +default_symfile_segments (bfd *abfd) +{ + int num_sections, i; + asection *sect; + struct symfile_segment_data *data; + CORE_ADDR low, high; + + /* Relocatable files contain enough information to position each + loadable section independently; they should not be relocated + in segments. */ + if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) == 0) + return NULL; + + /* Make sure there is at least one loadable section in the file. */ + for (sect = abfd->sections; sect != NULL; sect = sect->next) + { + if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0) + continue; + + break; + } + if (sect == NULL) + return NULL; + + low = bfd_get_section_vma (abfd, sect); + high = low + bfd_get_section_size (sect); + + data = XZALLOC (struct symfile_segment_data); + data->num_segments = 1; + data->segment_bases = XCALLOC (1, CORE_ADDR); + data->segment_sizes = XCALLOC (1, CORE_ADDR); + + num_sections = bfd_count_sections (abfd); + data->segment_info = XCALLOC (num_sections, int); + + for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next) + { + CORE_ADDR vma; + + if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0) + continue; + + vma = bfd_get_section_vma (abfd, sect); + if (vma < low) + low = vma; + if (vma + bfd_get_section_size (sect) > high) + high = vma + bfd_get_section_size (sect); + + data->segment_info[i] = 1; + } + + data->segment_bases[0] = low; + data->segment_sizes[0] = high - low; + + return data; +} + /* Process a symbol file, as either the main file or as a dynamically loaded file. @@ -686,7 +756,7 @@ syms_from_objfile (struct objfile *objfile, gdb_assert (! (addrs && offsets)); init_entry_point_info (objfile); - find_sym_fns (objfile); + objfile->sf = find_sym_fns (objfile->obfd); if (objfile->sf == NULL) return; /* No symbols. */ @@ -947,7 +1017,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty, { struct objfile *objfile; struct partial_symtab *psymtab; - char *debugfile; + char *debugfile = NULL; struct section_addr_info *orig_addrs = NULL; struct cleanup *my_cleanups; const char *name = bfd_get_filename (abfd); @@ -1011,7 +1081,11 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty, } } - debugfile = find_separate_debug_file (objfile); + /* If the file has its own symbol tables it has no separate debug info. + `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS. + `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'. */ + if (objfile->psymtabs == NULL) + debugfile = find_separate_debug_file (objfile); if (debugfile) { if (addrs != NULL) @@ -1067,8 +1141,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty, new_symfile_objfile (objfile, mainline, from_tty); - if (deprecated_target_new_objfile_hook) - deprecated_target_new_objfile_hook (objfile); + observer_notify_new_objfile (objfile); bfd_cache_close_all (); return (objfile); @@ -1145,15 +1218,104 @@ symbol_file_clear (int from_tty) storage has just been released, we'd better wipe the solib descriptors as well. */ -#if defined(SOLIB_RESTART) - SOLIB_RESTART (); -#endif + no_shared_libraries (NULL, from_tty); symfile_objfile = NULL; if (from_tty) printf_unfiltered (_("No symbol file now.\n")); } +struct build_id + { + size_t size; + gdb_byte data[1]; + }; + +/* Locate NT_GNU_BUILD_ID from ABFD and return its content. */ + +static struct build_id * +build_id_bfd_get (bfd *abfd) +{ + struct build_id *retval; + + if (!bfd_check_format (abfd, bfd_object) + || bfd_get_flavour (abfd) != bfd_target_elf_flavour + || elf_tdata (abfd)->build_id == NULL) + return NULL; + + retval = xmalloc (sizeof *retval - 1 + elf_tdata (abfd)->build_id_size); + retval->size = elf_tdata (abfd)->build_id_size; + memcpy (retval->data, elf_tdata (abfd)->build_id, retval->size); + + return retval; +} + +/* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value. */ + +static int +build_id_verify (const char *filename, struct build_id *check) +{ + bfd *abfd; + struct build_id *found = NULL; + int retval = 0; + + /* We expect to be silent on the non-existing files. */ + abfd = bfd_openr (filename, gnutarget); + if (abfd == NULL) + return 0; + + found = build_id_bfd_get (abfd); + + if (found == NULL) + warning (_("File \"%s\" has no build-id, file skipped"), filename); + else if (found->size != check->size + || memcmp (found->data, check->data, found->size) != 0) + warning (_("File \"%s\" has a different build-id, file skipped"), filename); + else + retval = 1; + + if (!bfd_close (abfd)) + warning (_("cannot close \"%s\": %s"), filename, + bfd_errmsg (bfd_get_error ())); + return retval; +} + +static char * +build_id_to_debug_filename (struct build_id *build_id) +{ + char *link, *s, *retval = NULL; + gdb_byte *data = build_id->data; + size_t size = build_id->size; + + /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */ + link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1 + + 2 * size + (sizeof ".debug" - 1) + 1); + s = link + sprintf (link, "%s/.build-id/", debug_file_directory); + if (size > 0) + { + size--; + s += sprintf (s, "%02x", (unsigned) *data++); + } + if (size > 0) + *s++ = '/'; + while (size-- > 0) + s += sprintf (s, "%02x", (unsigned) *data++); + strcpy (s, ".debug"); + + /* lrealpath() is expensive even for the usually non-existent files. */ + if (access (link, F_OK) == 0) + retval = lrealpath (link); + xfree (link); + + if (retval != NULL && !build_id_verify (retval, build_id)) + { + xfree (retval); + retval = NULL; + } + + return retval; +} + static char * get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out) { @@ -1231,6 +1393,25 @@ find_separate_debug_file (struct objfile *objfile) bfd_size_type debuglink_size; unsigned long crc32; int i; + struct build_id *build_id; + + build_id = build_id_bfd_get (objfile->obfd); + if (build_id != NULL) + { + char *build_id_name; + + build_id_name = build_id_to_debug_filename (build_id); + free (build_id); + /* Prevent looping on a stripped .debug file. */ + if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0) + { + warning (_("\"%s\": separate debug info file has no debug info"), + build_id_name); + xfree (build_id_name); + } + else if (build_id_name != NULL) + return build_id_name; + } basename = get_debug_link_info (objfile, &crc32); @@ -1392,7 +1573,7 @@ symbol_file_command (char *args, int from_tty) stabs we find, but we can't do that until later when we read in full symbols. */ -static void +void set_initial_language (void) { struct partial_symtab *pst; @@ -1507,29 +1688,23 @@ add_symtab_fns (struct sym_fns *sf) struct sym_fns in the objfile structure, that contains cached information about the symbol file. */ -static void -find_sym_fns (struct objfile *objfile) +static struct sym_fns * +find_sym_fns (bfd *abfd) { struct sym_fns *sf; - enum bfd_flavour our_flavour = bfd_get_flavour (objfile->obfd); - char *our_target = bfd_get_target (objfile->obfd); + enum bfd_flavour our_flavour = bfd_get_flavour (abfd); if (our_flavour == bfd_target_srec_flavour || our_flavour == bfd_target_ihex_flavour || our_flavour == bfd_target_tekhex_flavour) - return; /* No symbols. */ + return NULL; /* No symbols. */ for (sf = symtab_fns; sf != NULL; sf = sf->next) - { - if (our_flavour == sf->sym_flavour) - { - objfile->sf = sf; - return; - } - } + if (our_flavour == sf->sym_flavour) + return sf; error (_("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown."), - bfd_get_target (objfile->obfd)); + bfd_get_target (abfd)); } @@ -1882,7 +2057,7 @@ print_transfer_performance (struct ui_file *stream, const struct timeval *start_time, const struct timeval *end_time) { - unsigned long time_count; + ULONGEST time_count; /* Compute the elapsed time in milliseconds, as a tradeoff between accuracy and overflow. */ @@ -1892,9 +2067,23 @@ print_transfer_performance (struct ui_file *stream, ui_out_text (uiout, "Transfer rate: "); if (time_count > 0) { - ui_out_field_fmt (uiout, "transfer-rate", "%lu", - 1000 * (data_count * 8) / time_count); - ui_out_text (uiout, " bits/sec"); + unsigned long rate = ((ULONGEST) data_count * 1000) / time_count; + + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate * 8); + ui_out_text (uiout, " bits/sec"); + } + else if (rate < 1024) + { + ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate); + ui_out_text (uiout, " bytes/sec"); + } + else + { + ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate / 1024); + ui_out_text (uiout, " KB/sec"); + } } else { @@ -2213,7 +2402,6 @@ reread_symbols (void) sizeof (objfile->msymbol_hash)); memset (&objfile->msymbol_demangled_hash, 0, sizeof (objfile->msymbol_demangled_hash)); - objfile->fundamental_types = NULL; clear_objfile_data (objfile); if (objfile->sf != NULL) { @@ -2360,6 +2548,8 @@ reread_separate_symbols (struct objfile *objfile) objfile->separate_debug_objfile->separate_debug_objfile_backlink = objfile; } + if (debug_file) + xfree (debug_file); } @@ -2494,6 +2684,7 @@ init_filename_language_table (void) add_filename_language (".f", language_fortran); add_filename_language (".F", language_fortran); add_filename_language (".s", language_asm); + add_filename_language (".sx", language_asm); add_filename_language (".S", language_asm); add_filename_language (".pas", language_pascal); add_filename_language (".p", language_pascal); @@ -2643,8 +2834,7 @@ clear_symtab_users (void) breakpoint_re_set (); set_default_breakpoint (0, 0, 0, 0); clear_pc_function_cache (); - if (deprecated_target_new_objfile_hook) - deprecated_target_new_objfile_hook (NULL); + observer_notify_new_objfile (NULL); /* Clear globals which might have pointed into a removed objfile. FIXME: It's not clear which of these are supposed to persist @@ -2952,75 +3142,6 @@ add_psymbol_to_list (char *name, int namelength, domain_enum domain, return psym; } -/* Add a symbol with a long value to a psymtab. This differs from - * add_psymbol_to_list above in taking both a mangled and a demangled - * name. */ - -void -add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name, - int dem_namelength, 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) -{ - struct partial_symbol *psym; - char *buf = alloca (namelength + 1); - /* 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; - - /* Create local copy of the partial symbol */ - - memcpy (buf, name, namelength); - buf[namelength] = '\0'; - DEPRECATED_SYMBOL_NAME (&psymbol) = deprecated_bcache (buf, namelength + 1, - objfile->psymbol_cache); - - buf = alloca (dem_namelength + 1); - memcpy (buf, dem_name, dem_namelength); - buf[dem_namelength] = '\0'; - - switch (language) - { - case language_c: - case language_cplus: - SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) = - deprecated_bcache (buf, dem_namelength + 1, objfile->psymbol_cache); - break; - /* FIXME What should be done for the default case? Ignoring for now. */ - } - - /* 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_INIT_LANGUAGE_SPECIFIC (&psymbol, language); - - /* Stash the partial symbol away in the cache */ - psym = deprecated_bcache (&psymbol, sizeof (struct partial_symbol), - objfile->psymbol_cache); - - /* Save pointer to partial symbol in psymtab, growing symtab if needed. */ - if (list->next >= list->list + list->size) - { - extend_psymbol_list (list, objfile); - } - *list->next++ = psym; - OBJSTAT (objfile, n_psyms++); -} - /* Initialize storage for partial symbols. */ void @@ -3114,10 +3235,6 @@ init_psymbol_list (struct objfile *objfile, int total_symbols) enum overlay_debugging_state overlay_debugging = ovly_off; int overlay_cache_invalid = 0; /* True if need to refresh mapped state */ -/* Target vector for refreshing overlay mapped state */ -static void simple_overlay_update (struct obj_section *); -void (*target_overlay_update) (struct obj_section *) = simple_overlay_update; - /* Function: section_is_overlay (SECTION) Returns true if SECTION has VMA not equal to LMA, ie. SECTION is loaded at an address different from where it will "run". */ @@ -3171,9 +3288,9 @@ overlay_is_mapped (struct obj_section *osect) case ovly_off: return 0; /* overlay debugging off */ case ovly_auto: /* overlay debugging automatic */ - /* Unles there is a target_overlay_update function, + /* Unles there is a gdbarch_overlay_update function, there's really nothing useful to do here (can't really go auto) */ - if (target_overlay_update) + if (gdbarch_overlay_update_p (current_gdbarch)) { if (overlay_cache_invalid) { @@ -3181,7 +3298,7 @@ overlay_is_mapped (struct obj_section *osect) overlay_cache_invalid = 0; } if (osect->ovly_mapped == -1) - (*target_overlay_update) (osect); + gdbarch_overlay_update (current_gdbarch, osect); } /* fall thru to manual case */ case ovly_on: /* overlay debugging manual */ @@ -3397,13 +3514,13 @@ list_overlays_command (char *args, int from_tty) name = bfd_section_name (objfile->obfd, osect->the_bfd_section); printf_filtered ("Section %s, loaded at ", name); - deprecated_print_address_numeric (lma, 1, gdb_stdout); + fputs_filtered (paddress (lma), gdb_stdout); puts_filtered (" - "); - deprecated_print_address_numeric (lma + size, 1, gdb_stdout); + fputs_filtered (paddress (lma + size), gdb_stdout); printf_filtered (", mapped at "); - deprecated_print_address_numeric (vma, 1, gdb_stdout); + fputs_filtered (paddress (vma), gdb_stdout); puts_filtered (" - "); - deprecated_print_address_numeric (vma + size, 1, gdb_stdout); + fputs_filtered (paddress (vma + size), gdb_stdout); puts_filtered ("\n"); nmapped++; @@ -3534,8 +3651,8 @@ overlay_off_command (char *args, int from_tty) static void overlay_load_command (char *args, int from_tty) { - if (target_overlay_update) - (*target_overlay_update) (NULL); + if (gdbarch_overlay_update_p (current_gdbarch)) + gdbarch_overlay_update (current_gdbarch, NULL); else error (_("This target does not know how to read its overlay state.")); } @@ -3559,7 +3676,7 @@ overlay_command (char *args, int from_tty) This is GDB's default target overlay layer. It works with the minimal overlay manager supplied as an example by Cygnus. The - entry point is via a function pointer "target_overlay_update", + entry point is via a function pointer "gdbarch_overlay_update", so targets that use a different runtime overlay manager can substitute their own overlay_update function and take over the function pointer. @@ -3606,7 +3723,8 @@ enum ovly_index { VMA, SIZE, LMA, MAPPED }; -#define TARGET_LONG_BYTES (TARGET_LONG_BIT / TARGET_CHAR_BIT) +#define TARGET_LONG_BYTES (gdbarch_long_bit (current_gdbarch) \ + / TARGET_CHAR_BIT) /* Throw away the cached copy of _ovly_table */ static void @@ -3762,7 +3880,7 @@ simple_overlay_update_1 (struct obj_section *osect) If a cached entry can't be found or the cache isn't valid, then re-read the entire cache, and go ahead and update all sections. */ -static void +void simple_overlay_update (struct obj_section *osect) { struct objfile *objfile; @@ -3846,6 +3964,133 @@ symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf) return bfd_simple_get_relocated_section_contents (abfd, sectp, buf, NULL); } +struct symfile_segment_data * +get_symfile_segment_data (bfd *abfd) +{ + struct sym_fns *sf = find_sym_fns (abfd); + + if (sf == NULL) + return NULL; + + return sf->sym_segments (abfd); +} + +void +free_symfile_segment_data (struct symfile_segment_data *data) +{ + xfree (data->segment_bases); + xfree (data->segment_sizes); + xfree (data->segment_info); + xfree (data); +} + + +/* Given: + - DATA, containing segment addresses from the object file ABFD, and + the mapping from ABFD's sections onto the segments that own them, + and + - SEGMENT_BASES[0 .. NUM_SEGMENT_BASES - 1], holding the actual + segment addresses reported by the target, + store the appropriate offsets for each section in OFFSETS. + + If there are fewer entries in SEGMENT_BASES than there are segments + in DATA, then apply SEGMENT_BASES' last entry to all the segments. + + If there are more, then verify that all the excess addresses are + the same as the last legitimate one, and then ignore them. This + allows "TextSeg=X;DataSeg=X" qOffset replies for files which have + only a single segment. */ +int +symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data, + struct section_offsets *offsets, + int num_segment_bases, + const CORE_ADDR *segment_bases) +{ + int i; + asection *sect; + + /* It doesn't make sense to call this function unless you have some + segment base addresses. */ + gdb_assert (segment_bases > 0); + + /* If we do not have segment mappings for the object file, we + can not relocate it by segments. */ + gdb_assert (data != NULL); + gdb_assert (data->num_segments > 0); + + /* Check any extra SEGMENT_BASES entries. */ + if (num_segment_bases > data->num_segments) + for (i = data->num_segments; i < num_segment_bases; i++) + if (segment_bases[i] != segment_bases[data->num_segments - 1]) + return 0; + + for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next) + { + int which = data->segment_info[i]; + + gdb_assert (0 <= which && which <= data->num_segments); + + /* Don't bother computing offsets for sections that aren't + loaded as part of any segment. */ + if (! which) + continue; + + /* Use the last SEGMENT_BASES entry as the address of any extra + segments mentioned in DATA->segment_info. */ + if (which > num_segment_bases) + which = num_segment_bases; + + offsets->offsets[i] = (segment_bases[which - 1] + - data->segment_bases[which - 1]); + } + + return 1; +} + +static void +symfile_find_segment_sections (struct objfile *objfile) +{ + bfd *abfd = objfile->obfd; + int i; + asection *sect; + struct symfile_segment_data *data; + + data = get_symfile_segment_data (objfile->obfd); + if (data == NULL) + return; + + if (data->num_segments != 1 && data->num_segments != 2) + { + free_symfile_segment_data (data); + return; + } + + for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next) + { + CORE_ADDR vma; + int which = data->segment_info[i]; + + if (which == 1) + { + if (objfile->sect_index_text == -1) + objfile->sect_index_text = sect->index; + + if (objfile->sect_index_rodata == -1) + objfile->sect_index_rodata = sect->index; + } + else if (which == 2) + { + if (objfile->sect_index_data == -1) + objfile->sect_index_data = sect->index; + + if (objfile->sect_index_bss == -1) + objfile->sect_index_bss = sect->index; + } + } + + free_symfile_segment_data (data); +} + void _initialize_symfile (void) {