gdb: link so_list using intrusive_list

Replace the hand-made linked list implementation with intrusive_list,
simplying management of list items.

Change-Id: I7f55fd88325bb197cc655c9be5a2ec966d8cc48d
Approved-By: Pedro Alves <pedro@palves.net>
Reviewed-By: Reviewed-By: Lancelot Six <lancelot.six@amd.com>
This commit is contained in:
Simon Marchi 2023-10-19 10:55:38 -04:00
parent 98107b0b17
commit 8971d2788e
12 changed files with 178 additions and 252 deletions

View file

@ -163,15 +163,15 @@ mi_cmd_file_list_shared_libraries (const char *command,
/* Print the table header. */ /* Print the table header. */
ui_out_emit_list list_emitter (uiout, "shared-libraries"); ui_out_emit_list list_emitter (uiout, "shared-libraries");
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
{ {
if (so->so_name.empty ()) if (so.so_name.empty ())
continue; continue;
if (pattern != nullptr && !re_exec (so->so_name.c_str ())) if (pattern != nullptr && !re_exec (so.so_name.c_str ()))
continue; continue;
ui_out_emit_tuple tuple_emitter (uiout, NULL); ui_out_emit_tuple tuple_emitter (uiout, NULL);
mi_output_solib_attribs (uiout, *so); mi_output_solib_attribs (uiout, so);
} }
} }

View file

@ -132,8 +132,8 @@ void
program_space::free_all_objfiles () program_space::free_all_objfiles ()
{ {
/* Any objfile reference would become stale. */ /* Any objfile reference would become stale. */
for (struct so_list *so : current_program_space->solibs ()) for (const struct so_list &so : current_program_space->solibs ())
gdb_assert (so->objfile == NULL); gdb_assert (so.objfile == NULL);
while (!objfiles_list.empty ()) while (!objfiles_list.empty ())
objfiles_list.front ()->unlink (); objfiles_list.front ()->unlink ();

View file

@ -28,6 +28,7 @@
#include "solist.h" #include "solist.h"
#include "gdbsupport/next-iterator.h" #include "gdbsupport/next-iterator.h"
#include "gdbsupport/safe-iterator.h" #include "gdbsupport/safe-iterator.h"
#include "gdbsupport/intrusive_list.h"
#include <list> #include <list>
#include <vector> #include <vector>
@ -253,12 +254,9 @@ struct program_space
is outside all objfiles in this progspace. */ is outside all objfiles in this progspace. */
struct objfile *objfile_for_address (CORE_ADDR address); struct objfile *objfile_for_address (CORE_ADDR address);
/* Return a range adapter for iterating over all the solibs in this /* Return the list of all the solibs in this program space. */
program space. Use it like: intrusive_list<struct so_list> &solibs ()
{ return so_list; }
for (so_list *so : pspace->solibs ()) { ... } */
so_list_range solibs () const
{ return so_list_range (this->so_list); }
/* Close and clear exec_bfd. If we end up with no target sections /* Close and clear exec_bfd. If we end up with no target sections
to read memory from, this unpushes the exec_ops target. */ to read memory from, this unpushes the exec_ops target. */
@ -361,7 +359,7 @@ struct program_space
/* List of shared objects mapped into this space. Managed by /* List of shared objects mapped into this space. Managed by
solib.c. */ solib.c. */
struct so_list *so_list = NULL; intrusive_list<struct so_list> so_list;
/* Number of calls to solib_add. */ /* Number of calls to solib_add. */
unsigned int solib_add_generation = 0; unsigned int solib_add_generation = 0;

View file

@ -445,21 +445,20 @@ solib_aix_solib_create_inferior_hook (int from_tty)
/* Implement the "current_sos" target_so_ops method. */ /* Implement the "current_sos" target_so_ops method. */
static struct so_list * static intrusive_list<so_list>
solib_aix_current_sos (void) solib_aix_current_sos ()
{ {
struct so_list *start = NULL, *last = NULL;
int ix;
gdb::optional<std::vector<lm_info_aix>> &library_list gdb::optional<std::vector<lm_info_aix>> &library_list
= solib_aix_get_library_list (current_inferior (), NULL); = solib_aix_get_library_list (current_inferior (), NULL);
if (!library_list.has_value ()) if (!library_list.has_value ())
return NULL; return {};
intrusive_list<so_list> sos;
/* Build a struct so_list for each entry on the list. /* Build a struct so_list for each entry on the list.
We skip the first entry, since this is the entry corresponding We skip the first entry, since this is the entry corresponding
to the main executable, not a shared library. */ to the main executable, not a shared library. */
for (ix = 1; ix < library_list->size (); ix++) for (int ix = 1; ix < library_list->size (); ix++)
{ {
so_list *new_solib = new so_list; so_list *new_solib = new so_list;
std::string so_name; std::string so_name;
@ -488,16 +487,10 @@ solib_aix_current_sos (void)
new_solib->lm_info = gdb::make_unique<lm_info_aix> (info); new_solib->lm_info = gdb::make_unique<lm_info_aix> (info);
/* Add it to the list. */ /* Add it to the list. */
if (!start) sos.push_back (*new_solib);
last = start = new_solib;
else
{
last->next = new_solib;
last = new_solib;
}
} }
return start; return sos;
} }
/* Implement the "open_symbol_file_object" target_so_ops method. */ /* Implement the "open_symbol_file_object" target_so_ops method. */

View file

@ -212,32 +212,31 @@ open_symbol_file_object (int from_tty)
/* Build a list of currently loaded shared objects. See solib-svr4.c. */ /* Build a list of currently loaded shared objects. See solib-svr4.c. */
static struct so_list * static intrusive_list<so_list>
darwin_current_sos (void) darwin_current_sos ()
{ {
type *ptr_type type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr; = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
enum bfd_endian byte_order = type_byte_order (ptr_type); enum bfd_endian byte_order = type_byte_order (ptr_type);
int ptr_len = ptr_type->length (); int ptr_len = ptr_type->length ();
unsigned int image_info_size; unsigned int image_info_size;
struct so_list *head = NULL;
struct so_list *tail = NULL;
int i;
darwin_info *info = get_darwin_info (current_program_space); darwin_info *info = get_darwin_info (current_program_space);
/* Be sure image infos are loaded. */ /* Be sure image infos are loaded. */
darwin_load_image_infos (info); darwin_load_image_infos (info);
if (!darwin_dyld_version_ok (info)) if (!darwin_dyld_version_ok (info))
return NULL; return {};
image_info_size = ptr_len * 3; image_info_size = ptr_len * 3;
intrusive_list<so_list> sos;
/* Read infos for each solib. /* Read infos for each solib.
The first entry was rumored to be the executable itself, but this is not The first entry was rumored to be the executable itself, but this is not
true when a large number of shared libraries are used (table expanded ?). true when a large number of shared libraries are used (table expanded ?).
We now check all entries, but discard executable images. */ We now check all entries, but discard executable images. */
for (i = 0; i < info->all_image.count; i++) for (int i = 0; i < info->all_image.count; i++)
{ {
CORE_ADDR iinfo = info->all_image.info + i * image_info_size; CORE_ADDR iinfo = info->all_image.info + i * image_info_size;
gdb_byte buf[image_info_size]; gdb_byte buf[image_info_size];
@ -282,16 +281,10 @@ darwin_current_sos (void)
li->lm_addr = load_addr; li->lm_addr = load_addr;
newobj->lm_info = std::move (li); newobj->lm_info = std::move (li);
sos.push_back (*newobj);
if (head == NULL)
head = newobj;
else
tail->next = newobj;
tail = newobj;
} }
return head; return sos;
} }
/* Check LOAD_ADDR points to a Mach-O executable header. Return LOAD_ADDR /* Check LOAD_ADDR points to a Mach-O executable header. Return LOAD_ADDR

View file

@ -512,14 +512,13 @@ lm_base (void)
themselves. The declaration of `struct so_list' says which fields themselves. The declaration of `struct so_list' says which fields
we provide values for. */ we provide values for. */
static struct so_list * static intrusive_list<so_list>
dsbt_current_sos (void) dsbt_current_sos (void)
{ {
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ()); bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
CORE_ADDR lm_addr; CORE_ADDR lm_addr;
struct so_list *sos_head = NULL;
struct so_list **sos_next_ptr = &sos_head;
dsbt_info *info = get_dsbt_info (current_program_space); dsbt_info *info = get_dsbt_info (current_program_space);
intrusive_list<so_list> sos;
/* Make sure that the main executable has been relocated. This is /* Make sure that the main executable has been relocated. This is
required in order to find the address of the global offset table, required in order to find the address of the global offset table,
@ -616,10 +615,7 @@ dsbt_current_sos (void)
sop->so_original_name = sop->so_name; sop->so_original_name = sop->so_name;
} }
sop->lm_info = std::move (li); sos.push_back (*sop);
*sos_next_ptr = sop;
sos_next_ptr = &sop->next;
} }
else else
{ {
@ -630,7 +626,7 @@ dsbt_current_sos (void)
sizeof (lm_buf.l_next), byte_order); sizeof (lm_buf.l_next), byte_order);
} }
return sos_head; return sos;
} }
/* Return 1 if PC lies in the dynamic symbol resolution code of the /* Return 1 if PC lies in the dynamic symbol resolution code of the

View file

@ -306,13 +306,12 @@ lm_base (void)
/* Implement the "current_sos" target_so_ops method. */ /* Implement the "current_sos" target_so_ops method. */
static struct so_list * static intrusive_list<so_list>
frv_current_sos (void) frv_current_sos ()
{ {
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ()); bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
CORE_ADDR lm_addr, mgot; CORE_ADDR lm_addr, mgot;
struct so_list *sos_head = NULL; intrusive_list<so_list> sos;
struct so_list **sos_next_ptr = &sos_head;
/* Make sure that the main executable has been relocated. This is /* Make sure that the main executable has been relocated. This is
required in order to find the address of the global offset table, required in order to find the address of the global offset table,
@ -399,10 +398,7 @@ frv_current_sos (void)
sop->so_original_name = sop->so_name; sop->so_original_name = sop->so_name;
} }
sop->lm_info = std::move (li); sos.push_back (*sop);
*sos_next_ptr = sop;
sos_next_ptr = &sop->next;
} }
else else
{ {
@ -415,7 +411,7 @@ frv_current_sos (void)
enable_break2 (); enable_break2 ();
return sos_head; return sos;
} }
@ -856,10 +852,10 @@ main_got (void)
CORE_ADDR CORE_ADDR
frv_fdpic_find_global_pointer (CORE_ADDR addr) frv_fdpic_find_global_pointer (CORE_ADDR addr)
{ {
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
{ {
int seg; int seg;
auto *li = gdb::checked_static_cast<lm_info_frv *> (so->lm_info.get ()); auto *li = gdb::checked_static_cast<lm_info_frv *> (so.lm_info.get ());
int_elf32_fdpic_loadmap *map = li->map; int_elf32_fdpic_loadmap *map = li->map;
for (seg = 0; seg < map->nsegs; seg++) for (seg = 0; seg < map->nsegs; seg++)
@ -913,12 +909,12 @@ frv_fdpic_find_canonical_descriptor (CORE_ADDR entry_point)
in list of shared objects. */ in list of shared objects. */
if (addr == 0) if (addr == 0)
{ {
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
{ {
auto *li = gdb::checked_static_cast<lm_info_frv *> (so->lm_info.get ()); auto *li = gdb::checked_static_cast<lm_info_frv *> (so.lm_info.get ());
addr = find_canonical_descriptor_in_load_object addr = find_canonical_descriptor_in_load_object
(entry_point, got_value, name, so->abfd.get (), li); (entry_point, got_value, name, so.abfd.get(), li);
if (addr != 0) if (addr != 0)
break; break;
@ -1065,11 +1061,11 @@ frv_fetch_objfile_link_map (struct objfile *objfile)
/* The other link map addresses may be found by examining the list /* The other link map addresses may be found by examining the list
of shared libraries. */ of shared libraries. */
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
{ {
auto *li = gdb::checked_static_cast<lm_info_frv *> (so->lm_info.get ()); auto *li = gdb::checked_static_cast<lm_info_frv *> (so.lm_info.get ());
if (so->objfile == objfile) if (so.objfile == objfile)
return li->lm_addr; return li->lm_addr;
} }

View file

@ -204,11 +204,10 @@ rocm_solib_handle_event ()
/* Create so_list objects from rocm_so objects in SOS. */ /* Create so_list objects from rocm_so objects in SOS. */
static so_list * static intrusive_list<so_list>
so_list_from_rocm_sos (const std::vector<rocm_so> &sos) so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
{ {
struct so_list *dst = nullptr; intrusive_list<so_list> dst;
struct so_list **link = &dst;
for (const rocm_so &so : sos) for (const rocm_so &so : sos)
{ {
@ -218,9 +217,7 @@ so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
newobj->so_name = so.name; newobj->so_name = so.name;
newobj->so_original_name = so.unique_name; newobj->so_original_name = so.unique_name;
newobj->next = nullptr; dst.push_back (*newobj);
*link = newobj;
link = &newobj->next;
} }
return dst; return dst;
@ -229,30 +226,27 @@ so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
/* Build a list of `struct so_list' objects describing the shared /* Build a list of `struct so_list' objects describing the shared
objects currently loaded in the inferior. */ objects currently loaded in the inferior. */
static struct so_list * static intrusive_list<so_list>
rocm_solib_current_sos () rocm_solib_current_sos ()
{ {
/* First, retrieve the host-side shared library list. */ /* First, retrieve the host-side shared library list. */
so_list *head = svr4_so_ops.current_sos (); intrusive_list<so_list> sos = svr4_so_ops.current_sos ();
/* Then, the device-side shared library list. */ /* Then, the device-side shared library list. */
std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list; std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;
if (dev_sos.empty ()) if (dev_sos.empty ())
return head; return sos;
so_list *dev_so_list = so_list_from_rocm_sos (dev_sos); intrusive_list<so_list> dev_so_list = so_list_from_rocm_sos (dev_sos);
if (head == nullptr) if (sos.empty ())
return dev_so_list; return dev_so_list;
/* Append our libraries to the end of the list. */ /* Append our libraries to the end of the list. */
so_list *tail; sos.splice (std::move (dev_so_list));
for (tail = head; tail->next; tail = tail->next)
/* Nothing. */;
tail->next = dev_so_list;
return head; return sos;
} }
namespace { namespace {

View file

@ -954,7 +954,7 @@ open_symbol_file_object (int from_tty)
struct svr4_library_list struct svr4_library_list
{ {
/* The tail pointer of the current namespace. This is internal to XML /* The so list for the current namespace. This is internal to XML
parsing. */ parsing. */
std::vector<svr4_so> *cur_list; std::vector<svr4_so> *cur_list;
@ -990,11 +990,10 @@ svr4_clear_so (const so_list &so)
/* Create the so_list objects equivalent to the svr4_sos in SOS. */ /* Create the so_list objects equivalent to the svr4_sos in SOS. */
static so_list * static intrusive_list<so_list>
so_list_from_svr4_sos (const std::vector<svr4_so> &sos) so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
{ {
struct so_list *dst = NULL; intrusive_list<so_list> dst;
struct so_list **link = &dst;
for (const svr4_so &so : sos) for (const svr4_so &so : sos)
{ {
@ -1004,9 +1003,7 @@ so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
newobj->so_original_name = so.name; newobj->so_original_name = so.name;
newobj->lm_info = gdb::make_unique<lm_info_svr4> (*so.lm_info); newobj->lm_info = gdb::make_unique<lm_info_svr4> (*so.lm_info);
newobj->next = NULL; dst.push_back (*newobj);
*link = newobj;
link = &newobj->next;
} }
return dst; return dst;
@ -1186,11 +1183,11 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
/* If no shared library information is available from the dynamic /* If no shared library information is available from the dynamic
linker, build a fallback list from other sources. */ linker, build a fallback list from other sources. */
static struct so_list * static intrusive_list<so_list>
svr4_default_sos (svr4_info *info) svr4_default_sos (svr4_info *info)
{ {
if (!info->debug_loader_offset_p) if (!info->debug_loader_offset_p)
return NULL; return {};
so_list *newobj = new so_list; so_list *newobj = new so_list;
auto li = gdb::make_unique<lm_info_svr4> (); auto li = gdb::make_unique<lm_info_svr4> ();
@ -1203,7 +1200,10 @@ svr4_default_sos (svr4_info *info)
newobj->so_name = info->debug_loader_name; newobj->so_name = info->debug_loader_name;
newobj->so_original_name = newobj->so_name; newobj->so_original_name = newobj->so_name;
return newobj; intrusive_list<so_list> sos;
sos.push_back (*newobj);
return sos;
} }
/* Read the whole inferior libraries chain starting at address LM. /* Read the whole inferior libraries chain starting at address LM.
@ -1372,32 +1372,15 @@ svr4_current_sos_direct (struct svr4_info *info)
/* Collect sos read and stored by the probes interface. */ /* Collect sos read and stored by the probes interface. */
static so_list * static intrusive_list<so_list>
svr4_collect_probes_sos (svr4_info *info) svr4_collect_probes_sos (svr4_info *info)
{ {
so_list *res = nullptr; intrusive_list<so_list> res;
so_list **pnext = &res;
for (const auto &tuple : info->solib_lists) for (const auto &tuple : info->solib_lists)
{ {
const std::vector<svr4_so> &sos = tuple.second; const std::vector<svr4_so> &sos = tuple.second;
res.splice (so_list_from_svr4_sos (sos));
/* Allow the linker to report empty namespaces. */
if (sos.empty ())
continue;
*pnext = so_list_from_svr4_sos (sos);
/* Update PNEXT to point to the next member of the last element. */
gdb_assert (*pnext != nullptr);
for (;;)
{
so_list *next = *pnext;
if (next == nullptr)
break;
pnext = &next->next;
}
} }
return res; return res;
@ -1406,10 +1389,10 @@ svr4_collect_probes_sos (svr4_info *info)
/* Implement the main part of the "current_sos" target_so_ops /* Implement the main part of the "current_sos" target_so_ops
method. */ method. */
static struct so_list * static intrusive_list<so_list>
svr4_current_sos_1 (svr4_info *info) svr4_current_sos_1 (svr4_info *info)
{ {
so_list *sos = nullptr; intrusive_list<so_list> sos;
/* If we're using the probes interface, we can use the cache as it will /* If we're using the probes interface, we can use the cache as it will
be maintained by probe update/reload actions. */ be maintained by probe update/reload actions. */
@ -1419,12 +1402,12 @@ svr4_current_sos_1 (svr4_info *info)
/* If we're not using the probes interface or if we didn't cache /* If we're not using the probes interface or if we didn't cache
anything, read the sos to fill the cache, then collect them from the anything, read the sos to fill the cache, then collect them from the
cache. */ cache. */
if (sos == nullptr) if (sos.empty ())
{ {
svr4_current_sos_direct (info); svr4_current_sos_direct (info);
sos = svr4_collect_probes_sos (info); sos = svr4_collect_probes_sos (info);
if (sos == nullptr) if (sos.empty ())
sos = svr4_default_sos (info); sos = svr4_default_sos (info);
} }
@ -1433,11 +1416,11 @@ svr4_current_sos_1 (svr4_info *info)
/* Implement the "current_sos" target_so_ops method. */ /* Implement the "current_sos" target_so_ops method. */
static struct so_list * static intrusive_list<so_list>
svr4_current_sos (void) svr4_current_sos ()
{ {
svr4_info *info = get_svr4_info (current_program_space); svr4_info *info = get_svr4_info (current_program_space);
struct so_list *so_head = svr4_current_sos_1 (info); intrusive_list<so_list> sos = svr4_current_sos_1 (info);
struct mem_range vsyscall_range; struct mem_range vsyscall_range;
/* Filter out the vDSO module, if present. Its symbol file would /* Filter out the vDSO module, if present. Its symbol file would
@ -1446,13 +1429,8 @@ svr4_current_sos (void)
if (gdbarch_vsyscall_range (current_inferior ()->arch (), &vsyscall_range) if (gdbarch_vsyscall_range (current_inferior ()->arch (), &vsyscall_range)
&& vsyscall_range.length != 0) && vsyscall_range.length != 0)
{ {
struct so_list **sop; for (auto so = sos.begin (); so != sos.end (); )
sop = &so_head;
while (*sop != NULL)
{ {
struct so_list *so = *sop;
/* We can't simply match the vDSO by starting address alone, /* We can't simply match the vDSO by starting address alone,
because lm_info->l_addr_inferior (and also l_addr) do not because lm_info->l_addr_inferior (and also l_addr) do not
necessarily represent the real starting address of the necessarily represent the real starting address of the
@ -1499,16 +1477,17 @@ svr4_current_sos (void)
if (address_in_mem_range (li->l_ld, &vsyscall_range)) if (address_in_mem_range (li->l_ld, &vsyscall_range))
{ {
*sop = so->next; auto next = sos.erase (so);
free_so (*so); free_so (*so);
so = next;
break; break;
} }
sop = &so->next; ++so;
} }
} }
return so_head; return sos;
} }
/* Get the address of the link_map for a given OBJFILE. */ /* Get the address of the link_map for a given OBJFILE. */
@ -1528,11 +1507,11 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
/* The other link map addresses may be found by examining the list /* The other link map addresses may be found by examining the list
of shared libraries. */ of shared libraries. */
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
if (so->objfile == objfile) if (so.objfile == objfile)
{ {
auto *li auto *li
= gdb::checked_static_cast<lm_info_svr4 *> (so->lm_info.get ()); = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
return li->lm_addr; return li->lm_addr;
} }
@ -2369,13 +2348,13 @@ enable_break (struct svr4_info *info, int from_tty)
/* On a running target, we can get the dynamic linker's base /* On a running target, we can get the dynamic linker's base
address from the shared library table. */ address from the shared library table. */
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
{ {
if (svr4_same_1 (interp_name, so->so_original_name.c_str ())) if (svr4_same_1 (interp_name, so.so_original_name.c_str ()))
{ {
load_addr_found = 1; load_addr_found = 1;
loader_found_in_list = 1; loader_found_in_list = 1;
load_addr = lm_addr_check (*so, tmp_bfd.get ()); load_addr = lm_addr_check (so, tmp_bfd.get ());
break; break;
} }
} }
@ -3259,7 +3238,7 @@ svr4_lp64_fetch_link_map_offsets (void)
/* Return the DSO matching OBJFILE or nullptr if none can be found. */ /* Return the DSO matching OBJFILE or nullptr if none can be found. */
static so_list * static const so_list *
find_solib_for_objfile (struct objfile *objfile) find_solib_for_objfile (struct objfile *objfile)
{ {
if (objfile == nullptr) if (objfile == nullptr)
@ -3270,9 +3249,9 @@ find_solib_for_objfile (struct objfile *objfile)
if (objfile->separate_debug_objfile_backlink != nullptr) if (objfile->separate_debug_objfile_backlink != nullptr)
objfile = objfile->separate_debug_objfile_backlink; objfile = objfile->separate_debug_objfile_backlink;
for (so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
if (so->objfile == objfile) if (so.objfile == objfile)
return so; return &so;
return nullptr; return nullptr;
} }
@ -3285,7 +3264,7 @@ find_solib_for_objfile (struct objfile *objfile)
right thing for the main executable. */ right thing for the main executable. */
static CORE_ADDR static CORE_ADDR
find_debug_base_for_solib (so_list *solib) find_debug_base_for_solib (const so_list *solib)
{ {
if (solib == nullptr) if (solib == nullptr)
return 0; return 0;
@ -3346,7 +3325,7 @@ svr4_iterate_over_objfiles_in_search_order
/* The linker namespace to iterate identified by the address of its /* The linker namespace to iterate identified by the address of its
r_debug object, defaulting to the initial namespace. */ r_debug object, defaulting to the initial namespace. */
CORE_ADDR initial = elf_locate_base (); CORE_ADDR initial = elf_locate_base ();
so_list *curr_solib = find_solib_for_objfile (current_objfile); const so_list *curr_solib = find_solib_for_objfile (current_objfile);
CORE_ADDR debug_base = find_debug_base_for_solib (curr_solib); CORE_ADDR debug_base = find_debug_base_for_solib (curr_solib);
if (debug_base == 0) if (debug_base == 0)
debug_base = initial; debug_base = initial;
@ -3361,7 +3340,7 @@ svr4_iterate_over_objfiles_in_search_order
If we fail, e.g. for manually added symbol files or for the main If we fail, e.g. for manually added symbol files or for the main
executable, we assume that they were added to the initial executable, we assume that they were added to the initial
namespace. */ namespace. */
so_list *solib = find_solib_for_objfile (objfile); const so_list *solib = find_solib_for_objfile (objfile);
CORE_ADDR solib_base = find_debug_base_for_solib (solib); CORE_ADDR solib_base = find_debug_base_for_solib (solib);
if (solib_base == 0) if (solib_base == 0)
solib_base = initial; solib_base = initial;

View file

@ -227,25 +227,22 @@ solib_target_parse_libraries (const char *library)
} }
#endif #endif
static struct so_list * static intrusive_list<so_list>
solib_target_current_sos (void) solib_target_current_sos (void)
{ {
so_list *start = NULL, *last = NULL; intrusive_list<so_list> sos;
/* Fetch the list of shared libraries. */ /* Fetch the list of shared libraries. */
gdb::optional<gdb::char_vector> library_document gdb::optional<gdb::char_vector> library_document
= target_read_stralloc (current_inferior ()->top_target (), = target_read_stralloc (current_inferior ()->top_target (),
TARGET_OBJECT_LIBRARIES, NULL); TARGET_OBJECT_LIBRARIES, NULL);
if (!library_document) if (!library_document)
return NULL; return {};
/* Parse the list. */ /* Parse the list. */
std::vector<lm_info_target_up> library_list std::vector<lm_info_target_up> library_list
= solib_target_parse_libraries (library_document->data ()); = solib_target_parse_libraries (library_document->data ());
if (library_list.empty ())
return NULL;
/* Build a struct so_list for each entry on the list. */ /* Build a struct so_list for each entry on the list. */
for (lm_info_target_up &info : library_list) for (lm_info_target_up &info : library_list)
{ {
@ -257,16 +254,10 @@ solib_target_current_sos (void)
new_solib->lm_info = std::move (info); new_solib->lm_info = std::move (info);
/* Add it to the list. */ /* Add it to the list. */
if (!start) sos.push_back (*new_solib);
last = start = new_solib;
else
{
last->next = new_solib;
last = new_solib;
}
} }
return start; return sos;
} }
static void static void

View file

@ -734,10 +734,10 @@ solib_read_symbols (so_list &so, symfile_add_flags flags)
in the list of shared libraries. Return false otherwise. */ in the list of shared libraries. Return false otherwise. */
static bool static bool
solib_used (const struct so_list *const known) solib_used (const so_list &known)
{ {
for (const struct so_list *pivot : current_program_space->solibs ()) for (const so_list &pivot : current_program_space->solibs ())
if (pivot != known && pivot->objfile == known->objfile) if (&pivot != &known && pivot.objfile == known.objfile)
return true; return true;
return false; return false;
} }
@ -766,8 +766,6 @@ void
update_solib_list (int from_tty) update_solib_list (int from_tty)
{ {
const target_so_ops *ops = gdbarch_so_ops (current_inferior ()->arch ()); const target_so_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
struct so_list *inferior = ops->current_sos();
struct so_list *gdb, **gdb_link;
/* We can reach here due to changing solib-search-path or the /* We can reach here due to changing solib-search-path or the
sysroot, before having any inferior. */ sysroot, before having any inferior. */
@ -818,42 +816,38 @@ update_solib_list (int from_tty)
the time we're done walking GDB's list, the inferior's list the time we're done walking GDB's list, the inferior's list
contains only the new shared objects, which we then add. */ contains only the new shared objects, which we then add. */
gdb = current_program_space->so_list; intrusive_list<so_list> inferior = ops->current_sos ();
gdb_link = &current_program_space->so_list; intrusive_list<so_list>::iterator gdb_iter
while (gdb) = current_program_space->so_list.begin ();
while (gdb_iter != current_program_space->so_list.end ())
{ {
struct so_list *i = inferior; intrusive_list<so_list>::iterator inferior_iter = inferior.begin ();
struct so_list **i_link = &inferior;
/* Check to see whether the shared object *gdb also appears in /* Check to see whether the shared object *gdb also appears in
the inferior's current list. */ the inferior's current list. */
while (i) for (; inferior_iter != inferior.end (); ++inferior_iter)
{ {
if (ops->same) if (ops->same)
{ {
if (ops->same (*gdb, *i)) if (ops->same (*gdb_iter, *inferior_iter))
break; break;
} }
else else
{ {
if (filename_cmp (gdb->so_original_name.c_str (), if (!filename_cmp (gdb_iter->so_original_name.c_str (),
i->so_original_name.c_str ()) == 0) inferior_iter->so_original_name.c_str ()))
break; break;
} }
i_link = &i->next;
i = *i_link;
} }
/* If the shared object appears on the inferior's list too, then /* If the shared object appears on the inferior's list too, then
it's still loaded, so we don't need to do anything. Delete it's still loaded, so we don't need to do anything. Delete
it from the inferior's list, and leave it on GDB's list. */ it from the inferior's list, and leave it on GDB's list. */
if (i) if (inferior_iter != inferior.end ())
{ {
*i_link = i->next; inferior.erase (inferior_iter);
free_so (*i); free_so (*inferior_iter);
gdb_link = &gdb->next; ++gdb_iter;
gdb = *gdb_link;
} }
/* If it's not on the inferior's list, remove it from GDB's tables. */ /* If it's not on the inferior's list, remove it from GDB's tables. */
@ -861,52 +855,49 @@ update_solib_list (int from_tty)
{ {
/* Notify any observer that the shared object has been /* Notify any observer that the shared object has been
unloaded before we remove it from GDB's tables. */ unloaded before we remove it from GDB's tables. */
notify_solib_unloaded (current_program_space, *gdb); notify_solib_unloaded (current_program_space, *gdb_iter);
current_program_space->deleted_solibs.push_back (gdb->so_name); current_program_space->deleted_solibs.push_back (gdb_iter->so_name);
*gdb_link = gdb->next; intrusive_list<so_list>::iterator gdb_iter_next
= current_program_space->so_list.erase (gdb_iter);
/* Unless the user loaded it explicitly, free SO's objfile. */ /* Unless the user loaded it explicitly, free SO's objfile. */
if (gdb->objfile && ! (gdb->objfile->flags & OBJF_USERLOADED) if (gdb_iter->objfile != nullptr
&& !solib_used (gdb)) && !(gdb_iter->objfile->flags & OBJF_USERLOADED)
gdb->objfile->unlink (); && !solib_used (*gdb_iter))
gdb_iter->objfile->unlink ();
/* Some targets' section tables might be referring to /* Some targets' section tables might be referring to
sections from so.abfd; remove them. */ sections from so.abfd; remove them. */
current_program_space->remove_target_sections (gdb); current_program_space->remove_target_sections (&*gdb_iter);
free_so (*gdb); free_so (*gdb_iter);
gdb = *gdb_link; gdb_iter = gdb_iter_next;
} }
} }
/* Now the inferior's list contains only shared objects that don't /* Now the inferior's list contains only shared objects that don't
appear in GDB's list --- those that are newly loaded. Add them appear in GDB's list --- those that are newly loaded. Add them
to GDB's shared object list. */ to GDB's shared object list. */
if (inferior) if (!inferior.empty ())
{ {
int not_found = 0; int not_found = 0;
const char *not_found_filename = NULL; const char *not_found_filename = NULL;
struct so_list *i;
/* Add the new shared objects to GDB's list. */
*gdb_link = inferior;
/* Fill in the rest of each of the `struct so_list' nodes. */ /* Fill in the rest of each of the `struct so_list' nodes. */
for (i = inferior; i; i = i->next) for (so_list &new_so : inferior)
{ {
current_program_space->added_solibs.push_back (i); current_program_space->added_solibs.push_back (&new_so);
try try
{ {
/* Fill in the rest of the `struct so_list' node. */ /* Fill in the rest of the `struct so_list' node. */
if (!solib_map_sections (*i)) if (!solib_map_sections (new_so))
{ {
not_found++; not_found++;
if (not_found_filename == NULL) if (not_found_filename == NULL)
not_found_filename = i->so_original_name.c_str (); not_found_filename = new_so.so_original_name.c_str ();
} }
} }
@ -919,9 +910,12 @@ update_solib_list (int from_tty)
/* Notify any observer that the shared object has been /* Notify any observer that the shared object has been
loaded now that we've added it to GDB's tables. */ loaded now that we've added it to GDB's tables. */
notify_solib_loaded (*i); notify_solib_loaded (new_so);
} }
/* Add the new shared objects to GDB's list. */
current_program_space->so_list.splice (std::move (inferior));
/* If a library was not found, issue an appropriate warning /* If a library was not found, issue an appropriate warning
message. We have to use a single call to warning in case the message. We have to use a single call to warning in case the
front end does something special with warnings, e.g., pop up front end does something special with warnings, e.g., pop up
@ -1015,8 +1009,8 @@ solib_add (const char *pattern, int from_tty, int readsyms)
if (from_tty) if (from_tty)
add_flags |= SYMFILE_VERBOSE; add_flags |= SYMFILE_VERBOSE;
for (struct so_list *gdb : current_program_space->solibs ()) for (so_list &gdb : current_program_space->solibs ())
if (! pattern || re_exec (gdb->so_name.c_str ())) if (! pattern || re_exec (gdb.so_name.c_str ()))
{ {
/* Normally, we would read the symbols from that library /* Normally, we would read the symbols from that library
only if READSYMS is set. However, we're making a small only if READSYMS is set. However, we're making a small
@ -1024,20 +1018,20 @@ solib_add (const char *pattern, int from_tty, int readsyms)
need the library symbols to be loaded in order to provide need the library symbols to be loaded in order to provide
thread support (x86-linux for instance). */ thread support (x86-linux for instance). */
const int add_this_solib = const int add_this_solib =
(readsyms || libpthread_solib_p (*gdb)); (readsyms || libpthread_solib_p (gdb));
any_matches = true; any_matches = true;
if (add_this_solib) if (add_this_solib)
{ {
if (gdb->symbols_loaded) if (gdb.symbols_loaded)
{ {
/* If no pattern was given, be quiet for shared /* If no pattern was given, be quiet for shared
libraries we have already loaded. */ libraries we have already loaded. */
if (pattern && (from_tty || info_verbose)) if (pattern && (from_tty || info_verbose))
gdb_printf (_("Symbols already loaded for %s\n"), gdb_printf (_("Symbols already loaded for %s\n"),
gdb->so_name.c_str ()); gdb.so_name.c_str ());
} }
else if (solib_read_symbols (*gdb, add_flags)) else if (solib_read_symbols (gdb, add_flags))
loaded_any_symbols = true; loaded_any_symbols = true;
} }
} }
@ -1089,11 +1083,11 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
so we need to make two passes over the libs. */ so we need to make two passes over the libs. */
nr_libs = 0; nr_libs = 0;
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
{ {
if (!so->so_name.empty ()) if (!so.so_name.empty ())
{ {
if (pattern && ! re_exec (so->so_name.c_str ())) if (pattern && ! re_exec (so.so_name.c_str ()))
continue; continue;
++nr_libs; ++nr_libs;
} }
@ -1110,20 +1104,20 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
uiout->table_body (); uiout->table_body ();
for (struct so_list *so : current_program_space->solibs ()) for (const so_list &so : current_program_space->solibs ())
{ {
if (so->so_name.empty ()) if (so.so_name.empty ())
continue; continue;
if (pattern && ! re_exec (so->so_name.c_str ())) if (pattern && ! re_exec (so.so_name.c_str ()))
continue; continue;
ui_out_emit_tuple tuple_emitter (uiout, "lib"); ui_out_emit_tuple tuple_emitter (uiout, "lib");
if (so->addr_high != 0) if (so.addr_high != 0)
{ {
uiout->field_core_addr ("from", gdbarch, so->addr_low); uiout->field_core_addr ("from", gdbarch, so.addr_low);
uiout->field_core_addr ("to", gdbarch, so->addr_high); uiout->field_core_addr ("to", gdbarch, so.addr_high);
} }
else else
{ {
@ -1132,16 +1126,16 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
} }
if (! top_level_interpreter ()->interp_ui_out ()->is_mi_like_p () if (! top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ()
&& so->symbols_loaded && so.symbols_loaded
&& !objfile_has_symbols (so->objfile)) && !objfile_has_symbols (so.objfile))
{ {
so_missing_debug_info = true; so_missing_debug_info = true;
uiout->field_string ("syms-read", "Yes (*)"); uiout->field_string ("syms-read", "Yes (*)");
} }
else else
uiout->field_string ("syms-read", so->symbols_loaded ? "Yes" : "No"); uiout->field_string ("syms-read", so.symbols_loaded ? "Yes" : "No");
uiout->field_string ("name", so->so_name, file_name_style.style ()); uiout->field_string ("name", so.so_name, file_name_style.style ());
uiout->text ("\n"); uiout->text ("\n");
} }
@ -1189,13 +1183,11 @@ solib_contains_address_p (const so_list &solib,
const char * const char *
solib_name_from_address (struct program_space *pspace, CORE_ADDR address) solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
{ {
struct so_list *so = NULL; for (const so_list &so : pspace->so_list)
if (solib_contains_address_p (so, address))
return so.so_name.c_str ();
for (so = pspace->so_list; so; so = so->next) return nullptr;
if (solib_contains_address_p (*so, address))
return so->so_name.c_str ();
return (0);
} }
/* See solib.h. */ /* See solib.h. */
@ -1220,15 +1212,13 @@ clear_solib (void)
disable_breakpoints_in_shlibs (); disable_breakpoints_in_shlibs ();
while (current_program_space->so_list) current_program_space->so_list.clear_and_dispose ([] (so_list *so)
{ {
struct so_list *so = current_program_space->so_list;
current_program_space->so_list = so->next;
notify_solib_unloaded (current_program_space, *so); notify_solib_unloaded (current_program_space, *so);
current_program_space->remove_target_sections (so); current_program_space->remove_target_sections (&so);
free_so (*so); free_so (*so);
} });
if (ops->clear_solib != nullptr) if (ops->clear_solib != nullptr)
ops->clear_solib (current_program_space); ops->clear_solib (current_program_space);
@ -1323,17 +1313,17 @@ reload_shared_libraries_1 (int from_tty)
if (print_symbol_loading_p (from_tty, 0, 0)) if (print_symbol_loading_p (from_tty, 0, 0))
gdb_printf (_("Loading symbols for shared libraries.\n")); gdb_printf (_("Loading symbols for shared libraries.\n"));
for (struct so_list *so : current_program_space->solibs ()) for (so_list &so : current_program_space->solibs ())
{ {
const char *found_pathname = NULL; const char *found_pathname = NULL;
bool was_loaded = so->symbols_loaded != 0; bool was_loaded = so.symbols_loaded != 0;
symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET; symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;
if (from_tty) if (from_tty)
add_flags |= SYMFILE_VERBOSE; add_flags |= SYMFILE_VERBOSE;
gdb::unique_xmalloc_ptr<char> filename gdb::unique_xmalloc_ptr<char> filename
(tilde_expand (so->so_original_name.c_str ())); (tilde_expand (so.so_original_name.c_str ()));
gdb_bfd_ref_ptr abfd (solib_bfd_open (filename.get ())); gdb_bfd_ref_ptr abfd (solib_bfd_open (filename.get ()));
if (abfd != NULL) if (abfd != NULL)
found_pathname = bfd_get_filename (abfd.get ()); found_pathname = bfd_get_filename (abfd.get ());
@ -1342,26 +1332,26 @@ reload_shared_libraries_1 (int from_tty)
symbol file, close that. */ symbol file, close that. */
if ((found_pathname == NULL && was_loaded) if ((found_pathname == NULL && was_loaded)
|| (found_pathname != NULL || (found_pathname != NULL
&& filename_cmp (found_pathname, so->so_name.c_str ()) != 0)) && filename_cmp (found_pathname, so.so_name.c_str ()) != 0))
{ {
if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED) if (so.objfile && ! (so.objfile->flags & OBJF_USERLOADED)
&& !solib_used (so)) && !solib_used (so))
so->objfile->unlink (); so.objfile->unlink ();
current_program_space->remove_target_sections (so); current_program_space->remove_target_sections (&so);
so->clear (); so.clear ();
} }
/* If this shared library is now associated with a new symbol /* If this shared library is now associated with a new symbol
file, open it. */ file, open it. */
if (found_pathname != NULL if (found_pathname != NULL
&& (!was_loaded && (!was_loaded
|| filename_cmp (found_pathname, so->so_name.c_str ()) != 0)) || filename_cmp (found_pathname, so.so_name.c_str ()) != 0))
{ {
bool got_error = false; bool got_error = false;
try try
{ {
solib_map_sections (*so); solib_map_sections (so);
} }
catch (const gdb_exception_error &e) catch (const gdb_exception_error &e)
@ -1373,8 +1363,8 @@ reload_shared_libraries_1 (int from_tty)
} }
if (!got_error if (!got_error
&& (auto_solib_add || was_loaded || libpthread_solib_p (*so))) && (auto_solib_add || was_loaded || libpthread_solib_p (so)))
solib_read_symbols (*so, add_flags); solib_read_symbols (so, add_flags);
} }
} }
} }
@ -1730,9 +1720,9 @@ remove_user_added_objfile (struct objfile *objfile)
{ {
if (objfile != 0 && objfile->flags & OBJF_USERLOADED) if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
{ {
for (struct so_list *so : objfile->pspace->solibs ()) for (so_list &so : objfile->pspace->solibs ())
if (so->objfile == objfile) if (so.objfile == objfile)
so->objfile = NULL; so.objfile = nullptr;
} }
} }

View file

@ -36,7 +36,7 @@ struct lm_info
using lm_info_up = std::unique_ptr<lm_info>; using lm_info_up = std::unique_ptr<lm_info>;
struct so_list struct so_list : intrusive_list_node<so_list>
{ {
/* Free symbol-file related contents of SO and reset for possible reloading /* Free symbol-file related contents of SO and reset for possible reloading
of SO. If we have opened a BFD for SO, close it. If we have placed SO's of SO. If we have opened a BFD for SO, close it. If we have placed SO's
@ -52,8 +52,6 @@ struct so_list
dynamic linker's tables in the inferior, and are initialized by dynamic linker's tables in the inferior, and are initialized by
current_sos. */ current_sos. */
struct so_list *next = nullptr; /* next structure in linked list */
/* A pointer to target specific link map information. Often this /* A pointer to target specific link map information. Often this
will be a copy of struct link_map from the user process, but will be a copy of struct link_map from the user process, but
it need not be; it can be any collection of data needed to it need not be; it can be any collection of data needed to
@ -121,7 +119,7 @@ struct target_so_ops
inferior --- we don't examine any of the shared library files inferior --- we don't examine any of the shared library files
themselves. The declaration of `struct so_list' says which fields themselves. The declaration of `struct so_list' says which fields
we provide values for. */ we provide values for. */
struct so_list *(*current_sos) (void); intrusive_list<so_list> (*current_sos) ();
/* Find, open, and read the symbols for the main executable. If /* Find, open, and read the symbols for the main executable. If
FROM_TTY is non-zero, allow messages to be printed. */ FROM_TTY is non-zero, allow messages to be printed. */
@ -171,8 +169,6 @@ struct target_so_ops
void (*handle_event) (void); void (*handle_event) (void);
}; };
using so_list_range = next_range<so_list>;
/* Free the memory associated with a (so_list *). */ /* Free the memory associated with a (so_list *). */
void free_so (so_list &so); void free_so (so_list &so);