* gas/nios2/nios2.exp: Add copyright.
[deliverable/binutils-gdb.git] / gdb / rs6000-nat.c
index 073f167caf4e03ded73dba24d3538b7c79afcc39..a40b9a76fe78d47dc522cb079da4345f1446da3a 100644 (file)
@@ -1,7 +1,6 @@
 /* IBM RS/6000 native-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 1986-1987, 1989, 1991-2004, 2007-2012 Free Software
-   Foundation, Inc.
+   Copyright (C) 1986-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -53,6 +52,7 @@
 #include <a.out.h>
 #include <sys/file.h>
 #include "gdb_stat.h"
+#include "gdb_bfd.h"
 #include <sys/core.h>
 #define __LDINFO_PTRACE32__    /* for __ld_info32 */
 #define __LDINFO_PTRACE64__    /* for __ld_info64 */
@@ -75,7 +75,7 @@
 #ifndef ARCH3264
 # define ARCH64() 0
 #else
-# define ARCH64() (register_size (target_gdbarch, 0) == 8)
+# define ARCH64() (register_size (target_gdbarch (), 0) == 8)
 #endif
 
 /* Union of 32-bit and 64-bit versions of ld_info.  */
@@ -651,6 +651,71 @@ vmap_secs (struct vmap *vp, LdInfo *ldi, int arch64)
   vp->tstart += vp->toffs;
 }
 
+/* If the .bss section's VMA is set to an address located before
+   the end of the .data section, causing the two sections to overlap,
+   return the overlap in bytes.  Otherwise, return zero.
+
+   Motivation:
+
+   The GNU linker sometimes sets the start address of the .bss session
+   before the end of the .data section, making the 2 sections overlap.
+   The loader appears to handle this situation gracefully, by simply
+   loading the bss section right after the end of the .data section.
+
+   This means that the .data and the .bss sections are sometimes
+   no longer relocated by the same amount.  The problem is that
+   the ldinfo data does not contain any information regarding
+   the relocation of the .bss section, assuming that it would be
+   identical to the information provided for the .data section
+   (this is what would normally happen if the program was linked
+   correctly).
+
+   GDB therefore needs to detect those cases, and make the corresponding
+   adjustment to the .bss section offset computed from the ldinfo data
+   when necessary.  This function returns the adjustment amount  (or
+   zero when no adjustment is needed).  */
+
+static CORE_ADDR
+bss_data_overlap (struct objfile *objfile)
+{
+  struct obj_section *osect;
+  struct bfd_section *data = NULL;
+  struct bfd_section *bss = NULL;
+
+  /* First, find the .data and .bss sections.  */
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    {
+      if (strcmp (bfd_section_name (objfile->obfd,
+                                   osect->the_bfd_section),
+                 ".data") == 0)
+       data = osect->the_bfd_section;
+      else if (strcmp (bfd_section_name (objfile->obfd,
+                                        osect->the_bfd_section),
+                      ".bss") == 0)
+       bss = osect->the_bfd_section;
+    }
+
+  /* If either section is not defined, there can be no overlap.  */
+  if (data == NULL || bss == NULL)
+    return 0;
+
+  /* Assume the problem only occurs with linkers that place the .bss
+     section after the .data section (the problem has only been
+     observed when using the GNU linker, and the default linker
+     script always places the .data and .bss sections in that order).  */
+  if (bfd_section_vma (objfile->obfd, bss)
+      < bfd_section_vma (objfile->obfd, data))
+    return 0;
+
+  if (bfd_section_vma (objfile->obfd, bss)
+      < bfd_section_vma (objfile->obfd, data) + bfd_get_section_size (data))
+    return ((bfd_section_vma (objfile->obfd, data)
+            + bfd_get_section_size (data))
+           - bfd_section_vma (objfile->obfd, bss));
+
+  return 0;
+}
+
 /* Handle symbol translation on vmapping.  */
 
 static void
@@ -687,6 +752,10 @@ vmap_symtab (struct vmap *vp)
   new_offsets->offsets[SECT_OFF_DATA (objfile)] = vp->dstart - vp->dvma;
   new_offsets->offsets[SECT_OFF_BSS (objfile)] = vp->dstart - vp->dvma;
 
+  /* Perform the same adjustment as the loader if the .data and
+     .bss sections overlap.  */
+  new_offsets->offsets[SECT_OFF_BSS (objfile)] += bss_data_overlap (objfile);
+
   objfile_relocate (objfile, new_offsets);
 }
 \f
@@ -745,20 +814,13 @@ add_vmap (LdInfo *ldi)
   mem = xstrdup (mem);
 
   fd = LDI_FD (ldi, arch64);
-  if (fd < 0)
-    /* Note that this opens it once for every member; a possible
-       enhancement would be to only open it once for every object.  */
-    abfd = bfd_openr (filename, gnutarget);
-  else
-    abfd = bfd_fdopenr (filename, gnutarget, fd);
-  gdb_bfd_ref (abfd);
+  abfd = gdb_bfd_open (filename, gnutarget, fd < 0 ? -1 : fd);
   if (!abfd)
     {
       warning (_("Could not open `%s' as an executable file: %s"),
               filename, bfd_errmsg (bfd_get_error ()));
       return NULL;
     }
-  gdb_bfd_stash_filename (abfd);
 
   /* Make sure we have an object file.  */
 
@@ -767,13 +829,17 @@ add_vmap (LdInfo *ldi)
 
   else if (bfd_check_format (abfd, bfd_archive))
     {
-      last = 0;
-      /* FIXME??? am I tossing BFDs?  bfd?  */
-      while ((last = bfd_openr_next_archived_file (abfd, last)))
+      last = gdb_bfd_openr_next_archived_file (abfd, NULL);
+      while (last != NULL)
        {
-         gdb_bfd_ref (last);
+         bfd *next;
+
          if (strcmp (mem, last->filename) == 0)
            break;
+
+         next = gdb_bfd_openr_next_archived_file (abfd, last);
+         gdb_bfd_unref (last);
+         last = next;
        }
 
       if (!last)
@@ -793,6 +859,9 @@ add_vmap (LdInfo *ldi)
        }
 
       vp = map_vmap (last, abfd);
+      /* map_vmap acquired a reference to LAST, so we can release
+        ours.  */
+      gdb_bfd_unref (last);
     }
   else
     {
@@ -801,13 +870,17 @@ add_vmap (LdInfo *ldi)
       gdb_bfd_unref (abfd);
       return NULL;
     }
-  gdb_bfd_ref (vp->bfd);
   obj = allocate_objfile (vp->bfd, 0);
   vp->objfile = obj;
 
   /* Always add symbols for the main objfile.  */
   if (vp == vmap || auto_solib_add)
     vmap_add_symbols (vp);
+
+  /* Anything needing a reference to ABFD has already acquired it, so
+     release our local reference.  */
+  gdb_bfd_unref (abfd);
+
   return vp;
 }
 \f
This page took 0.025588 seconds and 4 git commands to generate.