aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2013-01-01 08:37:20 +0000
committerJoel Brobecker <brobecker@gnat.com>2013-01-01 08:37:20 +0000
commit8333c85bf882a6ec58bd0be69f713542f7f446fd (patch)
treef5a13c713964d4d2f98313dcac843c2138e9e257
parent6e58437e3b25675483adfd1a044510c0731ef942 (diff)
downloadgdb-8333c85bf882a6ec58bd0be69f713542f7f446fd.zip
gdb-8333c85bf882a6ec58bd0be69f713542f7f446fd.tar.gz
gdb-8333c85bf882a6ec58bd0be69f713542f7f446fd.tar.bz2
ppc-aix: .bss relocation problem when overlapping with the .data section
It has been observed that the GNU linker can sometimes improperly set the address of the .bss section in such a way that it overlaps with the end of the .data section. This causes problems in GDB when trying to print the value of variables located in that section, because the loader appears to be gracefully but silently adjusting the address of the .bss section to avoid the overlap, thus causing a mismatch between the address where GDB thinks it is, vs the address where it actually lives. This patch works around the problem while it a fix in the linker is being explored. gdb/ChangeLog: * rs6000-nat.c (bss_data_overlap): New function. (vmap_symtab): Use it to adjust the .bss section's offset.
-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);
}