gdb/testsuite/
[binutils-gdb.git] / gdb / solib-svr4.c
index 2ae9b50eddbb81bc76b9f6b238b055f64142044c..d031303ec3775421651271e670e48ea2cf903c75 100644 (file)
@@ -243,12 +243,10 @@ LM_ADDR_CHECK (struct so_list *so, bfd *abfd)
              l_addr = l_dynaddr - dynaddr;
 
              if (info_verbose)
-               {
-                 warning (_(".dynamic section for \"%s\" "
-                            "is not at the expected address"), so->so_name);
-                 warning (_("difference appears to be caused by prelink, "
-                            "adjusting expectations"));
-               }
+               printf_unfiltered (_("Using PIC (Position Independent Code) "
+                                    "prelink displacement %s for \"%s\".\n"),
+                                  paddress (target_gdbarch, l_addr),
+                                  so->so_name);
            }
          else
            warning (_(".dynamic section for \"%s\" "
@@ -273,6 +271,16 @@ LM_NEXT (struct so_list *so)
                                ptr_type);
 }
 
+static CORE_ADDR
+LM_PREV (struct so_list *so)
+{
+  struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
+
+  return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
+                               ptr_type);
+}
+
 static CORE_ADDR
 LM_NAME (struct so_list *so)
 {
@@ -286,16 +294,12 @@ LM_NAME (struct so_list *so)
 static int
 IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so)
 {
-  struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
-  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
-
   /* Assume that everything is a library if the dynamic loader was loaded
      late by a static executable.  */
   if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
     return 0;
 
-  return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
-                               ptr_type) == 0;
+  return LM_PREV (so) == 0;
 }
 
 /* Per pspace SVR4 specific data.  */
@@ -577,7 +581,6 @@ find_program_interpreter (void)
      interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
      if (interp_sect != NULL)
       {
-       CORE_ADDR sect_addr = bfd_section_vma (exec_bfd, interp_sect);
        int sect_size = bfd_section_size (exec_bfd, interp_sect);
 
        buf = xmalloc (sect_size);
@@ -720,6 +723,7 @@ scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr)
     if (arch_size == 32)
       {
        Elf32_External_Dyn *dynp = (Elf32_External_Dyn *) buf;
+
        dyn_tag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag,
                                            4, byte_order);
        dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr,
@@ -728,6 +732,7 @@ scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr)
     else
       {
        Elf64_External_Dyn *dynp = (Elf64_External_Dyn *) buf;
+
        dyn_tag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag,
                                            8, byte_order);
        dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr,
@@ -790,6 +795,7 @@ elf_locate_base (void)
       struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
       gdb_byte *pbuf;
       int pbuf_size = TYPE_LENGTH (ptr_type);
+
       pbuf = alloca (pbuf_size);
       /* DT_MIPS_RLD_MAP contains a pointer to the address
         of the dynamic link structure.  */
@@ -865,7 +871,8 @@ locate_base (struct svr4_info *info)
 }
 
 /* Find the first element in the inferior's dynamic link map, and
-   return its address in the inferior.
+   return its address in the inferior.  Return zero if the address
+   could not be determined.
 
    FIXME: Perhaps we should validate the info somehow, perhaps by
    checking r_version for a known version number, or r_state for
@@ -1103,7 +1110,7 @@ svr4_default_sos (void)
 static struct so_list *
 svr4_current_sos (void)
 {
-  CORE_ADDR lm;
+  CORE_ADDR lm, prev_lm;
   struct so_list *head = 0;
   struct so_list **link_ptr = &head;
   CORE_ADDR ldsomap = 0;
@@ -1122,6 +1129,7 @@ svr4_current_sos (void)
 
   /* Walk the inferior's link map list, and build our list of
      `struct so_list' nodes.  */
+  prev_lm = 0;
   lm = solib_svr4_r_map (info);
 
   while (lm)
@@ -1129,6 +1137,7 @@ svr4_current_sos (void)
       struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
       struct so_list *new = XZALLOC (struct so_list);
       struct cleanup *old_chain = make_cleanup (xfree, new);
+      CORE_ADDR next_lm;
 
       new->lm_info = xmalloc (sizeof (struct lm_info));
       make_cleanup (xfree, new->lm_info);
@@ -1140,14 +1149,21 @@ svr4_current_sos (void)
 
       read_memory (lm, new->lm_info->lm, lmo->link_map_size);
 
-      lm = LM_NEXT (new);
+      next_lm = LM_NEXT (new);
+
+      if (LM_PREV (new) != prev_lm)
+       {
+         warning (_("Corrupted shared library list"));
+         free_so (new);
+         next_lm = 0;
+       }
 
       /* For SVR4 versions, the first entry in the link map is for the
          inferior executable, so we must ignore it.  For some versions of
          SVR4, it has no name.  For others (Solaris 2.3 for example), it
          does have a name, so we can no longer use a missing name to
          decide when to ignore it. */
-      if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
+      else if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
        {
          info->main_lm_addr = new->lm_info->lm_addr;
          free_so (new);
@@ -1184,12 +1200,18 @@ svr4_current_sos (void)
            }
        }
 
+      prev_lm = lm;
+      lm = next_lm;
+
       /* On Solaris, the dynamic linker is not in the normal list of
         shared objects, so make sure we pick it up too.  Having
         symbol information for the dynamic linker is quite crucial
         for skipping dynamic linker resolver code.  */
       if (lm == 0 && ldsomap == 0)
-       lm = ldsomap = solib_svr4_r_ldsomap (info);
+       {
+         lm = ldsomap = solib_svr4_r_ldsomap (info);
+         prev_lm = 0;
+       }
 
       discard_cleanups (old_chain);
     }
@@ -1500,6 +1522,7 @@ enable_break (struct svr4_info *info, int from_tty)
        {
          struct regcache *regcache
            = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
+
          load_addr = (regcache_read_pc (regcache)
                       - exec_entry_point (tmp_bfd, tmp_bfd_target));
        }
@@ -1659,7 +1682,10 @@ read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
   return buf;
 }
 
-/* We relocate all of the sections by the same amount.  This
+/* Return 1 and fill *DISPLACEMENTP with detected PIE offset of inferior
+   exec_bfd.  Otherwise return 0.
+
+   We relocate all of the sections by the same amount.  This
    behavior is mandated by recent editions of the System V ABI. 
    According to the System V Application Binary Interface,
    Edition 4.1, page 5-5:
@@ -1699,8 +1725,8 @@ read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
      should either be removed or modified to accomodate the new file
      type.  - Kevin, Nov 2000. ]  */
 
-static CORE_ADDR
-svr4_exec_displacement (void)
+static int
+svr4_exec_displacement (CORE_ADDR *displacementp)
 {
   /* ENTRY_POINT is a possible function descriptor - before
      a call to gdbarch_convert_from_func_ptr_addr.  */
@@ -1764,7 +1790,20 @@ svr4_exec_displacement (void)
        return 0;
     }
 
-  return displacement;
+  if (info_verbose)
+    {
+      /* It can be printed repeatedly as there is no easy way to check
+        the executable symbols/file has been already relocated to
+        displacement.  */
+
+      printf_unfiltered (_("Using PIE (Position Independent Executable) "
+                          "displacement %s for \"%s\".\n"),
+                        paddress (target_gdbarch, displacement),
+                        bfd_get_filename (exec_bfd));
+    }
+
+  *displacementp = displacement;
+  return 1;
 }
 
 /* Relocate the main executable.  This function should be called upon
@@ -1775,11 +1814,25 @@ svr4_exec_displacement (void)
 static void
 svr4_relocate_main_executable (void)
 {
-  CORE_ADDR displacement = svr4_exec_displacement ();
+  CORE_ADDR displacement;
+
+  if (symfile_objfile)
+    {
+      int i;
+
+      /* Remote target may have already set specific offsets by `qOffsets'
+        which should be preferred.  */
 
-  /* Even if DISPLACEMENT is 0 still try to relocate it as this is a new
-     difference of in-memory vs. in-file addresses and we could already
-     relocate the executable at this function to improper address before.  */
+      for (i = 0; i < symfile_objfile->num_sections; i++)
+       if (ANOFFSET (symfile_objfile->section_offsets, i) != 0)
+         return;
+    }
+
+  if (! svr4_exec_displacement (&displacement))
+    return;
+
+  /* Even DISPLACEMENT 0 is a valid new difference of in-memory vs. in-file
+     addresses.  */
 
   if (symfile_objfile)
     {
@@ -1860,8 +1913,10 @@ svr4_relocate_main_executable (void)
 static void
 svr4_solib_create_inferior_hook (int from_tty)
 {
+#if defined(_SCO_DS)
   struct inferior *inf;
   struct thread_info *tp;
+#endif /* defined(_SCO_DS) */
   struct svr4_info *info;
 
   info = get_svr4_info ();
@@ -2014,6 +2069,7 @@ static int
 svr4_have_link_map_offsets (void)
 {
   struct solib_svr4_ops *ops = gdbarch_data (target_gdbarch, solib_svr4_data);
+
   return (ops->fetch_link_map_offsets != NULL);
 }
 \f