X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsymfile.c;h=8d63484af1177a8c22e8a4cac0ca394478667efd;hb=697f7479bbe7c27def5b0f3b5cc06143bb5c88ab;hp=461b800d1d8d2f9016073ca1734c0694c62248b4;hpb=fbd3554072496c7dd0436df90cb0b051c63fe313;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/symfile.c b/gdb/symfile.c index 461b800d1d..8d63484af1 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1,6 +1,8 @@ /* Generic symbol file reading for the GNU debugger, GDB. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001 Free Software Foundation, Inc. + + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by Cygnus Support, using pieces from other GDB modules. This file is part of GDB. @@ -36,8 +38,9 @@ #include "demangle.h" #include "inferior.h" /* for write_pc */ #include "gdb-stabs.h" -#include "obstack.h" +#include "gdb_obstack.h" #include "completer.h" +#include "bcache.h" #include #include @@ -118,6 +121,8 @@ static void cashier_psymtab (struct partial_symtab *); bfd *symfile_bfd_open (char *); +int get_section_index (struct objfile *, char *); + static void find_sym_fns (struct objfile *); static void decrement_reading_symtab (void *); @@ -535,6 +540,34 @@ default_symfile_offsets (struct objfile *objfile, if (sect) objfile->sect_index_rodata = sect->index; + /* 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. */ + + for (i = 0; i < objfile->num_sections; i++) + { + if (ANOFFSET (objfile->section_offsets, i) != 0) + { + break; + } + } + if (i == objfile->num_sections) + { + if (objfile->sect_index_text == -1) + objfile->sect_index_text = 0; + if (objfile->sect_index_data == -1) + objfile->sect_index_data = 0; + if (objfile->sect_index_bss == -1) + objfile->sect_index_bss = 0; + if (objfile->sect_index_rodata == -1) + objfile->sect_index_rodata = 0; + } } /* Process a symbol file, as either the main file or as a dynamically @@ -575,6 +608,9 @@ syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs, init_entry_point_info (objfile); find_sym_fns (objfile); + if (objfile->sf == NULL) + return; /* No symbols. */ + /* Make sure that partially constructed symbol tables will be cleaned up if an error occurs during symbol reading. */ old_chain = make_cleanup_free_objfile (objfile); @@ -889,6 +925,9 @@ symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs, } } + if (objfile->sf == NULL) + return objfile; /* No symbols. */ + new_symfile_objfile (objfile, mainline, from_tty); if (target_new_objfile_hook) @@ -1092,7 +1131,7 @@ symfile_bfd_open (char *name) error ("\"%s\": can't open to read symbols: %s.", name, bfd_errmsg (bfd_get_error ())); } - sym_bfd->cacheable = true; + sym_bfd->cacheable = 1; if (!bfd_check_format (sym_bfd, bfd_object)) { @@ -1107,6 +1146,18 @@ symfile_bfd_open (char *name) return (sym_bfd); } +/* Return the section index for the given section name. Return -1 if + the section was not found. */ +int +get_section_index (struct objfile *objfile, char *section_name) +{ + asection *sect = bfd_get_section_by_name (objfile->obfd, section_name); + if (sect) + return sect->index; + else + return -1; +} + /* Link a new symtab_fns into the global symtab_fns list. Called on gdb startup by the _initialize routine in each object file format reader, to register information about each format the the reader is prepared @@ -1132,6 +1183,11 @@ find_sym_fns (struct objfile *objfile) enum bfd_flavour our_flavour = bfd_get_flavour (objfile->obfd); char *our_target = bfd_get_target (objfile->obfd); + if (our_flavour == bfd_target_srec_flavour + || our_flavour == bfd_target_ihex_flavour + || our_flavour == bfd_target_tekhex_flavour) + return; /* No symbols. */ + /* Special kludge for apollo. See dstread.c. */ if (STREQN (our_target, "apollo", 6)) our_flavour = (enum bfd_flavour) -2; @@ -1174,19 +1230,133 @@ load_command (char *arg, int from_tty) static int download_write_size = 512; static int validate_download = 0; +/* Callback service function for generic_load (bfd_map_over_sections). */ + +static void +add_section_size_callback (bfd *abfd, asection *asec, void *data) +{ + bfd_size_type *sum = data; + + *sum += bfd_get_section_size_before_reloc (asec); +} + +/* Opaque data for load_section_callback. */ +struct load_section_data { + unsigned long load_offset; + unsigned long write_count; + unsigned long data_count; + bfd_size_type total_size; +}; + +/* Callback service function for generic_load (bfd_map_over_sections). */ + +static void +load_section_callback (bfd *abfd, asection *asec, void *data) +{ + struct load_section_data *args = data; + + if (bfd_get_section_flags (abfd, asec) & SEC_LOAD) + { + bfd_size_type size = bfd_get_section_size_before_reloc (asec); + if (size > 0) + { + char *buffer; + struct cleanup *old_chain; + CORE_ADDR lma = bfd_section_lma (abfd, asec) + args->load_offset; + bfd_size_type block_size; + int err; + const char *sect_name = bfd_get_section_name (abfd, asec); + bfd_size_type sent; + + 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 (xfree, buffer); + + /* Is this really necessary? I guess it gives the user something + to look at during a long download. */ + ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n", + sect_name, paddr_nz (size), paddr_nz (lma)); + + bfd_get_section_contents (abfd, asec, buffer, 0, size); + + sent = 0; + do + { + int len; + bfd_size_type 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; + 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 (xfree, 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); + } + args->data_count += len; + lma += len; + buffer += len; + args->write_count += 1; + 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, + args->data_count, args->total_size); + } + while (sent < size); + + if (err != 0) + error ("Memory access error while loading section %s.", sect_name); + + do_cleanups (old_chain); + } + } +} + void generic_load (char *args, int from_tty) { 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 */ - 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; - bfd_size_type total_size = 0; + struct load_section_data cbdata; + CORE_ADDR entry; + + cbdata.load_offset = 0; /* Offset to add to vma for each section. */ + cbdata.write_count = 0; /* Number of writes needed. */ + cbdata.data_count = 0; /* Number of bytes written to target memory. */ + cbdata.total_size = 0; /* Total size of all bfd sectors. */ /* Parse the input argument - the user can specify a load offset as a second argument. */ @@ -1198,13 +1368,13 @@ generic_load (char *args, int from_tty) { char *endptr; - load_offset = strtoul (offptr, &endptr, 0); + cbdata.load_offset = strtoul (offptr, &endptr, 0); if (offptr == endptr) error ("Invalid download offset:%s\n", offptr); *offptr = '\0'; } else - load_offset = 0; + cbdata.load_offset = 0; /* Open the file for loading. */ loadfile_bfd = bfd_openr (filename, gnutarget); @@ -1225,129 +1395,24 @@ generic_load (char *args, int from_tty) bfd_errmsg (bfd_get_error ())); } - for (s = loadfile_bfd->sections; s; s = s->next) - if (bfd_get_section_flags (loadfile_bfd, s) & SEC_LOAD) - total_size += bfd_get_section_size_before_reloc (s); + bfd_map_over_sections (loadfile_bfd, add_section_size_callback, + (void *) &cbdata.total_size); start_time = time (NULL); - for (s = loadfile_bfd->sections; s; s = s->next) - { - if (s->flags & SEC_LOAD) - { - bfd_size_type size = bfd_get_section_size_before_reloc (s); - - if (size > 0) - { - char *buffer; - struct cleanup *old_chain; - CORE_ADDR lma = bfd_section_lma (loadfile_bfd, s) + load_offset; - bfd_size_type block_size; - int err; - const char *sect_name = bfd_get_section_name (loadfile_bfd, s); - bfd_size_type sent; - - 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 (xfree, buffer); - - /* Is this really necessary? I guess it gives the user something - to look at during a long download. */ -#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); - - sent = 0; - do - { - int len; - bfd_size_type 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; - 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 (xfree, - 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; - write_count += 1; - 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, - data_count, total_size); - } - while (sent < size); - - if (err != 0) - error ("Memory access error while loading section %s.", - sect_name); - - do_cleanups (old_chain); - } - } - } + bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata); end_time = time (NULL); - { - CORE_ADDR entry = bfd_get_start_address (loadfile_bfd); -#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", "%lu", data_count); - ui_out_text (uiout, "\n"); - -#else - fprintf_unfiltered (gdb_stdout, - "Start address 0x%s, load size %lu\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); - } + entry = bfd_get_start_address (loadfile_bfd); + 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", "%lu", cbdata.data_count); + ui_out_text (uiout, "\n"); + /* We were doing this in remote-mips.c, I suspect it is right + for other targets too. */ + write_pc (entry); /* 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 @@ -1355,8 +1420,8 @@ generic_load (char *args, int from_tty) loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c does. */ - print_transfer_performance (gdb_stdout, data_count, write_count, - end_time - start_time); + print_transfer_performance (gdb_stdout, cbdata.data_count, + cbdata.write_count, end_time - start_time); do_cleanups (old_cleanups); } @@ -1381,7 +1446,6 @@ print_transfer_performance (struct ui_file *stream, unsigned long write_count, unsigned long time_count) { -#ifdef UI_OUT ui_out_text (uiout, "Transfer rate: "); if (time_count > 0) { @@ -1401,16 +1465,6 @@ print_transfer_performance (struct ui_file *stream, ui_out_text (uiout, " bytes/write"); } ui_out_text (uiout, ".\n"); -#else - fprintf_unfiltered (stream, "Transfer rate: "); - if (time_count > 0) - fprintf_unfiltered (stream, "%lu bits/sec", (data_count * 8) / time_count); - else - fprintf_unfiltered (stream, "%lu bits in <1 sec", (data_count * 8)); - if (write_count > 0) - fprintf_unfiltered (stream, ", %lu bytes/write", data_count / write_count); - fprintf_unfiltered (stream, ".\n"); -#endif } /* This function allows the addition of incrementally linked object files. @@ -1687,7 +1741,10 @@ reread_symbols (void) sizeof (objfile->static_psymbols)); /* Free the obstacks for non-reusable objfiles */ - free_bcache (&objfile->psymbol_cache); + bcache_xfree (objfile->psymbol_cache); + objfile->psymbol_cache = bcache_xmalloc (); + bcache_xfree (objfile->macro_cache); + objfile->macro_cache = bcache_xmalloc (); obstack_free (&objfile->psymbol_obstack, 0); obstack_free (&objfile->symbol_obstack, 0); obstack_free (&objfile->type_obstack, 0); @@ -1711,8 +1768,8 @@ reread_symbols (void) objfile->md = NULL; /* obstack_specify_allocation also initializes the obstack so it is empty. */ - obstack_specify_allocation (&objfile->psymbol_cache.cache, 0, 0, - xmalloc, xfree); + objfile->psymbol_cache = bcache_xmalloc (); + objfile->macro_cache = bcache_xmalloc (); obstack_specify_allocation (&objfile->psymbol_obstack, 0, 0, xmalloc, xfree); obstack_specify_allocation (&objfile->symbol_obstack, 0, 0, @@ -1806,8 +1863,9 @@ add_filename_language (char *ext, enum language lang) if (fl_table_next >= fl_table_size) { fl_table_size += 10; - filename_language_table = xrealloc (filename_language_table, - fl_table_size); + filename_language_table = + xrealloc (filename_language_table, + fl_table_size * sizeof (*filename_language_table)); } filename_language_table[fl_table_next].ext = xstrdup (ext); @@ -1905,9 +1963,9 @@ init_filename_language_table (void) add_filename_language (".c++", language_cplus); add_filename_language (".java", language_java); add_filename_language (".class", language_java); - add_filename_language (".ch", language_chill); - add_filename_language (".c186", language_chill); - add_filename_language (".c286", language_chill); + /* OBSOLETE add_filename_language (".ch", language_chill); */ + /* OBSOLETE add_filename_language (".c186", language_chill); */ + /* OBSOLETE add_filename_language (".c286", language_chill); */ add_filename_language (".f", language_fortran); add_filename_language (".F", language_fortran); add_filename_language (".s", language_asm); @@ -2320,7 +2378,7 @@ add_psymbol_to_list (char *name, int namelength, namespace_enum namespace, /* Create local copy of the partial symbol */ memcpy (buf, name, namelength); buf[namelength] = '\0'; - SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache); + SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, objfile->psymbol_cache); /* val and coreaddr are mutually exclusive, one of them *will* be zero */ if (val != 0) { @@ -2337,7 +2395,7 @@ add_psymbol_to_list (char *name, int namelength, namespace_enum namespace, SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language); /* Stash the partial symbol away in the cache */ - psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache); + psym = 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) @@ -2372,7 +2430,7 @@ add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name, memcpy (buf, name, namelength); buf[namelength] = '\0'; - SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache); + SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, objfile->psymbol_cache); buf = alloca (dem_namelength + 1); memcpy (buf, dem_name, dem_namelength); @@ -2383,11 +2441,11 @@ add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name, case language_c: case language_cplus: SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) = - bcache (buf, dem_namelength + 1, &objfile->psymbol_cache); + bcache (buf, dem_namelength + 1, objfile->psymbol_cache); break; - case language_chill: - SYMBOL_CHILL_DEMANGLED_NAME (&psymbol) = - bcache (buf, dem_namelength + 1, &objfile->psymbol_cache); + /* OBSOLETE case language_chill: */ + /* OBSOLETE SYMBOL_CHILL_DEMANGLED_NAME (&psymbol) = */ + /* OBSOLETE bcache (buf, dem_namelength + 1, objfile->psymbol_cache); */ /* FIXME What should be done for the default case? Ignoring for now. */ } @@ -2408,7 +2466,7 @@ add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name, SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language); /* Stash the partial symbol away in the cache */ - psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache); + psym = 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) @@ -2509,7 +2567,7 @@ init_psymbol_list (struct objfile *objfile, int total_symbols) /* Overlay debugging state: */ -int overlay_debugging = 0; /* 0 == off, 1 == manual, -1 == auto */ +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 */ @@ -2566,9 +2624,9 @@ overlay_is_mapped (struct obj_section *osect) switch (overlay_debugging) { default: - case 0: + case ovly_off: return 0; /* overlay debugging off */ - case -1: /* overlay debugging automatic */ + case ovly_auto: /* overlay debugging automatic */ /* Unles there is a target_overlay_update function, there's really nothing useful to do here (can't really go auto) */ if (target_overlay_update) @@ -2582,7 +2640,7 @@ overlay_is_mapped (struct obj_section *osect) (*target_overlay_update) (osect); } /* fall thru to manual case */ - case 1: /* overlay debugging manual */ + case ovly_on: /* overlay debugging manual */ return osect->ovly_mapped == 1; } } @@ -2897,7 +2955,8 @@ the 'overlay manual' command."); static void overlay_auto_command (char *args, int from_tty) { - overlay_debugging = -1; + overlay_debugging = ovly_auto; + enable_overlay_breakpoints (); if (info_verbose) printf_filtered ("Automatic overlay debugging enabled."); } @@ -2909,7 +2968,8 @@ overlay_auto_command (char *args, int from_tty) static void overlay_manual_command (char *args, int from_tty) { - overlay_debugging = 1; + overlay_debugging = ovly_on; + disable_overlay_breakpoints (); if (info_verbose) printf_filtered ("Overlay debugging enabled."); } @@ -2921,7 +2981,8 @@ overlay_manual_command (char *args, int from_tty) static void overlay_off_command (char *args, int from_tty) { - overlay_debugging = 0; + overlay_debugging = ovly_off; + disable_overlay_breakpoints (); if (info_verbose) printf_filtered ("Overlay debugging disabled."); } @@ -3211,7 +3272,7 @@ _initialize_symfile (void) "Load symbol table from executable file FILE.\n\ The `file' command can also load symbol tables, as well as setting the file\n\ to execute.", &cmdlist); - c->completer = filename_completer; + set_cmd_completer (c, filename_completer); c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, "Usage: add-symbol-file FILE ADDR [-s -s ...]\n\ @@ -3219,9 +3280,9 @@ Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\ ADDR is the starting address of the file's text.\n\ The optional arguments are section-name section-address pairs and\n\ should be specified if the data and bss segments are not contiguous\n\ -with the text. SECT is a section name to be loaded at SECT_ADDR.", +with the text. SECT is a section name to be loaded at SECT_ADDR.", &cmdlist); - c->completer = filename_completer; + set_cmd_completer (c, filename_completer); c = add_cmd ("add-shared-symbol-files", class_files, add_shared_symbol_files_command, @@ -3233,7 +3294,7 @@ with the text. SECT is a section name to be loaded at SECT_ADDR.", c = add_cmd ("load", class_files, load_command, "Dynamically load FILE into the running program, and record its symbols\n\ for access from GDB.", &cmdlist); - c->completer = filename_completer; + set_cmd_completer (c, filename_completer); add_show_from_set (add_set_cmd ("symbol-reloading", class_support, var_boolean, @@ -3274,7 +3335,7 @@ for access from GDB.", &cmdlist); "Set mapping between filename extension and source language.\n\ Usage: set extension-language .foo bar", &setlist); - c->function.cfunc = set_ext_lang_command; + set_cmd_cfunc (c, set_ext_lang_command); add_info ("extensions", info_ext_lang_command, "All filename extensions associated with a source language.");