Tue Nov 5 10:21:02 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / somsolib.c
index 16d9fa0a44ddc3c34424a1fc9be6bb7915a6d2e9..b24e6722a63572279b29241cad205e2e6089e164 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.
 
@@ -35,17 +35,14 @@ and by Cygnus Support.  */
 #include "inferior.h"
 #include "gdb-stabs.h"
 #include "gdbcmd.h"
+#include "language.h"
 
 /* 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
@@ -100,6 +97,8 @@ static struct so_list *so_list_head;
 
 static void som_sharedlibrary_info_command PARAMS ((char *, int));
 
+static void som_solib_sharedlibrary_command PARAMS ((char *, int));
+
 /* Add symbols from shared libraries into the symtab list.  */
 
 void
@@ -234,6 +233,7 @@ som_solib_add (arg_string, from_tty, target)
       struct so_list *new_so;
       struct so_list *so_list = so_list_head;
       struct section_table *p;
+      struct stat statbuf;
 
       if (addr == 0)
        break;
@@ -268,7 +268,22 @@ 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.  */
+      /* 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.  */
       if (so_list || !strcmp (name, symfile_objfile->name))
        {
          status = target_read_memory (addr + 36, buf, 4);
@@ -289,7 +304,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)
        {
@@ -405,6 +420,12 @@ som_solib_add (arg_string, from_tty, target)
       if (status != 0)
        {
          int old, new;
+         int update_coreops;
+
+         /* 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;
 
          new = new_so->sections_end - new_so->sections;
          /* Add sections from the shared library to the core target.  */
@@ -422,6 +443,16 @@ som_solib_add (arg_string, from_tty, target)
                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.  */
+         if (update_coreops)
+           {
+             core_ops.to_sections = target->to_sections;
+             core_ops.to_sections_end = target->to_sections_end;
+           }
+
+         /* Copy over the old data before it gets clobbered.  */
          memcpy ((char *)(target->to_sections + old),
                  new_so->sections,
                  ((sizeof (struct section_table)) * new));
@@ -467,11 +498,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; 
 
@@ -484,12 +520,125 @@ som_solib_create_inferior_hook()
   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
     return;
 
+  have_endo = 0;
+  /* If __d_pid is present, then put the inferior's pid into __d_pid.  hpux9
+     requires __d_pid to be set.  hpux10 doesn't require __d_pid to be set
+     and the symbol may not be available. 
+
+     Never warn about __d_pid.  */
+  msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
+  if (msymbol != NULL)
+    {
+      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");
+         goto keep_going;
+       }
+    }
+
+  /* If __d_trap_fptr exists, then load whatever's at that address
+     and put it into __dld_hook.  */
+  msymbol = lookup_minimal_symbol ("__d_trap_fptr", NULL, symfile_objfile);
+  if (msymbol != NULL)
+    {
+      anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+      status = target_read_memory (anaddr, buf, 4);
+      anaddr = extract_unsigned_integer (buf, 4);
+
+      /* If it's a plabel, then get the address of the real function.
+        Egad.  This is just the opposite of how hpux9 and _DLD_HOOK
+        works.  */
+      if (anaddr | 0x2)
+       {
+         status = target_read_memory (anaddr & ~0x2, buf, 4);
+         anaddr = extract_unsigned_integer (buf, 4);
+       }
+    }
+  else
+    {
+      /* 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.  */
+      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 /usr/lib/end.o.");
+         warning ("GDB will be unable to track shl_load/shl_unload calls");
+         goto keep_going;
+       }
+      anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+      /* Grrr, this might not be an export symbol!  We have to find the
+        export stub.  */
+      ALL_OBJFILES (objfile)
+       {
+         extern struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR pc));
+
+         /* What a crock.  */
+         msymbol
+           = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
+                                                     NULL, objfile);
+         /* Found a symbol with the right name.  */
+         if (msymbol)
+           {
+             struct unwind_table_entry *u;
+             /* It must be a shared library trampoline.  */
+             if (MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+               continue;
+
+             /* It must also be an export stub.  */
+             u = find_unwind_entry (SYMBOL_VALUE (msymbol));
+             if (!u || u->stub_type != EXPORT)
+               continue;
+
+             /* OK.  Looks like the correct import stub.  */
+             anaddr = SYMBOL_VALUE (msymbol);
+             break;
+           }
+        }
+     }
+  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 /usr/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 /usr/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");
+      goto keep_going;
       return;
     }
 
@@ -504,7 +653,7 @@ som_solib_create_inferior_hook()
   dld_flags = extract_unsigned_integer (buf, 4);
 
   /* Turn on the flags we care about.  */
-  dld_flags |= 0x5;
+  dld_flags |= (0x5 | (have_endo << 1));
   store_unsigned_integer (buf, 4, dld_flags);
   status = target_write_memory (anaddr, buf, 4);
   if (status != 0)
@@ -513,7 +662,15 @@ som_solib_create_inferior_hook()
       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 /usr/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)
     {
@@ -522,11 +679,9 @@ som_solib_create_inferior_hook()
     }
 
   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!  */
@@ -539,29 +694,7 @@ som_solib_create_inferior_hook()
       free (so_list_head);
       so_list_head = temp->next;
     }
-
-  /* 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
-    {
-      target_resume (-1, 0, stop_signal);
-      wait_for_inferior ();
-    }
-  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))
-    {
-      error ("Unable to remove breakpoint at _start.\n");
-      return;
-    }
-
-  if (auto_solib_add_at_startup)
-    som_solib_add ((char *) 0, 0, (struct target_ops *) 0);
+  clear_symtab_users ();
 }
 
 /* Return the GOT value for the shared library in which ADDR belongs.  If
@@ -696,10 +829,11 @@ _initialize_som_solib ()
            "Status of loaded shared object libraries.");
   add_show_from_set
     (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
-                 (char *) &auto_solib_add_at_startup,
+                 (char *) &auto_solib_add,
                  "Set autoloading of shared library symbols at startup.\n\
 If nonzero, symbols from all shared object libraries will be loaded\n\
-automatically when the inferior begins execution.  Otherwise, symbols\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded.  Otherwise, symbols\n\
 must be loaded manually, using `sharedlibrary'.",
                  &setlist),
      &showlist);
This page took 0.026358 seconds and 4 git commands to generate.