aboutsummaryrefslogtreecommitdiff
path: root/gdb/solib-svr4.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2009-05-18 19:08:10 +0000
committerPedro Alves <palves@redhat.com>2009-05-18 19:08:10 +0000
commit1a816a878078a6b9f9358d444f881af4e353e891 (patch)
tree2efa8b31e5f3db6ecf102ae8f9677785e8798f01 /gdb/solib-svr4.c
parent989f09292e0b24bcc24df34a383d72316d1ee69e (diff)
downloadgdb-1a816a878078a6b9f9358d444f881af4e353e891.zip
gdb-1a816a878078a6b9f9358d444f881af4e353e891.tar.gz
gdb-1a816a878078a6b9f9358d444f881af4e353e891.tar.bz2
* solib-svr4.c: Include observer.h.
(debug_base, debug_loader_offset_p, debug_loader_offset) (debug_loader_name, main_lm_addr): Move these globals... (struct svr4_info): ... into this new structure. (svr4_info_p): New typedef. (svr4_info): New global. (get_svr4_info, remove_svr4_info, solib_svr4_inferior_exit): New functions. (locate_base, solib_svr4_r_map, solib_svr4_r_brk) (solib_svr4_r_ldsomap): Add svr4_info argument. Adjust to per-inferior svr4. (open_symbol_file_object): Adjust to per-inferior svr4. (svr4_default_sos, svr4_current_sos, svr4_fetch_objfile_link_map): Ditto. (enable_break): Add svr4_info argument. Adjust to per-inferior svr4. (enable_break, svr4_solib_create_inferior_hook, svr4_clear_solib): Adjust to per-inferior svr4. (_initialize_svr4_solib): Install the solib_svr4_inferior_exit observer.
Diffstat (limited to 'gdb/solib-svr4.c')
-rw-r--r--gdb/solib-svr4.c187
1 files changed, 138 insertions, 49 deletions
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 31c81f8..cf42fcb 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -34,6 +34,7 @@
#include "inferior.h"
#include "regcache.h"
#include "gdbthread.h"
+#include "observer.h"
#include "gdb_assert.h"
@@ -272,19 +273,89 @@ IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so)
ptr_type) == 0;
}
-static CORE_ADDR debug_base; /* Base of dynamic linker structures */
+/* Per-inferior SVR4 specific data. */
-/* Validity flag for debug_loader_offset. */
-static int debug_loader_offset_p;
+struct svr4_info
+{
+ int pid;
+
+ CORE_ADDR debug_base; /* Base of dynamic linker structures */
+
+ /* Validity flag for debug_loader_offset. */
+ int debug_loader_offset_p;
+
+ /* Load address for the dynamic linker, inferred. */
+ CORE_ADDR debug_loader_offset;
+
+ /* Name of the dynamic linker, valid if debug_loader_offset_p. */
+ char *debug_loader_name;
+
+ /* Load map address for the main executable. */
+ CORE_ADDR main_lm_addr;
+};
+
+/* List of known processes using solib-svr4 shared libraries, storing
+ the required bookkeeping for each. */
+
+typedef struct svr4_info *svr4_info_p;
+DEF_VEC_P(svr4_info_p);
+VEC(svr4_info_p) *svr4_info = NULL;
+
+/* Get svr4 data for inferior PID (target id). If none is found yet,
+ add it now. This function always returns a valid object. */
+
+struct svr4_info *
+get_svr4_info (int pid)
+{
+ int ix;
+ struct svr4_info *it;
+
+ gdb_assert (pid != 0);
+
+ for (ix = 0; VEC_iterate (svr4_info_p, svr4_info, ix, it); ++ix)
+ {
+ if (it->pid == pid)
+ return it;
+ }
+
+ it = XZALLOC (struct svr4_info);
+ it->pid = pid;
+
+ VEC_safe_push (svr4_info_p, svr4_info, it);
+
+ return it;
+}
+
+/* Get rid of any svr4 related bookkeeping for inferior PID (target
+ id). */
-/* Load address for the dynamic linker, inferred. */
-static CORE_ADDR debug_loader_offset;
+static void
+remove_svr4_info (int pid)
+{
+ int ix;
+ struct svr4_info *it;
-/* Name of the dynamic linker, valid if debug_loader_offset_p. */
-static char *debug_loader_name;
+ for (ix = 0; VEC_iterate (svr4_info_p, svr4_info, ix, it); ++ix)
+ {
+ if (it->pid == pid)
+ {
+ VEC_unordered_remove (svr4_info_p, svr4_info, ix);
+ return;
+ }
+ }
+}
+
+/* This is an "inferior_exit" observer. Inferior PID (target id) is
+ being removed from the inferior list, because it exited, was
+ killed, detached, or we just dropped the connection to the debug
+ interface --- discard any solib-svr4 related bookkeeping for this
+ inferior. */
-/* Load map address for the main executable. */
-static CORE_ADDR main_lm_addr;
+static void
+solib_svr4_inferior_exit (int pid)
+{
+ remove_svr4_info (pid);
+}
/* Local function prototypes */
@@ -715,7 +786,7 @@ elf_locate_base (void)
SYNOPSIS
- CORE_ADDR locate_base (void)
+ CORE_ADDR locate_base (struct svr4_info *)
DESCRIPTION
@@ -745,7 +816,7 @@ elf_locate_base (void)
*/
static CORE_ADDR
-locate_base (void)
+locate_base (struct svr4_info *info)
{
/* Check to see if we have a currently valid address, and if so, avoid
doing all this work again and just return the cached address. If
@@ -753,13 +824,13 @@ locate_base (void)
section for ELF executables. There's no point in doing any of this
though if we don't have some link map offsets to work with. */
- if (debug_base == 0 && svr4_have_link_map_offsets ())
+ if (info->debug_base == 0 && svr4_have_link_map_offsets ())
{
if (exec_bfd != NULL
&& bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
- debug_base = elf_locate_base ();
+ info->debug_base = elf_locate_base ();
}
- return (debug_base);
+ return info->debug_base;
}
/* Find the first element in the inferior's dynamic link map, and
@@ -770,30 +841,32 @@ locate_base (void)
RT_CONSISTENT. */
static CORE_ADDR
-solib_svr4_r_map (void)
+solib_svr4_r_map (struct svr4_info *info)
{
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
- return read_memory_typed_address (debug_base + lmo->r_map_offset, ptr_type);
+ return read_memory_typed_address (info->debug_base + lmo->r_map_offset,
+ ptr_type);
}
/* Find r_brk from the inferior's debug base. */
static CORE_ADDR
-solib_svr4_r_brk (void)
+solib_svr4_r_brk (struct svr4_info *info)
{
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
- return read_memory_typed_address (debug_base + lmo->r_brk_offset, ptr_type);
+ return read_memory_typed_address (info->debug_base + lmo->r_brk_offset,
+ ptr_type);
}
/* Find the link map for the dynamic linker (if it is not in the
normal list of loaded shared objects). */
static CORE_ADDR
-solib_svr4_r_ldsomap (void)
+solib_svr4_r_ldsomap (struct svr4_info *info)
{
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
@@ -801,12 +874,13 @@ solib_svr4_r_ldsomap (void)
/* Check version, and return zero if `struct r_debug' doesn't have
the r_ldsomap member. */
- version = read_memory_unsigned_integer (debug_base + lmo->r_version_offset,
- lmo->r_version_size);
+ version
+ = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
+ lmo->r_version_size);
if (version < 2 || lmo->r_ldsomap_offset == -1)
return 0;
- return read_memory_typed_address (debug_base + lmo->r_ldsomap_offset,
+ return read_memory_typed_address (info->debug_base + lmo->r_ldsomap_offset,
ptr_type);
}
@@ -844,18 +918,19 @@ open_symbol_file_object (void *from_ttyp)
int l_name_size = TYPE_LENGTH (ptr_type);
gdb_byte *l_name_buf = xmalloc (l_name_size);
struct cleanup *cleanups = make_cleanup (xfree, l_name_buf);
+ struct svr4_info *info = get_svr4_info (PIDGET (inferior_ptid));
if (symfile_objfile)
if (!query (_("Attempt to reload symbols from process? ")))
return 0;
/* Always locate the debug struct, in case it has moved. */
- debug_base = 0;
- if (locate_base () == 0)
+ info->debug_base = 0;
+ if (locate_base (info) == 0)
return 0; /* failed somehow... */
/* First link map member should be the executable. */
- lm = solib_svr4_r_map ();
+ lm = solib_svr4_r_map (info);
if (lm == 0)
return 0; /* failed somehow... */
@@ -894,10 +969,13 @@ open_symbol_file_object (void *from_ttyp)
static struct so_list *
svr4_default_sos (void)
{
+ struct inferior *inf = current_inferior ();
+ struct svr4_info *info = get_svr4_info (inf->pid);
+
struct so_list *head = NULL;
struct so_list **link_ptr = &head;
- if (debug_loader_offset_p)
+ if (info->debug_loader_offset_p)
{
struct so_list *new = XZALLOC (struct so_list);
@@ -905,11 +983,12 @@ svr4_default_sos (void)
/* Nothing will ever check the cached copy of the link
map if we set l_addr. */
- new->lm_info->l_addr = debug_loader_offset;
+ new->lm_info->l_addr = info->debug_loader_offset;
new->lm_info->lm_addr = 0;
new->lm_info->lm = NULL;
- strncpy (new->so_name, debug_loader_name, SO_NAME_MAX_PATH_SIZE - 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';
strcpy (new->so_original_name, new->so_name);
@@ -946,19 +1025,27 @@ svr4_current_sos (void)
struct so_list *head = 0;
struct so_list **link_ptr = &head;
CORE_ADDR ldsomap = 0;
+ struct inferior *inf;
+ struct svr4_info *info;
+
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return NULL;
+
+ inf = current_inferior ();
+ info = get_svr4_info (inf->pid);
/* Always locate the debug struct, in case it has moved. */
- debug_base = 0;
- locate_base ();
+ info->debug_base = 0;
+ locate_base (info);
/* If we can't find the dynamic linker's base structure, this
must not be a dynamically linked executable. Hmm. */
- if (! debug_base)
+ if (! info->debug_base)
return svr4_default_sos ();
/* Walk the inferior's link map list, and build our list of
`struct so_list' nodes. */
- lm = solib_svr4_r_map ();
+ lm = solib_svr4_r_map (info);
while (lm)
{
@@ -985,7 +1072,7 @@ svr4_current_sos (void)
decide when to ignore it. */
if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
{
- main_lm_addr = new->lm_info->lm_addr;
+ info->main_lm_addr = new->lm_info->lm_addr;
free_so (new);
}
else
@@ -1025,7 +1112,7 @@ svr4_current_sos (void)
symbol information for the dynamic linker is quite crucial
for skipping dynamic linker resolver code. */
if (lm == 0 && ldsomap == 0)
- lm = ldsomap = solib_svr4_r_ldsomap ();
+ lm = ldsomap = solib_svr4_r_ldsomap (info);
discard_cleanups (old_chain);
}
@@ -1042,14 +1129,15 @@ CORE_ADDR
svr4_fetch_objfile_link_map (struct objfile *objfile)
{
struct so_list *so;
+ struct svr4_info *info = get_svr4_info (PIDGET (inferior_ptid));
/* Cause svr4_current_sos() to be run if it hasn't been already. */
- if (main_lm_addr == 0)
+ if (info->main_lm_addr == 0)
solib_add (NULL, 0, &current_target, auto_solib_add);
/* svr4_current_sos() will set main_lm_addr for the main executable. */
if (objfile == symfile_objfile)
- return main_lm_addr;
+ return info->main_lm_addr;
/* The other link map addresses may be found by examining the list
of shared libraries. */
@@ -1157,13 +1245,14 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ)
*/
static int
-enable_break (void)
+enable_break (struct svr4_info *info)
{
struct minimal_symbol *msymbol;
char **bkpt_namep;
asection *interp_sect;
gdb_byte *interp_name;
CORE_ADDR sym_addr;
+ struct inferior *inf = current_inferior ();
/* First, remove all the solib event breakpoints. Their addresses
may have changed since the last time we ran the program. */
@@ -1179,8 +1268,8 @@ enable_break (void)
solib_add (NULL, 0, &current_target, auto_solib_add);
sym_addr = 0;
- if (debug_base && solib_svr4_r_map () != 0)
- sym_addr = solib_svr4_r_brk ();
+ if (info->debug_base && solib_svr4_r_map (info) != 0)
+ sym_addr = solib_svr4_r_brk (info);
if (sym_addr != 0)
{
@@ -1298,9 +1387,9 @@ enable_break (void)
if (!loader_found_in_list)
{
- debug_loader_name = xstrdup (interp_name);
- debug_loader_offset_p = 1;
- debug_loader_offset = load_addr;
+ info->debug_loader_name = xstrdup (interp_name);
+ info->debug_loader_offset_p = 1;
+ info->debug_loader_offset = load_addr;
solib_add (NULL, 0, &current_target, auto_solib_add);
}
@@ -1578,6 +1667,9 @@ svr4_solib_create_inferior_hook (void)
{
struct inferior *inf;
struct thread_info *tp;
+ struct svr4_info *info;
+
+ info = get_svr4_info (PIDGET (inferior_ptid));
/* Relocate the main executable if necessary. */
svr4_relocate_main_executable ();
@@ -1585,7 +1677,7 @@ svr4_solib_create_inferior_hook (void)
if (!svr4_have_link_map_offsets ())
return;
- if (!enable_break ())
+ if (!enable_break (info))
return;
#if defined(_SCO_DS)
@@ -1617,12 +1709,7 @@ svr4_solib_create_inferior_hook (void)
static void
svr4_clear_solib (void)
{
- debug_base = 0;
- debug_loader_offset_p = 0;
- debug_loader_offset = 0;
- xfree (debug_loader_name);
- debug_loader_name = NULL;
- main_lm_addr = 0;
+ remove_svr4_info (PIDGET (inferior_ptid));
}
static void
@@ -1832,4 +1919,6 @@ _initialize_svr4_solib (void)
svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
svr4_so_ops.same = svr4_same;
+
+ observer_attach_inferior_exit (solib_svr4_inferior_exit);
}