* config/pa/tm-hppa.h: Define lots register offsets needed by
[deliverable/binutils-gdb.git] / gdb / osfsolib.c
index 843448a681b2535ef9a7258edb865e6b81bd0870..017d4a99c465d111a2057db842516e7f095cbdf0 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle OSF/1 shared libraries for GDB, the GNU Debugger.
-   Copyright 1993 Free Software Foundation, Inc.
+   Copyright 1993, 1994 Free Software Foundation, Inc.
    
 This file is part of GDB.
 
@@ -39,26 +39,58 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "inferior.h"
 #include "language.h"
 
-#define MAX_PATH_SIZE 256              /* FIXME: Should be dynamic */
-
-/* FIXME: This is a terrible hack for shared library support under OSF/1.
-   The main problem is that the needed definitions are not contained in
-   the system header files.
-   The ldr_* routines described in loader(3) would be the way to go here.
-   But they do not work for arbitrary target processes (as documented).  */
+#define MAX_PATH_SIZE 1024             /* FIXME: Should be dynamic */
+
+/* When handling shared libraries, GDB has to find out the pathnames
+   of all shared libraries that are currently loaded (to read in their
+   symbols) and where the shared libraries are loaded in memory
+   (to relocate them properly from their prelinked addresses to the
+   current load address).
+
+   Under OSF/1 there are two possibilities to get at this information:
+   1) Peek around in the runtime loader structures.
+      These are not documented, and they are not defined in the system
+      header files. The definitions below were obtained by experimentation,
+      but they seem stable enough.
+   2) Use the undocumented libxproc.a library, which contains the
+      equivalent ldr_* routines.
+      This approach is somewhat cleaner, but it requires that the GDB
+      executable is dynamically linked. In addition it requires a
+      NAT_CLIBS= -lxproc -Wl,-expect_unresolved,ldr_process_context
+      linker specification for GDB and all applications that are using
+      libgdb.
+   We will use the peeking approach until it becomes unwieldy.  */
 
 #ifndef USE_LDR_ROUTINES
+
+/* Definition of runtime loader structures, found by experimentation.  */
 #define RLD_CONTEXT_ADDRESS    0x3ffc0000000
 
 typedef struct
 {
        CORE_ADDR next;
        CORE_ADDR previous;
-       CORE_ADDR unknown;
+       CORE_ADDR unknown1;
        char *module_name;
        CORE_ADDR modinfo_addr;
+       long module_id;
+       CORE_ADDR unknown2;
+       CORE_ADDR unknown3;
+       long region_count;
+       CORE_ADDR regioninfo_addr;
 } ldr_module_info_t;
 
+typedef struct
+{
+       long unknown1;
+       CORE_ADDR regionname_addr;
+       long protection;
+       CORE_ADDR vaddr;
+       CORE_ADDR mapaddr;
+       long size;
+       long unknown2[5];
+} ldr_region_info_t;
+
 typedef struct
 {
        CORE_ADDR unknown1;
@@ -68,20 +100,53 @@ typedef struct
 } ldr_context_t;
 
 static ldr_context_t ldr_context;
+
 #else
+
 #include <loader.h>
+static ldr_process_t fake_ldr_process;
+
+/* Called by ldr_* routines to read memory from the current target.  */
+
+static int ldr_read_memory PARAMS ((CORE_ADDR, char *, int, int));
+
+static int
+ldr_read_memory (memaddr, myaddr, len, readstring)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int readstring;
+{
+  int result;
+  char *buffer;
+
+  if (readstring)
+    {
+      target_read_string (memaddr, &buffer, len, &result);
+      if (result == 0)
+        strcpy (myaddr, buffer);
+      free (buffer);
+    }
+  else
+    result = target_read_memory (memaddr, myaddr, len);
+
+  if (result != 0)
+    result = -result;
+  return result;
+}
+
 #endif
 
 /* Define our own link_map structure.
    This will help to share code with solib.c.  */
 
 struct link_map {
-  CORE_ADDR l_addr;                    /* address at which object mapped */
+  CORE_ADDR l_offset;                  /* prelink to load address offset */
   char *l_name;                                /* full name of loaded object */
   ldr_module_info_t module_info;       /* corresponding module info */
 };
 
-#define LM_ADDR(so) ((so) -> lm.l_addr)
+#define LM_OFFSET(so) ((so) -> lm.l_offset)
 #define LM_NAME(so) ((so) -> lm.l_name)
 
 struct so_list {
@@ -209,10 +274,10 @@ solib_map_sections (so)
   for (p = so -> sections; p < so -> sections_end; p++)
     {
       /* Relocate the section binding addresses as recorded in the shared
-        object's file by the base address to which the object was actually
-        mapped. */
-      p -> addr += (CORE_ADDR) LM_ADDR (so);
-      p -> endaddr += (CORE_ADDR) LM_ADDR (so);
+        object's file by the offset to get the address to which the
+        object was actually mapped.  */
+      p -> addr += LM_OFFSET (so);
+      p -> endaddr += LM_OFFSET (so);
       so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
       if (STREQ (p -> the_bfd_section -> name, ".text"))
        {
@@ -251,9 +316,13 @@ first_link_map_member ()
   ldr_module_t mod_id = LDR_NULL_MODULE;
   size_t retsize;
 
-  if (ldr_next_module(inferior_pid, &mod_id) != 0
+  fake_ldr_process = ldr_core_process ();
+  ldr_set_core_reader (ldr_read_memory);
+  ldr_xdetach (fake_ldr_process);
+  if (ldr_xattach (fake_ldr_process) != 0
+      || ldr_next_module(fake_ldr_process, &mod_id) != 0
       || mod_id == LDR_NULL_MODULE
-      || ldr_inq_module(inferior_pid, mod_id,
+      || ldr_inq_module(fake_ldr_process, mod_id,
                        &first_lm.module_info, sizeof(ldr_module_info_t),
                        &retsize) != 0)
     return lm;
@@ -287,12 +356,12 @@ next_link_map_member (so_list_ptr)
   struct link_map *lm = NULL;
   static struct link_map next_lm;
 #ifdef USE_LDR_ROUTINES
-  ldr_module_t mod_id = lm->module_info.lmi_modid;
+  ldr_module_t mod_id = so_list_ptr->lm.module_info.lmi_modid;
   size_t retsize;
 
-  if (ldr_next_module(inferior_pid, &mod_id) != 0
+  if (ldr_next_module(fake_ldr_process, &mod_id) != 0
       || mod_id == LDR_NULL_MODULE
-      || ldr_inq_module(inferior_pid, mod_id,
+      || ldr_inq_module(fake_ldr_process, mod_id,
                        &next_lm.module_info, sizeof(ldr_module_info_t),
                        &retsize) != 0)
     return lm;
@@ -327,10 +396,21 @@ xfer_link_map_member (so_list_ptr, lm)
      struct so_list *so_list_ptr;
      struct link_map *lm;
 {
+  int i;
   so_list_ptr->lm = *lm;
 
-  /* OSF/1 has absolute addresses in shared libraries.  */
-  LM_ADDR (so_list_ptr) = 0;
+  /* OSF/1 shared libraries are pre-linked to particular addresses,
+     but the runtime loader may have to relocate them if the
+     address ranges of the libraries used by the target executable clash,
+     or if the target executable is linked with the -taso option.
+     The offset is the difference between the address where the shared
+     library is mapped and the pre-linked address of the shared library.
+
+     FIXME:  GDB is currently unable to relocate the shared library
+     sections by different offsets. If sections are relocated by
+     different offsets, put out a warning and use the offset of the
+     first section for all remaining sections.  */
+  LM_OFFSET (so_list_ptr) = 0;
 
   /* There is one entry that has no name (for the inferior executable)
      since it is not a shared object. */
@@ -343,6 +423,26 @@ xfer_link_map_member (so_list_ptr, lm)
       if (len > MAX_PATH_SIZE)
        len = MAX_PATH_SIZE;
       strncpy (so_list_ptr->so_name, LM_NAME (so_list_ptr), MAX_PATH_SIZE);
+      so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
+
+      for (i = 0; i < lm->module_info.lmi_nregion; i++)
+       {
+         ldr_region_info_t region_info;
+         size_t retsize;
+         CORE_ADDR region_offset;
+
+         if (ldr_inq_region (fake_ldr_process, lm->module_info.lmi_modid,
+                             i, &region_info, sizeof (region_info),
+                             &retsize) != 0)
+           break;
+         region_offset = (CORE_ADDR) region_info.lri_mapaddr
+                         - (CORE_ADDR) region_info.lri_vaddr;
+         if (i == 0)
+           LM_OFFSET (so_list_ptr) = region_offset;
+         else if (LM_OFFSET (so_list_ptr) != region_offset)
+           warning ("cannot handle shared library relocation for %s (%s)",
+                    so_list_ptr->so_name, region_info.lri_name);
+       }
 #else
       int errcode;
       char *buffer;
@@ -353,9 +453,37 @@ xfer_link_map_member (so_list_ptr, lm)
               safe_strerror (errcode));
       strncpy (so_list_ptr->so_name, buffer, MAX_PATH_SIZE - 1);
       free (buffer);
-#endif
       so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
 
+      for (i = 0; i < lm->module_info.region_count; i++)
+       {
+         ldr_region_info_t region_info;
+         CORE_ADDR region_offset;
+
+         if (target_read_memory (lm->module_info.regioninfo_addr
+                                  + i * sizeof (region_info),
+                                 (char *) &region_info,
+                                 sizeof (region_info)) != 0)
+           break;
+         region_offset = region_info.mapaddr - region_info.vaddr;
+         if (i == 0)
+           LM_OFFSET (so_list_ptr) = region_offset;
+         else if (LM_OFFSET (so_list_ptr) != region_offset)
+           {
+             char *region_name;
+             target_read_string (region_info.regionname_addr, &buffer,
+                                 MAX_PATH_SIZE - 1, &errcode);
+             if (errcode == 0)
+               region_name = buffer;
+             else
+               region_name = "??";
+             warning ("cannot handle shared library relocation for %s (%s)",
+                       so_list_ptr->so_name, region_name);
+             free (buffer);
+           }
+       }
+#endif
+
       solib_map_sections (so_list_ptr);
     }
 }
@@ -481,9 +609,7 @@ solib_add (arg_string, from_tty, target)
   
   
   /* Add the shared library sections to the section table of the
-     specified target, if any. We have to do this before reading the
-     symbol files as symbol_file_add calls reinit_frame_cache and
-     creating a new frame might access memory in the shared library.  */
+     specified target, if any.  */
   if (target)
     {
       /* Count how many new section_table entries there are.  */
@@ -554,6 +680,11 @@ solib_add (arg_string, from_tty, target)
            }
        }
     }
+
+  /* Getting new symbols may change our opinion about what is
+     frameless.  */
+  if (so_last)
+    reinit_frame_cache ();
 }
 
 /*
@@ -676,7 +807,9 @@ clear_solib()
       if (so_list_head -> abfd)
        {
          bfd_filename = bfd_get_filename (so_list_head -> abfd);
-         bfd_close (so_list_head -> abfd);
+         if (!bfd_close (so_list_head -> abfd))
+           warning ("cannot close \"%s\": %s",
+                    bfd_filename, bfd_errmsg (bfd_get_error ()));
        }
       else
        /* This happens for the executable on SVR4.  */
@@ -732,7 +865,9 @@ solib_create_inferior_hook()
 
   /* Nothing to do for statically bound executables.  */
 
-  if (symfile_objfile == 0 || symfile_objfile->ei.entry_file_lowpc == stop_pc)
+  if (symfile_objfile == NULL
+      || symfile_objfile->obfd == NULL
+      || ((bfd_get_file_flags (symfile_objfile->obfd) & DYNAMIC) == 0))
     return;
 
   /* Now run the target.  It will eventually get a SIGTRAP, at
@@ -750,12 +885,12 @@ solib_create_inferior_hook()
     }
   while (stop_signal != TARGET_SIGNAL_TRAP);
 
-  /*  solib_add will call reinit_frame_cache via symbol_file_add.
+  /*  solib_add will call reinit_frame_cache.
       But we are stopped in the runtime loader and we do not have symbols
       for the runtime loader. So heuristic_proc_start will be called
       and will put out an annoying warning.
-      Resetting stop_soon_quietly after symbol loading suppresses
-      the warning.  */
+      Delaying the resetting of stop_soon_quietly until after symbol loading
+      suppresses the warning.  */
   solib_add ((char *) 0, 0, (struct target_ops *) 0);
   stop_soon_quietly = 0;
 }
This page took 0.03262 seconds and 4 git commands to generate.