2011-02-28 Michael Snyder <msnyder@vmware.com>
[deliverable/binutils-gdb.git] / gdb / solib-svr4.c
index 2ae9b50eddbb81bc76b9f6b238b055f64142044c..432da9963ebe1b0c14797e6a21e7a112ada13b28 100644 (file)
@@ -1,7 +1,7 @@
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
-   2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -52,7 +52,7 @@ static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static int svr4_have_link_map_offsets (void);
 static void svr4_relocate_main_executable (void);
 
-/* Link map info to include in an allocated so_list entry */
+/* Link map info to include in an allocated so_list entry */
 
 struct lm_info
   {
@@ -80,7 +80,7 @@ struct lm_info
    SVR4 systems will fall back to using a symbol as the "startup
    mapping complete" breakpoint address.  */
 
-static char *solib_break_names[] =
+static const char * const solib_break_names[] =
 {
   "r_debug_state",
   "_r_debug_state",
@@ -92,7 +92,7 @@ static char *solib_break_names[] =
   NULL
 };
 
-static char *bkpt_names[] =
+static const char * const bkpt_names[] =
 {
   "_start",
   "__start",
@@ -100,7 +100,7 @@ static char *bkpt_names[] =
   NULL
 };
 
-static char *main_name_list[] =
+static const  char * const main_name_list[] =
 {
   "main_$main",
   NULL
@@ -140,7 +140,7 @@ svr4_same (struct so_list *gdb, struct so_list *inferior)
   return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
 }
 
-/* link map access functions */
+/* link map access functions */
 
 static CORE_ADDR
 LM_ADDR_FROM_LINK_MAP (struct so_list *so)
@@ -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,23 +294,19 @@ 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.  */
 
 struct svr4_info
 {
-  CORE_ADDR debug_base;        /* Base of dynamic linker structures */
+  CORE_ADDR debug_base;        /* Base of dynamic linker structures */
 
   /* Validity flag for debug_loader_offset.  */
   int debug_loader_offset_p;
@@ -353,9 +357,7 @@ get_svr4_info (void)
 
 /* Local function prototypes */
 
-static int match_main (char *);
-
-static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
+static int match_main (const char *);
 
 /*
 
@@ -383,7 +385,7 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
  */
 
 static CORE_ADDR
-bfd_lookup_symbol (bfd *abfd, char *symname)
+bfd_lookup_symbol (bfd *abfd, const char *symname)
 {
   long storage_needed;
   asymbol *sym;
@@ -577,7 +579,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);
@@ -593,7 +594,7 @@ find_program_interpreter (void)
 }
 
 
-/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is
+/* Scan for DYNTAG in .dynamic section of ABFD.  If DYNTAG is found 1 is
    returned and the corresponding PTR is set.  */
 
 static int
@@ -720,6 +721,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 +730,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 +793,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 +869,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
@@ -987,7 +992,7 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
   If FROM_TTYP dereferences to a non-zero integer, allow messages to
   be printed.  This parameter is a pointer rather than an int because
   open_symbol_file_object() is called via catch_errors() and
-  catch_errors() requires a pointer argument. */
+  catch_errors() requires a pointer argument.  */
 
 static int
 open_symbol_file_object (void *from_ttyp)
@@ -1010,12 +1015,12 @@ open_symbol_file_object (void *from_ttyp)
   /* Always locate the debug struct, in case it has moved.  */
   info->debug_base = 0;
   if (locate_base (info) == 0)
-    return 0;  /* failed somehow... */
+    return 0;  /* failed somehow...  */
 
   /* First link map member should be the executable.  */
   lm = solib_svr4_r_map (info);
   if (lm == 0)
-    return 0;  /* failed somehow... */
+    return 0;  /* failed somehow...  */
 
   /* Read address of name from target memory to GDB.  */
   read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size);
@@ -1103,7 +1108,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 +1127,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 +1135,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 +1147,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)
+         decide when to ignore it.  */
+      else if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
        {
          info->main_lm_addr = new->lm_info->lm_addr;
          free_so (new);
@@ -1184,12 +1198,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);
     }
@@ -1231,9 +1251,9 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
    non-zero iff SONAME matches one of the known main executable names.  */
 
 static int
-match_main (char *soname)
+match_main (const char *soname)
 {
-  char **mainp;
+  const char * const *mainp;
 
   for (mainp = main_name_list; *mainp != NULL; mainp++)
     {
@@ -1325,7 +1345,7 @@ static int
 enable_break (struct svr4_info *info, int from_tty)
 {
   struct minimal_symbol *msymbol;
-  char **bkpt_namep;
+  const char * const *bkpt_namep;
   asection *interp_sect;
   gdb_byte *interp_name;
   CORE_ADDR sym_addr;
@@ -1349,8 +1369,8 @@ enable_break (struct svr4_info *info, int from_tty)
 
       sym_addr = gdbarch_addr_bits_remove
        (target_gdbarch, gdbarch_convert_from_func_ptr_addr (target_gdbarch,
-                                                             sym_addr,
-                                                             &current_target));
+                                                            sym_addr,
+                                                            &current_target));
 
       /* On at least some versions of Solaris there's a dynamic relocation
         on _r_debug.r_brk and SYM_ADDR may not be relocated yet, e.g., if
@@ -1500,6 +1520,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));
        }
@@ -1586,17 +1607,20 @@ enable_break (struct svr4_info *info, int from_tty)
        }
     }
 
-  for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
+  if (!current_inferior ()->attach_flag)
     {
-      msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
-      if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+      for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
        {
-         sym_addr = SYMBOL_VALUE_ADDRESS (msymbol);
-         sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
-                                                        sym_addr,
-                                                        &current_target);
-         create_solib_event_breakpoint (target_gdbarch, sym_addr);
-         return 1;
+         msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
+         if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+           {
+             sym_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+             sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
+                                                            sym_addr,
+                                                            &current_target);
+             create_solib_event_breakpoint (target_gdbarch, sym_addr);
+             return 1;
+           }
        }
     }
   return 0;
@@ -1630,7 +1654,6 @@ enable_break (struct svr4_info *info, int from_tty)
 static void
 svr4_special_symbol_handling (void)
 {
-  svr4_relocate_main_executable ();
 }
 
 /* Read the ELF program headers from ABFD.  Return the contents and
@@ -1659,8 +1682,11 @@ read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
   return buf;
 }
 
-/* We relocate all of the sections by the same amount.  This
-   behavior is mandated by recent editions of the System V ABI. 
+/* 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.  */
@@ -1749,13 +1775,251 @@ svr4_exec_displacement (void)
         really do not match.  */
       int phdrs_size, phdrs2_size, ok = 1;
       gdb_byte *buf, *buf2;
+      int arch_size;
 
-      buf = read_program_header (-1, &phdrs_size, NULL);
+      buf = read_program_header (-1, &phdrs_size, &arch_size);
       buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
-      if (buf != NULL && buf2 != NULL
-         && (phdrs_size != phdrs2_size
-             || memcmp (buf, buf2, phdrs_size) != 0))
-       ok = 0;
+      if (buf != NULL && buf2 != NULL)
+       {
+         enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+
+         /* We are dealing with three different addresses.  EXEC_BFD
+            represents current address in on-disk file.  target memory content
+            may be different from EXEC_BFD as the file may have been prelinked
+            to a different address after the executable has been loaded.
+            Moreover the address of placement in target memory can be
+            different from what the program headers in target memory say -
+            this is the goal of PIE.
+
+            Detected DISPLACEMENT covers both the offsets of PIE placement and
+            possible new prelink performed after start of the program.  Here
+            relocate BUF and BUF2 just by the EXEC_BFD vs. target memory
+            content offset for the verification purpose.  */
+
+         if (phdrs_size != phdrs2_size
+             || bfd_get_arch_size (exec_bfd) != arch_size)
+           ok = 0;
+         else if (arch_size == 32
+                  && phdrs_size >= sizeof (Elf32_External_Phdr)
+                  && phdrs_size % sizeof (Elf32_External_Phdr) == 0)
+           {
+             Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
+             Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
+             CORE_ADDR displacement = 0;
+             int i;
+
+             /* DISPLACEMENT could be found more easily by the difference of
+                ehdr2->e_entry.  But we haven't read the ehdr yet, and we
+                already have enough information to compute that displacement
+                with what we've read.  */
+
+             for (i = 0; i < ehdr2->e_phnum; i++)
+               if (phdr2[i].p_type == PT_LOAD)
+                 {
+                   Elf32_External_Phdr *phdrp;
+                   gdb_byte *buf_vaddr_p, *buf_paddr_p;
+                   CORE_ADDR vaddr, paddr;
+                   CORE_ADDR displacement_vaddr = 0;
+                   CORE_ADDR displacement_paddr = 0;
+
+                   phdrp = &((Elf32_External_Phdr *) buf)[i];
+                   buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+                   buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+
+                   vaddr = extract_unsigned_integer (buf_vaddr_p, 4,
+                                                     byte_order);
+                   displacement_vaddr = vaddr - phdr2[i].p_vaddr;
+
+                   paddr = extract_unsigned_integer (buf_paddr_p, 4,
+                                                     byte_order);
+                   displacement_paddr = paddr - phdr2[i].p_paddr;
+
+                   if (displacement_vaddr == displacement_paddr)
+                     displacement = displacement_vaddr;
+
+                   break;
+                 }
+
+             /* Now compare BUF and BUF2 with optional DISPLACEMENT.  */
+
+             for (i = 0; i < phdrs_size / sizeof (Elf32_External_Phdr); i++)
+               {
+                 Elf32_External_Phdr *phdrp;
+                 Elf32_External_Phdr *phdr2p;
+                 gdb_byte *buf_vaddr_p, *buf_paddr_p;
+                 CORE_ADDR vaddr, paddr;
+                 asection *plt2_asect;
+
+                 phdrp = &((Elf32_External_Phdr *) buf)[i];
+                 buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+                 buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+                 phdr2p = &((Elf32_External_Phdr *) buf2)[i];
+
+                 /* PT_GNU_STACK is an exception by being never relocated by
+                    prelink as its addresses are always zero.  */
+
+                 if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+                   continue;
+
+                 /* Check also other adjustment combinations - PR 11786.  */
+
+                 vaddr = extract_unsigned_integer (buf_vaddr_p, 4,
+                                                   byte_order);
+                 vaddr -= displacement;
+                 store_unsigned_integer (buf_vaddr_p, 4, byte_order, vaddr);
+
+                 paddr = extract_unsigned_integer (buf_paddr_p, 4,
+                                                   byte_order);
+                 paddr -= displacement;
+                 store_unsigned_integer (buf_paddr_p, 4, byte_order, paddr);
+
+                 if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+                   continue;
+
+                 /* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS.  */
+                 plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt");
+                 if (plt2_asect)
+                   {
+                     int content2;
+                     gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz;
+                     CORE_ADDR filesz;
+
+                     content2 = (bfd_get_section_flags (exec_bfd, plt2_asect)
+                                 & SEC_HAS_CONTENTS) != 0;
+
+                     filesz = extract_unsigned_integer (buf_filesz_p, 4,
+                                                        byte_order);
+
+                     /* PLT2_ASECT is from on-disk file (exec_bfd) while
+                        FILESZ is from the in-memory image.  */
+                     if (content2)
+                       filesz += bfd_get_section_size (plt2_asect);
+                     else
+                       filesz -= bfd_get_section_size (plt2_asect);
+
+                     store_unsigned_integer (buf_filesz_p, 4, byte_order,
+                                             filesz);
+
+                     if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+                       continue;
+                   }
+
+                 ok = 0;
+                 break;
+               }
+           }
+         else if (arch_size == 64
+                  && phdrs_size >= sizeof (Elf64_External_Phdr)
+                  && phdrs_size % sizeof (Elf64_External_Phdr) == 0)
+           {
+             Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
+             Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
+             CORE_ADDR displacement = 0;
+             int i;
+
+             /* DISPLACEMENT could be found more easily by the difference of
+                ehdr2->e_entry.  But we haven't read the ehdr yet, and we
+                already have enough information to compute that displacement
+                with what we've read.  */
+
+             for (i = 0; i < ehdr2->e_phnum; i++)
+               if (phdr2[i].p_type == PT_LOAD)
+                 {
+                   Elf64_External_Phdr *phdrp;
+                   gdb_byte *buf_vaddr_p, *buf_paddr_p;
+                   CORE_ADDR vaddr, paddr;
+                   CORE_ADDR displacement_vaddr = 0;
+                   CORE_ADDR displacement_paddr = 0;
+
+                   phdrp = &((Elf64_External_Phdr *) buf)[i];
+                   buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+                   buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+
+                   vaddr = extract_unsigned_integer (buf_vaddr_p, 8,
+                                                     byte_order);
+                   displacement_vaddr = vaddr - phdr2[i].p_vaddr;
+
+                   paddr = extract_unsigned_integer (buf_paddr_p, 8,
+                                                     byte_order);
+                   displacement_paddr = paddr - phdr2[i].p_paddr;
+
+                   if (displacement_vaddr == displacement_paddr)
+                     displacement = displacement_vaddr;
+
+                   break;
+                 }
+
+             /* Now compare BUF and BUF2 with optional DISPLACEMENT.  */
+
+             for (i = 0; i < phdrs_size / sizeof (Elf64_External_Phdr); i++)
+               {
+                 Elf64_External_Phdr *phdrp;
+                 Elf64_External_Phdr *phdr2p;
+                 gdb_byte *buf_vaddr_p, *buf_paddr_p;
+                 CORE_ADDR vaddr, paddr;
+                 asection *plt2_asect;
+
+                 phdrp = &((Elf64_External_Phdr *) buf)[i];
+                 buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+                 buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+                 phdr2p = &((Elf64_External_Phdr *) buf2)[i];
+
+                 /* PT_GNU_STACK is an exception by being never relocated by
+                    prelink as its addresses are always zero.  */
+
+                 if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+                   continue;
+
+                 /* Check also other adjustment combinations - PR 11786.  */
+
+                 vaddr = extract_unsigned_integer (buf_vaddr_p, 8,
+                                                   byte_order);
+                 vaddr -= displacement;
+                 store_unsigned_integer (buf_vaddr_p, 8, byte_order, vaddr);
+
+                 paddr = extract_unsigned_integer (buf_paddr_p, 8,
+                                                   byte_order);
+                 paddr -= displacement;
+                 store_unsigned_integer (buf_paddr_p, 8, byte_order, paddr);
+
+                 if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+                   continue;
+
+                 /* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS.  */
+                 plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt");
+                 if (plt2_asect)
+                   {
+                     int content2;
+                     gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz;
+                     CORE_ADDR filesz;
+
+                     content2 = (bfd_get_section_flags (exec_bfd, plt2_asect)
+                                 & SEC_HAS_CONTENTS) != 0;
+
+                     filesz = extract_unsigned_integer (buf_filesz_p, 8,
+                                                        byte_order);
+
+                     /* PLT2_ASECT is from on-disk file (exec_bfd) while
+                        FILESZ is from the in-memory image.  */
+                     if (content2)
+                       filesz += bfd_get_section_size (plt2_asect);
+                     else
+                       filesz -= bfd_get_section_size (plt2_asect);
+
+                     store_unsigned_integer (buf_filesz_p, 8, byte_order,
+                                             filesz);
+
+                     if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+                       continue;
+                   }
+
+                 ok = 0;
+                 break;
+               }
+           }
+         else
+           ok = 0;
+       }
 
       xfree (buf);
       xfree (buf2);
@@ -1764,22 +2028,63 @@ 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
-   stopping the inferior process at the entry point to the program. 
+   stopping the inferior process at the entry point to the program.
    The entry point from BFD is compared to the AT_ENTRY of AUXV and if they are
    different, the main executable is relocated by the proper amount.  */
 
 static void
 svr4_relocate_main_executable (void)
 {
-  CORE_ADDR displacement = svr4_exec_displacement ();
+  CORE_ADDR displacement;
+
+  /* If we are re-running this executable, SYMFILE_OBJFILE->SECTION_OFFSETS
+     probably contains the offsets computed using the PIE displacement
+     from the previous run, which of course are irrelevant for this run.
+     So we need to determine the new PIE displacement and recompute the
+     section offsets accordingly, even if SYMFILE_OBJFILE->SECTION_OFFSETS
+     already contains pre-computed offsets.
+
+     If we cannot compute the PIE displacement, either:
 
-  /* 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.  */
+       - The executable is not PIE.
+
+       - SYMFILE_OBJFILE does not match the executable started in the target.
+        This can happen for main executable symbols loaded at the host while
+        `ld.so --ld-args main-executable' is loaded in the target.
+
+     Then we leave the section offsets untouched and use them as is for
+     this run.  Either:
+
+       - These section offsets were properly reset earlier, and thus
+        already contain the correct values.  This can happen for instance
+        when reconnecting via the remote protocol to a target that supports
+        the `qOffsets' packet.
+
+       - The section offsets were not reset earlier, and the best we can
+        hope is that the old offsets are still applicable to the new run.  */
+
+  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,15 +2165,16 @@ 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 ();
 
   /* Relocate the main executable if necessary.  */
-  if (current_inferior ()->attach_flag == 0)
-    svr4_relocate_main_executable ();
+  svr4_relocate_main_executable ();
 
   if (!svr4_have_link_map_offsets ())
     return;
@@ -1884,21 +2190,21 @@ svr4_solib_create_inferior_hook (int from_tty)
      Now run the target.  It will eventually hit the breakpoint, at
      which point all of the libraries will have been mapped in and we
      can go groveling around in the dynamic linker structures to find
-     out what we need to know about them. */
+     out what we need to know about them.  */
 
   inf = current_inferior ();
   tp = inferior_thread ();
 
   clear_proceed_status ();
-  inf->stop_soon = STOP_QUIETLY;
-  tp->stop_signal = TARGET_SIGNAL_0;
+  inf->control.stop_soon = STOP_QUIETLY;
+  tp->suspend.stop_signal = TARGET_SIGNAL_0;
   do
     {
-      target_resume (pid_to_ptid (-1), 0, tp->stop_signal);
+      target_resume (pid_to_ptid (-1), 0, tp->suspend.stop_signal);
       wait_for_inferior (0);
     }
-  while (tp->stop_signal != TARGET_SIGNAL_TRAP);
-  inf->stop_soon = NO_STOP_QUIETLY;
+  while (tp->suspend.stop_signal != TARGET_SIGNAL_TRAP);
+  inf->control.stop_soon = NO_STOP_QUIETLY;
 #endif /* defined(_SCO_DS) */
 }
 
@@ -2014,6 +2320,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
@@ -2087,7 +2394,7 @@ svr4_lp64_fetch_link_map_offsets (void)
 
 struct target_so_ops svr4_so_ops;
 
-/* Lookup global symbol for ELF DSOs linked with -Bsymbolic. Those DSOs have a
+/* Lookup global symbol for ELF DSOs linked with -Bsymbolic.  Those DSOs have a
    different rule for symbol lookup.  The lookup begins here in the DSO, not in
    the main executable.  */
 
This page took 0.032502 seconds and 4 git commands to generate.