/* Handle shared libraries for GDB, the GNU Debugger.
- Copyright 1990, 91, 92, 93, 94, 95, 96, 98, 1999, 2000
+
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002, 2003, 2005
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 "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"
+
+/* Architecture-specific operations. */
+
+/* Per-architecture data key. */
+static struct gdbarch_data *solib_data;
+
+static void *
+solib_init (struct obstack *obstack)
+{
+ struct target_so_ops **ops;
+
+ ops = OBSTACK_ZALLOC (obstack, struct target_so_ops *);
+ *ops = current_target_so_ops;
+ return ops;
+}
+
+static struct target_so_ops *
+solib_ops (struct gdbarch *gdbarch)
+{
+ struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
+ return *ops;
+}
+\f
/* external data declarations */
/* Local function prototypes */
-static void do_clear_solib (PTR);
+static void do_clear_solib (void *);
/* If non-zero, this is a prefix that will be added to the front of the name
shared libraries with an absolute filename for loading. */
symbol files. This takes precedence over the environment variables PATH
and LD_LIBRARY_PATH. */
static char *solib_search_path = NULL;
+static void
+show_solib_search_path (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+The search path for loading non-absolute shared library symbol files is %s.\n"),
+ value);
+}
/*
(or set of directories, as in LD_LIBRARY_PATH) to search for all
shared libraries if not found in SOLIB_ABSOLUTE_PREFIX.
- Search order:
- * If path is absolute, look in SOLIB_ABSOLUTE_PREFIX.
- * If path is absolute, look for it literally (unmodified).
+ Search algorithm:
+ * If there is a solib_absolute_prefix and path is absolute:
+ * Search for solib_absolute_prefix/path.
+ * else
+ * Look for it literally (unmodified).
* Look in SOLIB_SEARCH_PATH.
- * Look in inferior's $PATH.
- * Look in inferior's $LD_LIBRARY_PATH.
+ * If available, use target defined search function.
+ * If solib_absolute_prefix is NOT set, perform the following two searches:
+ * Look in inferior's $PATH.
+ * Look in inferior's $LD_LIBRARY_PATH.
+ *
+ * The last check avoids doing this search when targetting remote
+ * machines since solib_absolute_prefix will almost always be set.
RETURNS
-
+
file handle for opened solib, or -1 for failure. */
int
solib_open (char *in_pathname, char **found_pathname)
{
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
int found_file = -1;
char *temp_pathname = NULL;
+ char *p = in_pathname;
- if (ROOTED_P (in_pathname))
+ while (*p && !IS_DIR_SEPARATOR (*p))
+ p++;
+
+ if (*p)
{
- if (solib_absolute_prefix == NULL)
+ if (! IS_ABSOLUTE_PATH (in_pathname) || solib_absolute_prefix == NULL)
temp_pathname = in_pathname;
else
{
- int prefix_len = strlen (solib_absolute_prefix);
+ int prefix_len = strlen (solib_absolute_prefix);
/* Remove trailing slashes from absolute prefix. */
- while (prefix_len > 0 && SLASH_P (solib_absolute_prefix[prefix_len - 1]))
+ while (prefix_len > 0
+ && IS_DIR_SEPARATOR (solib_absolute_prefix[prefix_len - 1]))
prefix_len--;
/* Cat the prefixed pathname together. */
strncpy (temp_pathname, solib_absolute_prefix, prefix_len);
temp_pathname[prefix_len] = '\0';
strcat (temp_pathname, in_pathname);
-
}
+
/* Now see if we can open it. */
found_file = open (temp_pathname, O_RDONLY, 0);
}
- /* If not found, next search the solib_search_path (if any). */
+ /* If the search in solib_absolute_prefix failed, and the path name is
+ absolute at this point, make it relative. (openp will try and open the
+ file according to its absolute path otherwise, which is not what we want.)
+ Affects subsequent searches for this solib. */
+ if (found_file < 0 && IS_ABSOLUTE_PATH (in_pathname))
+ {
+ /* First, get rid of any drive letters etc. */
+ while (!IS_DIR_SEPARATOR (*in_pathname))
+ in_pathname++;
+
+ /* Next, get rid of all leading dir separators. */
+ while (IS_DIR_SEPARATOR (*in_pathname))
+ in_pathname++;
+ }
+
+ /* If not found, search the solib_search_path (if any). */
+ if (found_file < 0 && solib_search_path != NULL)
+ found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
+ in_pathname, O_RDONLY, 0, &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)
- found_file = openp (solib_search_path,
- 1, in_pathname, O_RDONLY, 0, &temp_pathname);
+ found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
+ lbasename (in_pathname), O_RDONLY, 0,
+ &temp_pathname);
+
+ /* If not found, try to use target supplied solib search method */
+ if (found_file < 0 && ops->find_and_open_solib)
+ found_file = ops->find_and_open_solib (in_pathname, O_RDONLY,
+ &temp_pathname);
/* If not found, next search the inferior's $PATH environment variable. */
- if (found_file < 0 && solib_search_path != NULL)
+ if (found_file < 0 && solib_absolute_prefix == NULL)
found_file = openp (get_in_environ (inferior_environ, "PATH"),
- 1, in_pathname, O_RDONLY, 0, &temp_pathname);
+ OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY, 0,
+ &temp_pathname);
/* If not found, next search the inferior's $LD_LIBRARY_PATH
environment variable. */
- if (found_file < 0 && solib_search_path != NULL)
+ if (found_file < 0 && solib_absolute_prefix == NULL)
found_file = openp (get_in_environ (inferior_environ, "LD_LIBRARY_PATH"),
- 1, in_pathname, O_RDONLY, 0, &temp_pathname);
+ OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY, 0,
+ &temp_pathname);
/* Done. If not found, tough luck. Return found_file and
(optionally) found_pathname. */
if (found_pathname != NULL && temp_pathname != NULL)
- *found_pathname = strsave (temp_pathname);
+ *found_pathname = xstrdup (temp_pathname);
return found_file;
}
*/
static int
-solib_map_sections (PTR arg)
+solib_map_sections (void *arg)
{
struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
char *filename;
if (!abfd)
{
close (scratch_chan);
- error ("Could not open `%s' as an executable file: %s",
+ error (_("Could not open `%s' as an executable file: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
/* Leave bfd open, core_xfer_memory and "info files" need it. */
so->abfd = abfd;
- abfd->cacheable = true;
+ bfd_set_cacheable (abfd, 1);
/* copy full path name into so_name, so that later symbol_file_add
can find it */
if (strlen (scratch_pathname) >= SO_NAME_MAX_PATH_SIZE)
- error ("Full path name length of shared library exceeds SO_NAME_MAX_PATH_SIZE in so_list structure.");
+ error (_("Full path name length of shared library exceeds SO_NAME_MAX_PATH_SIZE in so_list structure."));
strcpy (so->so_name, scratch_pathname);
if (!bfd_check_format (abfd, bfd_object))
{
- error ("\"%s\": not in executable format: %s.",
+ error (_("\"%s\": not in executable format: %s."),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
if (build_section_table (abfd, &so->sections, &so->sections_end))
{
- error ("Can't find the file sections in `%s': %s",
+ error (_("Can't find the file sections in `%s': %s"),
bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
}
for (p = so->sections; p < so->sections_end; p++)
{
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
+
/* Relocate the section binding addresses as recorded in the shared
object's file by the base address to which the object was actually
mapped. */
- TARGET_SO_RELOCATE_SECTION_ADDRESSES (so, p);
- if (STREQ (p->the_bfd_section->name, ".text"))
+ ops->relocate_section_addresses (so, p);
+ if (strcmp (p->the_bfd_section->name, ".text") == 0)
{
so->textsection = p;
}
void
free_so (struct so_list *so)
{
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
char *bfd_filename = 0;
if (so->sections)
{
bfd_filename = bfd_get_filename (so->abfd);
if (! bfd_close (so->abfd))
- warning ("cannot close \"%s\": %s",
+ warning (_("cannot close \"%s\": %s"),
bfd_filename, bfd_errmsg (bfd_get_error ()));
}
if (bfd_filename)
xfree (bfd_filename);
- TARGET_SO_FREE_SO (so);
+ ops->free_so (so);
xfree (so);
}
+/* Return address of first so_list entry in master shared object list. */
+struct so_list *
+master_so_list (void)
+{
+ return so_list_head;
+}
+
+
/* A small stub to get us past the arg-passing pinhole of catch_errors. */
static int
-symbol_add_stub (PTR arg)
+symbol_add_stub (void *arg)
{
- register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+ struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
struct section_addr_info *sap;
/* Have we already loaded this shared object? */
return (1);
}
+/* Read in symbols for shared object SO. If FROM_TTY is non-zero, be
+ chatty about it. Return non-zero if any symbols were actually
+ loaded. */
+
+int
+solib_read_symbols (struct so_list *so, int from_tty)
+{
+ if (so->symbols_loaded)
+ {
+ if (from_tty)
+ printf_unfiltered (_("Symbols already loaded for %s\n"), so->so_name);
+ }
+ else
+ {
+ if (catch_errors (symbol_add_stub, so,
+ "Error while reading shared library symbols:\n",
+ RETURN_MASK_ALL))
+ {
+ if (from_tty)
+ printf_unfiltered (_("Loaded symbols for %s\n"), so->so_name);
+ so->symbols_loaded = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
/* LOCAL FUNCTION
the section table. But we only use this for core files and
processes we've just attached to, so that's okay. */
-void
+static void
update_solib_list (int from_tty, struct target_ops *target)
{
- struct so_list *inferior = TARGET_SO_CURRENT_SOS ();
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
+ struct so_list *inferior = ops->current_sos();
struct so_list *gdb, **gdb_link;
/* If we are attaching to a running process for which we
symbols now! */
if (attach_flag &&
symfile_objfile == NULL)
- catch_errors (TARGET_SO_OPEN_SYMBOL_FILE_OBJECT, (PTR) &from_tty,
+ catch_errors (ops->open_symbol_file_object, &from_tty,
"Error reading attached process's symbol file.\n",
RETURN_MASK_ALL);
/* If it's not on the inferior's list, remove it from GDB's tables. */
else
{
+ /* Notify any observer that the shared object has been
+ unloaded before we remove it from GDB's tables. */
+ observer_notify_solib_unloaded (gdb);
+
*gdb_link = gdb->next;
/* Unless the user loaded it explicitly, free SO's objfile. */
catch_errors (solib_map_sections, i,
"Error while mapping shared library sections:\n",
RETURN_MASK_ALL);
- }
-
- /* If requested, add the shared objects' sections to the the
- TARGET's section table. */
- if (target)
- {
- int new_sections;
- /* Figure out how many sections we'll need to add in total. */
- new_sections = 0;
- for (i = inferior; i; i = i->next)
- new_sections += (i->sections_end - i->sections);
-
- if (new_sections > 0)
+ /* If requested, add the shared object's sections to the TARGET's
+ section table. Do this immediately after mapping the object so
+ that later nodes in the list can query this object, as is needed
+ in solib-osf.c. */
+ if (target)
{
- int space = target_resize_to_sections (target, new_sections);
-
- for (i = inferior; i; i = i->next)
+ int count = (i->sections_end - i->sections);
+ if (count > 0)
{
- int count = (i->sections_end - i->sections);
+ int space = target_resize_to_sections (target, count);
memcpy (target->to_sections + space,
i->sections,
count * sizeof (i->sections[0]));
- space += count;
}
}
+
+ /* 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);
}
}
}
SYNOPSIS
- void solib_add (char *pattern, int from_tty, struct target_ops *TARGET)
+ void solib_add (char *pattern, int from_tty, struct target_ops
+ *TARGET, int readsyms)
DESCRIPTION
match PATTERN. (If we've already read a shared object's symbol
info, leave it alone.) If PATTERN is zero, read them all.
+ 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. */
void
-solib_add (char *pattern, int from_tty, struct target_ops *target)
+solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
{
struct so_list *gdb;
char *re_err = re_comp (pattern);
if (re_err)
- error ("Invalid regexp: %s", re_err);
+ error (_("Invalid regexp: %s"), re_err);
}
update_solib_list (from_tty, target);
if (! pattern || re_exec (gdb->so_name))
{
any_matches = 1;
-
- if (gdb->symbols_loaded)
- {
- if (from_tty)
- printf_unfiltered ("Symbols already loaded for %s\n",
- gdb->so_name);
- }
- else
- {
- if (catch_errors
- (symbol_add_stub, gdb,
- "Error while reading shared library symbols:\n",
- RETURN_MASK_ALL))
- {
- if (from_tty)
- printf_unfiltered ("Loaded symbols for %s\n",
- gdb->so_name);
- gdb->symbols_loaded = 1;
- loaded_any_symbols = 1;
- }
- }
+ if (readsyms && solib_read_symbols (gdb, from_tty))
+ loaded_any_symbols = 1;
}
if (from_tty && pattern && ! any_matches)
if (loaded_any_symbols)
{
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
+
/* Getting new symbols may change our opinion about what is
frameless. */
reinit_frame_cache ();
- TARGET_SO_SPECIAL_SYMBOL_HANDLING ();
+ ops->special_symbol_handling ();
}
}
}
static void
info_sharedlibrary_command (char *ignore, int from_tty)
{
- register struct so_list *so = NULL; /* link map state variable */
+ struct so_list *so = NULL; /* link map state variable */
int header_done = 0;
int addr_width;
- char *addr_fmt;
- int arch_size;
-
- if (exec_bfd == NULL)
- {
- printf_unfiltered ("No executable file.\n");
- return;
- }
- arch_size = bfd_get_arch_size (exec_bfd);
- /* Default to 32-bit in case of failure (non-elf). */
- if (arch_size == 32 || arch_size == -1)
- {
- addr_width = 8 + 4;
- addr_fmt = "08l";
- }
- else if (arch_size == 64)
- {
- addr_width = 16 + 4;
- addr_fmt = "016l";
- }
+ if (TARGET_PTR_BIT == 32)
+ addr_width = 8 + 4;
+ else if (TARGET_PTR_BIT == 64)
+ addr_width = 16 + 4;
else
{
- internal_error ("%s:%d: bfd_get_arch_size() returned unknown size %d",
- __FILE__, __LINE__, arch_size);
+ internal_error (__FILE__, __LINE__,
+ _("TARGET_PTR_BIT returned unknown size %d"),
+ TARGET_PTR_BIT);
}
update_solib_list (from_tty, 0);
printf_unfiltered ("%-*s", addr_width,
so->textsection != NULL
- ? local_hex_string_custom (
- (unsigned long) so->textsection->addr,
- addr_fmt)
+ ? hex_string_custom (
+ (LONGEST) so->textsection->addr,
+ addr_width - 4)
: "");
printf_unfiltered ("%-*s", addr_width,
so->textsection != NULL
- ? local_hex_string_custom (
- (unsigned long) so->textsection->endaddr,
- addr_fmt)
+ ? hex_string_custom (
+ (LONGEST) so->textsection->endaddr,
+ addr_width - 4)
: "");
printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
printf_unfiltered ("%s\n", so->so_name);
}
if (so_list_head == NULL)
{
- printf_unfiltered ("No shared libraries loaded at this time.\n");
+ printf_unfiltered (_("No shared libraries loaded at this time.\n"));
}
}
char *
solib_address (CORE_ADDR address)
{
- register struct so_list *so = 0; /* link map state variable */
+ struct so_list *so = 0; /* link map state variable */
for (so = so_list_head; so; so = so->next)
{
void
clear_solib (void)
{
+ struct target_so_ops *ops = solib_ops (current_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
{
struct so_list *so = so_list_head;
so_list_head = so->next;
+ if (so->abfd)
+ remove_target_sections (so->abfd);
free_so (so);
}
- TARGET_SO_CLEAR_SOLIB ();
+ ops->clear_solib ();
}
static void
-do_clear_solib (PTR dummy)
+do_clear_solib (void *dummy)
{
solib_cleanup_queued = 0;
clear_solib ();
SYNOPSIS
- void solib_create_inferior_hook()
+ void solib_create_inferior_hook ()
DESCRIPTION
void
solib_create_inferior_hook (void)
{
- TARGET_SO_SOLIB_CREATE_INFERIOR_HOOK ();
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
+ ops->solib_create_inferior_hook();
}
+/* GLOBAL FUNCTION
+
+ in_solib_dynsym_resolve_code -- check to see if an address is in
+ dynamic loader's dynamic symbol
+ resolution code
+
+ SYNOPSIS
+
+ int in_solib_dynsym_resolve_code (CORE_ADDR pc)
+
+ DESCRIPTION
+
+ Determine if PC is in the dynamic linker's symbol resolution
+ code. Return 1 if so, 0 otherwise.
+*/
+
+int
+in_solib_dynsym_resolve_code (CORE_ADDR pc)
+{
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
+ return ops->in_dynsym_resolve_code (pc);
+}
/*
sharedlibrary_command (char *args, int from_tty)
{
dont_repeat ();
- solib_add (args, from_tty, (struct target_ops *) 0);
+ solib_add (args, from_tty, (struct target_ops *) 0, 1);
}
+/* LOCAL FUNCTION
+
+ no_shared_libraries -- handle command to explicitly discard symbols
+ from shared libraries.
+
+ DESCRIPTION
+
+ Implements the command "nosharedlibrary", which discards symbols
+ that have been auto-loaded from shared libraries. Symbols from
+ shared libraries that were added by explicit request of the user
+ are not discarded. Also called from remote.c. */
+
+void
+no_shared_libraries (char *ignored, int from_tty)
+{
+ objfile_purge_solibs ();
+ do_clear_solib (NULL);
+}
+
+static void
+reload_shared_libraries (char *ignored, int from_tty,
+ struct cmd_list_element *e)
+{
+ no_shared_libraries (NULL, from_tty);
+ solib_add (NULL, from_tty, NULL, auto_solib_add);
+}
+
+static void
+show_auto_solib_add (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Autoloading of shared library symbols is %s.\n"),
+ value);
+}
+
+
+extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
void
_initialize_solib (void)
{
+ struct cmd_list_element *c;
+
+ solib_data = gdbarch_data_register_pre_init (solib_init);
+
add_com ("sharedlibrary", class_files, sharedlibrary_command,
- "Load shared object library symbols for files matching REGEXP.");
+ _("Load shared object library symbols for files matching REGEXP."));
add_info ("sharedlibrary", info_sharedlibrary_command,
- "Status of loaded shared object libraries.");
-
- add_show_from_set
- (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
- (char *) &auto_solib_add,
- "Set autoloading of shared library symbols.\n\
-If nonzero, symbols from all shared object libraries will be loaded\n\
-automatically when the inferior begins execution or when the dynamic linker\n\
-informs gdb that a new library has been loaded. Otherwise, symbols\n\
-must be loaded manually, using `sharedlibrary'.",
- &setlist),
- &showlist);
-
- add_show_from_set
- (add_set_cmd ("solib-absolute-prefix", class_support, var_filename,
- (char *) &solib_absolute_prefix,
- "Set prefix for loading absolute shared library symbol files.\n\
-For other (relative) files, you can add values using `set solib-search-path'.",
- &setlist),
- &showlist);
- add_show_from_set
- (add_set_cmd ("solib-search-path", class_support, var_string,
- (char *) &solib_search_path,
- "Set the search path for loading non-absolute shared library symbol files.\n\
-This takes precedence over the environment variables PATH and LD_LIBRARY_PATH.",
- &setlist),
- &showlist);
-
+ _("Status of loaded shared object libraries."));
+ add_com ("nosharedlibrary", class_files, no_shared_libraries,
+ _("Unload all shared object library symbols."));
+
+ add_setshow_boolean_cmd ("auto-solib-add", class_support,
+ &auto_solib_add, _("\
+Set autoloading of shared library symbols."), _("\
+Show autoloading of shared library symbols."), _("\
+If \"on\", symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution, when the dynamic linker\n\
+informs gdb that a new library has been loaded, or when attaching to the\n\
+inferior. Otherwise, symbols must be loaded manually, using `sharedlibrary'."),
+ NULL,
+ show_auto_solib_add,
+ &setlist, &showlist);
+
+ add_setshow_filename_cmd ("solib-absolute-prefix", class_support,
+ &solib_absolute_prefix, _("\
+Set prefix for loading absolute shared library symbol files."), _("\
+Show prefix for loading absolute shared library symbol files."), _("\
+For other (relative) files, you can add values using `set solib-search-path'."),
+ reload_shared_libraries,
+ NULL,
+ &setlist, &showlist);
+
+ /* Set the default value of "solib-absolute-prefix" from the sysroot, if
+ one is set. */
+ solib_absolute_prefix = xstrdup (gdb_sysroot);
+
+ add_setshow_optional_filename_cmd ("solib-search-path", class_support,
+ &solib_search_path, _("\
+Set the search path for loading non-absolute shared library symbol files."), _("\
+Show the search path for loading non-absolute shared library symbol files."), _("\
+This takes precedence over the environment variables PATH and LD_LIBRARY_PATH."),
+ reload_shared_libraries,
+ show_solib_search_path,
+ &setlist, &showlist);
}