/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright (C) 1990-2014 Free Software Foundation, Inc.
+ Copyright (C) 1990-2017 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
#include "bcache.h"
#include "hashtab.h"
#include "readline/readline.h"
-#include "gdb_assert.h"
#include "block.h"
#include "observer.h"
#include "exec.h"
#include "stack.h"
#include "gdb_bfd.h"
#include "cli/cli-utils.h"
+#include "common/byte-vector.h"
+#include "selftest.h"
#include <sys/types.h>
#include <fcntl.h>
-#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
-#include <time.h>
-#include <sys/time.h>
+#include <chrono>
#include "psymtab.h"
/* 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,
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 std::vector<registered_sym_fns> symtab_fns;
-static VEC (registered_sym_fns) *symtab_fns = NULL;
+/* Values for "set print symbol-loading". */
+
+const char print_symbol_loading_off[] = "off";
+const char print_symbol_loading_brief[] = "brief";
+const char print_symbol_loading_full[] = "full";
+static const char *print_symbol_loading_enums[] =
+{
+ print_symbol_loading_off,
+ print_symbol_loading_brief,
+ print_symbol_loading_full,
+ NULL
+};
+static const char *print_symbol_loading = print_symbol_loading_full;
/* If non-zero, shared library symbols will be added automatically
when the inferior is created, new libraries are loaded, or when
int auto_solib_add = 1;
\f
-/* True if we are reading a symbol table. */
-
-int currently_reading_symtab = 0;
+/* Return non-zero if symbol-loading messages should be printed.
+ FROM_TTY is the standard from_tty argument to gdb commands.
+ If EXEC is non-zero the messages are for the executable.
+ Otherwise, messages are for shared libraries.
+ If FULL is non-zero then the caller is printing a detailed message.
+ E.g., the message includes the shared library name.
+ Otherwise, the caller is printing a brief "summary" message. */
-static void
-decrement_reading_symtab (void *dummy)
+int
+print_symbol_loading_p (int from_tty, int exec, int full)
{
- currently_reading_symtab--;
- gdb_assert (currently_reading_symtab >= 0);
+ if (!from_tty && !info_verbose)
+ return 0;
+
+ if (exec)
+ {
+ /* We don't check FULL for executables, there are few such
+ messages, therefore brief == full. */
+ return print_symbol_loading != print_symbol_loading_off;
+ }
+ if (full)
+ return print_symbol_loading == print_symbol_loading_full;
+ return print_symbol_loading == print_symbol_loading_brief;
}
+/* True if we are reading a symbol table. */
+
+int currently_reading_symtab = 0;
+
/* Increment currently_reading_symtab and return a cleanup that can be
used to decrement it. */
-struct cleanup *
+scoped_restore_tmpl<int>
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.
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);
int i;
/* `+ 1' for the NULL terminator. */
- array = xmalloc (sizeof (*array) * (addrs->num_sections + 1));
+ array = XNEWVEC (struct other_sections *, addrs->num_sections + 1);
for (i = 0; i < addrs->num_sections; i++)
array[i] = &addrs->other[i];
array[i] = NULL;
/* 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);
+ addrs_to_abfd_addrs = XCNEWVEC (struct other_sections *, addrs->num_sections);
make_cleanup (xfree, addrs_to_abfd_addrs);
while (*addrs_sorted)
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 = true;
/* find_separate_debug_file_in_section should be called only if there is
single binary with no existing separate debug info file. */
&& 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)
{
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);
static void
init_entry_point_info (struct objfile *objfile)
{
+ struct entry_info *ei = &objfile->per_bfd->ei;
+
+ if (ei->initialized)
+ return;
+ ei->initialized = 1;
+
/* Save startup file's range of PC addresses to help blockframe.c
decide where the bottom of the stack is. */
{
/* Executable file -- record its entry point so we'll recognize
the startup file because it contains the entry point. */
- objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
- objfile->ei.entry_point_p = 1;
+ ei->entry_point = bfd_get_start_address (objfile->obfd);
+ ei->entry_point_p = 1;
}
else if (bfd_get_file_flags (objfile->obfd) & DYNAMIC
&& bfd_get_start_address (objfile->obfd) != 0)
/* Some shared libraries may have entry points set and be
runnable. There's no clear way to indicate this, so just check
for values other than zero. */
- objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
- objfile->ei.entry_point_p = 1;
+ ei->entry_point = bfd_get_start_address (objfile->obfd);
+ ei->entry_point_p = 1;
}
else
{
/* Examination of non-executable.o files. Short-circuit this stuff. */
- objfile->ei.entry_point_p = 0;
+ ei->entry_point_p = 0;
}
- if (objfile->ei.entry_point_p)
+ if (ei->entry_point_p)
{
- CORE_ADDR entry_point = objfile->ei.entry_point;
+ struct obj_section *osect;
+ CORE_ADDR entry_point = ei->entry_point;
+ int found;
/* Make certain that the address points at real code, and not a
function descriptor. */
/* Remove any ISA markers, so that this matches entries in the
symbol table. */
- objfile->ei.entry_point
+ ei->entry_point
= gdbarch_addr_bits_remove (get_objfile_arch (objfile), entry_point);
+
+ found = 0;
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+ {
+ struct bfd_section *sect = osect->the_bfd_section;
+
+ if (entry_point >= bfd_get_section_vma (objfile->obfd, sect)
+ && entry_point < (bfd_get_section_vma (objfile->obfd, sect)
+ + bfd_get_section_size (sect)))
+ {
+ ei->the_bfd_section_index
+ = gdb_bfd_section_index (objfile->obfd, sect);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ ei->the_bfd_section_index = SECT_OFF_TEXT (objfile);
}
}
static void
syms_from_objfile_1 (struct objfile *objfile,
struct section_addr_info *addrs,
- int add_flags)
+ symfile_add_flags add_flags)
{
struct section_addr_info *local_addr = NULL;
struct cleanup *old_chain;
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<struct objfile> objfile_holder (objfile);
/* If ADDRS is NULL, put together a dummy address list.
We now establish the convention that an addr of zero means
if (symfile_objfile != NULL)
{
- free_objfile (symfile_objfile);
+ delete symfile_objfile;
gdb_assert (symfile_objfile == NULL);
}
/* Discard cleanups as symbol reading was successful. */
+ objfile_holder.release ();
discard_cleanups (old_chain);
xfree (local_addr);
}
static void
syms_from_objfile (struct objfile *objfile,
struct section_addr_info *addrs,
- int add_flags)
+ symfile_add_flags add_flags)
{
syms_from_objfile_1 (objfile, addrs, add_flags);
init_entry_point_info (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
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.
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,
+symbol_file_add_with_addrs (bfd *abfd, const char *name,
+ symfile_add_flags add_flags,
struct section_addr_info *addrs,
- int flags, struct objfile *parent)
+ objfile_flags flags, struct objfile *parent)
{
struct objfile *objfile;
const int from_tty = add_flags & SYMFILE_VERBOSE;
const int mainline = add_flags & SYMFILE_MAINLINE;
- const int should_print = ((from_tty || info_verbose)
+ const int should_print = (print_symbol_loading_p (from_tty, mainline, 1)
&& (readnow_symbol_files
|| (add_flags & SYMFILE_NO_READ) == 0));
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. */
&& !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);
return objfile; /* No symbols. */
}
- new_symfile_objfile (objfile, add_flags);
+ finish_new_objfile (objfile, add_flags);
observer_notify_new_objfile (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;
sap = build_section_addr_info_from_objfile (objfile);
my_cleanup = make_cleanup_free_section_addr_info (sap);
- new_objfile = symbol_file_add_with_addrs
+ symbol_file_add_with_addrs
(bfd, name, symfile_flags, sap,
objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
| OBJF_USERLOADED),
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,
+symbol_file_add_from_bfd (bfd *abfd, const char *name,
+ symfile_add_flags add_flags,
struct section_addr_info *addrs,
- int flags, struct objfile *parent)
+ objfile_flags flags, struct objfile *parent)
{
return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags,
parent);
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,
+ struct 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
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);
what is frameless. */
reinit_frame_cache ();
- if ((flags & SYMFILE_NO_READ) == 0)
+ if ((add_flags & SYMFILE_NO_READ) == 0)
set_initial_language ();
}
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,
struct objfile *parent_objfile)
{
unsigned long file_crc;
int file_crc_p;
- bfd *abfd;
struct stat parent_stat, abfd_stat;
int verified_as_different;
if (filename_cmp (name, 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);
- if (!abfd)
+ gdb_bfd_ref_ptr abfd (gdb_bfd_open (name, gnutarget, -1));
+
+ 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;
{
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)
{
struct cleanup *back_to;
int ix;
- /* Set I to max (strlen (canon_dir), strlen (dir)). */
+ if (separate_debug_file_debug)
+ printf_unfiltered (_("\nLooking for separate debug info (debug link) for "
+ "%s\n"), objfile_name (objfile));
+
+ /* Set I to std::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);
+ debugfile
+ = (char *) xmalloc (strlen (debug_file_directory) + 1
+ + i
+ + strlen (DEBUG_SUBDIRECTORY)
+ + strlen ("/")
+ + strlen (debuglink)
+ + 1);
/* First try in the same directory as the original file. */
strcpy (debugfile, dir);
char *
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<char> debuglink
+ (bfd_get_debug_link_info (objfile->obfd, &crc32));
if (debuglink == NULL)
{
return NULL;
}
- 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<char> canon_dir (lrealpath (dir.c_str ()));
- debugfile = find_separate_debug_file (dir, canon_dir, debuglink,
- crc32, objfile);
- xfree (canon_dir);
+ debugfile = find_separate_debug_file (dir.c_str (), canon_dir.get (),
+ debuglink.get (), crc32, objfile);
if (debugfile == NULL)
{
-#ifdef HAVE_LSTAT
/* For PR gdb/9538, try again with realpath (if different from the
original). */
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<char> 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:
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 ();
}
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;
- cleanups = make_cleanup_freeargv (argv);
- while (*argv != NULL)
+ if (from_tty)
+ add_flags |= SYMFILE_VERBOSE;
+
+ 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);
}
}
void
set_initial_language (void)
{
- enum language lang = language_unknown;
+ enum language lang = main_language ();
- if (language_of_main != language_unknown)
- lang = language_of_main;
- else
+ 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);
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;
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
- if (remote_filename_p (cname))
+ 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 ()));
+ char *absolute_name;
- 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<char> 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);
+ make_cleanup (xfree, absolute_name);
+ name = absolute_name;
+ }
- 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);
+
+ if (!bfd_check_format (sym_bfd.get (), bfd_object))
+ error (_("`%s': can't read symbols: %s."), name,
+ bfd_errmsg (bfd_get_error ()));
do_cleanups (back_to);
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);
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
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));
/* 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);
if (arg == NULL)
{
- char *parg;
+ const char *parg;
int count = 0;
parg = arg = get_exec_file (1);
if (count)
{
/* We need to quote this string so buildargv can pull it apart. */
- char *temp = xmalloc (strlen (arg) + count + 1 );
+ char *temp = (char *) xmalloc (strlen (arg) + count + 1 );
char *ptemp = temp;
- char *prev;
+ const char *prev;
make_cleanup (xfree, temp);
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);
}
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)
{
/* 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;
}
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;
load_section_callback (bfd *abfd, asection *asec, void *data)
{
struct memory_write_request *new_request;
- struct load_section_data *args = data;
+ struct load_section_data *args = (struct load_section_data *) data;
struct load_progress_section_data *section_data;
bfd_size_type size = bfd_get_section_size (asec);
gdb_byte *buffer;
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));
+ section_data = XCNEW (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->data = (gdb_byte *) xmalloc (size);
new_request->baton = section_data;
buffer = new_request->data;
static void
clear_memory_write_data (void *arg)
{
- VEC(memory_write_request_s) **vec_p = arg;
+ VEC(memory_write_request_s) **vec_p = (VEC(memory_write_request_s) **) arg;
VEC(memory_write_request_s) *vec = *vec_p;
int i;
struct memory_write_request *mr;
VEC_free (memory_write_request_s, vec);
}
+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 cleanup *old_cleanups;
struct load_section_data cbdata;
struct load_progress_data 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);
+ old_cleanups = 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<char> filename (tilde_expand (argv[0]));
if (argv[1] != NULL)
{
}
/* 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;
- }
+ perror_with_name (filename.get ());
- make_cleanup_bfd_unref (loadfile_bfd);
-
- 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);
+ 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
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);
+ end_time - start_time);
do_cleanups (old_cleanups);
}
-/* 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<milliseconds> (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.
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;
+ gdb::unique_xmalloc_ptr<char> 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;
+ std::vector<sect_opt> sect_opts = { { ".text", NULL } };
+ bool stop_processing_options = false;
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));
-
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)
+ if (stop_processing_options || *arg != '-')
{
- /* The first argument is the file name. */
- filename = tilde_expand (arg);
- make_cleanup (xfree, filename);
- }
- else if (argcnt == 1)
- {
- /* 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)
- {
- num_sect_opts *= 2;
- sect_opts = ((struct sect_opt *)
- xrealloc (sect_opts,
- num_sect_opts
- * sizeof (struct sect_opt)));
- }
- }
- 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)
+ if (filename == NULL)
{
- 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)));
- }
+ /* First non-option argument is always the filename. */
+ filename.reset (tilde_expand (arg));
}
- 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 <filename> <textaddress>"
- " [-readnow] [-s <secname> <addr>]*"));
+ 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
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);
+ printf_unfiltered (_("add symbol table from file \"%s\" at\n"),
+ filename.get ());
+ section_addrs = alloc_section_addr_info (sect_opts.size ());
make_cleanup (xfree, section_addrs);
- for (i = 0; i < section_index; i++)
+ 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].name = (char *) sec;
section_addrs->other[sec_num].addr = addr;
printf_unfiltered ("\t%s_addr = %s\n", sec,
paddress (gdbarch, addr));
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, section_addrs, flags);
add_target_sections_of_objfile (objf);
/* 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)
{
ALL_OBJFILES (objf)
{
- if (objf != 0
- && objf->flags & OBJF_USERLOADED
+ if ((objf->flags & OBJF_USERLOADED) != 0
+ && (objf->flags & OBJF_SHARED) != 0
&& objf->pspace == pspace && is_addr_in_objfile (addr, objf))
break;
}
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<char> filename (tilde_expand (argv[0]));
ALL_OBJFILES (objf)
{
- if (objf != 0
- && objf->flags & OBJF_USERLOADED
+ 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;
}
}
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
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<struct objfile *> new_objfiles;
/* With the addition of shared libraries, this should be modified,
the load time should be saved in the partial symbol tables, since
/* 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<struct objfile> 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),
/* 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);
/* 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;
objfile->template_symbols = NULL;
- objfile->msymbols = NULL;
- objfile->minimal_symbol_count = 0;
- memset (&objfile->msymbol_hash, 0,
- sizeof (objfile->msymbol_hash));
- memset (&objfile->msymbol_demangled_hash, 0,
- sizeof (objfile->msymbol_demangled_hash));
/* obstack_init also initializes the obstack so it is
empty. We could use obstack_specify_allocation but
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
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))
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
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
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)
+ observer_notify_new_objfile (iter);
/* At least one objfile has changed, so we can consider that
the executable we're debugging has changed too. */
observer_notify_executable_changed ();
}
-
- do_cleanups (all_cleanups);
}
\f
-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> 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;
}
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;
/* 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);
/* 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;
}
\f
-/* 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. */
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;
}
\f
-/* 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. */
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);
/* 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
{
if (overlay_debugging && section)
{
- bfd *abfd = section->objfile->obfd;
asection *bfd_section = section->the_bfd_section;
if (bfd_section_lma (abfd, bfd_section) != 0
{
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)
{
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)
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;
}
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;
}
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"));
}
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;
(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. "
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 ();
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 ();
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 ();
}
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 ();
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");
- help_list (overlaylist, "overlay ", -1, gdb_stdout);
+ help_list (overlaylist, "overlay ", all_commands, gdb_stdout);
}
/* Target Overlays for the "Simplest" overlay manager:
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
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. */
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);
static int
simple_read_overlay_table (void)
{
- struct minimal_symbol *novlys_msym;
+ struct bound_minimal_symbol novlys_msym;
struct bound_minimal_symbol ovly_table_msym;
struct gdbarch *gdbarch;
int word_size;
simple_free_overlay_table ();
novlys_msym = lookup_minimal_symbol ("_novlys", NULL, NULL);
- if (! novlys_msym)
+ if (! novlys_msym.minsym)
{
error (_("Error reading inferior's overlay table: "
"couldn't find `_novlys' variable\n"
word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
byte_order = gdbarch_byte_order (gdbarch);
- cache_novlys = read_memory_integer (SYMBOL_VALUE_ADDRESS (novlys_msym),
+ cache_novlys = read_memory_integer (BMSYMBOL_VALUE_ADDRESS (novlys_msym),
4, byte_order);
cache_ovly_table
- = (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table));
- cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym.minsym);
+ = (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,
cache_novlys * 4, word_size, byte_order);
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;
{
/* Does its cached location match what's currently in the
symtab? */
- struct minimal_symbol *minsym
+ struct bound_minimal_symbol minsym
= lookup_minimal_symbol ("_ovly_table", NULL, NULL);
- if (minsym == NULL)
+ if (minsym.minsym == NULL)
error (_("Error reading inferior's overlay table: couldn't "
"find `_ovly_table' array\n"
"in inferior. Use `overlay manual' mode."));
- if (cache_ovly_table_base == SYMBOL_VALUE_ADDRESS (minsym))
+ if (cache_ovly_table_base == BMSYMBOL_VALUE_ADDRESS (minsym))
/* Then go ahead and try to look up this single section in
the cache. */
if (simple_overlay_update_1 (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. */
static void
symfile_free_objfile (struct objfile *objfile)
{
- /* Remove the target sections of user-added objfiles. */
- if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
+ /* Remove the target sections owned by this objfile. */
+ if (objfile != NULL)
remove_target_sections ((void *) objfile);
}
See quick_symbol_functions.expand_symtabs_matching for details. */
void
-expand_partial_symbol_names (expand_symtabs_symbol_matcher_ftype *fun,
- void *data)
+expand_symtabs_matching
+ (gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+ const lookup_name_info &lookup_name,
+ gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+ gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+ enum search_domain kind)
{
struct objfile *objfile;
ALL_OBJFILES (objfile)
{
if (objfile->sf)
- objfile->sf->qf->expand_symtabs_matching (objfile, NULL, fun,
- ALL_DOMAIN, data);
+ objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher,
+ lookup_name,
+ symbol_matcher,
+ expansion_notify, kind);
}
}
See quick_symbol_functions.map_symbol_filenames for details. */
void
-map_partial_symbol_filenames (symbol_filename_ftype *fun, void *data,
- int need_fullname)
+map_symbol_filenames (symbol_filename_ftype *fun, void *data,
+ int need_fullname)
{
struct objfile *objfile;
}
}
+#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<char> 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)
{
observer_attach_free_objfile (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 <SECT> <SECT_ADDR> -s <SECT> <SECT_ADDR>\
- ...]\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);
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,
_("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."), _("\
NULL,
show_debug_file_directory,
&setlist, &showlist);
+
+ add_setshow_enum_cmd ("symbol-loading", no_class,
+ print_symbol_loading_enums, &print_symbol_loading,
+ _("\
+Set printing of symbol loading messages."), _("\
+Show printing of symbol loading messages."), _("\
+off == turn all messages off\n\
+brief == print messages for the executable,\n\
+ and brief messages for shared libraries\n\
+full == print messages for the executable,\n\
+ and messages for each shared library."),
+ 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
}