struct lm_info
{
- /* Pointer to copy of link map from inferior. The type is char *
- rather than void *, so that we may use byte offsets to find the
- various fields without the need for a cast. */
- gdb_byte *lm;
-
/* Amount by which addresses in the binary should be relocated to
- match the inferior. This could most often be taken directly
- from lm, but when prelinking is involved and the prelink base
- address changes, we may need a different offset, we want to
- warn about the difference and compute it only once. */
- CORE_ADDR l_addr;
+ match the inferior. The direct inferior value is L_ADDR_INFERIOR.
+ When prelinking is involved and the prelink base address changes,
+ we may need a different offset - the recomputed offset is in L_ADDR.
+ It is commonly the same value. It is cached as we want to warn about
+ the difference and compute it only once. L_ADDR is valid
+ iff L_ADDR_P. */
+ CORE_ADDR l_addr, l_addr_inferior;
+ unsigned int l_addr_p : 1;
/* The target location of lm. */
CORE_ADDR lm_addr;
+
+ /* Values read in from inferior's fields of the same name. */
+ CORE_ADDR l_ld, l_next, l_prev, l_name;
};
/* On SVR4 systems, a list of symbols in the dynamic linker where
return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
}
-/* link map access functions. */
-
-static CORE_ADDR
-lm_addr_from_link_map (struct so_list *so)
+static struct lm_info *
+lm_info_read (CORE_ADDR lm_addr)
{
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
+ gdb_byte *lm;
+ struct lm_info *lm_info;
+ struct cleanup *back_to;
+
+ lm = xmalloc (lmo->link_map_size);
+ back_to = make_cleanup (xfree, lm);
+
+ if (target_read_memory (lm_addr, lm, lmo->link_map_size) != 0)
+ {
+ warning (_("Error reading shared library list entry at %s"),
+ paddress (target_gdbarch, lm_addr)),
+ lm_info = NULL;
+ }
+ else
+ {
+ struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
- return extract_typed_address (so->lm_info->lm + lmo->l_addr_offset,
- ptr_type);
+ lm_info = xzalloc (sizeof (*lm_info));
+ lm_info->lm_addr = lm_addr;
+
+ lm_info->l_addr_inferior = extract_typed_address (&lm[lmo->l_addr_offset],
+ ptr_type);
+ lm_info->l_ld = extract_typed_address (&lm[lmo->l_ld_offset], ptr_type);
+ lm_info->l_next = extract_typed_address (&lm[lmo->l_next_offset],
+ ptr_type);
+ lm_info->l_prev = extract_typed_address (&lm[lmo->l_prev_offset],
+ ptr_type);
+ lm_info->l_name = extract_typed_address (&lm[lmo->l_name_offset],
+ ptr_type);
+ }
+
+ do_cleanups (back_to);
+
+ return lm_info;
}
static int
}
static CORE_ADDR
-lm_dynamic_from_link_map (struct so_list *so)
-{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
-
- return extract_typed_address (so->lm_info->lm + lmo->l_ld_offset,
- ptr_type);
-}
-
-static CORE_ADDR
lm_addr_check (struct so_list *so, bfd *abfd)
{
- if (so->lm_info->l_addr == (CORE_ADDR)-1)
+ if (!so->lm_info->l_addr_p)
{
struct bfd_section *dyninfo_sect;
CORE_ADDR l_addr, l_dynaddr, dynaddr;
- l_addr = lm_addr_from_link_map (so);
+ l_addr = so->lm_info->l_addr_inferior;
if (! abfd || ! has_lm_dynamic_from_link_map ())
goto set_addr;
- l_dynaddr = lm_dynamic_from_link_map (so);
+ l_dynaddr = so->lm_info->l_ld;
dyninfo_sect = bfd_get_section_by_name (abfd, ".dynamic");
if (dyninfo_sect == NULL)
set_addr:
so->lm_info->l_addr = l_addr;
+ so->lm_info->l_addr_p = 1;
}
return so->lm_info->l_addr;
}
-static CORE_ADDR
-lm_next (struct so_list *so)
-{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
-
- return extract_typed_address (so->lm_info->lm + lmo->l_next_offset,
- ptr_type);
-}
-
-static CORE_ADDR
-lm_prev (struct so_list *so)
-{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
-
- return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
- ptr_type);
-}
-
-static CORE_ADDR
-lm_name (struct so_list *so)
-{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
-
- return extract_typed_address (so->lm_info->lm + lmo->l_name_offset,
- ptr_type);
-}
-
/* Per pspace SVR4 specific data. */
struct svr4_info
lmo = svr4_fetch_link_map_offsets ();
new = XZALLOC (struct so_list);
old_chain = make_cleanup (xfree, new);
- new->lm_info = xmalloc (sizeof (struct lm_info));
+ new->lm_info = lm_info_read (ldsomap);
make_cleanup (xfree, new->lm_info);
- new->lm_info->l_addr = (CORE_ADDR)-1;
- new->lm_info->lm_addr = ldsomap;
- new->lm_info->lm = xzalloc (lmo->link_map_size);
- make_cleanup (xfree, new->lm_info->lm);
- read_memory (ldsomap, new->lm_info->lm, lmo->link_map_size);
- name_lm = lm_name (new);
+ name_lm = new->lm_info ? new->lm_info->l_name : 0;
do_cleanups (old_chain);
return (name_lm >= vaddr && name_lm < vaddr + size);
static void
svr4_free_so (struct so_list *so)
{
- if (so->lm_info)
- xfree (so->lm_info->lm);
xfree (so->lm_info);
}
new = XZALLOC (struct so_list);
- new->lm_info = xmalloc (sizeof (struct lm_info));
+ new->lm_info = xzalloc (sizeof (struct lm_info));
- /* Nothing will ever check the cached copy of the link
- map if we set l_addr. */
+ /* Nothing will ever check the other fields if we set l_addr_p. */
new->lm_info->l_addr = info->debug_loader_offset;
- new->lm_info->lm_addr = 0;
- new->lm_info->lm = NULL;
+ new->lm_info->l_addr_p = 1;
strncpy (new->so_name, info->debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1);
new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
new = XZALLOC (struct so_list);
old_chain = make_cleanup_free_so (new);
- new->lm_info = xmalloc (sizeof (struct lm_info));
- new->lm_info->l_addr = (CORE_ADDR) -1;
- new->lm_info->lm_addr = lm;
- new->lm_info->lm = xzalloc (lmo->link_map_size);
-
- read_memory (lm, new->lm_info->lm, lmo->link_map_size);
+ new->lm_info = lm_info_read (lm);
+ if (new->lm_info == NULL)
+ {
+ do_cleanups (old_chain);
+ break;
+ }
- next_lm = lm_next (new);
+ next_lm = new->lm_info->l_next;
- if (lm_prev (new) != prev_lm)
+ if (new->lm_info->l_prev != prev_lm)
{
warning (_("Corrupted shared library list"));
do_cleanups (old_chain);
SVR4, it has no name. For others (Solaris 2.3 for example), it
does have a name, so we can no longer use a missing name to
decide when to ignore it. */
- if (ignore_first && lm_prev (new) == 0)
+ if (ignore_first && new->lm_info->l_prev == 0)
{
struct svr4_info *info = get_svr4_info ();
}
/* Extract this shared object's name. */
- target_read_string (lm_name (new), &buffer,
+ target_read_string (new->lm_info->l_name, &buffer,
SO_NAME_MAX_PATH_SIZE - 1, &errcode);
if (errcode != 0)
{