[PATCH 21/24] gdb: link so_list using intrusive_list

Simon Marchi
2023-10-10T20:47:16Z

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

Change-Id: I7f55fd88325bb197cc655c9be5a2ec966d8cc48d
---
gdb/mi/mi-cmd-file.c | 8 +-
gdb/progspace.c | 4 +-
gdb/progspace.h | 12 ++-
gdb/solib-aix.c | 23 ++----
gdb/solib-darwin.c | 23 ++----
gdb/solib-dsbt.c | 12 +--
gdb/solib-frv.c | 30 ++++----
gdb/solib-rocm.c | 26 +++----
gdb/solib-svr4.c | 97 ++++++++++--------------
gdb/solib-target.c | 19 ++---
gdb/solib.c | 170 ++++++++++++++++++++-----------------------
gdb/solist.h | 6 +-
12 files changed, 179 insertions(+), 251 deletions(-)

diff --git a/gdb/mi/mi-cmd-file.c b/gdb/mi/mi-cmd-file.c
index 5f63ce4494cb..adc324e64fc8 100644
--- a/gdb/mi/mi-cmd-file.c
+++ b/gdb/mi/mi-cmd-file.c
@@ -163,14 +163,14 @@ mi_cmd_file_list_shared_libraries (const char *command,
/* Print the table header. */
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[0] == '\0')
+ if (so.so_name[0] == '\0')
continue;
- if (pattern != NULL && !re_exec (so->so_name.c_str ()))
+ if (pattern != NULL && !re_exec (so.so_name.c_str ()))
continue;

ui_out_emit_tuple tuple_emitter (uiout, NULL);
- mi_output_solib_attribs (uiout, *so);
+ mi_output_solib_attribs (uiout, so);
}
}
diff --git a/gdb/progspace.c b/gdb/progspace.c
index 555fa79ccce8..4b816b4dac8b 100644
--- a/gdb/progspace.c
+++ b/gdb/progspace.c
@@ -132,8 +132,8 @@ void
program_space::free_all_objfiles ()
{
/* Any objfile reference would become stale. */
- for (struct so_list *so : current_program_space->solibs ())
- gdb_assert (so->objfile == NULL);
+ for (const struct so_list &so : current_program_space->solibs ())
+ gdb_assert (so.objfile == NULL);

while (!objfiles_list.empty ())
objfiles_list.front ()->unlink ();
diff --git a/gdb/progspace.h b/gdb/progspace.h
index 20dfc2e92e83..0a762e6ad5c8 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -28,6 +28,7 @@
#include "solist.h"
#include "gdbsupport/next-iterator.h"
#include "gdbsupport/safe-iterator.h"
+#include "gdbsupport/intrusive_list.h"
#include
#include <vector>

@@ -253,12 +254,9 @@ struct program_space
is outside all objfiles in this progspace. */
struct objfile *objfile_for_address (CORE_ADDR address);

- /* Return a range adapter for iterating over all the solibs in this
- program space. Use it like:
-
- for (so_list *so : pspace->solibs ()) { ... } */
- so_list_range solibs () const
- { return so_list_range (this->so_list); }
+ /* Return the list of all the solibs in this program space. */
+ intrusive_list<struct so_list> &solibs ()
+ { return so_list; }

/* Close and clear exec_bfd. If we end up with no target sections
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
solib.c. */
- struct so_list *so_list = NULL;
+ intrusive_list<struct so_list> so_list;

/* Number of calls to solib_add. */
unsigned int solib_add_generation = 0;
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index e5e86c49e712..68798e8735ac 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -445,21 +445,20 @@ solib_aix_solib_create_inferior_hook (int from_tty)

/* Implement the "current_sos" target_so_ops method. */

-static struct so_list *
-solib_aix_current_sos (void)
+static intrusive_list<so_list>
+solib_aix_current_sos ()
{
- struct so_list *start = NULL, *last = NULL;
- int ix;
-
gdb::optional<std::vector<lm_info_aix>> &library_list
= solib_aix_get_library_list (current_inferior (), NULL);
if (!library_list.has_value ())
- return NULL;
+ return {};
+
+ intrusive_list<so_list> sos;

/* Build a struct so_list for each entry on the list.
We skip the first entry, since this is the entry corresponding
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;
std::string so_name;
@@ -488,16 +487,10 @@ solib_aix_current_sos (void)
new_solib->lm_info = gdb::make_unique<lm_info_aix> (info);

/* Add it to the list. */
- if (!start)
- last = start = new_solib;
- else
- {
- last->next = new_solib;
- last = new_solib;
- }
+ sos.push_back (*new_solib);
}

- return start;
+ return sos;
}

/* Implement the "open_symbol_file_object" target_so_ops method. */
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 2c62e16d386a..5e3aabbfb831 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -212,32 +212,31 @@ open_symbol_file_object (int from_tty)

/* Build a list of currently loaded shared objects. See solib-svr4.c. */

-static struct so_list *
-darwin_current_sos (void)
+static intrusive_list<so_list>
+darwin_current_sos ()
{
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
enum bfd_endian byte_order = type_byte_order (ptr_type);
int ptr_len = ptr_type->length ();
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);

/* Be sure image infos are loaded. */
darwin_load_image_infos (info);

if (!darwin_dyld_version_ok (info))
- return NULL;
+ return {};

image_info_size = ptr_len * 3;

+ intrusive_list<so_list> sos;
+
/* Read infos for each solib.
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 ?).
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;
gdb_byte buf[image_info_size];
@@ -282,16 +281,10 @@ darwin_current_sos (void)
li->lm_addr = load_addr;

newobj->lm_info = std::move (li);
-
- if (head == NULL)
- head = newobj;
- else
- tail->next = newobj;
-
- tail = newobj;
+ sos.push_back (*newobj);
}

- return head;
+ return sos;
}

/* Check LOAD_ADDR points to a Mach-O executable header. Return LOAD_ADDR
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index d3566b9590db..0c60ad69753d 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -512,14 +512,13 @@ lm_base (void)
themselves. The declaration of `struct so_list' says which fields
we provide values for. */

-static struct so_list *
+static intrusive_list<so_list>
dsbt_current_sos (void)
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
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);
+ intrusive_list<so_list> sos;

/* Make sure that the main executable has been relocated. This is
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->lm_info = std::move (li);
-
- *sos_next_ptr = sop;
- sos_next_ptr = &sop->next;
+ sos.push_back (*sop);
}
else
{
@@ -630,7 +626,7 @@ dsbt_current_sos (void)
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
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index d92c35339523..c391462ad9af 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -306,13 +306,12 @@ lm_base (void)

/* Implement the "current_sos" target_so_ops method. */

-static struct so_list *
-frv_current_sos (void)
+static intrusive_list<so_list>
+frv_current_sos ()
{
bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
CORE_ADDR lm_addr, mgot;
- struct so_list *sos_head = NULL;
- struct so_list **sos_next_ptr = &sos_head;
+ intrusive_list<so_list> sos;

/* Make sure that the main executable has been relocated. This is
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->lm_info = std::move (li);
-
- *sos_next_ptr = sop;
- sos_next_ptr = &sop->next;
+ sos.push_back (*sop);
}
else
{
@@ -415,7 +411,7 @@ frv_current_sos (void)

enable_break2 ();

- return sos_head;
+ return sos;
}

@@ -856,10 +852,10 @@ main_got (void)
CORE_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;
- 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;

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. */
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
- (entry_point, got_value, name, so->abfd.get (), li);
+ (entry_point, got_value, name, so.abfd.get(), li);

if (addr != 0)
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
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;
}

diff --git a/gdb/solib-rocm.c b/gdb/solib-rocm.c
index bdd458995c21..0dc303b5a651 100644
--- a/gdb/solib-rocm.c
+++ b/gdb/solib-rocm.c
@@ -204,11 +204,10 @@ rocm_solib_handle_event ()

/* 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)
{
- struct so_list *dst = nullptr;
- struct so_list **link = &dst;
+ intrusive_list<so_list> dst;

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_original_name = so.unique_name;

- newobj->next = nullptr;
- *link = newobj;
- link = &newobj->next;
+ dst.push_back (*newobj);
}

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
objects currently loaded in the inferior. */

-static struct so_list *
+static intrusive_list<so_list>
rocm_solib_current_sos ()
{
/* 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. */
std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;

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;

/* Append our libraries to the end of the list. */
- so_list *tail;
- for (tail = head; tail->next; tail = tail->next)
- /* Nothing. */;
- tail->next = dev_so_list;
+ sos.splice (std::move (dev_so_list));

- return head;
+ return sos;
}

namespace {
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index b90b4ca2f680..6311599ff709 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -954,7 +954,7 @@ open_symbol_file_object (int from_tty)

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. */
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. */

-static so_list *
+static intrusive_list<so_list>
so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
{
- struct so_list *dst = NULL;
- struct so_list **link = &dst;
+ intrusive_list<so_list> dst;

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->lm_info = gdb::make_unique<lm_info_svr4> (*so.lm_info);

- newobj->next = NULL;
- *link = newobj;
- link = &newobj->next;
+ dst.push_back (*newobj);
}

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
linker, build a fallback list from other sources. */

-static struct so_list *
+static intrusive_list<so_list>
svr4_default_sos (svr4_info *info)
{
if (!info->debug_loader_offset_p)
- return NULL;
+ return {};

so_list *newobj = new so_list;
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_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.
@@ -1372,32 +1372,15 @@ svr4_current_sos_direct (struct svr4_info *info)

/* Collect sos read and stored by the probes interface. */

-static so_list *
+static intrusive_list<so_list>
svr4_collect_probes_sos (svr4_info *info)
{
- so_list *res = nullptr;
- so_list **pnext = &res;
+ intrusive_list<so_list> res;

for (const auto &tuple : info->solib_lists)
{
const std::vector<svr4_so> &sos = tuple.second;
-
- /* 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;
- }
+ res.splice (so_list_from_svr4_sos (sos));
}

return res;
@@ -1406,10 +1389,10 @@ svr4_collect_probes_sos (svr4_info *info)
/* Implement the main part of the "current_sos" target_so_ops
method. */

-static struct so_list *
+static intrusive_list<so_list>
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
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
anything, read the sos to fill the cache, then collect them from the
cache. */
- if (sos == nullptr)
+ if (sos.empty ())
{
svr4_current_sos_direct (info);

sos = svr4_collect_probes_sos (info);
- if (sos == nullptr)
+ if (sos.empty ())
sos = svr4_default_sos (info);
}

@@ -1433,11 +1416,11 @@ svr4_current_sos_1 (svr4_info *info)

/* Implement the "current_sos" target_so_ops method. */

-static struct so_list *
-svr4_current_sos (void)
+static intrusive_list<so_list>
+svr4_current_sos ()
{
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;

/* 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)
&& vsyscall_range.length != 0)
{
- struct so_list **sop;
-
- sop = &so_head;
- while (*sop != NULL)
+ for (auto so = sos.begin (); so != sos.end (); )
{
- struct so_list *so = *sop;
-
/* We can't simply match the vDSO by starting address alone,
because lm_info->l_addr_inferior (and also l_addr) do not
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))
{
- *sop = so->next;
+ auto next = sos.erase (so);
free_so (*so);
+ so = next;
break;
}

- sop = &so->next;
+ ++so;
}
}

- return so_head;
+ return sos;
}

/* 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
of shared libraries. */
- for (struct so_list *so : current_program_space->solibs ())
- if (so->objfile == objfile)
+ for (const so_list &so : current_program_space->solibs ())
+ if (so.objfile == objfile)
{
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;
}
@@ -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
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;
loader_found_in_list = 1;
- load_addr = lm_addr_check (*so, tmp_bfd.get ());
+ load_addr = lm_addr_check (so, tmp_bfd.get ());
break;
}
}
@@ -3259,7 +3238,7 @@ svr4_lp64_fetch_link_map_offsets (void)

/* 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)
{
if (objfile == nullptr)
@@ -3270,9 +3249,9 @@ find_solib_for_objfile (struct objfile *objfile)
if (objfile->separate_debug_objfile_backlink != nullptr)
objfile = objfile->separate_debug_objfile_backlink;

- for (so_list *so : current_program_space->solibs ())
- if (so->objfile == objfile)
- return so;
+ for (const so_list &so : current_program_space->solibs ())
+ if (so.objfile == objfile)
+ return &so;

return nullptr;
}
@@ -3285,7 +3264,7 @@ find_solib_for_objfile (struct objfile *objfile)
right thing for the main executable. */

static CORE_ADDR
-find_debug_base_for_solib (so_list *solib)
+find_debug_base_for_solib (const so_list *solib)
{
if (solib == nullptr)
return 0;
@@ -3346,7 +3325,7 @@ svr4_iterate_over_objfiles_in_search_order
/* The linker namespace to iterate identified by the address of its
r_debug object, defaulting to the initial namespace. */
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);
if (debug_base == 0)
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
executable, we assume that they were added to the initial
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);
if (solib_base == 0)
solib_base = initial;
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index 0881d7eda430..2e1c74f97e70 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -227,25 +227,22 @@ solib_target_parse_libraries (const char *library)
}
#endif

-static struct so_list *
+static intrusive_list<so_list>
solib_target_current_sos (void)
{
- so_list *start = NULL, *last = NULL;
+ intrusive_list<so_list> sos;

/* Fetch the list of shared libraries. */
gdb::optional<gdb::char_vector> library_document
= target_read_stralloc (current_inferior ()->top_target (),
TARGET_OBJECT_LIBRARIES, NULL);
if (!library_document)
- return NULL;
+ return {};

/* Parse the list. */
std::vector<lm_info_target_up> library_list
= solib_target_parse_libraries (library_document->data ());

- if (library_list.empty ())
- return NULL;
-
/* Build a struct so_list for each entry on the 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);

/* Add it to the list. */
- if (!start)
- last = start = new_solib;
- else
- {
- last->next = new_solib;
- last = new_solib;
- }
+ sos.push_back (*new_solib);
}

- return start;
+ return sos;
}

static void
diff --git a/gdb/solib.c b/gdb/solib.c
index 1815b0910208..9c10340ff583 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -734,10 +734,10 @@ solib_read_symbols (so_list &so, symfile_add_flags flags)
in the list of shared libraries. Return false otherwise. */

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 ())
- if (pivot != known && pivot->objfile == known->objfile)
+ for (const so_list &pivot : current_program_space->solibs ())
+ if (&pivot != &known && pivot.objfile == known.objfile)
return true;
return false;
}
@@ -766,8 +766,6 @@ void
update_solib_list (int from_tty)
{
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
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
contains only the new shared objects, which we then add. */

- gdb = current_program_space->so_list;
- gdb_link = &current_program_space->so_list;
- while (gdb)
+ intrusive_list<so_list> inferior = ops->current_sos ();
+ intrusive_list<so_list>::iterator gdb_iter
+ = current_program_space->so_list.begin ();
+ while (gdb_iter != current_program_space->so_list.end ())
{
- struct so_list *i = inferior;
- struct so_list **i_link = &inferior;
+ intrusive_list<so_list>::iterator inferior_iter = inferior.begin ();

/* Check to see whether the shared object *gdb also appears in
the inferior's current list. */
- while (i)
+ for (; inferior_iter != inferior.end (); ++inferior_iter)
{
if (ops->same)
{
- if (ops->same (*gdb, *i))
+ if (ops->same (*gdb_iter, *inferior_iter))
break;
}
else
{
- if (filename_cmp (gdb->so_original_name.c_str (),
- i->so_original_name.c_str ()) == 0)
- break;
+ if (!filename_cmp (gdb_iter->so_original_name.c_str (),
+ inferior_iter->so_original_name.c_str ()))
+ break;
}
-
- i_link = &i->next;
- i = *i_link;
}

/* 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 from the inferior's list, and leave it on GDB's list. */
- if (i)
+ if (inferior_iter != inferior.end ())
{
- *i_link = i->next;
- free_so (*i);
- gdb_link = &gdb->next;
- gdb = *gdb_link;
+ inferior.erase (inferior_iter);
+ free_so (*inferior_iter);
+ ++gdb_iter;
}

/* 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
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. */
- if (gdb->objfile && ! (gdb->objfile->flags & OBJF_USERLOADED)
- && !solib_used (gdb))
- gdb->objfile->unlink ();
+ if (gdb_iter->objfile != nullptr
+ && !(gdb_iter->objfile->flags & OBJF_USERLOADED)
+ && !solib_used (*gdb_iter))
+ gdb_iter->objfile->unlink ();

/* Some targets' section tables might be referring to
sections from so.abfd; remove them. */
- current_program_space->remove_target_sections (gdb);
+ current_program_space->remove_target_sections (&*gdb_iter);

- free_so (*gdb);
- gdb = *gdb_link;
+ free_so (*gdb_iter);
+ gdb_iter = gdb_iter_next;
}
}

/* Now the inferior's list contains only shared objects that don't
appear in GDB's list --- those that are newly loaded. Add them
to GDB's shared object list. */
- if (inferior)
+ if (!inferior.empty ())
{
int not_found = 0;
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. */
- 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
{
/* Fill in the rest of the `struct so_list' node. */
- if (!solib_map_sections (*i))
+ if (!solib_map_sections (new_so))
{
not_found++;
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
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
message. We have to use a single call to warning in case the
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)
add_flags |= SYMFILE_VERBOSE;

- for (struct so_list *gdb : current_program_space->solibs ())
- if (! pattern || re_exec (gdb->so_name.c_str ()))
+ for (so_list &gdb : current_program_space->solibs ())
+ if (! pattern || re_exec (gdb.so_name.c_str ()))
{
/* Normally, we would read the symbols from that library
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
thread support (x86-linux for instance). */
const int add_this_solib =
- (readsyms || libpthread_solib_p (*gdb));
+ (readsyms || libpthread_solib_p (gdb));

any_matches = true;
if (add_this_solib)
{
- if (gdb->symbols_loaded)
+ if (gdb.symbols_loaded)
{
/* If no pattern was given, be quiet for shared
libraries we have already loaded. */
if (pattern && (from_tty || info_verbose))
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;
}
}
@@ -1089,11 +1083,11 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
so we need to make two passes over the libs. */

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[0])
+ if (so.so_name[0])
{
- if (pattern && ! re_exec (so->so_name.c_str ()))
+ if (pattern && ! re_exec (so.so_name.c_str ()))
continue;
++nr_libs;
}
@@ -1110,19 +1104,19 @@ info_sharedlibrary_command (const char *pattern, int from_tty)

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[0])
+ if (! so.so_name[0])
continue;
- if (pattern && ! re_exec (so->so_name.c_str ()))
+ if (pattern && ! re_exec (so.so_name.c_str ()))
continue;

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 ("to", gdbarch, so->addr_high);
+ uiout->field_core_addr ("from", gdbarch, so.addr_low);
+ uiout->field_core_addr ("to", gdbarch, so.addr_high);
}
else
{
@@ -1131,16 +1125,16 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
}

if (! top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ()
- && so->symbols_loaded
- && !objfile_has_symbols (so->objfile))
+ && so.symbols_loaded
+ && !objfile_has_symbols (so.objfile))
{
so_missing_debug_info = true;
uiout->field_string ("syms-read", "Yes (*)");
}
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");
}
@@ -1188,13 +1182,11 @@ solib_contains_address_p (const so_list &solib,
const char *
solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
{
- struct so_list *so = NULL;
-
- for (so = pspace->so_list; so; so = so->next)
- if (solib_contains_address_p (*so, address))
- return so->so_name.c_str ();
+ for (const so_list &so : pspace->so_list)
+ if (solib_contains_address_p (so, address))
+ return so.so_name.c_str ();

- return (0);
+ return nullptr;
}

/* See solib.h. */
@@ -1219,15 +1211,13 @@ clear_solib (void)

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;
+ notify_solib_unloaded (current_program_space, so);
+ current_program_space->remove_target_sections (&so);
+ free_so (so);
+ });

- current_program_space->so_list = so->next;
- notify_solib_unloaded (current_program_space, *so);
- current_program_space->remove_target_sections (so);
- free_so (*so);
- }

if (ops->clear_solib != nullptr)
ops->clear_solib (current_program_space);
@@ -1322,17 +1312,17 @@ reload_shared_libraries_1 (int from_tty)
if (print_symbol_loading_p (from_tty, 0, 0))
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;
- bool was_loaded = so->symbols_loaded != 0;
+ bool was_loaded = so.symbols_loaded != 0;
symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;

if (from_tty)
add_flags |= SYMFILE_VERBOSE;

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 ()));
if (abfd != NULL)
found_pathname = bfd_get_filename (abfd.get ());
@@ -1341,26 +1331,26 @@ reload_shared_libraries_1 (int from_tty)
symbol file, close that. */
if ((found_pathname == NULL && was_loaded)
|| (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))
- so->objfile->unlink ();
- current_program_space->remove_target_sections (so);
- so->clear ();
+ so.objfile->unlink ();
+ current_program_space->remove_target_sections (&so);
+ so.clear ();
}

/* If this shared library is now associated with a new symbol
file, open it. */
if (found_pathname != NULL
&& (!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;

try
{
- solib_map_sections (*so);
+ solib_map_sections (so);
}

catch (const gdb_exception_error &e)
@@ -1372,8 +1362,8 @@ reload_shared_libraries_1 (int from_tty)
}

if (!got_error
- && (auto_solib_add || was_loaded || libpthread_solib_p (*so)))
- solib_read_symbols (*so, add_flags);
+ && (auto_solib_add || was_loaded || libpthread_solib_p (so)))
+ solib_read_symbols (so, add_flags);
}
}
}
@@ -1729,9 +1719,9 @@ remove_user_added_objfile (struct objfile *objfile)
{
if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
{
- for (struct so_list *so : objfile->pspace->solibs ())
- if (so->objfile == objfile)
- so->objfile = NULL;
+ for (so_list &so : objfile->pspace->solibs ())
+ if (so.objfile == objfile)
+ so.objfile = nullptr;
}
}

diff --git a/gdb/solist.h b/gdb/solist.h
index 9320acb7fd3e..31b823a3a482 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -36,7 +36,7 @@ struct 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
of SO. If we have opened a BFD for SO, close it. If we have placed SO's
@@ -121,7 +121,7 @@ struct target_so_ops
inferior --- we don't examine any of the shared library files
themselves. The declaration of `struct so_list' says which fields
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
FROM_TTY is non-zero, allow messages to be printed. */
@@ -171,8 +171,6 @@ struct target_so_ops
void (*handle_event) (void);
};

-using so_list_range = next_range<so_list>;
-
/* Free the memory associated with a (so_list *). */
void free_so (so_list &so);

--
2.42.0