* A few more improvements to gx jit prototype.
[deliverable/binutils-gdb.git] / gdb / solib.c
index 6f8c3760bc82b67611e9b308138e91f9251e2241..3f6e73002358c6f410de960e056c7eeb866dd791 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998
    Free Software Foundation, Inc.
    
 This file is part of GDB.
@@ -21,6 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 
+/* This file is only compilable if link.h is available. */
+
+#ifdef HAVE_LINK_H
+
 #include <sys/types.h>
 #include <signal.h>
 #include "gdb_string.h"
@@ -66,6 +70,7 @@ static char *solib_break_names[] = {
   "r_debug_state",
   "_r_debug_state",
   "_dl_debug_state",
+  "rtld_db_dlactivity",
   NULL
 };
 #endif
@@ -144,11 +149,19 @@ static struct so_list *so_list_head;      /* List of known shared objects */
 static CORE_ADDR debug_base;           /* Base of dynamic linker structures */
 static CORE_ADDR breakpoint_addr;      /* Address where end bkpt is set */
 
+static int solib_cleanup_queued = 0;    /* make_run_cleanup called */
+
 extern int
 fdmatch PARAMS ((int, int));           /* In libiberty */
 
 /* Local function prototypes */
 
+static void
+do_clear_solib PARAMS ((PTR));
+
+static int
+match_main PARAMS ((char *));
+
 static void
 special_symbol_handling PARAMS ((struct so_list *));
 
@@ -158,9 +171,6 @@ sharedlibrary_command PARAMS ((char *, int));
 static int
 enable_break PARAMS ((void));
 
-static int
-disable_break PARAMS ((void));
-
 static void
 info_sharedlibrary_command PARAMS ((char *, int));
 
@@ -176,8 +186,8 @@ first_link_map_member PARAMS ((void));
 static CORE_ADDR
 locate_base PARAMS ((void));
 
-static void
-solib_map_sections PARAMS ((struct so_list *));
+static int
+solib_map_sections PARAMS ((char *));
 
 #ifdef SVR4_SHARED_LIBS
 
@@ -186,6 +196,9 @@ elf_locate_base PARAMS ((void));
 
 #else
 
+static int
+disable_break PARAMS ((void));
+
 static void
 allocate_rt_common_objfile PARAMS ((void));
 
@@ -194,6 +207,15 @@ solib_add_common_symbols PARAMS ((struct rtc_symb *));
 
 #endif
 
+/* If non-zero, this is a prefix that will be added to the front of the name
+   shared libraries with an absolute filename for loading.  */
+static char *solib_absolute_prefix = NULL;
+
+/* If non-empty, this is a search path for loading non-absolute shared library
+   symbol files.  This takes precedence over the environment variables PATH
+   and LD_LIBRARY_PATH.  */
+static char *solib_search_path = NULL;
+
 /*
 
 LOCAL FUNCTION
@@ -202,7 +224,7 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static void solib_map_sections (struct so_list *so)
+       static int solib_map_sections (struct so_list *so)
 
 DESCRIPTION
 
@@ -221,10 +243,11 @@ FIXMES
        expansion stuff?).
  */
 
-static void
-solib_map_sections (so)
-     struct so_list *so;
+static int
+solib_map_sections (arg)
+     char *arg;
 {
+  struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
   char *filename;
   char *scratch_pathname;
   int scratch_chan;
@@ -233,10 +256,38 @@ solib_map_sections (so)
   bfd *abfd;
   
   filename = tilde_expand (so -> so_name);
-  old_chain = make_cleanup (free, filename);
   
-  scratch_chan = openp (get_in_environ (inferior_environ, "PATH"), 
-                       1, filename, O_RDONLY, 0, &scratch_pathname);
+  if (solib_absolute_prefix && ROOTED_P (filename))
+    /* Prefix shared libraries with absolute filenames with
+       SOLIB_ABSOLUTE_PREFIX.  */
+    {
+      char *pfxed_fn;
+      int pfx_len;
+
+      pfx_len = strlen (solib_absolute_prefix);
+
+      /* Remove trailing slashes.  */
+      while (pfx_len > 0 && SLASH_P (solib_absolute_prefix[pfx_len - 1]))
+       pfx_len--;
+
+      pfxed_fn = xmalloc (pfx_len + strlen (filename) + 1);
+      strcpy (pfxed_fn, solib_absolute_prefix);
+      strcat (pfxed_fn, filename);
+      free (filename);
+
+      filename = pfxed_fn;
+    }
+
+  old_chain = make_cleanup (free, filename);
+
+  scratch_chan = -1;
+
+  if (solib_search_path)
+    scratch_chan = openp (solib_search_path,
+                         1, filename, O_RDONLY, 0, &scratch_pathname);
+  if (scratch_chan < 0)
+    scratch_chan = openp (get_in_environ (inferior_environ, "PATH"), 
+                         1, filename, O_RDONLY, 0, &scratch_pathname);
   if (scratch_chan < 0)
     {
       scratch_chan = openp (get_in_environ 
@@ -293,6 +344,8 @@ solib_map_sections (so)
 
   /* Free the file names, close the file now.  */
   do_cleanups (old_chain);
+
+  return (1);
 }
 
 #ifndef SVR4_SHARED_LIBS
@@ -346,7 +399,6 @@ solib_add_common_symbols (rtc_symp)
   struct nlist inferior_rtc_nlist;
   int len;
   char *name;
-  char *origname;
 
   /* Remove any runtime common symbols from previous runs.  */
 
@@ -377,18 +429,16 @@ solib_add_common_symbols (rtc_symp)
             behind the name of the symbol. */
          len = inferior_rtc_nlist.n_value - inferior_rtc_nlist.n_un.n_strx;
 
-         origname = name = xmalloc (len);
+         name = xmalloc (len);
          read_memory ((CORE_ADDR) inferior_rtc_nlist.n_un.n_name, name, len);
 
          /* Allocate the runtime common objfile if necessary. */
          if (rt_common_objfile == NULL)
            allocate_rt_common_objfile ();
 
-         name = obsavestring (name, strlen (name),
-                              &rt_common_objfile -> symbol_obstack);
          prim_record_minimal_symbol (name, inferior_rtc_nlist.n_value,
                                      mst_bss, rt_common_objfile);
-         free (origname);
+         free (name);
        }
       rtc_symp = inferior_rtc_symb.rtc_next;
     }
@@ -641,8 +691,7 @@ elf_locate_base ()
   /* Find the DT_DEBUG entry in the the .dynamic section.
      For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
      no DT_DEBUG entries.  */
-  /* FIXME: In lack of a 64 bit ELF ABI the following code assumes
-     a 32 bit ELF ABI target.  */
+#ifndef TARGET_ELF64
   for (bufend = buf + dyninfo_sect_size;
        buf < bufend;
        buf += sizeof (Elf32_External_Dyn))
@@ -673,6 +722,25 @@ elf_locate_base ()
        }
 #endif
     }
+#else /* ELF64 */
+  for (bufend = buf + dyninfo_sect_size;
+       buf < bufend;
+       buf += sizeof (Elf64_External_Dyn))
+    {
+      Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *)buf;
+      long dyn_tag;
+      CORE_ADDR dyn_ptr;
+
+      dyn_tag = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
+      if (dyn_tag == DT_NULL)
+       break;
+      else if (dyn_tag == DT_DEBUG)
+       {
+         dyn_ptr = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
+         return dyn_ptr;
+       }
+    }
+#endif
 
   /* DT_DEBUG entry not found.  */
   return 0;
@@ -756,7 +824,7 @@ locate_base ()
        debug_base = elf_locate_base ();
 #ifdef HANDLE_SVR4_EXEC_EMULATORS
       /* Try it the hard way for emulated executables.  */
-      else if (inferior_pid != 0)
+      else if (inferior_pid != 0 && target_has_execution)
        proc_iterate_over_mappings (look_for_base);
 #endif
     }
@@ -898,6 +966,13 @@ find_solib (so_list_ptr)
       else
        {
          so_list_head = new;
+
+         if (! solib_cleanup_queued)
+           {
+             make_run_cleanup (do_clear_solib);
+             solib_cleanup_queued = 1;
+           }
+         
        }      
       so_list_next = new;
       read_memory ((CORE_ADDR) lm, (char *) &(new -> lm),
@@ -914,12 +989,17 @@ find_solib (so_list_ptr)
          target_read_string ((CORE_ADDR) LM_NAME (new), &buffer,
                              MAX_PATH_SIZE - 1, &errcode);
          if (errcode != 0)
-           error ("find_solib: Can't read pathname for load map: %s\n",
-                  safe_strerror (errcode));
+           {
+             warning ("find_solib: Can't read pathname for load map: %s\n",
+                      safe_strerror (errcode));
+             return (so_list_next);
+           }
          strncpy (new -> so_name, buffer, MAX_PATH_SIZE - 1);
          new -> so_name[MAX_PATH_SIZE - 1] = '\0';
          free (buffer);
-         solib_map_sections (new);
+         catch_errors (solib_map_sections, (char *) new,
+                       "Error while mapping shared library sections:\n",
+                       RETURN_MASK_ALL);
        }      
     }
   return (so_list_next);
@@ -932,12 +1012,34 @@ symbol_add_stub (arg)
      char *arg;
 {
   register struct so_list *so = (struct so_list *) arg;        /* catch_errs bogon */
+  CORE_ADDR text_addr = 0;
+
+  if (so -> textsection)
+    text_addr = so -> textsection -> addr;
+  else if (so -> abfd != NULL)
+    {
+      asection *lowest_sect;
+
+      /* If we didn't find a mapped non zero sized .text section, set up
+        text_addr so that the relocation in symbol_file_add does no harm.  */
+
+      lowest_sect = bfd_get_section_by_name (so -> abfd, ".text");
+      if (lowest_sect == NULL)
+       bfd_map_over_sections (so -> abfd, find_lowest_section,
+                              (PTR) &lowest_sect);
+      if (lowest_sect)
+       text_addr = bfd_section_vma (so -> abfd, lowest_sect)
+                   + (CORE_ADDR) LM_ADDR (so);
+    }
   
+  ALL_OBJFILES (so -> objfile)
+    {
+      if (strcmp (so -> objfile -> name, so -> so_name) == 0)
+       return 1;
+    }
   so -> objfile =
     symbol_file_add (so -> so_name, so -> from_tty,
-                    (so->textsection == NULL
-                     ? 0
-                     : (unsigned int) so -> textsection -> addr),
+                    text_addr,
                     0, 0, 0);
   return (1);
 }
@@ -1114,30 +1216,41 @@ info_sharedlibrary_command (ignore, from_tty)
 {
   register struct so_list *so = NULL;          /* link map state variable */
   int header_done = 0;
-  
+  int addr_width;
+  char *addr_fmt;
+
   if (exec_bfd == NULL)
     {
       printf_unfiltered ("No exec file.\n");
       return;
     }
+
+#ifndef TARGET_ELF64
+  addr_width = 8+4;
+  addr_fmt = "08l";
+#else
+  addr_width = 16+4;
+  addr_fmt = "016l";
+#endif
+
   while ((so = find_solib (so)) != NULL)
     {
       if (so -> so_name[0])
        {
          if (!header_done)
            {
-             printf_unfiltered("%-12s%-12s%-12s%s\n", "From", "To", "Syms Read",
-                    "Shared Object Library");
+             printf_unfiltered("%-*s%-*s%-12s%s\n", addr_width, "From",
+                               addr_width, "To", "Syms Read",
+                               "Shared Object Library");
              header_done++;
            }
-         /* FIXME-32x64: need print_address_numeric with field width or
-            some such.  */
-         printf_unfiltered ("%-12s",
+
+         printf_unfiltered ("%-*s", addr_width,
                  local_hex_string_custom ((unsigned long) LM_ADDR (so),
-                                          "08l"));
-         printf_unfiltered ("%-12s",
+                                          addr_fmt));
+         printf_unfiltered ("%-*s", addr_width,
                  local_hex_string_custom ((unsigned long) so -> lmend,
-                                          "08l"));
+                                          addr_fmt));
          printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
          printf_unfiltered ("%s\n",  so -> so_name);
        }
@@ -1224,6 +1337,34 @@ clear_solib()
   debug_base = 0;
 }
 
+static void
+do_clear_solib (dummy)
+     PTR dummy;
+{
+  solib_cleanup_queued = 0;
+  clear_solib ();
+}
+
+#ifdef SVR4_SHARED_LIBS
+
+/* Return 1 if PC lies in the dynamic symbol resolution code of the
+   SVR4 run time loader.  */
+
+static CORE_ADDR interp_text_sect_low;
+static CORE_ADDR interp_text_sect_high;
+static CORE_ADDR interp_plt_sect_low;
+static CORE_ADDR interp_plt_sect_high;
+
+int
+in_svr4_dynsym_resolve_code (pc)
+     CORE_ADDR pc;
+{
+  return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
+         || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
+         || in_plt_section (pc, NULL));
+}
+#endif
+
 /*
 
 LOCAL FUNCTION
@@ -1241,6 +1382,8 @@ DESCRIPTION
 
 */
 
+#ifndef SVR4_SHARED_LIBS
+
 static int
 disable_break ()
 {
@@ -1289,6 +1432,8 @@ disable_break ()
   return (status);
 }
 
+#endif /* #ifdef SVR4_SHARED_LIBS */
+
 /*
 
 LOCAL FUNCTION
@@ -1380,6 +1525,9 @@ enable_break ()
   remove_solib_event_breakpoints ();
 
 #ifdef SVR4_SHARED_LIBS
+  interp_text_sect_low = interp_text_sect_high = 0;
+  interp_plt_sect_low = interp_plt_sect_high = 0;
+
   /* Find the .interp section; if not found, warn the user and drop
      into the old breakpoint at symbol code.  */
   interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
@@ -1404,7 +1552,7 @@ enable_break ()
 
         This address is stored on the stack.  However, I've been unable
         to find any magic formula to find it for Solaris (appears to
-        be trivial on Linux).  Therefore, we have to try an alternate
+        be trivial on GNU/Linux).  Therefore, we have to try an alternate
         mechanism to find the dynamic linker's base address.  */
       tmp_bfd = bfd_openr (buf, gnutarget);
       if (tmp_bfd == NULL)
@@ -1423,6 +1571,25 @@ enable_break ()
         linker) and subtracting the offset of the entry point.  */
       load_addr = read_pc () - tmp_bfd->start_address;
 
+      /* Record the relocated start and end address of the dynamic linker
+        text and plt section for in_svr4_dynsym_resolve_code.  */
+      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+      if (interp_sect)
+       {
+         interp_text_sect_low =
+           bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+         interp_text_sect_high =
+           interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+       }
+      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+      if (interp_sect)
+       {
+         interp_plt_sect_low =
+           bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+         interp_plt_sect_high =
+           interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+       }
+
       /* Now try to set a breakpoint in the dynamic linker.  */
       for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
        {
@@ -1443,9 +1610,7 @@ enable_break ()
       /* For whatever reason we couldn't set a breakpoint in the dynamic
         linker.  Warn and drop into the old code.  */
 bkpt_at_symbol:
-      warning ("Unable to find dynamic linker breakpoint function.");
-      warning ("GDB will be unable to debug shared library initializers");
-      warning ("and track explicitly loaded dynamic code.");
+      warning ("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code.");
     }
 #endif
 
@@ -1464,7 +1629,7 @@ bkpt_at_symbol:
     }
 
   /* Nothing good happened.  */
-  return 0;
+  success = 0;
 
 #endif /* BKPT_AT_SYMBOL */
 
@@ -1546,8 +1711,8 @@ solib_create_inferior_hook()
       return;
     }
 
-#ifndef SVR4_SHARED_LIBS
-  /* Only SunOS needs the loop below, other systems should be using the
+#if !defined(SVR4_SHARED_LIBS) || defined(_SCO_DS)
+  /* SCO and SunOS need the loop below, other systems should be using the
      special shared library breakpoints and the shared library breakpoint
      service routine.
 
@@ -1566,7 +1731,8 @@ solib_create_inferior_hook()
     }
   while (stop_signal != TARGET_SIGNAL_TRAP);
   stop_soon_quietly = 0;
-  
+
+#if !defined(_SCO_DS)
   /* We are now either at the "mapping complete" breakpoint (or somewhere
      else, a condition we aren't prepared to deal with anyway), so adjust
      the PC as necessary after a breakpoint, disable the breakpoint, and
@@ -1585,6 +1751,7 @@ solib_create_inferior_hook()
 
   if (auto_solib_add)
     solib_add ((char *) 0, 0, (struct target_ops *) 0);
+#endif /* ! _SCO_DS */
 #endif
 }
 
@@ -1679,10 +1846,13 @@ int from_tty;
   solib_add (args, from_tty, (struct target_ops *) 0);
 }
 
+#endif /* HAVE_LINK_H */
+
 void
 _initialize_solib()
 {
-  
+#ifdef HAVE_LINK_H
+
   add_com ("sharedlibrary", class_files, sharedlibrary_command,
           "Load shared object library symbols for files matching REGEXP.");
   add_info ("sharedlibrary", info_sharedlibrary_command, 
@@ -1698,4 +1868,21 @@ informs gdb that a new library has been loaded.  Otherwise, symbols\n\
 must be loaded manually, using `sharedlibrary'.",
                  &setlist),
      &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("solib-absolute-prefix", class_support, var_filename,
+                 (char *) &solib_absolute_prefix,
+                 "Set prefix for loading absolute shared library symbol files.\n\
+For other (relative) files, you can add values using `set solib-search-path'.",
+                 &setlist),
+     &showlist);
+  add_show_from_set
+    (add_set_cmd ("solib-search-path", class_support, var_string,
+                 (char *) &solib_search_path,
+                 "Set the search path for loading non-absolute shared library symbol files.\n\
+This takes precedence over the environment variables PATH and LD_LIBRARY_PATH.",
+                 &setlist),
+     &showlist);
+
+#endif /* HAVE_LINK_H */
 }
This page took 0.029385 seconds and 4 git commands to generate.