/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright (C) 1990-2017 Free Software Foundation, Inc.
+ Copyright (C) 1990-2018 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
#include "hashtab.h"
#include "readline/readline.h"
#include "block.h"
-#include "observer.h"
+#include "observable.h"
#include "exec.h"
#include "parser-defs.h"
#include "varobj.h"
#include <sys/stat.h>
#include <ctype.h>
#include <chrono>
+#include <algorithm>
#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, symfile_add_flags add_flags,
objfile_flags flags);
*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
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;
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<const struct other_sections *>
+addrs_section_sort (const section_addr_info &addrs)
{
- struct other_sections **array;
int i;
- /* `+ 1' for the NULL terminator. */
- 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;
+ std::vector<const struct other_sections *> 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;
}
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. */
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<const struct other_sections *> 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<const struct other_sections *> 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 = XCNEWVEC (struct other_sections *, addrs->num_sections);
- make_cleanup (xfree, addrs_to_abfd_addrs);
+ std::vector<const struct other_sections *>
+ addrs_to_abfd_addrs (addrs->size (), nullptr);
- while (*addrs_sorted)
+ std::vector<const struct other_sections *>::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.
(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.
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
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 *)
static void
syms_from_objfile_1 (struct objfile *objfile,
- struct section_addr_info *addrs,
+ 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;
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)
{
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
(*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);
objfile_holder.release ();
discard_cleanups (old_chain);
- xfree (local_addr);
}
/* Same as syms_from_objfile_1, but also initializes the objfile
static void
syms_from_objfile (struct objfile *objfile,
- struct section_addr_info *addrs,
+ section_addr_info *addrs,
symfile_add_flags add_flags)
{
syms_from_objfile_1 (objfile, addrs, add_flags);
static struct objfile *
symbol_file_add_with_addrs (bfd *abfd, const char *name,
symfile_add_flags add_flags,
- struct section_addr_info *addrs,
+ section_addr_info *addrs,
objfile_flags flags, struct objfile *parent)
{
struct objfile *objfile;
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. */
if (objfile->sf == NULL)
{
- observer_notify_new_objfile (objfile);
+ gdb::observers::new_objfile.notify (objfile);
return objfile; /* No symbols. */
}
finish_new_objfile (objfile, add_flags);
- observer_notify_new_objfile (objfile);
+ gdb::observers::new_objfile.notify (objfile);
bfd_cache_close_all ();
return (objfile);
symfile_add_flags symfile_flags,
struct objfile *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);
symbol_file_add_with_addrs
- (bfd, name, symfile_flags, sap,
+ (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
struct objfile *
symbol_file_add_from_bfd (bfd *abfd, const char *name,
symfile_add_flags add_flags,
- struct section_addr_info *addrs,
+ section_addr_info *addrs,
objfile_flags flags, struct objfile *parent)
{
return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags,
struct objfile *
symbol_file_add (const char *name, symfile_add_flags add_flags,
- struct section_addr_info *addrs, objfile_flags flags)
+ section_addr_info *addrs, objfile_flags flags)
{
gdb_bfd_ref_ptr bfd (symfile_bfd_open (name));
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;
".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;
if (separate_debug_file_debug)
- printf_unfiltered (_(" Trying %s\n"), name);
+ printf_unfiltered (_(" Trying %s\n"), name.c_str ());
- gdb_bfd_ref_ptr abfd (gdb_bfd_open (name, gnutarget, -1));
+ gdb_bfd_ref_ptr abfd (gdb_bfd_open (name.c_str (), gnutarget, -1));
if (abfd == NULL)
return 0;
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;
}
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;
-
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
- = (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);
- 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;
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<gdb::unique_xmalloc_ptr<char>> 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<char> &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. */
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.
}
/* 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 *debugfile;
unsigned long crc32;
gdb::unique_xmalloc_ptr<char> debuglink
{
/* There's no separate debug info, hence there's no way we could
load it => no warning. */
- return NULL;
+ return std::string ();
}
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.c_str (), canon_dir.get (),
- debuglink.get (), crc32, objfile);
+ std::string debugfile
+ = find_separate_debug_file (dir.c_str (), canon_dir.get (),
+ debuglink.get (), crc32, objfile);
- if (debugfile == NULL)
+ if (debugfile.empty ())
{
/* For PR gdb/9538, try again with realpath (if different from the
original). */
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:
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;
gdb_argv built_argv (args);
- for (char *arg : built_argv)
+ for (arg = built_argv[0], idx = 0; arg != NULL; arg = built_argv[++idx])
{
- if (strcmp (arg, "-readnow") == 0)
- flags |= OBJF_READNOW;
- else if (*arg == '-')
- error (_("unknown option `%s'"), arg);
- else
+ if (stop_processing_options || *arg != '-')
{
- symbol_file_add_main_1 (arg, add_flags, flags);
- name = arg;
+ if (name == NULL)
+ name = arg;
+ else
+ 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, "--") == 0)
+ stop_processing_options = true;
+ else
+ error (_("Unrecognized argument \"%s\""), arg);
}
if (name == NULL)
error (_("no symbol file name was specified"));
+
+ validate_readnow_readnever (flags);
+
+ symbol_file_add_main_1 (name, add_flags, flags);
}
}
symfile_bfd_open (const char *name)
{
int desc = -1;
- struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+ gdb::unique_xmalloc_ptr<char> absolute_name;
if (!is_target_filename (name))
{
- char *absolute_name;
-
gdb::unique_xmalloc_ptr<char> expanded_name (tilde_expand (name));
/* Look down path for it, allocate 2nd new malloc'd copy. */
if (desc < 0)
perror_with_name (expanded_name.get ());
- make_cleanup (xfree, absolute_name);
- name = absolute_name;
+ name = absolute_name.get ();
}
gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (name, gnutarget, desc));
error (_("`%s': can't read symbols: %s."), name,
bfd_errmsg (bfd_get_error ()));
- do_cleanups (back_to);
-
return sym_bfd;
}
/* 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
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 = (char *) 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 ();
}
}
/* 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
*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<struct memory_write_request> requests;
+};
+
/* Target write callback routine for progress reporting. */
static void
static void
load_section_callback (bfd *abfd, asection *asec, void *data)
{
- struct memory_write_request *new_request;
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;
const char *sect_name = bfd_get_section_name (abfd, asec);
if ((bfd_get_section_flags (abfd, asec) & SEC_LOAD) == 0)
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 = 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 = (gdb_byte *) 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. */
-
-static void
-clear_memory_write_data (void *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;
+ load_progress_section_data *section_data
+ = new load_progress_section_data (args->progress_data, sect_name, size,
+ begin, buffer);
- 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,
void
generic_load (const char *args, int from_tty)
{
- struct cleanup *old_cleanups;
- 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;
-
- memset (&cbdata, 0, sizeof (cbdata));
- memset (&total_progress, 0, sizeof (total_progress));
- cbdata.progress_data = &total_progress;
-
- old_cleanups = make_cleanup (clear_memory_write_data, &cbdata.requests);
-
if (args == NULL)
error_no_arg (_("file to load"));
steady_clock::time_point end_time = steady_clock::now ();
- entry = bfd_get_start_address (loadfile_bfd.get ());
+ CORE_ADDR entry = bfd_get_start_address (loadfile_bfd.get ());
entry = gdbarch_addr_bits_remove (target_gdbarch (), entry);
uiout->text ("Start address ");
uiout->field_fmt ("address", "%s", paddress (target_gdbarch (), entry));
print_transfer_performance (gdb_stdout, total_progress.data_count,
total_progress.write_count,
end_time - start_time);
-
- do_cleanups (old_cleanups);
}
/* Report on STREAM the performance of a memory transfer operation,
gdb::unique_xmalloc_ptr<char> filename;
char *arg;
int argcnt = 0;
- int sec_num = 0;
- int expecting_sec_name = 0;
- int expecting_sec_addr = 0;
struct objfile *objf;
objfile_flags flags = OBJF_USERLOADED | OBJF_SHARED;
symfile_add_flags add_flags = 0;
const char *value;
};
- struct section_addr_info *section_addrs;
- std::vector<sect_opt> sect_opts;
- struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL);
+ std::vector<sect_opt> 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"));
+ 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.reset (tilde_expand (arg));
- }
- else if (argcnt == 1)
- {
- /* The second argument is always the text address at which
- to load the program. */
- sect_opt sect = { ".text", arg };
- sect_opts.push_back (sect);
- }
- else
- {
- /* It's an option (starting with '-') or it's an argument
- to an option. */
- if (expecting_sec_name)
+ if (filename == NULL)
{
- sect_opt sect = { arg, NULL };
- sect_opts.push_back (sect);
- expecting_sec_name = 0;
+ /* First non-option argument is always the filename. */
+ filename.reset (tilde_expand (arg));
}
- else if (expecting_sec_addr)
+ else if (!seen_addr)
{
- sect_opts.back ().value = arg;
- expecting_sec_addr = 0;
- }
- else if (strcmp (arg, "-readnow") == 0)
- flags |= OBJF_READNOW;
- else if (strcmp (arg, "-s") == 0)
- {
- 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 (sect_opts.empty ())
+ if (!seen_addr)
error (_("The address where %s has been loaded is missing"),
filename.get ());
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);
+ section_addr_info section_addrs;
for (sect_opt § : sect_opts)
{
CORE_ADDR addr;
/* Here we store the section offsets in the order they were
entered on the command line. */
- section_addrs->other[sec_num].name = (char *) 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).
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.get (), add_flags, 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);
}
\f
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 (auto iter : new_objfiles)
- observer_notify_new_objfile (iter);
+ 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 ();
}
}
\f
}
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)
{
char *cp = ext_args;
enum language lang;
clear_displays ();
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 ();
{
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)
simple_overlay_update_1 (struct obj_section *osect)
{
int i;
- bfd *obfd = osect->objfile->obfd;
asection *bsect = osect->the_bfd_section;
struct gdbarch *gdbarch = get_objfile_arch (osect->objfile);
int word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
if (section_is_overlay (osect))
{
int i;
- bfd *obfd = osect->objfile->obfd;
asection *bsect = osect->the_bfd_section;
for (i = 0; i < cache_novlys; i++)
void
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)
{
if (objfile->sf)
objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher,
+ lookup_name,
symbol_matcher,
expansion_notify, kind);
}
{
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 <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\
+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.\n\
-Usage: load [FILE] [OFFSET]"), &cmdlist);
+on its own."), &cmdlist);
set_cmd_completer (c, filename_completer);
add_prefix_cmd ("overlay", class_support, overlay_command,