configure.in -- decide whether to configure gdb.hp; configure -- regenerated.
[deliverable/binutils-gdb.git] / gdb / somsolib.c
index 8b5fc52b232d8b9258205da6fea44359ebd55da9..904ddf17cfc233e4a2cf99eb16208991f8429d46 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle HP SOM shared libraries for GDB, the GNU Debugger.
-   Copyright 1993 Free Software Foundation, Inc.
+   Copyright 1993, 1996 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +15,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 Written by the Center for Software Science at the Univerity of Utah
 and by Cygnus Support.  */
@@ -34,17 +34,46 @@ and by Cygnus Support.  */
 #include "objfiles.h"
 #include "inferior.h"
 #include "gdb-stabs.h"
+#include "gdb_stat.h"
+#include "gdbcmd.h"
+#include "assert.h"
+#include "language.h"
+
+#include <fcntl.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* Uncomment this to turn on some debugging output.
+ */
+
+/* #define SOLIB_DEBUG
+ */
+/* Defined in exec.c; used to prevent dangling pointer bug.
+ */
+extern struct target_ops exec_ops;
+
+/* This lives in hppa-tdep.c. */
+extern struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR pc));
+
+/* These ought to be defined in some public interface, but aren't.  They
+   define the meaning of the various bits in the distinguished __dld_flags
+   variable that is declared in every debuggable a.out on HP-UX, and that
+   is shared between the debugger and the dynamic linker.
+   */
+#define DLD_FLAGS_MAPPRIVATE    0x1
+#define DLD_FLAGS_HOOKVALID     0x2
+#define DLD_FLAGS_LISTVALID     0x4
+#define DLD_FLAGS_BOR_ENABLE    0x8
 
 /* TODO:
 
    * Most of this code should work for hp300 shared libraries.  Does
    anyone care enough to weed out any SOM-isms.
 
-   * Do we need/want a command to load a shared library?
-
-   * Support for hpux8 dynamic linker.
-
-   * Support for tracking user calls to dld_load, dld_unload.  */
+   * Support for hpux8 dynamic linker.  */
 
 /* The basic structure which describes a dynamically loaded object.  This
    data structure is private to the dynamic linker and isn't found in
@@ -64,7 +93,9 @@ struct som_solib_mapped_entry
   /* Version of this library.  */
   short library_version;
 
-  /* Start of text address, link-time text location, end of text address.  */
+  /* Start of text address,
+   * link-time text location (length of text area),
+   * end of text address.  */
   CORE_ADDR text_addr;
   CORE_ADDR text_link_addr;
   CORE_ADDR text_end;
@@ -82,6 +113,26 @@ struct som_solib_mapped_entry
 
   /* There are other fields, but I don't have information as to what is
      contained in them.  */
+
+  /* For versions from HPUX-10.30 and up */
+
+  /* Address in target of offset from thread-local register of
+   * start of this thread's data.  I.e., the first thread-local
+   * variable in this shared library starts at *(tsd_start_addr)
+   * from that area pointed to by cr27 (mpsfu_hi).
+   *
+   * We do the indirection as soon as we read it, so from then
+   * on it's the offset itself.
+   */
+  CORE_ADDR tsd_start_addr;
+
+  /* Following this are longwords holding:
+   *
+   * ?, ?, ?, ptr to -1, ptr to-1, ptr to lib name (leaf name),
+   * ptr to __data_start, ptr to __data_end
+   */
+
+  
 };
 
 /* A structure to keep track of all the known shared objects.  */
@@ -92,14 +143,287 @@ struct so_list
   bfd *abfd;
   struct section_table *sections;
   struct section_table *sections_end;
+/* elz: added this field to store the address in target space (in the
+   library) of the library descriptor (handle) which we read into
+   som_solib_mapped_entry structure*/
+  CORE_ADDR solib_addr;
   struct so_list *next;
+  
 };
 
 static struct so_list *so_list_head;
 
+
+/* This is the cumulative size in bytes of the symbol tables of all
+   shared objects on the so_list_head list.  (When we say size, here
+   we mean of the information before it is brought into memory and
+   potentially expanded by GDB.)  When adding a new shlib, this value
+   is compared against the threshold size, held by auto_solib_add
+   (in megabytes).  If adding symbols for the new shlib would cause
+   the total size to exceed the threshold, then the new shlib's symbols
+   are not loaded.
+   */
+static LONGEST  som_solib_total_st_size;
+
+/* When the threshold is reached for any shlib, we refuse to add
+   symbols for subsequent shlibs, even if those shlibs' symbols would
+   be small enough to fit under the threshold.  (Although this may
+   result in one, early large shlib preventing the loading of later,
+   smalller shlibs' symbols, it allows us to issue one informational
+   message.  The alternative, to issue a message for each shlib whose
+   symbols aren't loaded, could be a big annoyance where the threshold
+   is exceeded due to a very large number of shlibs.)
+   */
+static int  som_solib_st_size_threshold_exceeded;
+
+/* These addresses should be filled in by som_solib_create_inferior_hook.
+   They are also used elsewhere in this module.
+   */
+typedef struct {
+  CORE_ADDR  address;
+  struct unwind_table_entry *  unwind;
+} addr_and_unwind_t;
+
+/* When adding fields, be sure to clear them in _initialize_som_solib. */
+static struct {
+  boolean  is_valid;
+  addr_and_unwind_t  hook;
+  addr_and_unwind_t  hook_stub;
+  addr_and_unwind_t  load;
+  addr_and_unwind_t  load_stub;
+  addr_and_unwind_t  unload;
+  addr_and_unwind_t  unload2;
+  addr_and_unwind_t  unload_stub;
+} dld_cache;
+
+
+
 static void som_sharedlibrary_info_command PARAMS ((char *, int));
 
-/* Add symbols from shared libraries into the symtab list.  */
+static void som_solib_sharedlibrary_command PARAMS ((char *, int));
+
+static LONGEST
+som_solib_sizeof_symbol_table (filename)
+  char *  filename;
+{
+  bfd *  abfd;
+  int  desc;
+  char *  absolute_name;
+  LONGEST  st_size = (LONGEST) 0;
+  asection *  sect;
+
+  /* We believe that filename was handed to us by the dynamic linker, and
+     is therefore always an absolute path.
+     */
+  desc = openp (getenv ("PATH"), 1, filename, O_RDONLY | O_BINARY, 0, &absolute_name);
+  if (desc < 0)
+    {
+      perror_with_name (filename);
+    }
+  filename = absolute_name;
+
+  abfd = bfd_fdopenr (filename, gnutarget, desc);
+  if (! abfd)
+    {
+      close (desc);
+      make_cleanup (free, filename);
+      error ("\"%s\": can't open to read symbols: %s.", filename,
+            bfd_errmsg (bfd_get_error ()));
+    }
+  
+  if (!bfd_check_format (abfd, bfd_object))   /* Reads in section info */
+    {
+      bfd_close (abfd);        /* This also closes desc */
+      make_cleanup (free, filename);
+      error ("\"%s\": can't read symbols: %s.", filename,
+            bfd_errmsg (bfd_get_error ()));
+    }
+
+  /* Sum the sizes of the various sections that compose debug info. */
+
+  /* This contains non-DOC information. */
+  sect = bfd_get_section_by_name (abfd, "$DEBUG$");
+  if (sect)
+    st_size += (LONGEST) bfd_section_size (abfd, sect);
+
+  /* This contains DOC information. */
+  sect = bfd_get_section_by_name (abfd, "$PINFO$");
+  if (sect)
+    st_size += (LONGEST) bfd_section_size (abfd, sect);
+
+  bfd_close (abfd);    /* This also closes desc */
+  free (filename);
+
+  /* Unfortunately, just summing the sizes of various debug info
+     sections isn't a very accurate measurement of how much heap
+     space the debugger will need to hold them.  It also doesn't
+     account for space needed by linker (aka "minimal") symbols.
+
+     Anecdotal evidence suggests that just summing the sizes of
+     debug-info-related sections understates the heap space needed
+     to represent it internally by about an order of magnitude.
+
+     Since it's not exactly brain surgery we're doing here, rather
+     than attempt to more accurately measure the size of a shlib's
+     symbol table in GDB's heap, we'll just apply a 10x fudge-
+     factor to the debug info sections' size-sum.  No, this doesn't
+     account for minimal symbols in non-debuggable shlibs.  But it
+     all roughly washes out in the end.
+     */
+  return st_size * (LONGEST) 10;
+}
+
+
+static void
+som_solib_add_solib_objfile (so, name, from_tty, text_addr)
+  struct so_list *  so;
+  char *  name;
+  int  from_tty;
+  CORE_ADDR  text_addr;
+{
+  obj_private_data_t *obj_private;
+  
+  so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0, 0, 1);
+  so->abfd = so->objfile->obfd;
+
+  /* Mark this as a shared library and save private data.
+   */
+  so->objfile->flags |= OBJF_SHARED;
+
+  if( so->objfile->obj_private == NULL )
+    {
+      obj_private = (obj_private_data_t *)
+                        obstack_alloc( &so->objfile->psymbol_obstack,
+                                       sizeof( obj_private_data_t ));
+      obj_private->unwind_info = NULL;
+      obj_private->so_info     = NULL;
+      so->objfile->obj_private = (PTR) obj_private;
+   }
+
+  obj_private = (obj_private_data_t *) so->objfile->obj_private;
+  obj_private->so_info = so;
+
+  if (!bfd_check_format (so->abfd, bfd_object))
+    {
+      error ("\"%s\": not in executable format: %s.",
+             name, bfd_errmsg (bfd_get_error ()));
+    }
+}
+
+
+static void
+som_solib_load_symbols (so, name, from_tty, text_addr, target)
+  struct so_list *  so;
+  char *  name;
+  int  from_tty;
+  CORE_ADDR  text_addr;
+  struct target_ops *  target;
+{
+  struct section_table *  p;
+  int  status;
+  char  buf[4];
+  CORE_ADDR  presumed_data_start;
+
+#ifdef SOLIB_DEBUG
+  printf( "--Adding symbols for shared library \"%s\"\n", name );
+#endif
+
+  som_solib_add_solib_objfile (so, name, from_tty, text_addr);
+
+  /* Now we need to build a section table for this library since
+     we might be debugging a core file from a dynamically linked
+     executable in which the libraries were not privately mapped.  */
+  if (build_section_table (so->abfd,
+                           &so->sections,
+                           &so->sections_end))
+    {
+      error ("Unable to build section table for shared library\n.");
+      return;
+    }
+
+  /* Relocate all the sections based on where they got loaded.  */
+  for (p = so->sections; p < so->sections_end; p++)
+    {
+      if (p->the_bfd_section->flags & SEC_CODE)
+        {
+          p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT);
+          p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT);
+        }
+      else if (p->the_bfd_section->flags & SEC_DATA)
+        {
+          p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA);
+          p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA);
+        }
+    }
+
+  /* Now see if we need to map in the text and data for this shared
+     library (for example debugging a core file which does not use
+     private shared libraries.). 
+
+     Carefully peek at the first text address in the library.  If the
+     read succeeds, then the libraries were privately mapped and were
+     included in the core dump file.
+
+     If the peek failed, then the libraries were not privately mapped
+     and are not in the core file, we'll have to read them in ourselves.  */
+  status = target_read_memory (text_addr, buf, 4);
+  if (status != 0)
+    {
+      int old, new;
+      int update_coreops;
+      int update_execops;
+
+      /* We must update the to_sections field in the core_ops structure
+         here, otherwise we dereference a potential dangling pointer
+         for each call to target_read/write_memory within this routine.  */
+      update_coreops = core_ops.to_sections == target->to_sections;
+
+      /* Ditto exec_ops (this was a bug).
+       */
+      update_execops = exec_ops.to_sections == target->to_sections;
+
+      new = so->sections_end - so->sections;
+      /* Add sections from the shared library to the core target.  */
+      if (target->to_sections)
+        {
+          old = target->to_sections_end - target->to_sections;
+          target->to_sections = (struct section_table *)
+            xrealloc ((char *)target->to_sections,
+                      ((sizeof (struct section_table)) * (old + new)));
+        }
+      else
+        {
+          old = 0;
+          target->to_sections = (struct section_table *)
+            xmalloc ((sizeof (struct section_table)) * new);
+        }
+      target->to_sections_end = (target->to_sections + old + new);
+
+      /* Update the to_sections field in the core_ops structure
+         if needed, ditto exec_ops.  */
+      if (update_coreops)
+        {
+          core_ops.to_sections = target->to_sections;
+          core_ops.to_sections_end = target->to_sections_end;
+        }
+
+      if (update_execops)
+        {
+          exec_ops.to_sections = target->to_sections;
+          exec_ops.to_sections_end = target->to_sections_end;
+        }
+
+      /* Copy over the old data before it gets clobbered.  */
+      memcpy ((char *)(target->to_sections + old),
+              so->sections,
+              ((sizeof (struct section_table)) * new));
+    }
+}
+
+
+/* Add symbols from shared libraries into the symtab list, unless the
+   size threshold (specified by auto_solib_add, in megabytes) would
+   be exceeded.  */
 
 void
 som_solib_add (arg_string, from_tty, target)
@@ -114,6 +438,7 @@ som_solib_add (arg_string, from_tty, target)
   int status;
   unsigned int dld_flags;
   char buf[4], *re_err;
+  int  threshold_warning_given = 0;
 
   /* First validate our arguments.  */
   if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
@@ -160,15 +485,18 @@ som_solib_add (arg_string, from_tty, target)
     }
   dld_flags = extract_unsigned_integer (buf, 4);
 
-  /* __dld_list may not be valid.  If it's not valid tell the user.  */
-  if ((dld_flags & 4) == 0)
+  /* __dld_list may not be valid.  If not, then we punt, warning the user if
+     we were called as a result of the add-symfile command.
+     */
+  if ((dld_flags & DLD_FLAGS_LISTVALID) == 0)
     {
-      error ("__dld_list is not valid according to __dld_flags.\n");
+      if (from_tty)
+        error ("__dld_list is not valid according to __dld_flags.\n");
       return;
     }
 
   /* If the libraries were not mapped private, warn the user.  */
-  if ((dld_flags & 1) == 0)
+  if ((dld_flags & DLD_FLAGS_MAPPRIVATE) == 0)
     warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
 
   msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
@@ -204,7 +532,7 @@ som_solib_add (arg_string, from_tty, target)
 
   /* Using the information in __dld_list is the preferred method
      to get at shared library information.  It doesn't depend on
-     any functions in /usr/lib/end.o and has a chance of working
+     any functions in /opt/langtools/lib/end.o and has a chance of working
      with hpux10 when it is released.  */
   status = target_read_memory (addr, buf, 4);
   if (status != 0)
@@ -225,6 +553,14 @@ som_solib_add (arg_string, from_tty, target)
   while (so_list_tail && so_list_tail->next)
     so_list_tail = so_list_tail->next;
 
+#ifdef SOLIB_DEBUG
+  printf( "--About to read shared library list data\n" );
+#endif
+
+  /* "addr" will always point to the base of the
+   * current data entry describing the current
+   * shared library.
+   */
   while (1)
     {
       CORE_ADDR name_addr, text_addr;
@@ -232,7 +568,9 @@ som_solib_add (arg_string, from_tty, target)
       char *name;
       struct so_list *new_so;
       struct so_list *so_list = so_list_head;
-      struct section_table *p;
+      struct stat statbuf;
+      LONGEST  st_size;
+      int  is_main_program;
 
       if (addr == 0)
        break;
@@ -267,14 +605,52 @@ som_solib_add (arg_string, from_tty, target)
          so_list = so_list->next;
        }
 
-      /* We've already loaded this one or it's the main program, skip it.  */
-      if (so_list || !strcmp (name, symfile_objfile->name))
+      /* See if the file exists.  If not, give a warning, but don't
+        die.  */
+      status = stat (name, &statbuf);
+      if (status == -1)
+       {
+         warning ("Can't find file %s referenced in dld_list.", name);
+
+         status = target_read_memory (addr + 36, buf, 4);
+         if (status != 0)
+           goto err;
+
+         addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);          
+         continue;
+       }
+
+      /* If we've already loaded this one or it's the main program, skip it.  */
+      is_main_program = (strcmp (name, symfile_objfile->name) == 0);
+      if (so_list || is_main_program)
        {
+          /* This is the "next" pointer in the strcuture.
+           */
          status = target_read_memory (addr + 36, buf, 4);
          if (status != 0)
            goto err;
 
          addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
+
+          /* Record the main program's symbol table size. */
+          if (is_main_program && !so_list)
+            {
+              st_size = som_solib_sizeof_symbol_table (name);
+              som_solib_total_st_size += st_size;
+            }
+
+          /* Was this a shlib that we noted but didn't load the symbols for?
+             If so, were we invoked this time from the command-line, via
+             a 'sharedlibrary' or 'add-symbol-file' command?  If yes to
+             both, we'd better load the symbols this time.
+             */
+          if (from_tty && so_list && !is_main_program && (so_list->objfile == NULL))
+            som_solib_load_symbols (so_list,
+                                    name,
+                                    from_tty,
+                                    so_list->som_solib.text_addr,
+                                    target);
+
          continue;
        }
 
@@ -287,8 +663,7 @@ som_solib_add (arg_string, from_tty, target)
 
       text_addr = extract_unsigned_integer (buf, 4);
 
-
-      new_so = (struct so_list *) malloc (sizeof (struct so_list));
+      new_so = (struct so_list *) xmalloc (sizeof (struct so_list));
       memset ((char *)new_so, 0, sizeof (struct so_list));
       if (so_list_head == NULL)
        {
@@ -301,7 +676,10 @@ som_solib_add (arg_string, from_tty, target)
          so_list_tail = new_so;
        }
 
-      /* Fill in all the entries in GDB's shared library list.  */
+      /* Fill in all the entries in GDB's shared library list.
+       */
+       
+      new_so->solib_addr = addr;
       new_so->som_solib.name = name;
       status = target_read_memory (addr + 4, buf, 4);
       if (status != 0)
@@ -309,9 +687,16 @@ som_solib_add (arg_string, from_tty, target)
 
       new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
       new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
+        /* Following is "high water mark", highest version number
+         * seen, rather than plain version number.
+         */
       new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
       new_so->som_solib.text_addr = text_addr;
 
+        /* Q: What about longword at "addr + 8"?
+         * A: It's read above, out of order, into "text_addr".
+         */
+
       status = target_read_memory (addr + 12, buf, 4);
       if (status != 0)
        goto err;
@@ -353,80 +738,95 @@ som_solib_add (arg_string, from_tty, target)
        goto err;
 
       new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
-      addr = (CORE_ADDR)new_so->som_solib.next;
-
-      new_so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
-      new_so->abfd = new_so->objfile->obfd;
 
-      if (!bfd_check_format (new_so->abfd, bfd_object))
-       {
-         error ("\"%s\": not in executable format: %s.",
-                name, bfd_errmsg (bfd_get_error ()));
-       }
-
-      /* Now we need to build a section table for this library since
-        we might be debugging a core file from a dynamically linked
-        executable in which the libraries were not privately mapped.  */
-      if (build_section_table (new_so->abfd,
-                              &new_so->sections,
-                              &new_so->sections_end))
-       {
-         error ("Unable to build section table for shared library\n.");
-         return;
-       }
+      /* Note that we don't re-set "addr" to the next pointer
+       * until after we've read the trailing data.
+       */
 
-      /* Relocate all the sections based on where they got loaded.  */
-      for (p = new_so->sections; p < new_so->sections_end; p++)
-       {
-         if (p->the_bfd_section->flags & SEC_CODE)
-           {
-             p->addr += text_addr - new_so->som_solib.text_link_addr;
-             p->endaddr += text_addr - new_so->som_solib.text_link_addr;
-           }
-         else if (p->the_bfd_section->flags & SEC_DATA)
-           {
-             p->addr += new_so->som_solib.data_start;
-             p->endaddr += new_so->som_solib.data_start;
-           }
-       }
+      status = target_read_memory (addr + 40, buf, 4);
+      new_so->som_solib.tsd_start_addr = extract_unsigned_integer (buf, 4);
+      if (status != 0)
+        goto err;
 
-      /* Now see if we need to map in the text and data for this shared
-        library (for example debugging a core file which does not use
-        private shared libraries.). 
+      /* Now indirect via that value!
+       */
+      status = target_read_memory (new_so->som_solib.tsd_start_addr, buf, 4);
+      new_so->som_solib.tsd_start_addr = extract_unsigned_integer (buf, 4);
+      if (status != 0)
+        goto err;
+#ifdef SOLIB_DEBUG
+      printf( "\n+ library \"%s\" is described at 0x%x\n", name, addr );
+      printf( "  'version' is %d\n",          new_so->som_solib.struct_version );
+      printf( "  'bind_mode' is %d\n",        new_so->som_solib.bind_mode );
+      printf( "  'library_version' is %d\n",  new_so->som_solib.library_version );
+      printf( "  'text_addr' is 0x%x\n",      new_so->som_solib.text_addr );
+      printf( "  'text_link_addr' is 0x%x\n", new_so->som_solib.text_link_addr );
+      printf( "  'text_end' is 0x%x\n",       new_so->som_solib.text_end );
+      printf( "  'data_start' is 0x%x\n",     new_so->som_solib.data_start );
+      printf( "  'bss_start' is 0x%x\n",      new_so->som_solib.bss_start );
+      printf( "  'data_end' is 0x%x\n",       new_so->som_solib.data_end );
+      printf( "  'got_value' is %x\n",        new_so->som_solib.got_value );
+      printf( "  'next' is 0x%x\n",           new_so->som_solib.next );
+      printf( "  'tsd_start_addr' is 0x%x\n", new_so->som_solib.tsd_start_addr );
+#endif
+
+      /* Go on to the next shared library descriptor.
+       */
+      addr = (CORE_ADDR)new_so->som_solib.next;
 
-        Carefully peek at the first text address in the library.  If the
-        read succeeds, then the libraries were privately mapped and were
-        included in the core dump file.
 
-        If the peek failed, then the libraries were not privately mapped
-        and are not in the core file, we'll have to read them in ourselves.  */
-      status = target_read_memory (text_addr, buf, 4);
-      if (status != 0)
-       {
-         int old, new;
 
-         new = new_so->sections_end - new_so->sections;
-         /* Add sections from the shared library to the core target.  */
-         if (target->to_sections)
-           {
-             old = target->to_sections_end - target->to_sections;
-             target->to_sections = (struct section_table *)
-               xrealloc ((char *)target->to_sections,
-                         ((sizeof (struct section_table)) * (old + new)));
-           }
-         else
-           {
-             old = 0;
-             target->to_sections = (struct section_table *)
-               xmalloc ((sizeof (struct section_table)) * new);
-           }
-         target->to_sections_end = (target->to_sections + old + new);
-         memcpy ((char *)(target->to_sections + old),
-                 new_so->sections,
-                 ((sizeof (struct section_table)) * new));
-       }
+      /* At this point, we have essentially hooked the shlib into the
+         "info share" command.  However, we haven't yet loaded its
+         symbol table.  We must now decide whether we ought to, i.e.,
+         whether doing so would exceed the symbol table size threshold.
+
+         If the threshold has just now been exceeded, then we'll issue
+         a warning message (which explains how to load symbols manually,
+         if the user so desires).
+
+         If the threshold has just now or previously been exceeded,
+         we'll just add the shlib to the list of object files, but won't
+         actually load its symbols.  (This is more useful than it might
+         sound, for it allows us to e.g., still load and use the shlibs'
+         unwind information for stack tracebacks.)
+         */
+
+      /* Note that we DON'T want to preclude the user from using the
+         add-symbol-file command!  Thus, we only worry about the threshold
+         when we're invoked for other reasons.
+         */
+      st_size = som_solib_sizeof_symbol_table (name);
+      som_solib_st_size_threshold_exceeded =
+        !from_tty &&
+        ((st_size + som_solib_total_st_size) > (auto_solib_add * (LONGEST)1000000));
+
+      if (som_solib_st_size_threshold_exceeded)
+        {
+          if (! threshold_warning_given)
+            warning ("Symbols for some libraries have not been loaded, because\ndoing so would exceed the size threshold specified by auto-solib-add.\nTo manually load symbols, use the 'sharedlibrary' command.\nTo raise the threshold, set auto-solib-add to a larger value and rerun\nthe program.\n");
+          threshold_warning_given = 1;
+
+          /* We'll still make note of this shlib, even if we don't
+             read its symbols.  This allows us to use its unwind
+             information well enough to know how to e.g., correctly
+             do a traceback from a PC within the shlib, even if we
+             can't symbolize those PCs...
+             */
+          som_solib_add_solib_objfile (new_so, name, from_tty, text_addr);
+          continue;
+        }
+
+      som_solib_total_st_size += st_size;
+
+      /* This fills in new_so->objfile, among others. */
+      som_solib_load_symbols (new_so, name, from_tty, text_addr, target);
     }
 
+#ifdef SOLIB_DEBUG
+    printf( "--Done reading shared library data\n" );
+#endif
+
   /* Getting new symbols may change our opinion about what is
      frameless.  */
   reinit_frame_cache ();
@@ -466,11 +866,16 @@ void
 som_solib_create_inferior_hook()
 {
   struct minimal_symbol *msymbol;
-  unsigned int dld_flags, status;
+  unsigned int dld_flags, status, have_endo;
   asection *shlib_info;
-  char shadow_contents[BREAKPOINT_MAX], buf[4];
+  char buf[4];
+  struct objfile *objfile;
   CORE_ADDR anaddr;
 
+  /* First, remove all the solib event breakpoints.  Their addresses
+     may have changed since the last time we ran the program.  */
+  remove_solib_event_breakpoints ();
+
   if (symfile_objfile == NULL)
     return; 
 
@@ -483,49 +888,157 @@ som_solib_create_inferior_hook()
   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
     return;
 
+  have_endo = 0;
+  /* Slam the pid of the process into __d_pid; failing is only a warning!  */
+  msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
+  if (msymbol == NULL)
+    {
+      warning ("Unable to find __d_pid symbol in object file.");
+      warning ("Suggest linking with /opt/langtools/lib/end.o.");
+      warning ("GDB will be unable to track shl_load/shl_unload calls");
+      goto keep_going;
+    }
+
+  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+  store_unsigned_integer (buf, 4, inferior_pid);
+  status = target_write_memory (anaddr, buf, 4);
+  if (status != 0)
+    {
+      warning ("Unable to write __d_pid");
+      warning ("Suggest linking with /opt/langtools/lib/end.o.");
+      warning ("GDB will be unable to track shl_load/shl_unload calls");
+      goto keep_going;
+    }
+
+  /* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook;
+     This will force the dynamic linker to call __d_trap when significant
+     events occur.
+
+     Note that the above is the pre-HP-UX 9.0 behaviour.  At 9.0 and above,
+     the dld provides an export stub named "__d_trap" as well as the
+     function named "__d_trap" itself, but doesn't provide "_DLD_HOOK".
+     We'll look first for the old flavor and then the new.
+     */
+  msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile);
+  if (msymbol == NULL)
+      msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
+  if (msymbol == NULL)
+    {
+      warning ("Unable to find _DLD_HOOK symbol in object file.");
+      warning ("Suggest linking with /opt/langtools/lib/end.o.");
+      warning ("GDB will be unable to track shl_load/shl_unload calls");
+      goto keep_going;
+    }
+  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+  dld_cache.hook.address = anaddr;
+
+  /* Grrr, this might not be an export symbol!  We have to find the
+     export stub.  */
+  ALL_OBJFILES (objfile)
+    {
+      struct unwind_table_entry *u;
+      struct minimal_symbol *msymbol2;
+
+      /* What a crock.  */
+      msymbol2 = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
+                                                        NULL, objfile);
+      /* Found a symbol with the right name.  */
+      if (msymbol2)
+       {
+         struct unwind_table_entry *u;
+         /* It must be a shared library trampoline.  */
+         if (SYMBOL_TYPE (msymbol2) != mst_solib_trampoline)
+           continue;
+
+         /* It must also be an export stub.  */
+         u = find_unwind_entry (SYMBOL_VALUE (msymbol2));
+         if (!u || u->stub_unwind.stub_type != EXPORT)
+           continue;
+
+         /* OK.  Looks like the correct import stub.  */
+         anaddr = SYMBOL_VALUE (msymbol2);
+          dld_cache.hook_stub.address = anaddr;
+       }
+    }
+  store_unsigned_integer (buf, 4, anaddr);
+
+  msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
+  if (msymbol == NULL)
+    {
+      warning ("Unable to find __dld_hook symbol in object file.");
+      warning ("Suggest linking with /opt/langtools/lib/end.o.");
+      warning ("GDB will be unable to track shl_load/shl_unload calls");
+      goto keep_going;
+    }
+  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+  status = target_write_memory (anaddr, buf, 4);
+  
+  /* Now set a shlib_event breakpoint at __d_trap so we can track
+     significant shared library events.  */
+  msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
+  if (msymbol == NULL)
+    {
+      warning ("Unable to find __dld_d_trap symbol in object file.");
+      warning ("Suggest linking with /opt/langtools/lib/end.o.");
+      warning ("GDB will be unable to track shl_load/shl_unload calls");
+      goto keep_going;
+    }
+  create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+
+  /* We have all the support usually found in end.o, so we can track
+     shl_load and shl_unload calls.  */
+  have_endo = 1;
+
+keep_going:
+
   /* Get the address of __dld_flags, if no such symbol exists, then we can
      not debug the shared code.  */
   msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
   if (msymbol == NULL)
     {
       error ("Unable to find __dld_flags symbol in object file.\n");
-      return;
     }
 
   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+
   /* Read the current contents.  */
   status = target_read_memory (anaddr, buf, 4);
   if (status != 0)
     {
       error ("Unable to read __dld_flags\n");
-      return;
     }
   dld_flags = extract_unsigned_integer (buf, 4);
 
   /* Turn on the flags we care about.  */
-  dld_flags |= 0x5;
+  dld_flags |= DLD_FLAGS_MAPPRIVATE;
+  if (have_endo)
+    dld_flags |= DLD_FLAGS_HOOKVALID;
   store_unsigned_integer (buf, 4, dld_flags);
   status = target_write_memory (anaddr, buf, 4);
   if (status != 0)
     {
       error ("Unable to write __dld_flags\n");
-      return;
     }
 
-  /* Now find the address of _start and set a breakpoint there.  */
+  /* Now find the address of _start and set a breakpoint there. 
+     We still need this code for two reasons:
+
+       * Not all sites have /opt/langtools/lib/end.o, so it's not always
+       possible to track the dynamic linker's events.
+
+       * At this time no events are triggered for shared libraries
+       loaded at startup time (what a crock).  */
+       
   msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
   if (msymbol == NULL)
     {
       error ("Unable to find _start symbol in object file.\n");
-      return;
     }
 
   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
-  if (target_insert_breakpoint (anaddr, shadow_contents))
-    {
-      error ("Unable to set breakpoint at _start.\n");
-      return;
-    }
+
+  /* Make the breakpoint at "_start" a shared library event breakpoint.  */
+  create_solib_event_breakpoint (anaddr);
 
   /* Wipe out all knowledge of old shared libraries since their
      mapping can change from one exec to another!  */
@@ -533,35 +1046,329 @@ som_solib_create_inferior_hook()
     {
       struct so_list *temp;
 
-      free_objfile (so_list_head->objfile);
       temp = so_list_head;
       free (so_list_head);
       so_list_head = temp->next;
     }
+  clear_symtab_users ();
+}
+
+
+static void
+reset_inferior_pid (saved_inferior_pid)
+  int  saved_inferior_pid;
+{
+  inferior_pid = saved_inferior_pid;
+}
+
+
+/* This operation removes the "hook" between GDB and the dynamic linker,
+   which causes the dld to notify GDB of shared library events.
+
+   After this operation completes, the dld will no longer notify GDB of
+   shared library events.  To resume notifications, GDB must call
+   som_solib_create_inferior_hook.
+
+   This operation does not remove any knowledge of shared libraries which
+   GDB may already have been notified of.
+   */
+void
+som_solib_remove_inferior_hook (pid)
+  int  pid;
+{
+  CORE_ADDR  addr;
+  struct minimal_symbol *  msymbol;
+  int  status;
+  char  dld_flags_buffer [TARGET_INT_BIT/TARGET_CHAR_BIT];
+  unsigned int  dld_flags_value;
+  int  saved_inferior_pid = inferior_pid;
+  struct cleanup *  old_cleanups = make_cleanup (reset_inferior_pid, saved_inferior_pid);
+
+  /* Ensure that we're really operating on the specified process. */
+  inferior_pid = pid;
+
+  /* We won't bother to remove the solib breakpoints from this process.
+
+     In fact, on PA64 the breakpoint is hard-coded into the dld callback,
+     and thus we're not supposed to remove it.
+
+     Rather, we'll merely clear the dld_flags bit that enables callbacks.
+     */
+  msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+
+  addr = SYMBOL_VALUE_ADDRESS (msymbol);
+  status = target_read_memory (addr, dld_flags_buffer, TARGET_INT_BIT/TARGET_CHAR_BIT);
+
+  dld_flags_value = extract_unsigned_integer (dld_flags_buffer,
+                                              sizeof (dld_flags_value));
+
+  dld_flags_value &= ~DLD_FLAGS_HOOKVALID;
+  store_unsigned_integer (dld_flags_buffer,
+                          sizeof (dld_flags_value),
+                          dld_flags_value);
+  status = target_write_memory (addr, dld_flags_buffer, TARGET_INT_BIT/TARGET_CHAR_BIT);
+
+  do_cleanups (old_cleanups);
+}
+
+
+/* This function creates a breakpoint on the dynamic linker hook, which
+   is called when e.g., a shl_load or shl_unload call is made.  This
+   breakpoint will only trigger when a shl_load call is made.
+
+   If filename is NULL, then loads of any dll will be caught.  Else,
+   only loads of the file whose pathname is the string contained by
+   filename will be caught.
+
+   Undefined behaviour is guaranteed if this function is called before
+   som_solib_create_inferior_hook.
+   */
+void
+som_solib_create_catch_load_hook (pid, tempflag, filename, cond_string)
+  int  pid;
+  int  tempflag;
+  char *  filename;
+  char *  cond_string;
+{
+  create_solib_load_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
+}
+
+/* This function creates a breakpoint on the dynamic linker hook, which
+   is called when e.g., a shl_load or shl_unload call is made.  This
+   breakpoint will only trigger when a shl_unload call is made.
+
+   If filename is NULL, then unloads of any dll will be caught.  Else,
+   only unloads of the file whose pathname is the string contained by
+   filename will be caught.
+
+   Undefined behaviour is guaranteed if this function is called before
+   som_solib_create_inferior_hook.
+   */
+void
+som_solib_create_catch_unload_hook (pid, tempflag, filename, cond_string)
+  int  pid;
+  int  tempflag;
+  char *  filename;
+  char *  cond_string;
+{
+  create_solib_unload_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
+}
+
+int
+som_solib_have_load_event (pid)
+  int  pid;
+{
+  CORE_ADDR  event_kind;
+
+  event_kind = read_register (ARG0_REGNUM);
+  return (event_kind == SHL_LOAD);
+}
+
+int
+som_solib_have_unload_event (pid)
+  int  pid;
+{
+  CORE_ADDR  event_kind;
+
+  event_kind = read_register (ARG0_REGNUM);
+  return (event_kind == SHL_UNLOAD);
+}
 
-  /* Start the process again and wait for it to hit our breakpoint.  */
-  clear_proceed_status ();
-  stop_soon_quietly = 1;
-  stop_signal = TARGET_SIGNAL_0;
-  do
+static char *
+som_solib_library_pathname (pid)
+  int  pid;
+{
+  CORE_ADDR  dll_handle_address;
+  CORE_ADDR  dll_pathname_address;
+  struct som_solib_mapped_entry  dll_descriptor;
+  char *  p;
+  static char  dll_pathname [1024];
+
+  /* Read the descriptor of this newly-loaded library. */
+  dll_handle_address = read_register (ARG1_REGNUM);
+  read_memory (dll_handle_address, (char *) &dll_descriptor, sizeof (dll_descriptor));
+
+  /* We can find a pointer to the dll's pathname within the descriptor. */
+  dll_pathname_address = (CORE_ADDR) dll_descriptor.name;
+  
+  /* Read the pathname, one byte at a time. */
+  p = dll_pathname;
+  for (;;)
     {
-      target_resume (-1, 0, stop_signal);
-      wait_for_inferior ();
+      char  b;
+      read_memory (dll_pathname_address++, (char *) &b, 1);
+      *p++ = b;
+      if (b == '\0')
+        break;
     }
-  while (stop_signal != TARGET_SIGNAL_TRAP);
-  stop_soon_quietly = 0;
 
-  /* All the libraries should be mapped in now.  Remove our breakpoint and
-     read in the symbol tables from the shared libraries.  */
-  if (target_remove_breakpoint (anaddr, shadow_contents))
+  return dll_pathname;
+}
+
+char *
+som_solib_loaded_library_pathname (pid)
+  int  pid;
+{
+  if (! som_solib_have_load_event (pid))
+    error ("Must have a load event to use this query");
+
+  return som_solib_library_pathname (pid);
+}
+
+char *
+som_solib_unloaded_library_pathname (pid)
+  int  pid;
+{
+  if (! som_solib_have_unload_event (pid))
+    error ("Must have an unload event to use this query");
+
+  return som_solib_library_pathname (pid);
+}
+
+static void
+som_solib_desire_dynamic_linker_symbols ()
+{
+  struct objfile *objfile;
+  struct unwind_table_entry *u;
+  struct minimal_symbol *  dld_msymbol;
+
+  /* Do we already know the value of these symbols?  If so, then
+     we've no work to do.
+
+     (If you add clauses to this test, be sure to likewise update the
+     test within the loop.)
+     */
+  if (dld_cache.is_valid)
+    return;
+
+  ALL_OBJFILES (objfile)
     {
-      error ("Unable to remove breakpoint at _start.\n");
-      return;
+      dld_msymbol = lookup_minimal_symbol ("shl_load", NULL, objfile);
+      if (dld_msymbol != NULL)
+        {
+          dld_cache.load.address = SYMBOL_VALUE (dld_msymbol);
+          dld_cache.load.unwind = find_unwind_entry (dld_cache.load.address);
+        }
+
+      dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_load",
+                                                            NULL,
+                                                            objfile);
+      if (dld_msymbol != NULL)
+        {
+          if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
+            {
+              u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
+              if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
+                {
+                  dld_cache.load_stub.address = SYMBOL_VALUE (dld_msymbol);
+                  dld_cache.load_stub.unwind = u;
+                }
+            }
+        }
+
+      dld_msymbol = lookup_minimal_symbol ("shl_unload", NULL, objfile);
+      if (dld_msymbol != NULL)
+        {
+          dld_cache.unload.address = SYMBOL_VALUE (dld_msymbol);
+          dld_cache.unload.unwind = find_unwind_entry (dld_cache.unload.address);
+
+          /* ??rehrauer: I'm not sure exactly what this is, but it appears
+             that on some HPUX 10.x versions, there's two unwind regions to
+             cover the body of "shl_unload", the second being 4 bytes past
+             the end of the first.  This is a large hack to handle that
+             case, but since I don't seem to have any legitimate way to
+             look for this thing via the symbol table...
+             */
+          if (dld_cache.unload.unwind != NULL)
+            {
+              u = find_unwind_entry (dld_cache.unload.unwind->region_end + 4);
+              if (u != NULL)
+                {
+                  dld_cache.unload2.address = u->region_start;
+                  dld_cache.unload2.unwind = u;
+                }
+            }
+        }
+
+      dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_unload",
+                                                            NULL,
+                                                            objfile);
+      if (dld_msymbol != NULL)
+        {
+          if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
+            {
+              u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
+              if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
+                {
+                  dld_cache.unload_stub.address = SYMBOL_VALUE (dld_msymbol);
+                  dld_cache.unload_stub.unwind = u;
+                }
+            }
+        }
+
+      /* Did we find everything we were looking for?  If so, stop. */
+      if ((dld_cache.load.address != NULL) && (dld_cache.load_stub.address != NULL)
+          && (dld_cache.unload.address != NULL) && (dld_cache.unload_stub.address != NULL))
+        {
+          dld_cache.is_valid = 1;
+          break;
+        }
     }
 
-  som_solib_add ((char *) 0, 0, (struct target_ops *) 0);
+  dld_cache.hook.unwind = find_unwind_entry (dld_cache.hook.address);
+  dld_cache.hook_stub.unwind = find_unwind_entry (dld_cache.hook_stub.address);
+
+  /* We're prepared not to find some of these symbols, which is why
+     this function is a "desire" operation, and not a "require".
+     */
+}
+
+int
+som_solib_in_dynamic_linker (pid, pc)
+  int  pid;
+  CORE_ADDR  pc;
+{
+  struct unwind_table_entry *  u_pc;
+
+  /* Are we in the dld itself?
+
+     ??rehrauer: Large hack -- We'll assume that any address in a
+     shared text region is the dld's text.  This would obviously
+     fall down if the user attached to a process, whose shlibs
+     weren't mapped to a (writeable) private region.  However, in
+     that case the debugger probably isn't able to set the fundamental
+     breakpoint in the dld callback anyways, so this hack should be
+     safe.
+     */
+  if ((pc & (CORE_ADDR) 0xc0000000) == (CORE_ADDR) 0xc0000000)
+    return 1;
+
+  /* Cache the address of some symbols that are part of the dynamic
+     linker, if not already known.
+     */
+  som_solib_desire_dynamic_linker_symbols ();
+
+  /* Are we in the dld callback?  Or its export stub? */
+  u_pc = find_unwind_entry (pc);
+  if (u_pc == NULL)
+    return 0;
+
+  if ((u_pc == dld_cache.hook.unwind) || (u_pc == dld_cache.hook_stub.unwind))
+    return 1;
+
+  /* Or the interface of the dld (i.e., "shl_load" or friends)? */
+  if ((u_pc == dld_cache.load.unwind)
+      || (u_pc == dld_cache.unload.unwind)
+      || (u_pc == dld_cache.unload2.unwind)
+      || (u_pc == dld_cache.load_stub.unwind)
+      || (u_pc == dld_cache.unload_stub.unwind))
+    return 1;
+
+  /* Apparently this address isn't part of the dld's text. */
+  return 0;
 }
 
+
 /* Return the GOT value for the shared library in which ADDR belongs.  If
    ADDR isn't in any known shared library, return zero.  */
 
@@ -585,6 +1392,34 @@ som_solib_get_got_by_pc (addr)
   return got_value;
 }
 
+/*  elz:
+   Return the address of the handle of the shared library
+   in which ADDR belongs.  If
+   ADDR isn't in any known shared library, return zero.  */
+/* this function is used in hppa_fix_call_dummy in hppa-tdep.c*/
+
+CORE_ADDR
+som_solib_get_solib_by_pc (addr)
+     CORE_ADDR addr;
+{
+  struct so_list *so_list = so_list_head;
+
+  while (so_list)
+    {
+      if (so_list->som_solib.text_addr <= addr
+         && so_list->som_solib.text_end > addr)
+        {
+         break;
+        }
+      so_list = so_list->next;
+    }
+  if (so_list)
+   return so_list->solib_addr;
+  else
+   return 0;
+}
+
+
 int
 som_solib_section_offsets (objfile, offsets)
      struct objfile *objfile;
@@ -660,7 +1495,10 @@ som_sharedlibrary_info_command (ignore, from_tty)
       flags = so_list->som_solib.struct_version << 24;
       flags |= so_list->som_solib.bind_mode << 16;
       flags |= so_list->som_solib.library_version;
-      printf_unfiltered ("%s\n", so_list->som_solib.name);
+      printf_unfiltered ("%s", so_list->som_solib.name);
+      if (so_list->objfile == NULL)
+        printf_unfiltered ("  (symbols not loaded)");
+      printf_unfiltered ("\n");
       printf_unfiltered ("    %-12s", local_hex_string_custom (flags, "08l"));
       printf_unfiltered ("%-12s",
              local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
@@ -685,6 +1523,80 @@ som_solib_sharedlibrary_command (args, from_tty)
   som_solib_add (args, from_tty, (struct target_ops *) 0);
 }
 
+
+
+char *
+som_solib_address (addr)
+  CORE_ADDR  addr;
+{
+  struct so_list *  so = so_list_head;
+
+  while (so)
+    {
+      /* Is this address within this shlib's text range?  If so,
+         return the shlib's name.
+         */
+      if ((addr >= so->som_solib.text_addr) && (addr <= so->som_solib.text_end))
+        return so->som_solib.name;
+
+      /* Nope, keep looking... */
+      so = so->next;
+    }
+
+  /* No, we couldn't prove that the address is within a shlib. */
+  return NULL;
+}
+
+
+void
+som_solib_restart ()
+{
+  struct so_list *  sl = so_list_head;
+
+  /* Before the shlib info vanishes, use it to disable any breakpoints
+     that may still be active in those shlibs.
+     */
+  disable_breakpoints_in_shlibs ();
+
+  /* Discard all the shlib descriptors.
+     */
+  while (sl)
+    {
+      struct so_list *  next_sl = sl->next;
+      free (sl);
+      sl = next_sl;
+    }
+  so_list_head = NULL;
+
+  som_solib_total_st_size = (LONGEST) 0;
+  som_solib_st_size_threshold_exceeded = 0;
+
+  dld_cache.is_valid = 0;
+
+  dld_cache.hook.address = 0;
+  dld_cache.hook.unwind = NULL;
+
+  dld_cache.hook_stub.address = 0;
+  dld_cache.hook_stub.unwind = NULL;
+
+  dld_cache.load.address = 0;
+  dld_cache.load.unwind = NULL;
+
+  dld_cache.load_stub.address = 0;
+  dld_cache.load_stub.unwind = NULL;
+
+  dld_cache.unload.address = 0;
+  dld_cache.unload.unwind = NULL;
+
+  dld_cache.unload2.address = 0;
+  dld_cache.unload2.unwind = NULL;
+
+  dld_cache.unload_stub.address = 0;
+  dld_cache.unload_stub.unwind = NULL;
+}
+
+
+
 void
 _initialize_som_solib ()
 {
@@ -692,4 +1604,37 @@ _initialize_som_solib ()
            "Load shared object library symbols for files matching REGEXP.");
   add_info ("sharedlibrary", som_sharedlibrary_info_command,
            "Status of loaded shared object libraries.");
+  add_show_from_set
+    (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+                 (char *) &auto_solib_add,
+                 "Set autoloading size threshold (in megabytes) of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded, until the symbol table\n\
+of the program and libraries exceeds this threshold.\n\
+Otherwise, symbols must be loaded manually, using `sharedlibrary'.",
+                 &setlist),
+     &showlist);
+
+  /* ??rehrauer: On HP-UX, the kernel parameter MAXDSIZ limits how much
+     data space a process can use.  We ought to be reading MAXDSIZ and
+     setting auto_solib_add to some large fraction of that value.  If
+     not that, we maybe ought to be setting it smaller than the default
+     for MAXDSIZ (that being 64Mb, I believe).  However, [1] this threshold
+     is only crudely approximated rather than actually measured, and [2]
+     50 Mbytes is too small for debugging gdb itself.  Thus, the arbitrary
+     100 figure.
+     */
+  auto_solib_add = 100; /* Megabytes */
+
+  som_solib_restart ();
+}
+
+/* Get some HPUX-specific data from a shared lib.
+ */
+CORE_ADDR
+so_lib_thread_start_addr( so )
+    struct so_list *so;
+{
+    return so->som_solib.tsd_start_addr;
 }
This page took 0.037344 seconds and 4 git commands to generate.