aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/rs6000-nat.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c
index d7b9571..a40b9a7 100644
--- a/gdb/rs6000-nat.c
+++ b/gdb/rs6000-nat.c
@@ -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);
}