/* Handle shared libraries for GDB, the GNU Debugger.
- Copyright (C) 1990-2014 Free Software Foundation, Inc.
+ Copyright (C) 1990-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
-#include "exceptions.h"
#include "gdbcore.h"
#include "command.h"
#include "target.h"
#include "frame.h"
#include "gdb_regex.h"
#include "inferior.h"
-#include "environ.h"
+#include "gdbsupport/environ.h"
#include "language.h"
#include "gdbcmd.h"
#include "completer.h"
#include "filenames.h" /* for DOSish file names */
#include "exec.h"
#include "solist.h"
-#include "observer.h"
-#include "readline/readline.h"
+#include "observable.h"
+#include "readline/tilde.h"
#include "remote.h"
#include "solib.h"
#include "interps.h"
#include "filesystem.h"
#include "gdb_bfd.h"
-#include "filestuff.h"
+#include "gdbsupport/filestuff.h"
+#include "source.h"
+#include "cli/cli-style.h"
/* Architecture-specific operations. */
static const struct target_so_ops *
solib_ops (struct gdbarch *gdbarch)
{
- const struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
+ const struct target_so_ops **ops
+ = (const struct target_so_ops **) gdbarch_data (gdbarch, solib_data);
return *ops;
}
void
set_solib_ops (struct gdbarch *gdbarch, const struct target_so_ops *new_ops)
{
- const struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
+ const struct target_so_ops **ops
+ = (const struct target_so_ops **) gdbarch_data (gdbarch, solib_data);
*ops = new_ops;
}
configuration needs to call set_solib_ops. */
struct target_so_ops *current_target_so_ops;
-/* List of known shared objects */
-#define so_list_head current_program_space->so_list
-
/* Local function prototypes */
/* If non-empty, this is a search path for loading non-absolute shared library
# define DOS_BASED_FILE_SYSTEM 0
#endif
-/* Returns the full pathname of the shared library file, or NULL if
- not found. (The pathname is malloc'ed; it needs to be freed by the
- caller.) *FD is set to either -1 or an open file handle for the
- library.
+/* Return the full pathname of a binary file (the main executable or a
+ shared library file), or NULL if not found. If FD is non-NULL, *FD
+ is set to either -1 or an open file handle for the binary file.
Global variable GDB_SYSROOT is used as a prefix directory
- to search for shared libraries if they have an absolute path.
+ to search for binary files if they have an absolute path.
+ If GDB_SYSROOT starts with "target:" and target filesystem
+ is the local filesystem then the "target:" prefix will be
+ stripped before the search starts. This ensures that the
+ same search algorithm is used for local files regardless of
+ whether a "target:" prefix was used.
Global variable SOLIB_SEARCH_PATH is used as a prefix directory
(or set of directories, as in LD_LIBRARY_PATH) to search for all
- shared libraries if not found in GDB_SYSROOT.
+ shared libraries if not found in either the sysroot (if set) or
+ the local filesystem. SOLIB_SEARCH_PATH is not used when searching
+ for the main executable.
Search algorithm:
- * If there is a gdb_sysroot and path is absolute:
- * Search for gdb_sysroot/path.
+ * If a sysroot is set and path is absolute:
+ * Search for sysroot/path.
* else
* Look for it literally (unmodified).
- * Look in SOLIB_SEARCH_PATH.
- * If available, use target defined search function.
- * If gdb_sysroot is NOT set, perform the following two searches:
+ * If IS_SOLIB is non-zero:
+ * Look in SOLIB_SEARCH_PATH.
+ * If available, use target defined search function.
+ * If NO sysroot is set, perform the following two searches:
* Look in inferior's $PATH.
- * Look in inferior's $LD_LIBRARY_PATH.
+ * If IS_SOLIB is non-zero:
+ * Look in inferior's $LD_LIBRARY_PATH.
*
- * The last check avoids doing this search when targetting remote
- * machines since gdb_sysroot will almost always be set.
+ * The last check avoids doing this search when targeting remote
+ * machines since a sysroot will almost always be set.
*/
-char *
-solib_find (char *in_pathname, int *fd)
+static gdb::unique_xmalloc_ptr<char>
+solib_find_1 (const char *in_pathname, int *fd, int is_solib)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
int found_file = -1;
- char *temp_pathname = NULL;
- int gdb_sysroot_is_empty;
- const char *solib_symbols_extension
- = gdbarch_solib_symbols_extension (target_gdbarch ());
+ gdb::unique_xmalloc_ptr<char> temp_pathname;
const char *fskind = effective_target_file_system_kind ();
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- char *sysroot = NULL;
-
- /* If solib_symbols_extension is set, replace the file's
- extension. */
- if (solib_symbols_extension)
- {
- char *p = in_pathname + strlen (in_pathname);
-
- while (p > in_pathname && *p != '.')
- p--;
-
- if (*p == '.')
- {
- char *new_pathname;
-
- new_pathname = alloca (p - in_pathname + 1
- + strlen (solib_symbols_extension) + 1);
- memcpy (new_pathname, in_pathname, p - in_pathname + 1);
- strcpy (new_pathname + (p - in_pathname) + 1,
- solib_symbols_extension);
-
- in_pathname = new_pathname;
- }
- }
-
- gdb_sysroot_is_empty = (gdb_sysroot == NULL || *gdb_sysroot == 0);
-
- if (!gdb_sysroot_is_empty)
+ const char *sysroot = gdb_sysroot;
+ int prefix_len, orig_prefix_len;
+
+ /* If the absolute prefix starts with "target:" but the filesystem
+ accessed by the target_fileio_* methods is the local filesystem
+ then we strip the "target:" prefix now and work with the local
+ filesystem. This ensures that the same search algorithm is used
+ for all local files regardless of whether a "target:" prefix was
+ used. */
+ if (is_target_filename (sysroot) && target_filesystem_is_local ())
+ sysroot += strlen (TARGET_SYSROOT_PREFIX);
+
+ /* Strip any trailing slashes from the absolute prefix. */
+ prefix_len = orig_prefix_len = strlen (sysroot);
+
+ while (prefix_len > 0 && IS_DIR_SEPARATOR (sysroot[prefix_len - 1]))
+ prefix_len--;
+
+ std::string sysroot_holder;
+ if (prefix_len == 0)
+ sysroot = NULL;
+ else if (prefix_len != orig_prefix_len)
{
- int prefix_len = strlen (gdb_sysroot);
-
- /* Remove trailing slashes from absolute prefix. */
- while (prefix_len > 0
- && IS_DIR_SEPARATOR (gdb_sysroot[prefix_len - 1]))
- prefix_len--;
-
- sysroot = savestring (gdb_sysroot, prefix_len);
- make_cleanup (xfree, sysroot);
+ sysroot_holder = std::string (sysroot, prefix_len);
+ sysroot = sysroot_holder.c_str ();
}
/* If we're on a non-DOS-based system, backslashes won't be
char *p;
/* Avoid clobbering our input. */
- p = alloca (strlen (in_pathname) + 1);
+ p = (char *) alloca (strlen (in_pathname) + 1);
strcpy (p, in_pathname);
in_pathname = p;
3rd attempt, c:/foo/bar.dll ==> /sysroot/foo/bar.dll
*/
- if (!IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname) || gdb_sysroot_is_empty)
- temp_pathname = xstrdup (in_pathname);
+ if (!IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname) || sysroot == NULL)
+ temp_pathname.reset (xstrdup (in_pathname));
else
{
int need_dir_separator;
|-----------------+-----------+----------------|
| /some/dir | / | c:/foo/bar.dll |
| /some/dir | | /foo/bar.dll |
- | remote: | | c:/foo/bar.dll |
- | remote: | | /foo/bar.dll |
- | remote:some/dir | / | c:/foo/bar.dll |
- | remote:some/dir | | /foo/bar.dll |
+ | target: | | c:/foo/bar.dll |
+ | target: | | /foo/bar.dll |
+ | target:some/dir | / | c:/foo/bar.dll |
+ | target:some/dir | | /foo/bar.dll |
IOW, we don't need to add a separator if IN_PATHNAME already
- has one, or when the the sysroot is exactly "remote:".
+ has one, or when the sysroot is exactly "target:".
There's no need to check for drive spec explicitly, as we only
get here if IN_PATHNAME is considered an absolute path. */
need_dir_separator = !(IS_DIR_SEPARATOR (in_pathname[0])
- || strcmp (REMOTE_SYSROOT_PREFIX, sysroot) == 0);
+ || strcmp (TARGET_SYSROOT_PREFIX, sysroot) == 0);
/* Cat the prefixed pathname together. */
- temp_pathname = concat (sysroot,
- need_dir_separator ? SLASH_STRING : "",
- in_pathname, (char *) NULL);
+ temp_pathname.reset (concat (sysroot,
+ need_dir_separator ? SLASH_STRING : "",
+ in_pathname, (char *) NULL));
}
- /* Handle remote files. */
- if (remote_filename_p (temp_pathname))
+ /* Handle files to be accessed via the target. */
+ if (is_target_filename (temp_pathname.get ()))
{
- *fd = -1;
- do_cleanups (old_chain);
+ if (fd != NULL)
+ *fd = -1;
return temp_pathname;
}
/* Now see if we can open it. */
- found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
- if (found_file < 0)
- xfree (temp_pathname);
+ found_file = gdb_open_cloexec (temp_pathname.get (), O_RDONLY | O_BINARY, 0);
/* If the search in gdb_sysroot failed, and the path name has a
drive spec (e.g, c:/foo), try stripping ':' from the drive spec,
c:/foo/bar.dll ==> /sysroot/c/foo/bar.dll. */
if (found_file < 0
- && !gdb_sysroot_is_empty
+ && sysroot != NULL
&& HAS_TARGET_DRIVE_SPEC (fskind, in_pathname))
{
int need_dir_separator = !IS_DIR_SEPARATOR (in_pathname[2]);
- char *drive = savestring (in_pathname, 1);
+ char drive[2] = { in_pathname[0], '\0' };
- temp_pathname = concat (sysroot,
- SLASH_STRING,
- drive,
- need_dir_separator ? SLASH_STRING : "",
- in_pathname + 2, (char *) NULL);
- xfree (drive);
+ temp_pathname.reset (concat (sysroot,
+ SLASH_STRING,
+ drive,
+ need_dir_separator ? SLASH_STRING : "",
+ in_pathname + 2, (char *) NULL));
- found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
+ found_file = gdb_open_cloexec (temp_pathname.get (),
+ O_RDONLY | O_BINARY, 0);
if (found_file < 0)
{
- xfree (temp_pathname);
-
/* If the search in gdb_sysroot still failed, try fully
stripping the drive spec, and trying once more in the
sysroot before giving up.
c:/foo/bar.dll ==> /sysroot/foo/bar.dll. */
- temp_pathname = concat (sysroot,
- need_dir_separator ? SLASH_STRING : "",
- in_pathname + 2, (char *) NULL);
+ temp_pathname.reset (concat (sysroot,
+ need_dir_separator ? SLASH_STRING : "",
+ in_pathname + 2, (char *) NULL));
- found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
- if (found_file < 0)
- xfree (temp_pathname);
+ found_file = gdb_open_cloexec (temp_pathname.get (),
+ O_RDONLY | O_BINARY, 0);
}
}
- do_cleanups (old_chain);
-
/* We try to find the library in various ways. After each attempt,
either found_file >= 0 and temp_pathname is a malloc'd string, or
found_file < 0 and temp_pathname does not point to storage that
needs to be freed. */
if (found_file < 0)
- temp_pathname = NULL;
+ temp_pathname.reset (NULL);
/* If the search in gdb_sysroot failed, and the path name is
absolute at this point, make it relative. (openp will try and open the
in_pathname++;
}
- /* If not found, search the solib_search_path (if any). */
- if (found_file < 0 && solib_search_path != NULL)
+ /* If not found, and we're looking for a solib, search the
+ solib_search_path (if any). */
+ if (is_solib && found_file < 0 && solib_search_path != NULL)
found_file = openp (solib_search_path,
OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
in_pathname, O_RDONLY | O_BINARY, &temp_pathname);
- /* If not found, next search the solib_search_path (if any) for the basename
- only (ignoring the path). This is to allow reading solibs from a path
- that differs from the opened path. */
- if (found_file < 0 && solib_search_path != NULL)
+ /* If not found, and we're looking for a solib, next search the
+ solib_search_path (if any) for the basename only (ignoring the
+ path). This is to allow reading solibs from a path that differs
+ from the opened path. */
+ if (is_solib && found_file < 0 && solib_search_path != NULL)
found_file = openp (solib_search_path,
OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
target_lbasename (fskind, in_pathname),
O_RDONLY | O_BINARY, &temp_pathname);
- /* If not found, try to use target supplied solib search method. */
- if (found_file < 0 && ops->find_and_open_solib)
+ /* If not found, and we're looking for a solib, try to use target
+ supplied solib search method. */
+ if (is_solib && found_file < 0 && ops->find_and_open_solib)
found_file = ops->find_and_open_solib (in_pathname, O_RDONLY | O_BINARY,
&temp_pathname);
/* If not found, next search the inferior's $PATH environment variable. */
- if (found_file < 0 && gdb_sysroot_is_empty)
- found_file = openp (get_in_environ (current_inferior ()->environment,
- "PATH"),
+ if (found_file < 0 && sysroot == NULL)
+ found_file = openp (current_inferior ()->environment.get ("PATH"),
OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, in_pathname,
O_RDONLY | O_BINARY, &temp_pathname);
- /* If not found, next search the inferior's $LD_LIBRARY_PATH
- environment variable. */
- if (found_file < 0 && gdb_sysroot_is_empty)
- found_file = openp (get_in_environ (current_inferior ()->environment,
- "LD_LIBRARY_PATH"),
+ /* If not found, and we're looking for a solib, next search the
+ inferior's $LD_LIBRARY_PATH environment variable. */
+ if (is_solib && found_file < 0 && sysroot == NULL)
+ found_file = openp (current_inferior ()->environment.get
+ ("LD_LIBRARY_PATH"),
OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, in_pathname,
O_RDONLY | O_BINARY, &temp_pathname);
- *fd = found_file;
+ if (fd == NULL)
+ {
+ if (found_file >= 0)
+ close (found_file);
+ }
+ else
+ *fd = found_file;
+
return temp_pathname;
}
-/* Open and return a BFD for the shared library PATHNAME. If FD is not -1,
- it is used as file handle to open the file. Throws an error if the file
- could not be opened. Handles both local and remote file access.
-
- PATHNAME must be malloc'ed by the caller. It will be freed by this
- function. If unsuccessful, the FD will be closed (unless FD was
- -1). */
+/* Return the full pathname of the main executable, or NULL if not
+ found. If FD is non-NULL, *FD is set to either -1 or an open file
+ handle for the main executable. */
-bfd *
-solib_bfd_fopen (char *pathname, int fd)
+gdb::unique_xmalloc_ptr<char>
+exec_file_find (const char *in_pathname, int *fd)
{
- bfd *abfd;
+ gdb::unique_xmalloc_ptr<char> result;
+ const char *fskind = effective_target_file_system_kind ();
+
+ if (in_pathname == NULL)
+ return NULL;
- if (remote_filename_p (pathname))
+ if (*gdb_sysroot != '\0' && IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname))
{
- gdb_assert (fd == -1);
- abfd = remote_bfd_open (pathname, gnutarget);
+ result = solib_find_1 (in_pathname, fd, 0);
+
+ if (result == NULL && fskind == file_system_kind_dos_based)
+ {
+ char *new_pathname;
+
+ new_pathname = (char *) alloca (strlen (in_pathname) + 5);
+ strcpy (new_pathname, in_pathname);
+ strcat (new_pathname, ".exe");
+
+ result = solib_find_1 (new_pathname, fd, 0);
+ }
}
else
{
- abfd = gdb_bfd_open (pathname, gnutarget, fd);
+ /* It's possible we don't have a full path, but rather just a
+ filename. Some targets, such as HP-UX, don't provide the
+ full path, sigh.
+
+ Attempt to qualify the filename against the source path.
+ (If that fails, we'll just fall back on the original
+ filename. Not much more we can do...) */
+
+ if (!source_full_path_of (in_pathname, &result))
+ result.reset (xstrdup (in_pathname));
+ if (fd != NULL)
+ *fd = -1;
+ }
+
+ return result;
+}
+
+/* Return the full pathname of a shared library file, or NULL if not
+ found. If FD is non-NULL, *FD is set to either -1 or an open file
+ handle for the shared library.
+
+ The search algorithm used is described in solib_find_1's comment
+ above. */
+
+gdb::unique_xmalloc_ptr<char>
+solib_find (const char *in_pathname, int *fd)
+{
+ const char *solib_symbols_extension
+ = gdbarch_solib_symbols_extension (target_gdbarch ());
+
+ /* If solib_symbols_extension is set, replace the file's
+ extension. */
+ if (solib_symbols_extension != NULL)
+ {
+ const char *p = in_pathname + strlen (in_pathname);
- if (abfd)
- bfd_set_cacheable (abfd, 1);
+ while (p > in_pathname && *p != '.')
+ p--;
+
+ if (*p == '.')
+ {
+ char *new_pathname;
+
+ new_pathname
+ = (char *) alloca (p - in_pathname + 1
+ + strlen (solib_symbols_extension) + 1);
+ memcpy (new_pathname, in_pathname, p - in_pathname + 1);
+ strcpy (new_pathname + (p - in_pathname) + 1,
+ solib_symbols_extension);
+
+ in_pathname = new_pathname;
+ }
}
- if (!abfd)
+ return solib_find_1 (in_pathname, fd, 1);
+}
+
+/* Open and return a BFD for the shared library PATHNAME. If FD is not -1,
+ it is used as file handle to open the file. Throws an error if the file
+ could not be opened. Handles both local and remote file access.
+
+ If unsuccessful, the FD will be closed (unless FD was -1). */
+
+gdb_bfd_ref_ptr
+solib_bfd_fopen (const char *pathname, int fd)
+{
+ gdb_bfd_ref_ptr abfd (gdb_bfd_open (pathname, gnutarget, fd));
+
+ if (abfd != NULL && !gdb_bfd_has_target_filename (abfd.get ()))
+ bfd_set_cacheable (abfd.get (), 1);
+
+ if (abfd == NULL)
{
- make_cleanup (xfree, pathname);
+ /* Arrange to free PATHNAME when the error is thrown. */
error (_("Could not open `%s' as an executable file: %s"),
pathname, bfd_errmsg (bfd_get_error ()));
}
- xfree (pathname);
-
return abfd;
}
/* Find shared library PATHNAME and open a BFD for it. */
-bfd *
-solib_bfd_open (char *pathname)
+gdb_bfd_ref_ptr
+solib_bfd_open (const char *pathname)
{
- char *found_pathname;
int found_file;
- bfd *abfd;
const struct bfd_arch_info *b;
/* Search for shared library file. */
- found_pathname = solib_find (pathname, &found_file);
+ gdb::unique_xmalloc_ptr<char> found_pathname
+ = solib_find (pathname, &found_file);
if (found_pathname == NULL)
{
/* Return failure if the file could not be found, so that we can
}
/* Open bfd for shared library. */
- abfd = solib_bfd_fopen (found_pathname, found_file);
+ gdb_bfd_ref_ptr abfd (solib_bfd_fopen (found_pathname.get (), found_file));
/* Check bfd format. */
- if (!bfd_check_format (abfd, bfd_object))
- {
- make_cleanup_bfd_unref (abfd);
- error (_("`%s': not in executable format: %s"),
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
- }
+ if (!bfd_check_format (abfd.get (), bfd_object))
+ error (_("`%s': not in executable format: %s"),
+ bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
/* Check bfd arch. */
b = gdbarch_bfd_arch_info (target_gdbarch ());
- if (!b->compatible (b, bfd_get_arch_info (abfd)))
+ if (!b->compatible (b, bfd_get_arch_info (abfd.get ())))
warning (_("`%s': Shared library architecture %s is not compatible "
- "with target architecture %s."), bfd_get_filename (abfd),
- bfd_get_arch_info (abfd)->printable_name, b->printable_name);
+ "with target architecture %s."), bfd_get_filename (abfd.get ()),
+ bfd_get_arch_info (abfd.get ())->printable_name,
+ b->printable_name);
return abfd;
}
solib_map_sections (struct so_list *so)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
- char *filename;
struct target_section *p;
- struct cleanup *old_chain;
- bfd *abfd;
- filename = tilde_expand (so->so_name);
- old_chain = make_cleanup (xfree, filename);
- abfd = ops->bfd_open (filename);
- do_cleanups (old_chain);
+ gdb::unique_xmalloc_ptr<char> filename (tilde_expand (so->so_name));
+ gdb_bfd_ref_ptr abfd (ops->bfd_open (filename.get ()));
if (abfd == NULL)
return 0;
/* Leave bfd open, core_xfer_memory and "info files" need it. */
- so->abfd = abfd;
+ so->abfd = abfd.release ();
/* Copy the full path name into so_name, allowing symbol_file_add
to find it later. This also affects the =library-loaded GDB/MI
the library's host-side path. If we let the target dictate
that objfile's path, and the target is different from the host,
GDB/MI will not provide the correct host-side path. */
- if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE)
+ if (strlen (bfd_get_filename (so->abfd)) >= SO_NAME_MAX_PATH_SIZE)
error (_("Shared library file name is too long."));
- strcpy (so->so_name, bfd_get_filename (abfd));
+ strcpy (so->so_name, bfd_get_filename (so->abfd));
- if (build_section_table (abfd, &so->sections, &so->sections_end))
+ if (build_section_table (so->abfd, &so->sections, &so->sections_end))
{
error (_("Can't find the file sections in `%s': %s"),
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+ bfd_get_filename (so->abfd), bfd_errmsg (bfd_get_error ()));
}
for (p = so->sections; p < so->sections_end; p++)
loaded. */
int
-solib_read_symbols (struct so_list *so, int flags)
+solib_read_symbols (struct so_list *so, symfile_add_flags flags)
{
if (so->symbols_loaded)
{
}
else
{
- volatile struct gdb_exception e;
flags |= current_inferior ()->symfile_flags;
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ try
{
- struct section_addr_info *sap;
-
/* Have we already loaded this shared object? */
- ALL_OBJFILES (so->objfile)
+ so->objfile = nullptr;
+ for (objfile *objfile : current_program_space->objfiles ())
{
- if (filename_cmp (objfile_name (so->objfile), so->so_name) == 0
- && so->objfile->addr_low == so->addr_low)
- break;
+ if (filename_cmp (objfile_name (objfile), so->so_name) == 0
+ && objfile->addr_low == so->addr_low)
+ {
+ so->objfile = objfile;
+ break;
+ }
+ }
+ if (so->objfile == NULL)
+ {
+ section_addr_info sap
+ = build_section_addr_info_from_section_table (so->sections,
+ so->sections_end);
+ so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
+ flags, &sap,
+ OBJF_SHARED, NULL);
+ so->objfile->addr_low = so->addr_low;
}
- if (so->objfile != NULL)
- break;
-
- sap = build_section_addr_info_from_section_table (so->sections,
- so->sections_end);
- so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
- flags, sap, OBJF_SHARED,
- NULL);
- so->objfile->addr_low = so->addr_low;
- free_section_addr_info (sap);
+
+ so->symbols_loaded = 1;
+ }
+ catch (const gdb_exception_error &e)
+ {
+ exception_fprintf (gdb_stderr, e, _("Error while reading shared"
+ " library symbols for %s:\n"),
+ so->so_name);
}
- if (e.reason < 0)
- exception_fprintf (gdb_stderr, e, _("Error while reading shared"
- " library symbols for %s:\n"),
- so->so_name);
- else
- so->symbols_loaded = 1;
return 1;
}
return 0;
}
-/* Synchronize GDB's shared object list with inferior's.
-
- Extract the list of currently loaded shared objects from the
- inferior, and compare it with the list of shared objects currently
- in GDB's so_list_head list. Edit so_list_head to bring it in sync
- with the inferior's new list.
-
- If we notice that the inferior has unloaded some shared objects,
- free any symbolic info GDB had read about those shared objects.
-
- Don't load symbolic info for any new shared objects; just add them
- to the list, and leave their symbols_loaded flag clear.
-
- If FROM_TTY is non-null, feel free to print messages about what
- we're doing.
-
- If TARGET is non-null, add the sections of all new shared objects
- to TARGET's section table. Note that this doesn't remove any
- sections for shared objects that have been unloaded, and it
- doesn't check to see if the new shared objects are already present in
- the section table. But we only use this for core files and
- processes we've just attached to, so that's okay. */
+/* See solib.h. */
-static void
-update_solib_list (int from_tty, struct target_ops *target)
+void
+update_solib_list (int from_tty)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
struct so_list *inferior = ops->current_sos();
/* We can reach here due to changing solib-search-path or the
sysroot, before having any inferior. */
- if (target_has_execution && !ptid_equal (inferior_ptid, null_ptid))
+ if (target_has_execution && inferior_ptid != null_ptid)
{
struct inferior *inf = current_inferior ();
have not opened a symbol file, we may be able to get its
symbols now! */
if (inf->attach_flag && symfile_objfile == NULL)
- catch_errors (ops->open_symbol_file_object, &from_tty,
- "Error reading attached process's symbol file.\n",
- RETURN_MASK_ALL);
+ {
+ try
+ {
+ ops->open_symbol_file_object (from_tty);
+ }
+ catch (const gdb_exception &ex)
+ {
+ exception_fprintf (gdb_stderr, ex,
+ "Error reading attached "
+ "process's symbol file.\n");
+ }
+ }
}
/* GDB and the inferior's dynamic linker each maintain their own
{
/* Notify any observer that the shared object has been
unloaded before we remove it from GDB's tables. */
- observer_notify_solib_unloaded (gdb);
+ gdb::observers::solib_unloaded.notify (gdb);
- VEC_safe_push (char_ptr, current_program_space->deleted_solibs,
- xstrdup (gdb->so_name));
+ current_program_space->deleted_solibs.push_back (gdb->so_name);
*gdb_link = gdb->next;
/* Unless the user loaded it explicitly, free SO's objfile. */
if (gdb->objfile && ! (gdb->objfile->flags & OBJF_USERLOADED)
&& !solib_used (gdb))
- free_objfile (gdb->objfile);
+ delete gdb->objfile;
/* Some targets' section tables might be referring to
sections from so->abfd; remove them. */
/* Fill in the rest of each of the `struct so_list' nodes. */
for (i = inferior; i; i = i->next)
{
- volatile struct gdb_exception e;
i->pspace = current_program_space;
- VEC_safe_push (so_list_ptr, current_program_space->added_solibs, i);
+ current_program_space->added_solibs.push_back (i);
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ try
{
/* Fill in the rest of the `struct so_list' node. */
if (!solib_map_sections (i))
}
}
- if (e.reason < 0)
- exception_fprintf (gdb_stderr, e,
- _("Error while mapping shared "
- "library sections:\n"));
+ catch (const gdb_exception_error &e)
+ {
+ exception_fprintf (gdb_stderr, e,
+ _("Error while mapping shared "
+ "library sections:\n"));
+ }
/* Notify any observer that the shared object has been
loaded now that we've added it to GDB's tables. */
- observer_notify_solib_loaded (i);
+ gdb::observers::solib_loaded.notify (i);
}
/* If a library was not found, issue an appropriate warning
If READSYMS is 0, defer reading symbolic information until later
but still do any needed low level processing.
- FROM_TTY and TARGET are as described for update_solib_list, above. */
+ FROM_TTY is described for update_solib_list, above. */
void
-solib_add (const char *pattern, int from_tty,
- struct target_ops *target, int readsyms)
+solib_add (const char *pattern, int from_tty, int readsyms)
{
struct so_list *gdb;
error (_("Invalid regexp: %s"), re_err);
}
- update_solib_list (from_tty, target);
+ update_solib_list (from_tty);
/* Walk the list of currently loaded shared libraries, and read
symbols for any that match the pattern --- or any whose symbols
{
int any_matches = 0;
int loaded_any_symbols = 0;
- const int flags =
- SYMFILE_DEFER_BP_RESET | (from_tty ? SYMFILE_VERBOSE : 0);
+ symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;
+
+ if (from_tty)
+ add_flags |= SYMFILE_VERBOSE;
for (gdb = so_list_head; gdb; gdb = gdb->next)
if (! pattern || re_exec (gdb->so_name))
printf_unfiltered (_("Symbols already loaded for %s\n"),
gdb->so_name);
}
- else if (solib_read_symbols (gdb, flags))
+ else if (solib_read_symbols (gdb, add_flags))
loaded_any_symbols = 1;
}
}
if (loaded_any_symbols)
{
- const struct target_so_ops *ops = solib_ops (target_gdbarch ());
-
/* Getting new symbols may change our opinion about what is
frameless. */
reinit_frame_cache ();
-
- ops->special_symbol_handling ();
}
}
}
all. */
static void
-info_sharedlibrary_command (char *pattern, int from_tty)
+info_sharedlibrary_command (const char *pattern, int from_tty)
{
struct so_list *so = NULL; /* link map state variable */
int so_missing_debug_info = 0;
int addr_width;
int nr_libs;
- struct cleanup *table_cleanup;
struct gdbarch *gdbarch = target_gdbarch ();
struct ui_out *uiout = current_uiout;
/* "0x", a little whitespace, and two hex digits per byte of pointers. */
addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4);
- update_solib_list (from_tty, 0);
+ update_solib_list (from_tty);
- /* make_cleanup_ui_out_table_begin_end needs to know the number of
- rows, so we need to make two passes over the libs. */
+ /* ui_out_emit_table table_emitter needs to know the number of rows,
+ so we need to make two passes over the libs. */
for (nr_libs = 0, so = so_list_head; so; so = so->next)
{
}
}
- table_cleanup =
- make_cleanup_ui_out_table_begin_end (uiout, 4, nr_libs,
- "SharedLibraryTable");
-
- /* The "- 1" is because ui_out adds one space between columns. */
- ui_out_table_header (uiout, addr_width - 1, ui_left, "from", "From");
- ui_out_table_header (uiout, addr_width - 1, ui_left, "to", "To");
- ui_out_table_header (uiout, 12 - 1, ui_left, "syms-read", "Syms Read");
- ui_out_table_header (uiout, 0, ui_noalign,
- "name", "Shared Object Library");
-
- ui_out_table_body (uiout);
-
- for (so = so_list_head; so; so = so->next)
- {
- struct cleanup *lib_cleanup;
-
- if (! so->so_name[0])
- continue;
- if (pattern && ! re_exec (so->so_name))
- continue;
-
- lib_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "lib");
-
- if (so->addr_high != 0)
- {
- ui_out_field_core_addr (uiout, "from", gdbarch, so->addr_low);
- ui_out_field_core_addr (uiout, "to", gdbarch, so->addr_high);
- }
- else
- {
- ui_out_field_skip (uiout, "from");
- ui_out_field_skip (uiout, "to");
- }
-
- if (! ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))
- && so->symbols_loaded
- && !objfile_has_symbols (so->objfile))
- {
- so_missing_debug_info = 1;
- ui_out_field_string (uiout, "syms-read", "Yes (*)");
- }
- else
- ui_out_field_string (uiout, "syms-read",
- so->symbols_loaded ? "Yes" : "No");
-
- ui_out_field_string (uiout, "name", so->so_name);
+ {
+ ui_out_emit_table table_emitter (uiout, 4, nr_libs, "SharedLibraryTable");
- ui_out_text (uiout, "\n");
+ /* The "- 1" is because ui_out adds one space between columns. */
+ uiout->table_header (addr_width - 1, ui_left, "from", "From");
+ uiout->table_header (addr_width - 1, ui_left, "to", "To");
+ uiout->table_header (12 - 1, ui_left, "syms-read", "Syms Read");
+ uiout->table_header (0, ui_noalign, "name", "Shared Object Library");
- do_cleanups (lib_cleanup);
- }
+ uiout->table_body ();
- do_cleanups (table_cleanup);
+ ALL_SO_LIBS (so)
+ {
+ if (! so->so_name[0])
+ continue;
+ if (pattern && ! re_exec (so->so_name))
+ continue;
+
+ ui_out_emit_tuple tuple_emitter (uiout, "lib");
+
+ if (so->addr_high != 0)
+ {
+ uiout->field_core_addr ("from", gdbarch, so->addr_low);
+ uiout->field_core_addr ("to", gdbarch, so->addr_high);
+ }
+ else
+ {
+ uiout->field_skip ("from");
+ uiout->field_skip ("to");
+ }
+
+ if (! top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ()
+ && so->symbols_loaded
+ && !objfile_has_symbols (so->objfile))
+ {
+ so_missing_debug_info = 1;
+ uiout->field_string ("syms-read", "Yes (*)");
+ }
+ else
+ uiout->field_string ("syms-read", so->symbols_loaded ? "Yes" : "No");
+
+ uiout->field_string ("name", so->so_name, file_name_style.style ());
+
+ uiout->text ("\n");
+ }
+ }
if (nr_libs == 0)
{
if (pattern)
- ui_out_message (uiout, 0,
- _("No shared libraries matched.\n"));
+ uiout->message (_("No shared libraries matched.\n"));
else
- ui_out_message (uiout, 0,
- _("No shared libraries loaded at this time.\n"));
+ uiout->message (_("No shared libraries loaded at this time.\n"));
}
else
{
if (so_missing_debug_info)
- ui_out_message (uiout, 0,
- _("(*): Shared library is missing "
+ uiout->message (_("(*): Shared library is missing "
"debugging information.\n"));
}
}
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
- /* This function is expected to handle ELF shared libraries. It is
- also used on Solaris, which can run either ELF or a.out binaries
- (for compatibility with SunOS 4), both of which can use shared
- libraries. So we don't know whether we have an ELF executable or
- an a.out executable until the user chooses an executable file.
-
- ELF shared libraries don't get mapped into the address space
- until after the program starts, so we'd better not try to insert
- breakpoints in them immediately. We have to wait until the
- dynamic linker has loaded them; we'll hit a bp_shlib_event
- breakpoint (look for calls to create_solib_event_breakpoint) when
- it's ready.
-
- SunOS shared libraries seem to be different --- they're present
- as soon as the process begins execution, so there's no need to
- put off inserting breakpoints. There's also nowhere to put a
- bp_shlib_event breakpoint, so if we put it off, we'll never get
- around to it.
-
- So: disable breakpoints only if we're using ELF shared libs. */
- if (exec_bfd != NULL
- && bfd_get_flavour (exec_bfd) != bfd_target_aout_flavour)
- disable_breakpoints_in_shlibs ();
+ disable_breakpoints_in_shlibs ();
while (so_list_head)
{
struct so_list *so = so_list_head;
so_list_head = so->next;
- observer_notify_solib_unloaded (so);
+ gdb::observers::solib_unloaded.notify (so);
remove_target_sections (so);
free_so (so);
}
/* Implements the "sharedlibrary" command. */
static void
-sharedlibrary_command (char *args, int from_tty)
+sharedlibrary_command (const char *args, int from_tty)
{
dont_repeat ();
- solib_add (args, from_tty, (struct target_ops *) 0, 1);
+ solib_add (args, from_tty, 1);
}
/* Implements the command "nosharedlibrary", which discards symbols
are not discarded. Also called from remote.c. */
void
-no_shared_libraries (char *ignored, int from_tty)
+no_shared_libraries (const char *ignored, int from_tty)
{
/* The order of the two routines below is important: clear_solib notifies
the solib_unloaded observers, and some of these observers might need
/* Check for any newly added shared libraries if we're supposed to
be adding them automatically. Switch terminal for any messages
produced by breakpoint_re_set. */
- target_terminal_ours_for_output ();
- solib_add (NULL, 0, ¤t_target, auto_solib_add);
- target_terminal_inferior ();
+ target_terminal::ours_for_output ();
+ solib_add (NULL, 0, auto_solib_add);
+ target_terminal::inferior ();
}
/* Reload shared libraries, but avoid reloading the same symbol file
reload_shared_libraries_1 (int from_tty)
{
struct so_list *so;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
if (print_symbol_loading_p (from_tty, 0, 0))
printf_unfiltered (_("Loading symbols for shared libraries.\n"));
for (so = so_list_head; so != NULL; so = so->next)
{
- char *filename, *found_pathname = NULL;
- bfd *abfd;
+ const char *found_pathname = NULL;
int was_loaded = so->symbols_loaded;
- const int flags =
- SYMFILE_DEFER_BP_RESET | (from_tty ? SYMFILE_VERBOSE : 0);
+ symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;
+
+ if (from_tty)
+ add_flags |= SYMFILE_VERBOSE;
- filename = tilde_expand (so->so_original_name);
- make_cleanup (xfree, filename);
- abfd = solib_bfd_open (filename);
+ gdb::unique_xmalloc_ptr<char> filename
+ (tilde_expand (so->so_original_name));
+ gdb_bfd_ref_ptr abfd (solib_bfd_open (filename.get ()));
if (abfd != NULL)
- {
- found_pathname = xstrdup (bfd_get_filename (abfd));
- make_cleanup (xfree, found_pathname);
- gdb_bfd_unref (abfd);
- }
+ found_pathname = bfd_get_filename (abfd.get ());
/* If this shared library is no longer associated with its previous
symbol file, close that. */
{
if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED)
&& !solib_used (so))
- free_objfile (so->objfile);
+ delete so->objfile;
remove_target_sections (so);
clear_so (so);
}
&& (!was_loaded
|| filename_cmp (found_pathname, so->so_name) != 0))
{
- volatile struct gdb_exception e;
+ int got_error = 0;
- TRY_CATCH (e, RETURN_MASK_ERROR)
- solib_map_sections (so);
+ try
+ {
+ solib_map_sections (so);
+ }
+
+ catch (const gdb_exception_error &e)
+ {
+ exception_fprintf (gdb_stderr, e,
+ _("Error while mapping "
+ "shared library sections:\n"));
+ got_error = 1;
+ }
- if (e.reason < 0)
- exception_fprintf (gdb_stderr, e,
- _("Error while mapping "
- "shared library sections:\n"));
- else if (auto_solib_add || was_loaded || libpthread_solib_p (so))
- solib_read_symbols (so, flags);
+ if (!got_error
+ && (auto_solib_add || was_loaded || libpthread_solib_p (so)))
+ solib_read_symbols (so, add_flags);
}
}
-
- do_cleanups (old_chain);
}
static void
-reload_shared_libraries (char *ignored, int from_tty,
+reload_shared_libraries (const char *ignored, int from_tty,
struct cmd_list_element *e)
{
const struct target_so_ops *ops;
removed. Call it only after the solib target has been initialized by
solib_create_inferior_hook. */
- solib_add (NULL, 0, NULL, auto_solib_add);
+ solib_add (NULL, 0, auto_solib_add);
breakpoint_re_set ();
structures that are now freed. Also, getting new symbols may
change our opinion about what is frameless. */
reinit_frame_cache ();
+}
+
+/* Wrapper for reload_shared_libraries that replaces "remote:"
+ at the start of gdb_sysroot with "target:". */
+
+static void
+gdb_sysroot_changed (const char *ignored, int from_tty,
+ struct cmd_list_element *e)
+{
+ const char *old_prefix = "remote:";
+ const char *new_prefix = TARGET_SYSROOT_PREFIX;
- ops->special_symbol_handling ();
+ if (startswith (gdb_sysroot, old_prefix))
+ {
+ static int warning_issued = 0;
+
+ gdb_assert (strlen (old_prefix) == strlen (new_prefix));
+ memcpy (gdb_sysroot, new_prefix, strlen (new_prefix));
+
+ if (!warning_issued)
+ {
+ warning (_("\"%s\" is deprecated, use \"%s\" instead."),
+ old_prefix, new_prefix);
+ warning (_("sysroot set to \"%s\"."), gdb_sysroot);
+
+ warning_issued = 1;
+ }
+ }
+
+ reload_shared_libraries (ignored, from_tty, e);
}
static void
}
-/* Handler for library-specific lookup of global symbol NAME in OBJFILE. Call
- the library-specific handler if it is installed for the current target. */
-
-struct symbol *
-solib_global_lookup (const struct objfile *objfile,
- const char *name,
- const domain_enum domain)
-{
- const struct target_so_ops *ops = solib_ops (target_gdbarch ());
-
- if (ops->lookup_lib_global_symbol != NULL)
- return ops->lookup_lib_global_symbol (objfile, name, domain);
- return NULL;
-}
-
/* Lookup the value for a specific symbol from dynamic symbol table. Look
up symbol from ABFD. MATCH_SYM is a callback function to determine
whether to pick up a symbol. DATA is the input of this callback
CORE_ADDR
gdb_bfd_lookup_symbol_from_symtab (bfd *abfd,
- int (*match_sym) (asymbol *, void *),
- void *data)
+ int (*match_sym) (const asymbol *,
+ const void *),
+ const void *data)
{
long storage_needed = bfd_get_symtab_upper_bound (abfd);
CORE_ADDR symaddr = 0;
{
unsigned int i;
- asymbol **symbol_table = (asymbol **) xmalloc (storage_needed);
- struct cleanup *back_to = make_cleanup (xfree, symbol_table);
+ gdb::def_vector<asymbol *> storage (storage_needed / sizeof (asymbol *));
+ asymbol **symbol_table = storage.data ();
unsigned int number_of_symbols =
bfd_canonicalize_symtab (abfd, symbol_table);
if (match_sym (sym, data))
{
+ struct gdbarch *gdbarch = target_gdbarch ();
+ symaddr = sym->value;
+
+ /* Some ELF targets fiddle with addresses of symbols they
+ consider special. They use minimal symbols to do that
+ and this is needed for correct breakpoint placement,
+ but we do not have full data here to build a complete
+ minimal symbol, so just set the address and let the
+ targets cope with that. */
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && gdbarch_elf_make_msymbol_special_p (gdbarch))
+ {
+ struct minimal_symbol msym {};
+
+ SET_MSYMBOL_VALUE_ADDRESS (&msym, symaddr);
+ gdbarch_elf_make_msymbol_special (gdbarch, sym, &msym);
+ symaddr = MSYMBOL_VALUE_RAW_ADDRESS (&msym);
+ }
+
/* BFD symbols are section relative. */
- symaddr = sym->value + sym->section->vma;
+ symaddr += sym->section->vma;
break;
}
}
- do_cleanups (back_to);
}
return symaddr;
static CORE_ADDR
bfd_lookup_symbol_from_dyn_symtab (bfd *abfd,
- int (*match_sym) (asymbol *, void *),
- void *data)
+ int (*match_sym) (const asymbol *,
+ const void *),
+ const void *data)
{
long storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
CORE_ADDR symaddr = 0;
if (storage_needed > 0)
{
unsigned int i;
- asymbol **symbol_table = (asymbol **) xmalloc (storage_needed);
- struct cleanup *back_to = make_cleanup (xfree, symbol_table);
+ gdb::def_vector<asymbol *> storage (storage_needed / sizeof (asymbol *));
+ asymbol **symbol_table = storage.data ();
unsigned int number_of_symbols =
bfd_canonicalize_dynamic_symtab (abfd, symbol_table);
break;
}
}
- do_cleanups (back_to);
}
return symaddr;
}
CORE_ADDR
gdb_bfd_lookup_symbol (bfd *abfd,
- int (*match_sym) (asymbol *, void *),
- void *data)
+ int (*match_sym) (const asymbol *, const void *),
+ const void *data)
{
CORE_ADDR symaddr = gdb_bfd_lookup_symbol_from_symtab (abfd, match_sym, data);
}
}
-extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
-
void
_initialize_solib (void)
{
solib_data = gdbarch_data_register_pre_init (solib_init);
- observer_attach_free_objfile (remove_user_added_objfile);
+ gdb::observers::free_objfile.attach (remove_user_added_objfile);
add_com ("sharedlibrary", class_files, sharedlibrary_command,
_("Load shared object library symbols for files matching REGEXP."));
add_info ("sharedlibrary", info_sharedlibrary_command,
_("Status of loaded shared object libraries."));
+ add_info_alias ("dll", "sharedlibrary", 1);
add_com ("nosharedlibrary", class_files, no_shared_libraries,
_("Unload all shared object library symbols."));
show_auto_solib_add,
&setlist, &showlist);
- add_setshow_filename_cmd ("sysroot", class_support,
- &gdb_sysroot, _("\
+ add_setshow_optional_filename_cmd ("sysroot", class_support,
+ &gdb_sysroot, _("\
Set an alternate system root."), _("\
Show the current system root."), _("\
The system root is used to load absolute shared library symbol files.\n\
For other (relative) files, you can add directories using\n\
`set solib-search-path'."),
- reload_shared_libraries,
- NULL,
- &setlist, &showlist);
+ gdb_sysroot_changed,
+ NULL,
+ &setlist, &showlist);
add_alias_cmd ("solib-absolute-prefix", "sysroot", class_support, 0,
&setlist);