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.
This commit is contained in:
Joel Brobecker 2013-01-01 08:37:20 +00:00
parent 6e58437e3b
commit 8333c85bf8
1 changed files with 69 additions and 0 deletions

View File

@ -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);
}