struct gdb_bfd_data
{
/* Note that if ST is nullptr, then we simply fill in zeroes. */
- gdb_bfd_data (bfd *abfd, struct stat *st)
+ gdb_bfd_data (bfd *abfd, struct stat *st, int l_ns)
: mtime (st == nullptr ? 0 : st->st_mtime),
size (st == nullptr ? 0 : st->st_size),
inode (st == nullptr ? 0 : st->st_ino),
device_id (st == nullptr ? 0 : st->st_dev),
+ linker_namespace (l_ns),
relocation_computed (0),
needs_relocations (0),
crc_computed (0)
/* The device id of the file at the point the cache entry was made. */
dev_t device_id;
+ /* The Linker Namespace where the objfile that lead this file to be
+ read was loaded. */
+ int linker_namespace;
+
/* This is true if we have determined whether this BFD has any
sections requiring relocation. */
unsigned int relocation_computed : 1;
ino_t inode;
/* The device id of the file. */
dev_t device_id;
+ /* The Linker Namespace where the solib was loaded.
+ We do this because, even if the file is exactly the same,
+ we'll want to read the file again to recalculate symbol
+ addresses. */
+ int linker_namespace;
};
struct bfd_cache_hash
&& gdata->size == s.size
&& gdata->inode == s.inode
&& gdata->device_id == s.device_id
+ && gdata->linker_namespace == s.linker_namespace
&& strcmp (bfd_get_filename (abfd), s.filename) == 0);
}
};
BFD. */
static void
-gdb_bfd_init_data (struct bfd *abfd, struct stat *st)
+gdb_bfd_init_data (struct bfd *abfd, struct stat *st, int linker_namespace)
{
struct gdb_bfd_data *gdata;
/* Ask BFD to decompress sections in bfd_get_full_section_contents. */
abfd->flags |= BFD_DECOMPRESS;
- gdata = new gdb_bfd_data (abfd, st);
+ gdata = new gdb_bfd_data (abfd, st, linker_namespace);
bfd_set_usrdata (abfd, gdata);
/* This is the first we've seen it, so add it to the hash table. */
gdb_bfd_ref_ptr
gdb_bfd_open (const char *name, const char *target, int fd,
- bool warn_if_slow)
+ bool warn_if_slow, int linker_namespace)
{
bfd *abfd;
struct stat st;
search.size = st.st_size;
search.inode = st.st_ino;
search.device_id = st.st_dev;
+ search.linker_namespace = linker_namespace;
+
+ /* If a linker namespace was supplied, print it in the debug message. */
+ std::string linker_ns_str;
+ if (linker_namespace != -1)
+ linker_ns_str = string_printf ("[[%d]]::", linker_namespace);
if (bfd_sharing)
{
iter != gdb_bfd_cache.end ())
{
abfd = *iter;
- bfd_cache_debug_printf ("Reusing cached bfd %s for %s",
+ bfd_cache_debug_printf ("Reusing cached bfd %s for %s%s",
host_address_to_string (abfd),
+ linker_ns_str.c_str (),
bfd_get_filename (abfd));
close (fd);
return gdb_bfd_ref_ptr::new_reference (abfd);
bfd_set_cacheable (abfd, 1);
- bfd_cache_debug_printf ("Creating new bfd %s for %s",
+ bfd_cache_debug_printf ("Creating new bfd %s for %s%s",
host_address_to_string (abfd),
+ linker_ns_str.c_str (),
bfd_get_filename (abfd));
/* It's important to pass the already-computed stat info here,
and since we will enter it into the hash table using this
mtime, if the file changed at the wrong moment, the race would
lead to a hash table corruption. */
- gdb_bfd_init_data (abfd, &st);
+ gdb_bfd_init_data (abfd, &st, linker_namespace);
if (bfd_sharing)
{
gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
- bfd_cache_debug_printf ("Increase reference count on bfd %s (%s)",
+ std::string linker_ns_str;
+ if (gdata && gdata->linker_namespace != -1)
+ linker_ns_str = string_printf ("[[%d]]::", gdata->linker_namespace);
+
+ bfd_cache_debug_printf ("Increase reference count on bfd %s (%s%s)",
host_address_to_string (abfd),
+ linker_ns_str.c_str (),
bfd_get_filename (abfd));
if (gdata != NULL)
/* Caching only happens via gdb_bfd_open, so passing nullptr here is
fine. */
- gdb_bfd_init_data (abfd, nullptr);
+ gdb_bfd_init_data (abfd, nullptr, -1);
}
/* See gdb_bfd.h. */
gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
gdb_assert (gdata->refc >= 1);
+ std::string linker_ns_str;
+ if (gdata && gdata->linker_namespace != -1)
+ linker_ns_str = string_printf ("[[%d]]::", gdata->linker_namespace);
+
gdata->refc -= 1;
if (gdata->refc > 0)
{
- bfd_cache_debug_printf ("Decrease reference count on bfd %s (%s)",
+ bfd_cache_debug_printf ("Decrease reference count on bfd %s (%s%s)",
host_address_to_string (abfd),
+ linker_ns_str.c_str(),
bfd_get_filename (abfd));
return;
}
- bfd_cache_debug_printf ("Delete final reference count on bfd %s (%s)",
+ bfd_cache_debug_printf ("Delete final reference count on bfd %s (%s%s)",
host_address_to_string (abfd),
+ linker_ns_str.c_str (),
bfd_get_filename (abfd));
archive_bfd = gdata->archive_bfd;
be slow. */
gdb_bfd_ref_ptr gdb_bfd_open (const char *name, const char *target,
- int fd = -1, bool warn_if_slow = true);
+ int fd = -1, bool warn_if_slow = true,
+ int linker_namespace = -1);
/* Mark the CHILD BFD as being a member of PARENT. Also, increment
the reference count of CHILD. Calling this function ensures that
/* Implement the "bfd_open" solib_ops method. */
static gdb_bfd_ref_ptr
-solib_aix_bfd_open (const char *pathname)
+solib_aix_bfd_open (const solib &so)
{
/* The pathname is actually a synthetic filename with the following
form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
FIXME: This is a little hacky. Perhaps we should provide access
to the solib's lm_info here? */
+ std::string path = so.file_path ();
+ /* WIP: this is a convenience thing, I should really convert all pathnames to pathname.c_str(). */
+ const char *pathname = path.c_str ();
const int path_len = strlen (pathname);
const char *sep;
int filename_len;
}
\f
static gdb_bfd_ref_ptr
-darwin_bfd_open (const char *pathname)
+darwin_bfd_open (const solib &so)
{
+ std::string pathname = so.file_path ();
int found_file;
/* Search for shared library file. */
gdb::unique_xmalloc_ptr<char> found_pathname
- = solib_find (pathname, &found_file);
+ = solib_find (pathname.c_str (), &found_file);
if (found_pathname == NULL)
- perror_with_name (pathname);
+ perror_with_name (pathname.c_str ());
/* Open bfd for shared library. */
gdb_bfd_ref_ptr abfd (solib_bfd_fopen (found_pathname.get (), found_file));
/* The current filename for fat-binary BFDs is a name generated
by BFD, usually a string containing the name of the architecture.
Reset its value to the actual filename. */
- bfd_set_filename (res.get (), pathname);
+ bfd_set_filename (res.get (), pathname.c_str ());
return res;
}
dsbt_current_sos,
open_symbol_file_object,
dsbt_in_dynsym_resolve_code,
- solib_bfd_open,
+ solib_bfd_open_from_solib,
nullptr,
nullptr,
nullptr,
frv_current_sos,
open_symbol_file_object,
frv_in_dynsym_resolve_code,
- solib_bfd_open,
+ solib_bfd_open_from_solib,
nullptr,
nullptr,
nullptr,
static int
svr4_find_solib_ns (const solib &so)
{
- CORE_ADDR debug_base = find_debug_base_for_solib (&so);
svr4_info *info = get_svr4_info (current_program_space);
+
+ /* If we're reading the dynamic linker, there won't be any namespaces
+ registered yet. Here, we hope that that is the only situation in
+ which this function is called with an empty namespace_id vector,
+ and in that case we'll just return 0. */
+ if (info->namespace_id.empty ())
+ return 0;
+
+ CORE_ADDR debug_base = find_debug_base_for_solib (&so);
for (int i = 0; i < info->namespace_id.size (); i++)
{
if (info->namespace_id[i] == debug_base)
return ns_solibs;
}
+/* See solib_ops::bfd_open in solist.h.
+ This function is needed because svr4 implements support for
+ multiple namespaces, so we'll need to supply a linker_namespace
+ for the gdb_bfd_cache. Otherwise, this function should be
+ mostly the same as gdb/solib.c's solib_bfd_open. */
+static gdb_bfd_ref_ptr
+svr4_solib_bfd_open (const solib &so)
+{
+ int found_file;
+ const struct bfd_arch_info *b;
+ std::string pathname (so.file_path ());
+
+ /* Search for shared library file. */
+ gdb::unique_xmalloc_ptr<char> found_pathname
+ = solib_find (pathname.c_str (), &found_file);
+ if (found_pathname == NULL)
+ {
+ /* Return failure if the file could not be found, so that we can
+ accumulate messages about missing libraries. */
+ if (errno == ENOENT)
+ return NULL;
+
+ perror_with_name (pathname.c_str ());
+ }
+
+ /* Open bfd for shared library. */
+ gdb_bfd_ref_ptr abfd (gdb_bfd_open (found_pathname.get (), gnutarget,
+ found_file, true,
+ svr4_find_solib_ns (so)));
+
+ /* Check bfd format. */
+ 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 (current_inferior ()->arch ());
+ if (!b->compatible (b, bfd_get_arch_info (abfd.get ())))
+ error (_ ("`%s': Shared library architecture %s is not compatible "
+ "with target architecture %s."),
+ bfd_get_filename (abfd.get ()),
+ bfd_get_arch_info (abfd.get ())->printable_name, b->printable_name);
+
+ return abfd;
+}
+
const struct solib_ops svr4_so_ops =
{
svr4_relocate_section_addresses,
svr4_current_sos,
open_symbol_file_object,
svr4_in_dynsym_resolve_code,
- solib_bfd_open,
+ svr4_solib_bfd_open,
svr4_same,
svr4_keep_data_in_core,
svr4_update_solib_event_breakpoints,
solib_target_current_sos,
solib_target_open_symbol_file_object,
solib_target_in_dynsym_resolve_code,
- solib_bfd_open,
+ solib_bfd_open_from_solib,
nullptr,
nullptr,
nullptr,
return abfd;
}
+/* Default implementation for solib_ops::bfd_open. Extract the pathname
+ from the solib object and call solib_bfd_open with it. */
+
+gdb_bfd_ref_ptr
+solib_bfd_open_from_solib (const solib &so)
+{
+ std::string path = so.file_path ();
+
+ return solib_bfd_open (path.c_str ());
+}
+
/* Given a pointer to one of the shared objects in our list of mapped
objects, use the recorded name to open a bfd descriptor for the
object, build a section table, relocate all the section addresses
{
const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
- gdb::unique_xmalloc_ptr<char> filename (tilde_expand (so.so_name.c_str ()));
- gdb_bfd_ref_ptr abfd (ops->bfd_open (filename.get ()));
+ gdb_bfd_ref_ptr abfd (ops->bfd_open (so));
/* If we have a core target then the core target might have some helpful
information (i.e. build-ids) about the shared libraries we are trying
However, if it was good enough during the mapped file
processing, we assume it's good enough now. */
if (!mapped_file_info->filename ().empty ())
- abfd = ops->bfd_open (mapped_file_info->filename ().c_str ());
+ /* TODO: figure out if there's good reason to keep ops->bfd_open,
+ and if there's a good way to do so. */
+ abfd = solib_bfd_open (mapped_file_info->filename ().c_str ());
else
abfd = nullptr;
{
warning (_ ("Build-id of %ps does not match core file."),
styled_string (file_name_style.style (),
- filename.get ()));
+ so.file_path ().c_str ()));
abfd = nullptr;
}
}
if (from_tty)
add_flags |= SYMFILE_VERBOSE;
- gdb::unique_xmalloc_ptr<char> filename (
- tilde_expand (so.so_original_name.c_str ()));
- gdb_bfd_ref_ptr abfd (solib_bfd_open (filename.get ()));
+ std::string path = so.file_path ();
+ gdb_bfd_ref_ptr abfd (solib_bfd_open (path.c_str ()));
if (abfd != NULL)
found_pathname = bfd_get_filename (abfd.get ());
#include "symtab.h"
#include "gdb_bfd.h"
#include "gdbsupport/owning_intrusive_list.h"
+#include "gdbsupport/gdb_tilde_expand.h"
#include "target-section.h"
/* Base class for target-specific link map information. */
that supports outputting multiple segments once the related code
supports them. */
CORE_ADDR addr_low = 0, addr_high = 0;
+
+ /* Get the full path to the binary file described by this solib. */
+ std::string file_path () const
+ { return gdb_tilde_expand (so_name.c_str ()); }
};
struct solib_ops
int (*in_dynsym_resolve_code) (CORE_ADDR pc);
/* Find and open shared library binary file. */
- gdb_bfd_ref_ptr (*bfd_open) (const char *pathname);
+ gdb_bfd_ref_ptr (*bfd_open) (const solib &so);
/* Given two so_list objects, one from the GDB thread list
and another from the list returned by current_sos, return 1
extern gdb_bfd_ref_ptr solib_bfd_fopen (const char *pathname, int fd);
/* Find solib binary file and open it. */
-extern gdb_bfd_ref_ptr solib_bfd_open (const char *in_pathname);
+extern gdb_bfd_ref_ptr solib_bfd_open (const char *pathname);
+
+extern gdb_bfd_ref_ptr solib_bfd_open_from_solib (const solib &so);
/* A default implementation of the solib_ops::find_solib_addr callback.
This just returns an empty std::optional<CORE_ADDR> indicating GDB is