X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsymfile.c;h=b0a5f118346673fdec0108446725d544232460c6;hb=621846f4e258167be2147894e013c85e42de1447;hp=84858dcf07b21fe865ee9c34f8104943b36ac545;hpb=d03de42190b3b55fb195340dde8e595714a35090;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/symfile.c b/gdb/symfile.c index 84858dcf07..b0a5f11834 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1,6 +1,6 @@ /* Generic symbol file reading for the GNU debugger, GDB. - Copyright (C) 1990-2014 Free Software Foundation, Inc. + Copyright (C) 1990-2018 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -45,9 +45,8 @@ #include "bcache.h" #include "hashtab.h" #include "readline/readline.h" -#include "gdb_assert.h" #include "block.h" -#include "observer.h" +#include "observable.h" #include "exec.h" #include "parser-defs.h" #include "varobj.h" @@ -57,14 +56,15 @@ #include "stack.h" #include "gdb_bfd.h" #include "cli/cli-utils.h" +#include "common/byte-vector.h" +#include "selftest.h" #include #include -#include #include #include -#include -#include +#include +#include #include "psymtab.h" @@ -82,31 +82,17 @@ static void clear_symtab_users_cleanup (void *ignore); /* Global variables owned by this file. */ int readnow_symbol_files; /* Read full symbols immediately. */ +int readnever_symbol_files; /* Never read full symbols. */ /* Functions this file defines. */ -static void load_command (char *, int); - -static void symbol_file_add_main_1 (const char *args, int from_tty, int flags); - -static void add_symbol_file_command (char *, int); +static void symbol_file_add_main_1 (const char *args, symfile_add_flags add_flags, + objfile_flags flags); static const struct sym_fns *find_sym_fns (bfd *); -static void decrement_reading_symtab (void *); - static void overlay_invalidate_all (void); -static void overlay_auto_command (char *, int); - -static void overlay_manual_command (char *, int); - -static void overlay_off_command (char *, int); - -static void overlay_load_command (char *, int); - -static void overlay_command (char *, int); - static void simple_free_overlay_table (void); static void read_target_long_array (CORE_ADDR, unsigned int *, int, int, @@ -116,32 +102,26 @@ static int simple_read_overlay_table (void); static int simple_overlay_update_1 (struct obj_section *); -static void add_filename_language (char *ext, enum language lang); - -static void info_ext_lang_command (char *args, int from_tty); - -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 calls add_symtab_fns() to register information on each format it is prepared to read. */ -typedef struct +struct registered_sym_fns { + registered_sym_fns (bfd_flavour sym_flavour_, const struct sym_fns *sym_fns_) + : sym_flavour (sym_flavour_), sym_fns (sym_fns_) + {} + /* BFD flavour that we handle. */ enum bfd_flavour sym_flavour; /* The "vtable" of symbol functions. */ const struct sym_fns *sym_fns; -} registered_sym_fns; - -DEF_VEC_O (registered_sym_fns); +}; -static VEC (registered_sym_fns) *symtab_fns = NULL; +static std::vector symtab_fns; /* Values for "set print symbol-loading". */ @@ -199,22 +179,15 @@ print_symbol_loading_p (int from_tty, int exec, int full) int currently_reading_symtab = 0; -static void -decrement_reading_symtab (void *dummy) -{ - currently_reading_symtab--; - gdb_assert (currently_reading_symtab >= 0); -} - /* Increment currently_reading_symtab and return a cleanup that can be used to decrement it. */ -struct cleanup * +scoped_restore_tmpl increment_reading_symtab (void) { - ++currently_reading_symtab; - gdb_assert (currently_reading_symtab > 0); - return make_cleanup (decrement_reading_symtab, NULL); + gdb_assert (currently_reading_symtab >= 0); + return make_scoped_restore (¤tly_reading_symtab, + currently_reading_symtab + 1); } /* Remember the lowest-addressed loadable section we've seen. @@ -243,114 +216,69 @@ find_lowest_section (bfd *abfd, asection *sect, void *obj) *lowest = sect; } -/* Create a new section_addr_info, with room for NUM_SECTIONS. The - new object's 'num_sections' field is set to 0; it must be updated - by the caller. */ - -struct section_addr_info * -alloc_section_addr_info (size_t num_sections) -{ - struct section_addr_info *sap; - size_t size; - - size = (sizeof (struct section_addr_info) - + sizeof (struct other_sections) * (num_sections - 1)); - sap = (struct section_addr_info *) xmalloc (size); - memset (sap, 0, size); - - return sap; -} - /* Build (allocate and populate) a section_addr_info struct from an existing section table. */ -extern struct section_addr_info * +section_addr_info build_section_addr_info_from_section_table (const struct target_section *start, const struct target_section *end) { - struct section_addr_info *sap; const struct target_section *stp; - int oidx; - sap = alloc_section_addr_info (end - start); + section_addr_info sap; - for (stp = start, oidx = 0; stp != end; stp++) + for (stp = start; stp != end; stp++) { struct bfd_section *asect = stp->the_bfd_section; bfd *abfd = asect->owner; if (bfd_get_section_flags (abfd, asect) & (SEC_ALLOC | SEC_LOAD) - && oidx < end - start) - { - sap->other[oidx].addr = stp->addr; - sap->other[oidx].name = xstrdup (bfd_section_name (abfd, asect)); - sap->other[oidx].sectindex = gdb_bfd_section_index (abfd, asect); - oidx++; - } + && sap.size () < end - start) + sap.emplace_back (stp->addr, + bfd_section_name (abfd, asect), + gdb_bfd_section_index (abfd, asect)); } - sap->num_sections = oidx; - return sap; } /* Create a section_addr_info from section offsets in ABFD. */ -static struct section_addr_info * +static section_addr_info build_section_addr_info_from_bfd (bfd *abfd) { - struct section_addr_info *sap; - int i; struct bfd_section *sec; - sap = alloc_section_addr_info (bfd_count_sections (abfd)); - for (i = 0, sec = abfd->sections; sec != NULL; sec = sec->next) + section_addr_info sap; + for (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 (abfd, sec); - sap->other[i].name = xstrdup (bfd_get_section_name (abfd, sec)); - sap->other[i].sectindex = gdb_bfd_section_index (abfd, sec); - i++; - } - - sap->num_sections = i; + sap.emplace_back (bfd_get_section_vma (abfd, sec), + bfd_get_section_name (abfd, sec), + gdb_bfd_section_index (abfd, sec)); return sap; } /* Create a section_addr_info from section offsets in OBJFILE. */ -struct section_addr_info * +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; i++) + section_addr_info sap = build_section_addr_info_from_bfd (objfile->obfd); + for (i = 0; i < sap.size (); i++) { - int sectindex = sap->other[i].sectindex; + int sectindex = sap[i].sectindex; - sap->other[i].addr += objfile->section_offsets->offsets[sectindex]; + sap[i].addr += objfile->section_offsets->offsets[sectindex]; } return sap; } -/* Free all memory allocated by build_section_addr_info_from_section_table. */ - -extern void -free_section_addr_info (struct section_addr_info *sap) -{ - int idx; - - for (idx = 0; idx < sap->num_sections; idx++) - xfree (sap->other[idx].name); - xfree (sap); -} - /* Initialize OBJFILE's sect_index_* members. */ static void @@ -426,7 +354,7 @@ struct place_section_arg static void place_section (bfd *abfd, asection *sect, void *obj) { - struct place_section_arg *arg = obj; + struct place_section_arg *arg = (struct place_section_arg *) obj; CORE_ADDR *offsets = arg->offsets->offsets, start_addr; int done; ULONGEST align = ((ULONGEST) 1) << bfd_get_section_alignment (abfd, sect); @@ -484,25 +412,25 @@ place_section (bfd *abfd, asection *sect, void *obj) arg->lowest = start_addr + bfd_get_section_size (sect); } -/* Store struct section_addr_info as prepared (made relative and with SECTINDEX +/* Store section_addr_info as prepared (made relative and with SECTINDEX filled-in) by addr_info_make_relative into SECTION_OFFSETS of NUM_SECTIONS entries. */ void relative_addr_info_to_section_offsets (struct section_offsets *section_offsets, int num_sections, - const struct section_addr_info *addrs) + const section_addr_info &addrs) { int i; memset (section_offsets, 0, SIZEOF_N_SECTION_OFFSETS (num_sections)); /* Now calculate offsets for section that were specified by the caller. */ - for (i = 0; i < addrs->num_sections; i++) + for (i = 0; i < addrs.size (); i++) { const struct other_sections *osp; - osp = &addrs->other[i]; + osp = &addrs[i]; if (osp->sectindex == -1) continue; @@ -530,39 +458,36 @@ addr_section_name (const char *s) return s; } -/* qsort comparator for addrs_section_sort. Sort entries in ascending order by - their (name, sectindex) pair. sectindex makes the sort by name stable. */ +/* std::sort 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) +static bool +addrs_section_compar (const struct other_sections *a, + const struct other_sections *b) { - const struct other_sections *a = *((struct other_sections **) ap); - const struct other_sections *b = *((struct other_sections **) bp); int retval; - retval = strcmp (addr_section_name (a->name), addr_section_name (b->name)); - if (retval) - return retval; + retval = strcmp (addr_section_name (a->name.c_str ()), + addr_section_name (b->name.c_str ())); + if (retval != 0) + return retval < 0; - return a->sectindex - b->sectindex; + return a->sectindex < b->sectindex; } -/* Provide sorted array of pointers to sections of ADDRS. The array is - terminated by NULL. Caller is responsible to call xfree for it. */ +/* Provide sorted array of pointers to sections of ADDRS. */ -static struct other_sections ** -addrs_section_sort (struct section_addr_info *addrs) +static std::vector +addrs_section_sort (const 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; i++) - array[i] = &addrs->other[i]; - array[i] = NULL; + std::vector array (addrs.size ()); + for (i = 0; i < addrs.size (); i++) + array[i] = &addrs[i]; - qsort (array, i, sizeof (*array), addrs_section_compar); + std::sort (array.begin (), array.end (), addrs_section_compar); return array; } @@ -572,15 +497,11 @@ addrs_section_sort (struct section_addr_info *addrs) rebase ADDRS to start referencing different BFD than before. */ void -addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) +addr_info_make_relative (section_addr_info *addrs, bfd *abfd) { asection *lower_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. */ @@ -605,46 +526,44 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) 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); + std::vector addrs_sorted + = addrs_section_sort (*addrs); - 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); + section_addr_info abfd_addrs = build_section_addr_info_from_bfd (abfd); + std::vector abfd_addrs_sorted + = addrs_section_sort (abfd_addrs); /* 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); + std::vector + addrs_to_abfd_addrs (addrs->size (), nullptr); - while (*addrs_sorted) + std::vector::iterator abfd_sorted_iter + = abfd_addrs_sorted.begin (); + for (const struct other_sections *sect : addrs_sorted) { - const char *sect_name = addr_section_name ((*addrs_sorted)->name); + const char *sect_name = addr_section_name (sect->name.c_str ()); - while (*abfd_addrs_sorted - && strcmp (addr_section_name ((*abfd_addrs_sorted)->name), + while (abfd_sorted_iter != abfd_addrs_sorted.end () + && strcmp (addr_section_name ((*abfd_sorted_iter)->name.c_str ()), sect_name) < 0) - abfd_addrs_sorted++; + abfd_sorted_iter++; - if (*abfd_addrs_sorted - && strcmp (addr_section_name ((*abfd_addrs_sorted)->name), + if (abfd_sorted_iter != abfd_addrs_sorted.end () + && strcmp (addr_section_name ((*abfd_sorted_iter)->name.c_str ()), sect_name) == 0) { int index_in_addrs; /* Make the found item directly addressable from ADDRS. */ - index_in_addrs = *addrs_sorted - addrs->other; + index_in_addrs = sect - addrs->data (); gdb_assert (addrs_to_abfd_addrs[index_in_addrs] == NULL); - addrs_to_abfd_addrs[index_in_addrs] = *abfd_addrs_sorted; + addrs_to_abfd_addrs[index_in_addrs] = *abfd_sorted_iter; /* Never use the same ABFD entry twice. */ - abfd_addrs_sorted++; + abfd_sorted_iter++; } - - addrs_sorted++; } /* Calculate offsets for the loadable sections. @@ -657,27 +576,27 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) (the loadable section directly below it in memory). this_offset = lower_offset = lower_addr - lower_orig_addr */ - for (i = 0; i < addrs->num_sections; i++) + for (i = 0; i < addrs->size (); i++) { - struct other_sections *sect = addrs_to_abfd_addrs[i]; + const struct other_sections *sect = addrs_to_abfd_addrs[i]; if (sect) { /* This is the index used by BFD. */ - addrs->other[i].sectindex = sect->sectindex; + (*addrs)[i].sectindex = sect->sectindex; - if (addrs->other[i].addr != 0) + if ((*addrs)[i].addr != 0) { - addrs->other[i].addr -= sect->addr; - lower_offset = addrs->other[i].addr; + (*addrs)[i].addr -= sect->addr; + lower_offset = (*addrs)[i].addr; } else - addrs->other[i].addr = lower_offset; + (*addrs)[i].addr = lower_offset; } else { /* addr_section_name transformation is not used for SECT_NAME. */ - const char *sect_name = addrs->other[i].name; + const std::string §_name = (*addrs)[i].name; /* This section does not exist in ABFD, which is normally unexpected and we want to issue a warning. @@ -693,25 +612,23 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) For the sections `.bss' and `.sbss' see addr_section_name. */ - if (!(strcmp (sect_name, ".gnu.liblist") == 0 - || strcmp (sect_name, ".gnu.conflict") == 0 - || (strcmp (sect_name, ".bss") == 0 + if (!(sect_name == ".gnu.liblist" + || sect_name == ".gnu.conflict" + || (sect_name == ".bss" && i > 0 - && strcmp (addrs->other[i - 1].name, ".dynbss") == 0 + && (*addrs)[i - 1].name == ".dynbss" && addrs_to_abfd_addrs[i - 1] != NULL) - || (strcmp (sect_name, ".sbss") == 0 + || (sect_name == ".sbss" && i > 0 - && strcmp (addrs->other[i - 1].name, ".sdynbss") == 0 + && (*addrs)[i - 1].name == ".sdynbss" && addrs_to_abfd_addrs[i - 1] != NULL))) - warning (_("section %s not found in %s"), sect_name, + warning (_("section %s not found in %s"), sect_name.c_str (), bfd_get_filename (abfd)); - addrs->other[i].addr = 0; - addrs->other[i].sectindex = -1; + (*addrs)[i].addr = 0; + (*addrs)[i].sectindex = -1; } } - - do_cleanups (my_cleanup); } /* Parse the user's idea of an offset for dynamic linking, into our idea @@ -722,7 +639,7 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) void default_symfile_offsets (struct objfile *objfile, - const struct section_addr_info *addrs) + const section_addr_info &addrs) { objfile->num_sections = gdb_bfd_count_sections (objfile->obfd); objfile->section_offsets = (struct section_offsets *) @@ -872,10 +789,10 @@ default_symfile_segments (bfd *abfd) possibly force the partial symbols to be read. */ static void -read_symbols (struct objfile *objfile, int add_flags) +read_symbols (struct objfile *objfile, symfile_add_flags add_flags) { (*objfile->sf->sym_read) (objfile, add_flags); - objfile->per_bfd->minsyms_read = 1; + objfile->per_bfd->minsyms_read = true; /* find_separate_debug_file_in_section should be called only if there is single binary with no existing separate debug info file. */ @@ -883,8 +800,7 @@ read_symbols (struct objfile *objfile, int add_flags) && objfile->separate_debug_objfile == NULL && objfile->separate_debug_objfile_backlink == NULL) { - bfd *abfd = find_separate_debug_file_in_section (objfile); - struct cleanup *cleanup = make_cleanup_bfd_unref (abfd); + gdb_bfd_ref_ptr abfd (find_separate_debug_file_in_section (objfile)); if (abfd != NULL) { @@ -892,11 +808,9 @@ read_symbols (struct objfile *objfile, int add_flags) virtual section-as-bfd like the bfd filename containing the section. Therefore use also non-canonical name form for the same file containing the section. */ - symbol_file_add_separate (abfd, objfile->original_name, add_flags, - objfile); + symbol_file_add_separate (abfd.get (), objfile->original_name, + add_flags, objfile); } - - do_cleanups (cleanup); } if ((add_flags & SYMFILE_NO_READ) == 0) require_partial_symbols (objfile, 0); @@ -949,7 +863,7 @@ init_entry_point_info (struct objfile *objfile) entry_point = gdbarch_convert_from_func_ptr_addr (get_objfile_arch (objfile), entry_point, - ¤t_target); + target_stack); /* Remove any ISA markers, so that this matches entries in the symbol table. */ @@ -1000,10 +914,10 @@ init_entry_point_info (struct objfile *objfile) static void syms_from_objfile_1 (struct objfile *objfile, - struct section_addr_info *addrs, - int add_flags) + section_addr_info *addrs, + symfile_add_flags add_flags) { - struct section_addr_info *local_addr = NULL; + section_addr_info local_addr; struct cleanup *old_chain; const int mainline = add_flags & SYMFILE_MAINLINE; @@ -1018,24 +932,22 @@ syms_from_objfile_1 (struct objfile *objfile, objfile->num_sections = num_sections; objfile->section_offsets - = obstack_alloc (&objfile->objfile_obstack, size); + = (struct section_offsets *) obstack_alloc (&objfile->objfile_obstack, + size); memset (objfile->section_offsets, 0, size); return; } /* 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); + old_chain = make_cleanup (null_cleanup, NULL); + std::unique_ptr objfile_holder (objfile); /* If ADDRS is NULL, put together a dummy address list. We now establish the convention that an addr of zero means no load address was specified. */ if (! addrs) - { - local_addr = alloc_section_addr_info (1); - make_cleanup (xfree, local_addr); - addrs = local_addr; - } + addrs = &local_addr; if (mainline) { @@ -1047,7 +959,7 @@ syms_from_objfile_1 (struct objfile *objfile, if (symfile_objfile != NULL) { - free_objfile (symfile_objfile); + delete symfile_objfile; gdb_assert (symfile_objfile == NULL); } @@ -1065,7 +977,7 @@ syms_from_objfile_1 (struct objfile *objfile, We no longer warn if the lowest section is not a text segment (as happens for the PA64 port. */ - if (addrs->num_sections > 0) + if (addrs->size () > 0) addr_info_make_relative (addrs, objfile->obfd); /* Initialize symbol reading routines for this objfile, allow complaints to @@ -1075,14 +987,14 @@ syms_from_objfile_1 (struct objfile *objfile, (*objfile->sf->sym_init) (objfile); clear_complaints (&symfile_complaints, 1, add_flags & SYMFILE_VERBOSE); - (*objfile->sf->sym_offsets) (objfile, addrs); + (*objfile->sf->sym_offsets) (objfile, *addrs); read_symbols (objfile, add_flags); /* Discard cleanups as symbol reading was successful. */ + objfile_holder.release (); discard_cleanups (old_chain); - xfree (local_addr); } /* Same as syms_from_objfile_1, but also initializes the objfile @@ -1090,8 +1002,8 @@ syms_from_objfile_1 (struct objfile *objfile, static void syms_from_objfile (struct objfile *objfile, - struct section_addr_info *addrs, - int add_flags) + section_addr_info *addrs, + symfile_add_flags add_flags) { syms_from_objfile_1 (objfile, addrs, add_flags); init_entry_point_info (objfile); @@ -1101,8 +1013,8 @@ syms_from_objfile (struct objfile *objfile, symbols for a new objfile, or mapping in the symbols from a reusable objfile. ADD_FLAGS is a bitmask of enum symfile_add_flags. */ -void -new_symfile_objfile (struct objfile *objfile, int add_flags) +static void +finish_new_objfile (struct objfile *objfile, symfile_add_flags add_flags) { /* If this is the main symbol file we have to clean up all users of the old main symbol file. Otherwise it is sufficient to fixup all the @@ -1129,7 +1041,7 @@ new_symfile_objfile (struct objfile *objfile, int add_flags) ABFD is a BFD already open on the file, as from symfile_bfd_open. A new reference is acquired by this function. - For NAME description see allocate_objfile's definition. + For NAME description see the objfile constructor. ADD_FLAGS encodes verbosity, whether this is main symbol file or extra, such as dynamically loaded code, and what to do with breakpoins. @@ -1144,9 +1056,10 @@ new_symfile_objfile (struct objfile *objfile, int add_flags) Upon failure, jumps back to command level (never returns). */ static struct objfile * -symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags, - struct section_addr_info *addrs, - int flags, struct objfile *parent) +symbol_file_add_with_addrs (bfd *abfd, const char *name, + symfile_add_flags add_flags, + section_addr_info *addrs, + objfile_flags flags, struct objfile *parent) { struct objfile *objfile; const int from_tty = add_flags & SYMFILE_VERBOSE; @@ -1160,6 +1073,12 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags, flags |= OBJF_READNOW; add_flags &= ~SYMFILE_NO_READ; } + else if (readnever_symbol_files + || (parent != NULL && (parent->flags & OBJF_READNEVER))) + { + flags |= OBJF_READNEVER; + add_flags |= SYMFILE_NO_READ; + } /* Give user a chance to burp if we'd be interactively wiping out any existing symbols. */ @@ -1170,8 +1089,9 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags, && !query (_("Load new symbol table from \"%s\"? "), name)) error (_("Not confirmed.")); - objfile = allocate_objfile (abfd, name, - flags | (mainline ? OBJF_MAINLINE : 0)); + if (mainline) + flags |= OBJF_MAINLINE; + objfile = new struct objfile (abfd, name, flags); if (parent) add_separate_debug_objfile (objfile, parent); @@ -1232,42 +1152,36 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags, if (objfile->sf == NULL) { - observer_notify_new_objfile (objfile); + gdb::observers::new_objfile.notify (objfile); return objfile; /* No symbols. */ } - new_symfile_objfile (objfile, add_flags); + finish_new_objfile (objfile, add_flags); - observer_notify_new_objfile (objfile); + gdb::observers::new_objfile.notify (objfile); bfd_cache_close_all (); return (objfile); } /* Add BFD as a separate debug file for OBJFILE. For NAME description - see allocate_objfile's definition. */ + see the objfile constructor. */ void -symbol_file_add_separate (bfd *bfd, const char *name, int symfile_flags, +symbol_file_add_separate (bfd *bfd, const char *name, + symfile_add_flags symfile_flags, struct objfile *objfile) { - struct objfile *new_objfile; - struct section_addr_info *sap; - struct cleanup *my_cleanup; - /* Create section_addr_info. We can't directly use offsets from OBJFILE because sections of BFD may not match sections of OBJFILE and because vma may have been modified by tools such as prelink. */ - sap = build_section_addr_info_from_objfile (objfile); - my_cleanup = make_cleanup_free_section_addr_info (sap); + section_addr_info sap = build_section_addr_info_from_objfile (objfile); - new_objfile = symbol_file_add_with_addrs - (bfd, name, symfile_flags, sap, + symbol_file_add_with_addrs + (bfd, name, symfile_flags, &sap, objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW | OBJF_USERLOADED), objfile); - - do_cleanups (my_cleanup); } /* Process the symbol file ABFD, as either the main file or as a @@ -1275,9 +1189,10 @@ symbol_file_add_separate (bfd *bfd, const char *name, int symfile_flags, See symbol_file_add_with_addrs's comments for details. */ struct objfile * -symbol_file_add_from_bfd (bfd *abfd, const char *name, int add_flags, - struct section_addr_info *addrs, - int flags, struct objfile *parent) +symbol_file_add_from_bfd (bfd *abfd, const char *name, + symfile_add_flags add_flags, + section_addr_info *addrs, + objfile_flags flags, struct objfile *parent) { return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags, parent); @@ -1287,16 +1202,13 @@ symbol_file_add_from_bfd (bfd *abfd, const char *name, int add_flags, loaded file. See symbol_file_add_with_addrs's comments for details. */ struct objfile * -symbol_file_add (const char *name, int add_flags, - struct section_addr_info *addrs, int flags) +symbol_file_add (const char *name, symfile_add_flags add_flags, + section_addr_info *addrs, objfile_flags flags) { - bfd *bfd = symfile_bfd_open (name); - struct cleanup *cleanup = make_cleanup_bfd_unref (bfd); - struct objfile *objf; + gdb_bfd_ref_ptr bfd (symfile_bfd_open (name)); - objf = symbol_file_add_from_bfd (bfd, name, add_flags, addrs, flags, NULL); - do_cleanups (cleanup); - return objf; + return symbol_file_add_from_bfd (bfd.get (), name, add_flags, addrs, + flags, NULL); } /* Call symbol_file_add() with default values and update whatever is @@ -1308,16 +1220,16 @@ symbol_file_add (const char *name, int add_flags, command itself. */ void -symbol_file_add_main (const char *args, int from_tty) +symbol_file_add_main (const char *args, symfile_add_flags add_flags) { - symbol_file_add_main_1 (args, from_tty, 0); + symbol_file_add_main_1 (args, add_flags, 0); } static void -symbol_file_add_main_1 (const char *args, int from_tty, int flags) +symbol_file_add_main_1 (const char *args, symfile_add_flags add_flags, + objfile_flags flags) { - const int add_flags = (current_inferior ()->symfile_flags - | SYMFILE_MAINLINE | (from_tty ? SYMFILE_VERBOSE : 0)); + add_flags |= current_inferior ()->symfile_flags | SYMFILE_MAINLINE; symbol_file_add (args, add_flags, NULL, flags); @@ -1325,7 +1237,7 @@ symbol_file_add_main_1 (const char *args, int from_tty, int flags) what is frameless. */ reinit_frame_cache (); - if ((flags & SYMFILE_NO_READ) == 0) + if ((add_flags & SYMFILE_NO_READ) == 0) set_initial_language (); } @@ -1351,13 +1263,16 @@ symbol_file_clear (int from_tty) printf_unfiltered (_("No symbol file now.\n")); } +/* See symfile.h. */ + +int separate_debug_file_debug = 0; + static int -separate_debug_file_exists (const char *name, unsigned long crc, +separate_debug_file_exists (const std::string &name, unsigned long crc, struct objfile *parent_objfile) { unsigned long file_crc; int file_crc_p; - bfd *abfd; struct stat parent_stat, abfd_stat; int verified_as_different; @@ -1367,42 +1282,41 @@ separate_debug_file_exists (const char *name, unsigned long crc, ".debug" suffix as "/usr/lib/debug/path/to/file" is a separate tree where the separate debug infos with the same basename can exist. */ - if (filename_cmp (name, objfile_name (parent_objfile)) == 0) + if (filename_cmp (name.c_str (), objfile_name (parent_objfile)) == 0) return 0; - abfd = gdb_bfd_open_maybe_remote (name); + if (separate_debug_file_debug) + printf_unfiltered (_(" Trying %s\n"), name.c_str ()); + + gdb_bfd_ref_ptr abfd (gdb_bfd_open (name.c_str (), gnutarget, -1)); - if (!abfd) + if (abfd == NULL) return 0; /* Verify symlinks were not the cause of filename_cmp name difference above. Some operating systems, e.g. Windows, do not provide a meaningful st_ino; they always set it to zero. (Windows does provide a - meaningful st_dev.) Do not indicate a duplicate library in that - case. While there is no guarantee that a system that provides - meaningful inode numbers will never set st_ino to zero, this is - merely an optimization, so we do not need to worry about false - negatives. */ - - if (bfd_stat (abfd, &abfd_stat) == 0 + meaningful st_dev.) Files accessed from gdbservers that do not + support the vFile:fstat packet will also have st_ino set to zero. + Do not indicate a duplicate library in either case. While there + is no guarantee that a system that provides meaningful inode + numbers will never set st_ino to zero, this is merely an + optimization, so we do not need to worry about false negatives. */ + + if (bfd_stat (abfd.get (), &abfd_stat) == 0 && abfd_stat.st_ino != 0 && bfd_stat (parent_objfile->obfd, &parent_stat) == 0) { if (abfd_stat.st_dev == parent_stat.st_dev && abfd_stat.st_ino == parent_stat.st_ino) - { - gdb_bfd_unref (abfd); - return 0; - } + return 0; verified_as_different = 1; } else verified_as_different = 0; - file_crc_p = gdb_bfd_crc (abfd, &file_crc); - - gdb_bfd_unref (abfd); + file_crc_p = gdb_bfd_crc (abfd.get (), &file_crc); if (!file_crc_p) return 0; @@ -1411,9 +1325,9 @@ separate_debug_file_exists (const char *name, unsigned long crc, { unsigned long parent_crc; - /* If one (or both) the files are accessed for example the via "remote:" - gdbserver way it does not support the bfd_stat operation. Verify - whether those two files are not the same manually. */ + /* If the files could not be verified as different with + bfd_stat then we need to calculate the parent's CRC + to verify whether the files are different or not. */ if (!verified_as_different) { @@ -1424,7 +1338,7 @@ separate_debug_file_exists (const char *name, unsigned long crc, if (verified_as_different || parent_crc != file_crc) warning (_("the debug information found in \"%s\"" " does not match \"%s\" (CRC mismatch).\n"), - name, objfile_name (parent_objfile)); + name.c_str (), objfile_name (parent_objfile)); return 0; } @@ -1452,45 +1366,31 @@ show_debug_file_directory (struct ui_file *file, int from_tty, dirname(objfile->name) due to symlinks), and DEBUGLINK as the file we are looking for. CANON_DIR is the "realpath" form of DIR. DIR must contain a trailing '/'. - Returns the path of the file with separate debug info, of NULL. */ + Returns the path of the file with separate debug info, or an empty + string. */ -static char * +static std::string find_separate_debug_file (const char *dir, const char *canon_dir, const char *debuglink, unsigned long crc32, struct objfile *objfile) { - char *debugdir; - char *debugfile; - int i; - VEC (char_ptr) *debugdir_vec; - struct cleanup *back_to; - int ix; - - /* Set I to max (strlen (canon_dir), strlen (dir)). */ - i = strlen (dir); - if (canon_dir != NULL && strlen (canon_dir) > i) - i = strlen (canon_dir); - - debugfile = xmalloc (strlen (debug_file_directory) + 1 - + i - + strlen (DEBUG_SUBDIRECTORY) - + strlen ("/") - + strlen (debuglink) - + 1); + if (separate_debug_file_debug) + printf_unfiltered (_("\nLooking for separate debug info (debug link) for " + "%s\n"), objfile_name (objfile)); /* First try in the same directory as the original file. */ - strcpy (debugfile, dir); - strcat (debugfile, debuglink); + std::string debugfile = dir; + debugfile += debuglink; if (separate_debug_file_exists (debugfile, crc32, objfile)) return debugfile; /* Then try in the subdirectory named DEBUG_SUBDIRECTORY. */ - strcpy (debugfile, dir); - strcat (debugfile, DEBUG_SUBDIRECTORY); - strcat (debugfile, "/"); - strcat (debugfile, debuglink); + debugfile = dir; + debugfile += DEBUG_SUBDIRECTORY; + debugfile += "/"; + debugfile += debuglink; if (separate_debug_file_exists (debugfile, crc32, objfile)) return debugfile; @@ -1500,21 +1400,18 @@ find_separate_debug_file (const char *dir, Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will cause "/..." lookups. */ - debugdir_vec = dirnames_to_char_ptr_vec (debug_file_directory); - back_to = make_cleanup_free_char_ptr_vec (debugdir_vec); + std::vector> debugdir_vec + = dirnames_to_char_ptr_vec (debug_file_directory); - for (ix = 0; VEC_iterate (char_ptr, debugdir_vec, ix, debugdir); ++ix) + for (const gdb::unique_xmalloc_ptr &debugdir : debugdir_vec) { - strcpy (debugfile, debugdir); - strcat (debugfile, "/"); - strcat (debugfile, dir); - strcat (debugfile, debuglink); + debugfile = debugdir.get (); + debugfile += "/"; + debugfile += dir; + debugfile += debuglink; if (separate_debug_file_exists (debugfile, crc32, objfile)) - { - do_cleanups (back_to); - return debugfile; - } + return debugfile; /* If the file is in the sysroot, try using its base path in the global debugfile directory. */ @@ -1523,22 +1420,17 @@ find_separate_debug_file (const char *dir, strlen (gdb_sysroot)) == 0 && IS_DIR_SEPARATOR (canon_dir[strlen (gdb_sysroot)])) { - strcpy (debugfile, debugdir); - strcat (debugfile, canon_dir + strlen (gdb_sysroot)); - strcat (debugfile, "/"); - strcat (debugfile, debuglink); + debugfile = debugdir.get (); + debugfile += (canon_dir + strlen (gdb_sysroot)); + debugfile += "/"; + debugfile += debuglink; if (separate_debug_file_exists (debugfile, crc32, objfile)) - { - do_cleanups (back_to); - return debugfile; - } + return debugfile; } } - do_cleanups (back_to); - xfree (debugfile); - return NULL; + return std::string (); } /* Modify PATH to contain only "[/]directory/" part of PATH. @@ -1561,39 +1453,33 @@ terminate_after_last_dir_separator (char *path) } /* Find separate debuginfo for OBJFILE (using .gnu_debuglink section). - Returns pathname, or NULL. */ + Returns pathname, or an empty string. */ -char * +std::string find_separate_debug_file_by_debuglink (struct objfile *objfile) { - char *debuglink; - char *dir, *canon_dir; - char *debugfile; unsigned long crc32; - struct cleanup *cleanups; - debuglink = bfd_get_debug_link_info (objfile->obfd, &crc32); + gdb::unique_xmalloc_ptr debuglink + (bfd_get_debug_link_info (objfile->obfd, &crc32)); if (debuglink == NULL) { /* There's no separate debug info, hence there's no way we could load it => no warning. */ - return NULL; + return std::string (); } - cleanups = make_cleanup (xfree, debuglink); - dir = xstrdup (objfile_name (objfile)); - make_cleanup (xfree, dir); - terminate_after_last_dir_separator (dir); - canon_dir = lrealpath (dir); + std::string dir = objfile_name (objfile); + terminate_after_last_dir_separator (&dir[0]); + gdb::unique_xmalloc_ptr canon_dir (lrealpath (dir.c_str ())); - debugfile = find_separate_debug_file (dir, canon_dir, debuglink, - crc32, objfile); - xfree (canon_dir); + std::string debugfile + = find_separate_debug_file (dir.c_str (), canon_dir.get (), + debuglink.get (), crc32, objfile); - if (debugfile == NULL) + if (debugfile.empty ()) { -#ifdef HAVE_LSTAT /* For PR gdb/9538, try again with realpath (if different from the original). */ @@ -1602,31 +1488,37 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) if (lstat (objfile_name (objfile), &st_buf) == 0 && S_ISLNK (st_buf.st_mode)) { - char *symlink_dir; - - symlink_dir = lrealpath (objfile_name (objfile)); + gdb::unique_xmalloc_ptr symlink_dir + (lrealpath (objfile_name (objfile))); if (symlink_dir != NULL) { - make_cleanup (xfree, symlink_dir); - terminate_after_last_dir_separator (symlink_dir); - if (strcmp (dir, symlink_dir) != 0) + terminate_after_last_dir_separator (symlink_dir.get ()); + if (dir != symlink_dir.get ()) { /* Different directory, so try using it. */ - debugfile = find_separate_debug_file (symlink_dir, - symlink_dir, - debuglink, + debugfile = find_separate_debug_file (symlink_dir.get (), + symlink_dir.get (), + debuglink.get (), crc32, objfile); } } } -#endif /* HAVE_LSTAT */ } - do_cleanups (cleanups); return debugfile; } +/* Make sure that OBJF_{READNOW,READNEVER} are not set + simultaneously. */ + +static void +validate_readnow_readnever (objfile_flags flags) +{ + if ((flags & OBJF_READNOW) && (flags & OBJF_READNEVER)) + error (_("-readnow and -readnever cannot be used simultaneously")); +} + /* This is the symbol-file command. Read the file, analyze its symbols, and add a struct symtab to a symtab list. The syntax of the command is rather bizarre: @@ -1642,7 +1534,7 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) conventions (because it is confusing and inconvenient). */ void -symbol_file_command (char *args, int from_tty) +symbol_file_command (const char *args, int from_tty) { dont_repeat (); @@ -1652,31 +1544,42 @@ symbol_file_command (char *args, int from_tty) } else { - char **argv = gdb_buildargv (args); - int flags = OBJF_USERLOADED; - struct cleanup *cleanups; + objfile_flags flags = OBJF_USERLOADED; + symfile_add_flags add_flags = 0; char *name = NULL; + bool stop_processing_options = false; + int idx; + char *arg; + + if (from_tty) + add_flags |= SYMFILE_VERBOSE; - cleanups = make_cleanup_freeargv (argv); - while (*argv != NULL) + gdb_argv built_argv (args); + for (arg = built_argv[0], idx = 0; arg != NULL; arg = built_argv[++idx]) { - if (strcmp (*argv, "-readnow") == 0) - flags |= OBJF_READNOW; - else if (**argv == '-') - error (_("unknown option `%s'"), *argv); - else + if (stop_processing_options || *arg != '-') { - symbol_file_add_main_1 (*argv, from_tty, flags); - name = *argv; + if (name == NULL) + name = arg; + else + error (_("Unrecognized argument \"%s\""), arg); } - - argv++; + else if (strcmp (arg, "-readnow") == 0) + flags |= OBJF_READNOW; + else if (strcmp (arg, "-readnever") == 0) + flags |= OBJF_READNEVER; + else if (strcmp (arg, "--") == 0) + stop_processing_options = true; + else + error (_("Unrecognized argument \"%s\""), arg); } if (name == NULL) error (_("no symbol file name was specified")); - do_cleanups (cleanups); + validate_readnow_readnever (flags); + + symbol_file_add_main_1 (name, add_flags, flags); } } @@ -1699,7 +1602,7 @@ set_initial_language (void) if (lang == language_unknown) { char *name = main_name (); - struct symbol *sym = lookup_symbol (name, NULL, VAR_DOMAIN, NULL); + struct symbol *sym = lookup_symbol (name, NULL, VAR_DOMAIN, NULL).symbol; if (sym != NULL) lang = SYMBOL_LANGUAGE (sym); @@ -1715,92 +1618,53 @@ set_initial_language (void) expected_language = current_language; /* Don't warn the user. */ } -/* If NAME is a remote name open the file using remote protocol, otherwise - open it normally. Returns a new reference to the BFD. On error, - returns NULL with the BFD error set. */ - -bfd * -gdb_bfd_open_maybe_remote (const char *name) -{ - bfd *result; - - if (remote_filename_p (name)) - result = remote_bfd_open (name, gnutarget); - else - result = gdb_bfd_open (name, gnutarget, -1); - - return result; -} - /* Open the file specified by NAME and hand it off to BFD for preliminary analysis. Return a newly initialized bfd *, which includes a newly malloc'd` copy of NAME (tilde-expanded and made absolute). In case of trouble, error() is called. */ -bfd * -symfile_bfd_open (const char *cname) +gdb_bfd_ref_ptr +symfile_bfd_open (const char *name) { - bfd *sym_bfd; - int desc; - char *name, *absolute_name; - struct cleanup *back_to; + int desc = -1; - if (remote_filename_p (cname)) + gdb::unique_xmalloc_ptr absolute_name; + if (!is_target_filename (name)) { - sym_bfd = remote_bfd_open (cname, gnutarget); - if (!sym_bfd) - error (_("`%s': can't open to read symbols: %s."), cname, - bfd_errmsg (bfd_get_error ())); - - if (!bfd_check_format (sym_bfd, bfd_object)) - { - make_cleanup_bfd_unref (sym_bfd); - error (_("`%s': can't read symbols: %s."), cname, - bfd_errmsg (bfd_get_error ())); - } + gdb::unique_xmalloc_ptr expanded_name (tilde_expand (name)); - return sym_bfd; - } - - name = tilde_expand (cname); /* Returns 1st new malloc'd copy. */ - - /* Look down path for it, allocate 2nd new malloc'd copy. */ - desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, name, - O_RDONLY | O_BINARY, &absolute_name); + /* Look down path for it, allocate 2nd new malloc'd copy. */ + desc = openp (getenv ("PATH"), + OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, + expanded_name.get (), O_RDONLY | O_BINARY, &absolute_name); #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__) - if (desc < 0) - { - char *exename = alloca (strlen (name) + 5); + if (desc < 0) + { + char *exename = (char *) alloca (strlen (expanded_name.get ()) + 5); - strcat (strcpy (exename, name), ".exe"); - desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, - exename, O_RDONLY | O_BINARY, &absolute_name); - } + strcat (strcpy (exename, expanded_name.get ()), ".exe"); + desc = openp (getenv ("PATH"), + OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, + exename, O_RDONLY | O_BINARY, &absolute_name); + } #endif - if (desc < 0) - { - make_cleanup (xfree, name); - perror_with_name (name); - } + if (desc < 0) + perror_with_name (expanded_name.get ()); - xfree (name); - name = absolute_name; - back_to = make_cleanup (xfree, name); + name = absolute_name.get (); + } - sym_bfd = gdb_bfd_open (name, gnutarget, desc); - if (!sym_bfd) + gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (name, gnutarget, desc)); + if (sym_bfd == NULL) error (_("`%s': can't open to read symbols: %s."), name, bfd_errmsg (bfd_get_error ())); - bfd_set_cacheable (sym_bfd, 1); - if (!bfd_check_format (sym_bfd, bfd_object)) - { - make_cleanup_bfd_unref (sym_bfd); - error (_("`%s': can't read symbols: %s."), name, - bfd_errmsg (bfd_get_error ())); - } + if (!gdb_bfd_has_target_filename (sym_bfd.get ())) + bfd_set_cacheable (sym_bfd.get (), 1); - do_cleanups (back_to); + if (!bfd_check_format (sym_bfd.get (), bfd_object)) + error (_("`%s': can't read symbols: %s."), name, + bfd_errmsg (bfd_get_error ())); return sym_bfd; } @@ -1809,7 +1673,7 @@ symfile_bfd_open (const char *cname) the section was not found. */ int -get_section_index (struct objfile *objfile, char *section_name) +get_section_index (struct objfile *objfile, const char *section_name) { asection *sect = bfd_get_section_by_name (objfile->obfd, section_name); @@ -1828,9 +1692,7 @@ get_section_index (struct objfile *objfile, char *section_name) void add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf) { - registered_sym_fns fns = { flavour, sf }; - - VEC_safe_push (registered_sym_fns, symtab_fns, &fns); + symtab_fns.emplace_back (flavour, sf); } /* Initialize OBJFILE to read symbols from its associated BFD. It @@ -1841,18 +1703,16 @@ add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf) static const struct sym_fns * find_sym_fns (bfd *abfd) { - registered_sym_fns *rsf; enum bfd_flavour our_flavour = bfd_get_flavour (abfd); - int i; if (our_flavour == bfd_target_srec_flavour || our_flavour == bfd_target_ihex_flavour || our_flavour == bfd_target_tekhex_flavour) return NULL; /* No symbols. */ - for (i = 0; VEC_iterate (registered_sym_fns, symtab_fns, i, rsf); ++i) - if (our_flavour == rsf->sym_flavour) - return rsf->sym_fns; + for (const registered_sym_fns &rsf : symtab_fns) + if (our_flavour == rsf.sym_flavour) + return rsf.sym_fns; error (_("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown."), bfd_get_target (abfd)); @@ -1862,10 +1722,8 @@ find_sym_fns (bfd *abfd) /* This function runs the load command of our current target. */ static void -load_command (char *arg, int from_tty) +load_command (const char *arg, int from_tty) { - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); - dont_repeat (); /* The user might be reloading because the binary has changed. Take @@ -1873,40 +1731,28 @@ load_command (char *arg, int from_tty) reopen_exec_file (); reread_symbols (); + std::string temp; if (arg == NULL) { - char *parg; - int count = 0; + const char *parg, *prev; - parg = arg = get_exec_file (1); + arg = get_exec_file (1); - /* Count how many \ " ' tab space there are in the name. */ + /* We may need to quote this string so buildargv can pull it + apart. */ + prev = parg = arg; while ((parg = strpbrk (parg, "\\\"'\t "))) { - parg++; - count++; + temp.append (prev, parg - prev); + prev = parg++; + temp.push_back ('\\'); } - - if (count) + /* If we have not copied anything yet, then we didn't see a + character to quote, and we can just leave ARG unchanged. */ + if (!temp.empty ()) { - /* We need to quote this string so buildargv can pull it apart. */ - char *temp = xmalloc (strlen (arg) + count + 1 ); - char *ptemp = temp; - char *prev; - - make_cleanup (xfree, temp); - - prev = parg = arg; - while ((parg = strpbrk (parg, "\\\"'\t "))) - { - strncpy (ptemp, prev, parg - prev); - ptemp += parg - prev; - prev = parg++; - *ptemp++ = '\\'; - } - strcpy (ptemp, prev); - - arg = temp; + temp.append (prev); + arg = temp.c_str (); } } @@ -1915,8 +1761,6 @@ load_command (char *arg, int from_tty) /* After re-loading the executable, we don't really know which overlays are mapped any more. */ overlay_cache_invalid = 1; - - do_cleanups (cleanup); } /* This version of "load" should be usable for any target. Currently @@ -1935,44 +1779,68 @@ static int validate_download = 0; static void add_section_size_callback (bfd *abfd, asection *asec, void *data) { - bfd_size_type *sum = data; + bfd_size_type *sum = (bfd_size_type *) data; *sum += bfd_get_section_size (asec); } -/* Opaque data for load_section_callback. */ -struct load_section_data { - CORE_ADDR load_offset; - struct load_progress_data *progress_data; - VEC(memory_write_request_s) *requests; -}; - /* Opaque data for load_progress. */ -struct load_progress_data { +struct load_progress_data +{ /* Cumulative data. */ - unsigned long write_count; - unsigned long data_count; - bfd_size_type total_size; + unsigned long write_count = 0; + unsigned long data_count = 0; + bfd_size_type total_size = 0; }; /* Opaque data for load_progress for a single section. */ -struct load_progress_section_data { +struct load_progress_section_data +{ + load_progress_section_data (load_progress_data *cumulative_, + const char *section_name_, ULONGEST section_size_, + CORE_ADDR lma_, gdb_byte *buffer_) + : cumulative (cumulative_), section_name (section_name_), + section_size (section_size_), lma (lma_), buffer (buffer_) + {} + struct load_progress_data *cumulative; /* Per-section data. */ const char *section_name; - ULONGEST section_sent; + ULONGEST section_sent = 0; ULONGEST section_size; CORE_ADDR lma; gdb_byte *buffer; }; +/* Opaque data for load_section_callback. */ +struct load_section_data +{ + load_section_data (load_progress_data *progress_data_) + : progress_data (progress_data_) + {} + + ~load_section_data () + { + for (auto &&request : requests) + { + xfree (request.data); + delete ((load_progress_section_data *) request.baton); + } + } + + CORE_ADDR load_offset = 0; + struct load_progress_data *progress_data; + std::vector requests; +}; + /* Target write callback routine for progress reporting. */ static void load_progress (ULONGEST bytes, void *untyped_arg) { - struct load_progress_section_data *args = untyped_arg; + struct load_progress_section_data *args + = (struct load_progress_section_data *) untyped_arg; struct load_progress_data *totals; if (args == NULL) @@ -1986,9 +1854,10 @@ load_progress (ULONGEST bytes, void *untyped_arg) { /* The write is just starting. Let the user know we've started this section. */ - ui_out_message (current_uiout, 0, "Loading section %s, size %s lma %s\n", - args->section_name, hex_string (args->section_size), - paddress (target_gdbarch (), args->lma)); + current_uiout->message ("Loading section %s, size %s lma %s\n", + args->section_name, + hex_string (args->section_size), + paddress (target_gdbarch (), args->lma)); return; } @@ -2001,16 +1870,14 @@ load_progress (ULONGEST bytes, void *untyped_arg) might add a verify_memory() method to the target vector and then use that. remote.c could implement that method using the ``qCRC'' packet. */ - gdb_byte *check = xmalloc (bytes); - struct cleanup *verify_cleanups = make_cleanup (xfree, check); + gdb::byte_vector check (bytes); - if (target_read_memory (args->lma, check, bytes) != 0) + if (target_read_memory (args->lma, check.data (), bytes) != 0) error (_("Download verify read failed at %s"), paddress (target_gdbarch (), args->lma)); - if (memcmp (args->buffer, check, bytes) != 0) + if (memcmp (args->buffer, check.data (), bytes) != 0) error (_("Download verify compare failed at %s"), paddress (target_gdbarch (), args->lma)); - do_cleanups (verify_cleanups); } totals->data_count += bytes; args->lma += bytes; @@ -2036,11 +1903,8 @@ load_progress (ULONGEST bytes, void *untyped_arg) static void load_section_callback (bfd *abfd, asection *asec, void *data) { - struct memory_write_request *new_request; - struct load_section_data *args = data; - struct load_progress_section_data *section_data; + struct load_section_data *args = (struct load_section_data *) data; bfd_size_type size = bfd_get_section_size (asec); - gdb_byte *buffer; const char *sect_name = bfd_get_section_name (abfd, asec); if ((bfd_get_section_flags (abfd, asec) & SEC_LOAD) == 0) @@ -2049,74 +1913,36 @@ load_section_callback (bfd *abfd, asection *asec, void *data) if (size == 0) return; - new_request = VEC_safe_push (memory_write_request_s, - args->requests, NULL); - memset (new_request, 0, sizeof (struct memory_write_request)); - section_data = xcalloc (1, sizeof (struct load_progress_section_data)); - new_request->begin = bfd_section_lma (abfd, asec) + args->load_offset; - new_request->end = new_request->begin + size; /* FIXME Should size - be in instead? */ - new_request->data = xmalloc (size); - new_request->baton = section_data; - - buffer = new_request->data; - - section_data->cumulative = args->progress_data; - section_data->section_name = sect_name; - section_data->section_size = size; - section_data->lma = new_request->begin; - section_data->buffer = buffer; - + ULONGEST begin = bfd_section_lma (abfd, asec) + args->load_offset; + ULONGEST end = begin + size; + gdb_byte *buffer = (gdb_byte *) xmalloc (size); bfd_get_section_contents (abfd, asec, buffer, 0, size); -} -/* Clean up an entire memory request vector, including load - data and progress records. */ + load_progress_section_data *section_data + = new load_progress_section_data (args->progress_data, sect_name, size, + begin, buffer); -static void -clear_memory_write_data (void *arg) -{ - VEC(memory_write_request_s) **vec_p = arg; - VEC(memory_write_request_s) *vec = *vec_p; - int i; - struct memory_write_request *mr; - - for (i = 0; VEC_iterate (memory_write_request_s, vec, i, mr); ++i) - { - xfree (mr->data); - xfree (mr->baton); - } - VEC_free (memory_write_request_s, vec); + args->requests.emplace_back (begin, end, buffer, section_data); } +static void print_transfer_performance (struct ui_file *stream, + unsigned long data_count, + unsigned long write_count, + std::chrono::steady_clock::duration d); + void -generic_load (char *args, int from_tty) +generic_load (const char *args, int from_tty) { - bfd *loadfile_bfd; - struct timeval start_time, end_time; - char *filename; - struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0); - struct load_section_data cbdata; struct load_progress_data total_progress; + struct load_section_data cbdata (&total_progress); struct ui_out *uiout = current_uiout; - CORE_ADDR entry; - char **argv; - - memset (&cbdata, 0, sizeof (cbdata)); - memset (&total_progress, 0, sizeof (total_progress)); - cbdata.progress_data = &total_progress; - - make_cleanup (clear_memory_write_data, &cbdata.requests); - if (args == NULL) error_no_arg (_("file to load")); - argv = gdb_buildargv (args); - make_cleanup_freeargv (argv); + gdb_argv argv (args); - filename = tilde_expand (argv[0]); - make_cleanup (xfree, filename); + gdb::unique_xmalloc_ptr filename (tilde_expand (argv[0])); if (argv[1] != NULL) { @@ -2134,43 +1960,38 @@ generic_load (char *args, int from_tty) } /* Open the file for loading. */ - loadfile_bfd = gdb_bfd_open (filename, gnutarget, -1); + gdb_bfd_ref_ptr loadfile_bfd (gdb_bfd_open (filename.get (), gnutarget, -1)); if (loadfile_bfd == NULL) - { - perror_with_name (filename); - return; - } - - make_cleanup_bfd_unref (loadfile_bfd); + perror_with_name (filename.get ()); - if (!bfd_check_format (loadfile_bfd, bfd_object)) + if (!bfd_check_format (loadfile_bfd.get (), bfd_object)) { - error (_("\"%s\" is not an object file: %s"), filename, + error (_("\"%s\" is not an object file: %s"), filename.get (), bfd_errmsg (bfd_get_error ())); } - bfd_map_over_sections (loadfile_bfd, add_section_size_callback, + bfd_map_over_sections (loadfile_bfd.get (), add_section_size_callback, (void *) &total_progress.total_size); - bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata); + bfd_map_over_sections (loadfile_bfd.get (), load_section_callback, &cbdata); + + using namespace std::chrono; - gettimeofday (&start_time, NULL); + steady_clock::time_point start_time = steady_clock::now (); if (target_write_memory_blocks (cbdata.requests, flash_discard, load_progress) != 0) error (_("Load failed")); - gettimeofday (&end_time, NULL); + steady_clock::time_point end_time = steady_clock::now (); - entry = bfd_get_start_address (loadfile_bfd); + CORE_ADDR entry = bfd_get_start_address (loadfile_bfd.get ()); entry = gdbarch_addr_bits_remove (target_gdbarch (), entry); - ui_out_text (uiout, "Start address "); - ui_out_field_fmt (uiout, "address", "%s", paddress (target_gdbarch (), entry)); - ui_out_text (uiout, ", load size "); - ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count); - ui_out_text (uiout, "\n"); - /* We were doing this in remote-mips.c, I suspect it is right - for other targets too. */ + uiout->text ("Start address "); + uiout->field_fmt ("address", "%s", paddress (target_gdbarch (), entry)); + uiout->text (", load size "); + uiout->field_fmt ("load-size", "%lu", total_progress.data_count); + uiout->text ("\n"); regcache_write_pc (get_current_regcache (), entry); /* Reset breakpoints, now that we have changed the load image. For @@ -2183,69 +2004,61 @@ generic_load (char *args, int from_tty) 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 - file is loaded in. Some targets do (e.g., remote-vx.c) but - others don't (or didn't - perhaps they have all been deleted). */ - print_transfer_performance (gdb_stdout, total_progress.data_count, total_progress.write_count, - &start_time, &end_time); - - do_cleanups (old_cleanups); + end_time - start_time); } -/* Report how fast the transfer went. */ +/* Report on STREAM the performance of a memory transfer operation, + such as 'load'. DATA_COUNT is the number of bytes transferred. + WRITE_COUNT is the number of separate write operations, or 0, if + that information is not available. TIME is how long the operation + lasted. */ -void +static void print_transfer_performance (struct ui_file *stream, unsigned long data_count, unsigned long write_count, - const struct timeval *start_time, - const struct timeval *end_time) + std::chrono::steady_clock::duration time) { - ULONGEST time_count; + using namespace std::chrono; struct ui_out *uiout = current_uiout; - /* Compute the elapsed time in milliseconds, as a tradeoff between - accuracy and overflow. */ - time_count = (end_time->tv_sec - start_time->tv_sec) * 1000; - time_count += (end_time->tv_usec - start_time->tv_usec) / 1000; + milliseconds ms = duration_cast (time); - ui_out_text (uiout, "Transfer rate: "); - if (time_count > 0) + uiout->text ("Transfer rate: "); + if (ms.count () > 0) { - unsigned long rate = ((ULONGEST) data_count * 1000) / time_count; + unsigned long rate = ((ULONGEST) data_count * 1000) / ms.count (); - if (ui_out_is_mi_like_p (uiout)) + if (uiout->is_mi_like_p ()) { - ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate * 8); - ui_out_text (uiout, " bits/sec"); + uiout->field_fmt ("transfer-rate", "%lu", rate * 8); + uiout->text (" bits/sec"); } else if (rate < 1024) { - ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate); - ui_out_text (uiout, " bytes/sec"); + uiout->field_fmt ("transfer-rate", "%lu", rate); + uiout->text (" bytes/sec"); } else { - ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate / 1024); - ui_out_text (uiout, " KB/sec"); + uiout->field_fmt ("transfer-rate", "%lu", rate / 1024); + uiout->text (" KB/sec"); } } else { - ui_out_field_fmt (uiout, "transferred-bits", "%lu", (data_count * 8)); - ui_out_text (uiout, " bits in <1 sec"); + uiout->field_fmt ("transferred-bits", "%lu", (data_count * 8)); + uiout->text (" bits in <1 sec"); } if (write_count > 0) { - ui_out_text (uiout, ", "); - ui_out_field_fmt (uiout, "write-rate", "%lu", data_count / write_count); - ui_out_text (uiout, " bytes/write"); + uiout->text (", "); + uiout->field_fmt ("write-rate", "%lu", data_count / write_count); + uiout->text (" bytes/write"); } - ui_out_text (uiout, ".\n"); + uiout->text (".\n"); } /* This function allows the addition of incrementally linked object files. @@ -2258,109 +2071,89 @@ print_transfer_performance (struct ui_file *stream, value to use. We are now discontinuing this type of ad hoc syntax. */ static void -add_symbol_file_command (char *args, int from_tty) +add_symbol_file_command (const char *args, int from_tty) { struct gdbarch *gdbarch = get_current_arch (); - char *filename = NULL; - int flags = OBJF_USERLOADED | OBJF_SHARED; + gdb::unique_xmalloc_ptr filename; char *arg; - int section_index = 0; int argcnt = 0; - int sec_num = 0; - int i; - int expecting_sec_name = 0; - int expecting_sec_addr = 0; - char **argv; struct objfile *objf; + objfile_flags flags = OBJF_USERLOADED | OBJF_SHARED; + symfile_add_flags add_flags = 0; + + if (from_tty) + add_flags |= SYMFILE_VERBOSE; struct sect_opt { - char *name; - char *value; + const char *name; + const char *value; }; - struct section_addr_info *section_addrs; - struct sect_opt *sect_opts = NULL; - size_t num_sect_opts = 0; - struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL); - - num_sect_opts = 16; - sect_opts = (struct sect_opt *) xmalloc (num_sect_opts - * sizeof (struct sect_opt)); + std::vector sect_opts = { { ".text", NULL } }; + bool stop_processing_options = false; dont_repeat (); if (args == NULL) error (_("add-symbol-file takes a file name and an address")); - argv = gdb_buildargv (args); - make_cleanup_freeargv (argv); + bool seen_addr = false; + gdb_argv argv (args); for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt]) { - /* Process the argument. */ - if (argcnt == 0) - { - /* The first argument is the file name. */ - filename = tilde_expand (arg); - make_cleanup (xfree, filename); - } - else if (argcnt == 1) + if (stop_processing_options || *arg != '-') { - /* The second argument is always the text address at which - to load the program. */ - sect_opts[section_index].name = ".text"; - sect_opts[section_index].value = arg; - if (++section_index >= num_sect_opts) + if (filename == NULL) { - num_sect_opts *= 2; - sect_opts = ((struct sect_opt *) - xrealloc (sect_opts, - num_sect_opts - * sizeof (struct sect_opt))); + /* First non-option argument is always the filename. */ + filename.reset (tilde_expand (arg)); } - } - else - { - /* It's an option (starting with '-') or it's an argument - to an option. */ - if (expecting_sec_name) - { - sect_opts[section_index].name = arg; - expecting_sec_name = 0; - } - else if (expecting_sec_addr) - { - sect_opts[section_index].value = arg; - expecting_sec_addr = 0; - if (++section_index >= num_sect_opts) - { - num_sect_opts *= 2; - sect_opts = ((struct sect_opt *) - xrealloc (sect_opts, - num_sect_opts - * sizeof (struct sect_opt))); - } - } - else if (strcmp (arg, "-readnow") == 0) - flags |= OBJF_READNOW; - else if (strcmp (arg, "-s") == 0) + else if (!seen_addr) { - expecting_sec_name = 1; - expecting_sec_addr = 1; + /* The second non-option argument is always the text + address at which to load the program. */ + sect_opts[0].value = arg; + seen_addr = true; } else - error (_("USAGE: add-symbol-file " - " [-readnow] [-s ]*")); + error (_("Unrecognized argument \"%s\""), arg); + } + else if (strcmp (arg, "-readnow") == 0) + flags |= OBJF_READNOW; + else if (strcmp (arg, "-readnever") == 0) + flags |= OBJF_READNEVER; + else if (strcmp (arg, "-s") == 0) + { + if (argv[argcnt + 1] == NULL) + error (_("Missing section name after \"-s\"")); + else if (argv[argcnt + 2] == NULL) + error (_("Missing section address after \"-s\"")); + + sect_opt sect = { argv[argcnt + 1], argv[argcnt + 2] }; + + sect_opts.push_back (sect); + argcnt += 2; } + else if (strcmp (arg, "--") == 0) + stop_processing_options = true; + else + error (_("Unrecognized argument \"%s\""), arg); } + if (filename == NULL) + error (_("You must provide a filename to be loaded.")); + + validate_readnow_readnever (flags); + /* This command takes at least two arguments. The first one is a filename, and the second is the address where this file has been loaded. Abort now if this address hasn't been provided by the user. */ - if (section_index < 1) - error (_("The address where %s has been loaded is missing"), filename); + if (!seen_addr) + error (_("The address where %s has been loaded is missing"), + filename.get ()); /* Print the prompt for the query below. And save the arguments into a sect_addr_info structure to be passed around to other @@ -2368,24 +2161,22 @@ add_symbol_file_command (char *args, int from_tty) statements because hex_string returns a local static string. */ - printf_unfiltered (_("add symbol table from file \"%s\" at\n"), filename); - section_addrs = alloc_section_addr_info (section_index); - make_cleanup (xfree, section_addrs); - for (i = 0; i < section_index; i++) + printf_unfiltered (_("add symbol table from file \"%s\" at\n"), + filename.get ()); + section_addr_info section_addrs; + for (sect_opt § : sect_opts) { CORE_ADDR addr; - char *val = sect_opts[i].value; - char *sec = sect_opts[i].name; + const char *val = sect.value; + const char *sec = sect.name; addr = parse_and_eval_address (val); /* Here we store the section offsets in the order they were entered on the command line. */ - section_addrs->other[sec_num].name = sec; - section_addrs->other[sec_num].addr = addr; + section_addrs.emplace_back (addr, sec, 0); printf_unfiltered ("\t%s_addr = %s\n", sec, paddress (gdbarch, addr)); - sec_num++; /* The object's sections are initialized when a call is made to build_objfile_section_table (objfile). @@ -2393,42 +2184,35 @@ add_symbol_file_command (char *args, int from_tty) At this point, we don't know what file type this is, so we can't determine what section names are valid. */ } - section_addrs->num_sections = sec_num; if (from_tty && (!query ("%s", ""))) error (_("Not confirmed.")); - objf = symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0, - section_addrs, flags); + objf = symbol_file_add (filename.get (), add_flags, §ion_addrs, + flags); add_target_sections_of_objfile (objf); /* Getting new symbols may change our opinion about what is frameless. */ reinit_frame_cache (); - do_cleanups (my_cleanups); } /* This function removes a symbol file that was added via add-symbol-file. */ static void -remove_symbol_file_command (char *args, int from_tty) +remove_symbol_file_command (const char *args, int from_tty) { - char **argv; struct objfile *objf = NULL; - struct cleanup *my_cleanups; struct program_space *pspace = current_program_space; - struct gdbarch *gdbarch = get_current_arch (); dont_repeat (); if (args == NULL) error (_("remove-symbol-file: no symbol file provided")); - my_cleanups = make_cleanup (null_cleanup, NULL); - - argv = gdb_buildargv (args); + gdb_argv argv (args); if (strcmp (argv[0], "-a") == 0) { @@ -2454,20 +2238,18 @@ remove_symbol_file_command (char *args, int from_tty) else if (argv[0] != NULL) { /* Interpret the current argument as a file name. */ - char *filename; if (argv[1] != NULL) error (_("Junk after %s"), argv[0]); - filename = tilde_expand (argv[0]); - make_cleanup (xfree, filename); + gdb::unique_xmalloc_ptr filename (tilde_expand (argv[0])); ALL_OBJFILES (objf) { if ((objf->flags & OBJF_USERLOADED) != 0 && (objf->flags & OBJF_SHARED) != 0 && objf->pspace == pspace - && filename_cmp (filename, objfile_name (objf)) == 0) + && filename_cmp (filename.get (), objfile_name (objf)) == 0) break; } } @@ -2480,16 +2262,10 @@ remove_symbol_file_command (char *args, int from_tty) objfile_name (objf))) error (_("Not confirmed.")); - free_objfile (objf); + delete objf; clear_symtab_users (0); - - do_cleanups (my_cleanups); } -typedef struct objfile *objfilep; - -DEF_VEC_P (objfilep); - /* Re-read symbols if a symbol-file has changed. */ void @@ -2499,10 +2275,7 @@ reread_symbols (void) long new_modtime; struct stat new_statbuf; int res; - VEC (objfilep) *new_objfiles = NULL; - struct cleanup *all_cleanups; - - all_cleanups = make_cleanup (VEC_cleanup (objfilep), &new_objfiles); + std::vector new_objfiles; /* With the addition of shared libraries, this should be modified, the load time should be saved in the partial symbol tables, since @@ -2555,9 +2328,10 @@ reread_symbols (void) /* If we get an error, blow away this objfile (not sure if that is the correct response for things like shared libraries). */ - old_cleanups = make_cleanup_free_objfile (objfile); + std::unique_ptr objfile_holder (objfile); + /* We need to do this whenever any symbols go away. */ - make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); + old_cleanups = make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); if (exec_bfd != NULL && filename_cmp (bfd_get_filename (objfile->obfd), @@ -2593,22 +2367,16 @@ reread_symbols (void) /* Clean up any state BFD has sitting around. */ { - struct bfd *obfd = objfile->obfd; + gdb_bfd_ref_ptr obfd (objfile->obfd); char *obfd_filename; obfd_filename = bfd_get_filename (objfile->obfd); /* Open the new BFD before freeing the old one, so that the filename remains live. */ - objfile->obfd = gdb_bfd_open_maybe_remote (obfd_filename); + gdb_bfd_ref_ptr temp (gdb_bfd_open (obfd_filename, gnutarget, -1)); + objfile->obfd = temp.release (); if (objfile->obfd == NULL) - { - /* We have to make a cleanup and error here, rather - than erroring later, because once we unref OBFD, - OBFD_FILENAME will be freed. */ - make_cleanup_bfd_unref (obfd); - error (_("Can't open %s to read symbols."), obfd_filename); - } - gdb_bfd_unref (obfd); + error (_("Can't open %s to read symbols."), obfd_filename); } original_name = xstrdup (objfile->original_name); @@ -2629,21 +2397,18 @@ reread_symbols (void) /* FIXME: Do we have to free a whole linked list, or is this enough? */ - if (objfile->global_psymbols.list) - xfree (objfile->global_psymbols.list); - memset (&objfile->global_psymbols, 0, - sizeof (objfile->global_psymbols)); - if (objfile->static_psymbols.list) - xfree (objfile->static_psymbols.list); - memset (&objfile->static_psymbols, 0, - sizeof (objfile->static_psymbols)); + objfile->global_psymbols.clear (); + objfile->static_psymbols.clear (); /* Free the obstacks for non-reusable objfiles. */ psymbol_bcache_free (objfile->psymbol_cache); objfile->psymbol_cache = psymbol_bcache_init (); + + /* NB: after this call to obstack_free, objfiles_changed + will need to be called (see discussion below). */ obstack_free (&objfile->objfile_obstack, 0); objfile->sections = NULL; - objfile->symtabs = NULL; + objfile->compunit_symtabs = NULL; objfile->psymtabs = NULL; objfile->psymtabs_addrmap = NULL; objfile->free_psymtabs = NULL; @@ -2660,9 +2425,9 @@ reread_symbols (void) do it *after* the obstack has been initialized. */ set_objfile_per_bfd (objfile); - objfile->original_name = obstack_copy0 (&objfile->objfile_obstack, - original_name, - strlen (original_name)); + objfile->original_name + = (char *) obstack_copy0 (&objfile->objfile_obstack, original_name, + strlen (original_name)); /* Reset the sym_fns pointer. The ELF reader can change it based on whether .gdb_index is present, and we need it to @@ -2693,6 +2458,23 @@ reread_symbols (void) clear_complaints (&symfile_complaints, 1, 1); objfile->flags &= ~OBJF_PSYMTABS_READ; + + /* We are about to read new symbols and potentially also + DWARF information. Some targets may want to pass addresses + read from DWARF DIE's through an adjustment function before + saving them, like MIPS, which may call into + "find_pc_section". When called, that function will make + use of per-objfile program space data. + + Since we discarded our section information above, we have + dangling pointers in the per-objfile program space data + structure. Force GDB to update the section mapping + information by letting it know the objfile has changed, + making the dangling pointers point to correct data + again. */ + + objfiles_changed (); + read_symbols (objfile, 0); if (!objfile_has_symbols (objfile)) @@ -2711,6 +2493,7 @@ reread_symbols (void) reinit_frame_cache (); /* Discard cleanups as symbol reading was successful. */ + objfile_holder.release (); discard_cleanups (old_cleanups); /* If the mtime has changed between the time we set new_modtime @@ -2719,58 +2502,45 @@ reread_symbols (void) objfile->mtime = new_modtime; init_entry_point_info (objfile); - VEC_safe_push (objfilep, new_objfiles, objfile); + new_objfiles.push_back (objfile); } } - if (new_objfiles) + if (!new_objfiles.empty ()) { - int ix; - - /* Notify objfiles that we've modified objfile sections. */ - objfiles_changed (); - clear_symtab_users (0); /* clear_objfile_data for each objfile was called before freeing it and - observer_notify_new_objfile (NULL) has been called by + gdb::observers::new_objfile.notify (NULL) has been called by clear_symtab_users above. Notify the new files now. */ - for (ix = 0; VEC_iterate (objfilep, new_objfiles, ix, objfile); ix++) - observer_notify_new_objfile (objfile); + for (auto iter : new_objfiles) + gdb::observers::new_objfile.notify (objfile); /* At least one objfile has changed, so we can consider that the executable we're debugging has changed too. */ - observer_notify_executable_changed (); + gdb::observers::executable_changed.notify (); } - - do_cleanups (all_cleanups); } -typedef struct +struct filename_language { - char *ext; + filename_language (const std::string &ext_, enum language lang_) + : ext (ext_), lang (lang_) + {} + + std::string ext; enum language lang; -} -filename_language; +}; -static filename_language *filename_language_table; -static int fl_table_size, fl_table_next; +static std::vector filename_language_table; -static void -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 * sizeof (*filename_language_table)); - } +/* See symfile.h. */ - filename_language_table[fl_table_next].ext = xstrdup (ext); - filename_language_table[fl_table_next].lang = lang; - fl_table_next++; +void +add_filename_language (const char *ext, enum language lang) +{ + filename_language_table.emplace_back (ext, lang); } static char *ext_args; @@ -2785,9 +2555,9 @@ show_ext_args (struct ui_file *file, int from_tty, } static void -set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) +set_ext_lang_command (const char *args, + int from_tty, struct cmd_list_element *e) { - int i; char *cp = ext_args; enum language lang; @@ -2818,12 +2588,15 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) /* Lookup the language from among those we know. */ lang = language_enum (cp); + auto it = filename_language_table.begin (); /* Now lookup the filename extension: do we already know it? */ - for (i = 0; i < fl_table_next; i++) - if (0 == strcmp (ext_args, filename_language_table[i].ext)) - break; + for (; it != filename_language_table.end (); it++) + { + if (it->ext == ext_args) + break; + } - if (i >= fl_table_next) + if (it == filename_language_table.end ()) { /* New file extension. */ add_filename_language (ext_args, lang); @@ -2836,122 +2609,51 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) /* query ("Really make files of type %s '%s'?", */ /* ext_args, language_str (lang)); */ - xfree (filename_language_table[i].ext); - filename_language_table[i].ext = xstrdup (ext_args); - filename_language_table[i].lang = lang; + it->lang = lang; } } static void -info_ext_lang_command (char *args, int from_tty) +info_ext_lang_command (const char *args, int from_tty) { - int i; - printf_filtered (_("Filename extensions and the languages they represent:")); printf_filtered ("\n\n"); - for (i = 0; i < fl_table_next; i++) - printf_filtered ("\t%s\t- %s\n", - filename_language_table[i].ext, - language_str (filename_language_table[i].lang)); -} - -static void -init_filename_language_table (void) -{ - if (fl_table_size == 0) /* Protect against repetition. */ - { - fl_table_size = 20; - fl_table_next = 0; - filename_language_table = - xmalloc (fl_table_size * sizeof (*filename_language_table)); - add_filename_language (".c", language_c); - add_filename_language (".d", language_d); - add_filename_language (".C", language_cplus); - add_filename_language (".cc", language_cplus); - add_filename_language (".cp", language_cplus); - add_filename_language (".cpp", language_cplus); - add_filename_language (".cxx", language_cplus); - add_filename_language (".c++", language_cplus); - add_filename_language (".java", language_java); - add_filename_language (".class", language_java); - add_filename_language (".m", language_objc); - add_filename_language (".f", language_fortran); - add_filename_language (".F", language_fortran); - add_filename_language (".for", language_fortran); - add_filename_language (".FOR", language_fortran); - add_filename_language (".ftn", language_fortran); - add_filename_language (".FTN", language_fortran); - add_filename_language (".fpp", language_fortran); - add_filename_language (".FPP", language_fortran); - add_filename_language (".f90", language_fortran); - add_filename_language (".F90", language_fortran); - add_filename_language (".f95", language_fortran); - add_filename_language (".F95", language_fortran); - add_filename_language (".f03", language_fortran); - add_filename_language (".F03", language_fortran); - add_filename_language (".f08", language_fortran); - add_filename_language (".F08", 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); - add_filename_language (".pp", language_pascal); - add_filename_language (".adb", language_ada); - add_filename_language (".ads", language_ada); - add_filename_language (".a", language_ada); - add_filename_language (".ada", language_ada); - add_filename_language (".dg", language_ada); - } + for (const filename_language &entry : filename_language_table) + printf_filtered ("\t%s\t- %s\n", entry.ext.c_str (), + language_str (entry.lang)); } enum language deduce_language_from_filename (const char *filename) { - int i; - char *cp; + const char *cp; if (filename != NULL) if ((cp = strrchr (filename, '.')) != NULL) - for (i = 0; i < fl_table_next; i++) - if (strcmp (cp, filename_language_table[i].ext) == 0) - return filename_language_table[i].lang; + { + for (const filename_language &entry : filename_language_table) + if (entry.ext == cp) + return entry.lang; + } return language_unknown; } -/* allocate_symtab: - - Allocate and partly initialize a new symbol table. Return a pointer - to it. error() if no space. - - Caller must set these fields: - LINETABLE(symtab) - symtab->blockvector - symtab->dirname - symtab->free_code - symtab->free_ptr - */ +/* Allocate and initialize a new symbol table. + CUST is from the result of allocate_compunit_symtab. */ struct symtab * -allocate_symtab (const char *filename, struct objfile *objfile) +allocate_symtab (struct compunit_symtab *cust, const char *filename) { - struct symtab *symtab; + struct objfile *objfile = cust->objfile; + struct symtab *symtab + = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symtab); - symtab = (struct symtab *) - obstack_alloc (&objfile->objfile_obstack, sizeof (struct symtab)); - memset (symtab, 0, sizeof (*symtab)); - symtab->filename = bcache (filename, strlen (filename) + 1, + symtab->filename + = (const char *) bcache (filename, strlen (filename) + 1, objfile->per_bfd->filename_cache); symtab->fullname = NULL; symtab->language = deduce_language_from_filename (filename); - symtab->debugformat = "unknown"; - - /* Hook it to the objfile it comes from. */ - - symtab->objfile = objfile; - symtab->next = objfile->symtabs; - objfile->symtabs = symtab; /* This can be very verbose with lots of headers. Only print at higher debug levels. */ @@ -2975,15 +2677,73 @@ allocate_symtab (const char *filename, struct objfile *objfile) host_address_to_string (symtab), filename); } - return (symtab); + /* Add it to CUST's list of symtabs. */ + if (cust->filetabs == NULL) + { + cust->filetabs = symtab; + cust->last_filetab = symtab; + } + else + { + cust->last_filetab->next = symtab; + cust->last_filetab = symtab; + } + + /* Backlink to the containing compunit symtab. */ + symtab->compunit_symtab = cust; + + return symtab; +} + +/* Allocate and initialize a new compunit. + NAME is the name of the main source file, if there is one, or some + descriptive text if there are no source files. */ + +struct compunit_symtab * +allocate_compunit_symtab (struct objfile *objfile, const char *name) +{ + struct compunit_symtab *cu = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct compunit_symtab); + const char *saved_name; + + cu->objfile = objfile; + + /* The name we record here is only for display/debugging purposes. + Just save the basename to avoid path issues (too long for display, + relative vs absolute, etc.). */ + saved_name = lbasename (name); + cu->name + = (const char *) obstack_copy0 (&objfile->objfile_obstack, saved_name, + strlen (saved_name)); + + COMPUNIT_DEBUGFORMAT (cu) = "unknown"; + + if (symtab_create_debug) + { + fprintf_unfiltered (gdb_stdlog, + "Created compunit symtab %s for %s.\n", + host_address_to_string (cu), + cu->name); + } + + return cu; +} + +/* Hook CU to the objfile it comes from. */ + +void +add_compunit_symtab_to_objfile (struct compunit_symtab *cu) +{ + cu->next = cu->objfile->compunit_symtabs; + cu->objfile->compunit_symtabs = cu; } -/* Reset all data structures in gdb which may contain references to symbol - table data. ADD_FLAGS is a bitmask of enum symfile_add_flags. */ +/* Reset all data structures in gdb which may contain references to + symbol table data. */ void -clear_symtab_users (int add_flags) +clear_symtab_users (symfile_add_flags add_flags) { /* Someday, we should do better than this, by only blowing away the things that really need to be blown. */ @@ -2993,21 +2753,23 @@ clear_symtab_users (int add_flags) clear_current_source_symtab_and_line (); clear_displays (); - if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) - breakpoint_re_set (); clear_last_displayed_sal (); clear_pc_function_cache (); - observer_notify_new_objfile (NULL); + gdb::observers::new_objfile.notify (NULL); /* Clear globals which might have pointed into a removed objfile. FIXME: It's not clear which of these are supposed to persist between expressions and which ought to be reset each time. */ expression_context_block = NULL; - innermost_block = NULL; + innermost_block.reset (); /* Varobj may refer to old symbols, perform a cleanup. */ varobj_invalidate (); + /* Now that the various caches have been cleared, we can re_set + our breakpoints without risking it using stale data. */ + if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) + breakpoint_re_set (); } static void @@ -3078,7 +2840,6 @@ section_is_overlay (struct obj_section *section) { if (overlay_debugging && section) { - bfd *abfd = section->objfile->obfd; asection *bfd_section = section->the_bfd_section; if (bfd_section_lma (abfd, bfd_section) != 0 @@ -3140,7 +2901,7 @@ section_is_mapped (struct obj_section *osect) if (osect->ovly_mapped == -1) gdbarch_overlay_update (gdbarch, osect); } - /* fall thru to manual case */ + /* fall thru */ case ovly_on: /* overlay debugging manual */ return osect->ovly_mapped == 1; } @@ -3208,7 +2969,6 @@ overlay_unmapped_address (CORE_ADDR pc, struct obj_section *section) { if (section_is_overlay (section) && pc_in_mapped_range (pc, section)) { - bfd *abfd = section->objfile->obfd; asection *bfd_section = section->the_bfd_section; return pc + bfd_section_lma (abfd, bfd_section) @@ -3227,7 +2987,6 @@ overlay_mapped_address (CORE_ADDR pc, struct obj_section *section) { if (section_is_overlay (section) && pc_in_unmapped_range (pc, section)) { - bfd *abfd = section->objfile->obfd; asection *bfd_section = section->the_bfd_section; return pc + bfd_section_vma (abfd, bfd_section) @@ -3278,19 +3037,21 @@ find_pc_overlay (CORE_ADDR pc) struct obj_section *osect, *best_match = NULL; if (overlay_debugging) - ALL_OBJSECTIONS (objfile, osect) - if (section_is_overlay (osect)) - { - if (pc_in_mapped_range (pc, osect)) + { + ALL_OBJSECTIONS (objfile, osect) + if (section_is_overlay (osect)) { - if (section_is_mapped (osect)) - return osect; - else + if (pc_in_mapped_range (pc, osect)) + { + if (section_is_mapped (osect)) + return osect; + else + best_match = osect; + } + else if (pc_in_unmapped_range (pc, osect)) best_match = osect; } - else if (pc_in_unmapped_range (pc, osect)) - best_match = osect; - } + } return best_match; } @@ -3305,9 +3066,11 @@ find_pc_mapped_section (CORE_ADDR pc) struct obj_section *osect; if (overlay_debugging) - ALL_OBJSECTIONS (objfile, osect) - if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect)) - return osect; + { + ALL_OBJSECTIONS (objfile, osect) + if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect)) + return osect; + } return NULL; } @@ -3316,38 +3079,40 @@ find_pc_mapped_section (CORE_ADDR pc) Print a list of mapped sections and their PC ranges. */ static void -list_overlays_command (char *args, int from_tty) +list_overlays_command (const char *args, int from_tty) { int nmapped = 0; struct objfile *objfile; struct obj_section *osect; if (overlay_debugging) - ALL_OBJSECTIONS (objfile, osect) + { + ALL_OBJSECTIONS (objfile, osect) if (section_is_mapped (osect)) - { - struct gdbarch *gdbarch = get_objfile_arch (objfile); - const char *name; - bfd_vma lma, vma; - int size; - - vma = bfd_section_vma (objfile->obfd, osect->the_bfd_section); - lma = bfd_section_lma (objfile->obfd, osect->the_bfd_section); - size = bfd_get_section_size (osect->the_bfd_section); - name = bfd_section_name (objfile->obfd, osect->the_bfd_section); - - printf_filtered ("Section %s, loaded at ", name); - fputs_filtered (paddress (gdbarch, lma), gdb_stdout); - puts_filtered (" - "); - fputs_filtered (paddress (gdbarch, lma + size), gdb_stdout); - printf_filtered (", mapped at "); - fputs_filtered (paddress (gdbarch, vma), gdb_stdout); - puts_filtered (" - "); - fputs_filtered (paddress (gdbarch, vma + size), gdb_stdout); - puts_filtered ("\n"); - - nmapped++; - } + { + struct gdbarch *gdbarch = get_objfile_arch (objfile); + const char *name; + bfd_vma lma, vma; + int size; + + vma = bfd_section_vma (objfile->obfd, osect->the_bfd_section); + lma = bfd_section_lma (objfile->obfd, osect->the_bfd_section); + size = bfd_get_section_size (osect->the_bfd_section); + name = bfd_section_name (objfile->obfd, osect->the_bfd_section); + + printf_filtered ("Section %s, loaded at ", name); + fputs_filtered (paddress (gdbarch, lma), gdb_stdout); + puts_filtered (" - "); + fputs_filtered (paddress (gdbarch, lma + size), gdb_stdout); + printf_filtered (", mapped at "); + fputs_filtered (paddress (gdbarch, vma), gdb_stdout); + puts_filtered (" - "); + fputs_filtered (paddress (gdbarch, vma + size), gdb_stdout); + puts_filtered ("\n"); + + nmapped++; + } + } if (nmapped == 0) printf_filtered (_("No sections are mapped.\n")); } @@ -3356,7 +3121,7 @@ list_overlays_command (char *args, int from_tty) Mark the named section as mapped (ie. residing at its VMA address). */ static void -map_overlay_command (char *args, int from_tty) +map_overlay_command (const char *args, int from_tty) { struct objfile *objfile, *objfile2; struct obj_section *sec, *sec2; @@ -3401,10 +3166,10 @@ map_overlay_command (char *args, int from_tty) (ie. resident in its LMA address range, rather than the VMA range). */ static void -unmap_overlay_command (char *args, int from_tty) +unmap_overlay_command (const char *args, int from_tty) { struct objfile *objfile; - struct obj_section *sec; + struct obj_section *sec = NULL; if (!overlay_debugging) error (_("Overlay debugging not enabled. " @@ -3431,7 +3196,7 @@ unmap_overlay_command (char *args, int from_tty) Possibly this should be done via a set/show command. */ static void -overlay_auto_command (char *args, int from_tty) +overlay_auto_command (const char *args, int from_tty) { overlay_debugging = ovly_auto; enable_overlay_breakpoints (); @@ -3444,7 +3209,7 @@ overlay_auto_command (char *args, int from_tty) Possibly this should be done via a set/show command. */ static void -overlay_manual_command (char *args, int from_tty) +overlay_manual_command (const char *args, int from_tty) { overlay_debugging = ovly_on; disable_overlay_breakpoints (); @@ -3457,7 +3222,7 @@ overlay_manual_command (char *args, int from_tty) Possibly this should be done via a set/show command. */ static void -overlay_off_command (char *args, int from_tty) +overlay_off_command (const char *args, int from_tty) { overlay_debugging = ovly_off; disable_overlay_breakpoints (); @@ -3466,7 +3231,7 @@ overlay_off_command (char *args, int from_tty) } static void -overlay_load_command (char *args, int from_tty) +overlay_load_command (const char *args, int from_tty) { struct gdbarch *gdbarch = get_current_arch (); @@ -3483,7 +3248,7 @@ overlay_load_command (char *args, int from_tty) static struct cmd_list_element *overlaylist; static void -overlay_command (char *args, int from_tty) +overlay_command (const char *args, int from_tty) { printf_unfiltered ("\"overlay\" must be followed by the name of an overlay command.\n"); @@ -3506,12 +3271,12 @@ overlay_command (char *args, int from_tty) In this simple implementation, the target data structures are as follows: unsigned _novlys; /# number of overlay sections #/ unsigned _ovly_table[_novlys][4] = { - {VMA, SIZE, LMA, MAPPED}, /# one entry per overlay section #/ + {VMA, OSIZE, LMA, MAPPED}, /# one entry per overlay section #/ {..., ..., ..., ...}, } unsigned _novly_regions; /# number of overlay regions #/ unsigned _ovly_region_table[_novly_regions][3] = { - {VMA, SIZE, MAPPED_TO_LMA}, /# one entry per overlay region #/ + {VMA, OSIZE, MAPPED_TO_LMA}, /# one entry per overlay region #/ {..., ..., ...}, } These functions will attempt to update GDB's mappedness state in the @@ -3529,7 +3294,7 @@ static unsigned cache_novlys = 0; static CORE_ADDR cache_ovly_table_base = 0; enum ovly_index { - VMA, SIZE, LMA, MAPPED + VMA, OSIZE, LMA, MAPPED }; /* Throw away the cached copy of _ovly_table. */ @@ -3552,7 +3317,7 @@ read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, int len, int size, enum bfd_endian byte_order) { /* FIXME (alloca): Not safe if array is very large. */ - gdb_byte *buf = alloca (len * size); + gdb_byte *buf = (gdb_byte *) alloca (len * size); int i; read_memory (memaddr, buf, len * size); @@ -3598,7 +3363,7 @@ simple_read_overlay_table (void) cache_novlys = read_memory_integer (BMSYMBOL_VALUE_ADDRESS (novlys_msym), 4, byte_order); cache_ovly_table - = (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table)); + = (unsigned int (*)[4]) xmalloc (cache_novlys * sizeof (*cache_ovly_table)); cache_ovly_table_base = BMSYMBOL_VALUE_ADDRESS (ovly_table_msym); read_target_long_array (cache_ovly_table_base, (unsigned int *) cache_ovly_table, @@ -3618,25 +3383,21 @@ simple_read_overlay_table (void) static int simple_overlay_update_1 (struct obj_section *osect) { - int i, size; - bfd *obfd = osect->objfile->obfd; + int i; asection *bsect = osect->the_bfd_section; struct gdbarch *gdbarch = get_objfile_arch (osect->objfile); int word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT; enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - size = bfd_get_section_size (osect->the_bfd_section); for (i = 0; i < cache_novlys; i++) if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect) - && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect) - /* && cache_ovly_table[i][SIZE] == size */ ) + && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)) { read_target_long_array (cache_ovly_table_base + i * word_size, (unsigned int *) cache_ovly_table[i], 4, word_size, byte_order); if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect) - && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect) - /* && cache_ovly_table[i][SIZE] == size */ ) + && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)) { osect->ovly_mapped = cache_ovly_table[i][MAPPED]; return 1; @@ -3694,15 +3455,12 @@ simple_overlay_update (struct obj_section *osect) ALL_OBJSECTIONS (objfile, osect) if (section_is_overlay (osect)) { - int i, size; - bfd *obfd = osect->objfile->obfd; + int i; asection *bsect = osect->the_bfd_section; - size = bfd_get_section_size (bsect); for (i = 0; i < cache_novlys; i++) if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect) - && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect) - /* && cache_ovly_table[i][SIZE] == size */ ) + && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)) { /* obj_section matches i'th entry in ovly_table. */ osect->ovly_mapped = cache_ovly_table[i][MAPPED]; break; /* finished with inner for loop: break out. */ @@ -3902,10 +3660,12 @@ symfile_free_objfile (struct objfile *objfile) See quick_symbol_functions.expand_symtabs_matching for details. */ void -expand_symtabs_matching (expand_symtabs_file_matcher_ftype *file_matcher, - expand_symtabs_symbol_matcher_ftype *symbol_matcher, - enum search_domain kind, - void *data) +expand_symtabs_matching + (gdb::function_view file_matcher, + const lookup_name_info &lookup_name, + gdb::function_view symbol_matcher, + gdb::function_view expansion_notify, + enum search_domain kind) { struct objfile *objfile; @@ -3913,8 +3673,9 @@ expand_symtabs_matching (expand_symtabs_file_matcher_ftype *file_matcher, { if (objfile->sf) objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher, - symbol_matcher, kind, - data); + lookup_name, + symbol_matcher, + expansion_notify, kind); } } @@ -3936,26 +3697,95 @@ map_symbol_filenames (symbol_filename_ftype *fun, void *data, } } +#if GDB_SELF_TEST + +namespace selftests { +namespace filename_language { + +static void test_filename_language () +{ + /* This test messes up the filename_language_table global. */ + scoped_restore restore_flt = make_scoped_restore (&filename_language_table); + + /* Test deducing an unknown extension. */ + language lang = deduce_language_from_filename ("myfile.blah"); + SELF_CHECK (lang == language_unknown); + + /* Test deducing a known extension. */ + lang = deduce_language_from_filename ("myfile.c"); + SELF_CHECK (lang == language_c); + + /* Test adding a new extension using the internal API. */ + add_filename_language (".blah", language_pascal); + lang = deduce_language_from_filename ("myfile.blah"); + SELF_CHECK (lang == language_pascal); +} + +static void +test_set_ext_lang_command () +{ + /* This test messes up the filename_language_table global. */ + scoped_restore restore_flt = make_scoped_restore (&filename_language_table); + + /* Confirm that the .hello extension is not known. */ + language lang = deduce_language_from_filename ("cake.hello"); + SELF_CHECK (lang == language_unknown); + + /* Test adding a new extension using the CLI command. */ + gdb::unique_xmalloc_ptr args_holder (xstrdup (".hello rust")); + ext_args = args_holder.get (); + set_ext_lang_command (NULL, 1, NULL); + + lang = deduce_language_from_filename ("cake.hello"); + SELF_CHECK (lang == language_rust); + + /* Test overriding an existing extension using the CLI command. */ + int size_before = filename_language_table.size (); + args_holder.reset (xstrdup (".hello pascal")); + ext_args = args_holder.get (); + set_ext_lang_command (NULL, 1, NULL); + int size_after = filename_language_table.size (); + + lang = deduce_language_from_filename ("cake.hello"); + SELF_CHECK (lang == language_pascal); + SELF_CHECK (size_before == size_after); +} + +} /* namespace filename_language */ +} /* namespace selftests */ + +#endif /* GDB_SELF_TEST */ + void _initialize_symfile (void) { struct cmd_list_element *c; - observer_attach_free_objfile (symfile_free_objfile); + gdb::observers::free_objfile.attach (symfile_free_objfile); + +#define READNOW_READNEVER_HELP \ + "The '-readnow' option will cause GDB to read the entire symbol file\n\ +immediately. This makes the command slower, but may make future operations\n\ +faster.\n\ +The '-readnever' option will prevent GDB from reading the symbol file's\n\ +symbolic debug information." c = add_cmd ("symbol-file", class_files, symbol_file_command, _("\ Load symbol table from executable file FILE.\n\ +Usage: symbol-file [-readnow | -readnever] FILE\n\ The `file' command can also load symbol tables, as well as setting the file\n\ -to execute."), &cmdlist); +to execute.\n" READNOW_READNEVER_HELP), &cmdlist); set_cmd_completer (c, filename_completer); c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, _("\ Load symbols from FILE, assuming FILE has been dynamically loaded.\n\ -Usage: add-symbol-file FILE ADDR [-s -s \ - ...]\nADDR is the starting address of the file's text.\n\ -The optional arguments are section-name section-address pairs and\n\ +Usage: add-symbol-file FILE ADDR [-readnow | -readnever | \ +-s SECT-NAME SECT-ADDR]...\n\ +ADDR is the starting address of the file's text.\n\ +Each '-s' argument provides a section name and address, 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-NAME is a section name to be loaded at SECT-ADDR.\n" +READNOW_READNEVER_HELP), &cmdlist); set_cmd_completer (c, filename_completer); @@ -3971,7 +3801,10 @@ that lies within the boundaries of this symbol file in memory."), c = add_cmd ("load", class_files, load_command, _("\ Dynamically load FILE into the running program, and record its symbols\n\ for access from GDB.\n\ -A load OFFSET may also be given."), &cmdlist); +Usage: load [FILE] [OFFSET]\n\ +An optional load OFFSET may also be given as a literal address.\n\ +When OFFSET is provided, FILE must also be provided. FILE can be provided\n\ +on its own."), &cmdlist); set_cmd_completer (c, filename_completer); add_prefix_cmd ("overlay", class_support, overlay_command, @@ -4000,7 +3833,6 @@ A load OFFSET may also be given."), &cmdlist); _("Read the overlay mapping state from the target."), &overlaylist); /* Filename extension to source language lookup table: */ - init_filename_language_table (); add_setshow_string_noescape_cmd ("extension-language", class_files, &ext_args, _("\ Set mapping between filename extension and source language."), _("\ @@ -4038,4 +3870,19 @@ full == print messages for the executable,\n\ NULL, NULL, &setprintlist, &showprintlist); + + add_setshow_boolean_cmd ("separate-debug-file", no_class, + &separate_debug_file_debug, _("\ +Set printing of separate debug info file search debug."), _("\ +Show printing of separate debug info file search debug."), _("\ +When on, GDB prints the searched locations while looking for separate debug \ +info files."), NULL, NULL, &setdebuglist, &showdebuglist); + +#if GDB_SELF_TEST + selftests::register_test + ("filename_language", selftests::filename_language::test_filename_language); + selftests::register_test + ("set_ext_lang_command", + selftests::filename_language::test_set_ext_lang_command); +#endif }