gdb/
[binutils-gdb.git] / gdb / solib-svr4.c
index d685ea5a4d7a08705308857e5cb536550b3572bd..00e16b000a7c83857078dca599882da8a3cd4b07 100644 (file)
@@ -1,7 +1,7 @@
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
-   2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -866,6 +866,50 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
                                    ptr_type);
 }
 
+/* On Solaris systems with some versions of the dynamic linker,
+   ld.so's l_name pointer points to the SONAME in the string table
+   rather than into writable memory.  So that GDB can find shared
+   libraries when loading a core file generated by gcore, ensure that
+   memory areas containing the l_name string are saved in the core
+   file.  */
+
+static int
+svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
+{
+  struct svr4_info *info;
+  CORE_ADDR ldsomap;
+  struct so_list *new;
+  struct cleanup *old_chain;
+  struct link_map_offsets *lmo;
+  CORE_ADDR lm_name;
+
+  info = get_svr4_info ();
+
+  info->debug_base = 0;
+  locate_base (info);
+  if (!info->debug_base)
+    return 0;
+
+  ldsomap = solib_svr4_r_ldsomap (info);
+  if (!ldsomap)
+    return 0;
+
+  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));
+  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);
+  lm_name = LM_NAME (new);
+  do_cleanups (old_chain);
+
+  return (lm_name >= vaddr && lm_name < vaddr + size);
+}
+
 /*
 
   LOCAL FUNCTION
@@ -1221,7 +1265,7 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ)
  */
 
 static int
-enable_break (struct svr4_info *info)
+enable_break (struct svr4_info *info, int from_tty)
 {
   struct minimal_symbol *msymbol;
   char **bkpt_namep;
@@ -1241,7 +1285,7 @@ enable_break (struct svr4_info *info)
      mean r_brk has already been relocated.  Assume the dynamic linker
      is the object containing r_brk.  */
 
-  solib_add (NULL, 0, &current_target, auto_solib_add);
+  solib_add (NULL, from_tty, &current_target, auto_solib_add);
   sym_addr = 0;
   if (info->debug_base && solib_svr4_r_map (info) != 0)
     sym_addr = solib_svr4_r_brk (info);
@@ -1368,7 +1412,7 @@ enable_break (struct svr4_info *info)
          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);
+         solib_add (NULL, from_tty, &current_target, auto_solib_add);
        }
 
       /* Record the relocated start and end address of the dynamic linker
@@ -1436,8 +1480,11 @@ enable_break (struct svr4_info *info)
       msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
       if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
        {
-         create_solib_event_breakpoint (target_gdbarch,
-                                        SYMBOL_VALUE_ADDRESS (msymbol));
+         sym_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+         sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
+                                                        sym_addr,
+                                                        &current_target);
+         create_solib_event_breakpoint (target_gdbarch, sym_addr);
          return 1;
        }
     }
@@ -1447,8 +1494,11 @@ enable_break (struct svr4_info *info)
       msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
       if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
        {
-         create_solib_event_breakpoint (target_gdbarch,
-                                        SYMBOL_VALUE_ADDRESS (msymbol));
+         sym_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+         sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
+                                                        sym_addr,
+                                                        &current_target);
+         create_solib_event_breakpoint (target_gdbarch, sym_addr);
          return 1;
        }
     }
@@ -1601,7 +1651,7 @@ svr4_relocate_main_executable (void)
 
    SYNOPSIS
 
-   void svr4_solib_create_inferior_hook ()
+   void svr4_solib_create_inferior_hook (int from_tty)
 
    DESCRIPTION
 
@@ -1646,7 +1696,7 @@ svr4_relocate_main_executable (void)
  */
 
 static void
-svr4_solib_create_inferior_hook (void)
+svr4_solib_create_inferior_hook (int from_tty)
 {
   struct inferior *inf;
   struct thread_info *tp;
@@ -1660,7 +1710,7 @@ svr4_solib_create_inferior_hook (void)
   if (!svr4_have_link_map_offsets ())
     return;
 
-  if (!enable_break (info))
+  if (!enable_break (info, from_tty))
     return;
 
 #if defined(_SCO_DS)
@@ -1912,4 +1962,5 @@ _initialize_svr4_solib (void)
   svr4_so_ops.bfd_open = solib_bfd_open;
   svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
   svr4_so_ops.same = svr4_same;
+  svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
 }