This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 04/12] bfd/ * bfd/elf32-microblaze.c: Correct adjustment of global symbols
From: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Fixup symbol sizes after linker relaxation
This bug didn't affect code generation, but would have
affected debuggers that got the wrong view of things.
Correct an off-by one when comparing relaxation addresses
with symbol start.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
---
bfd/ChangeLog | 5 ++++
bfd/elf32-microblaze.c | 59 +++++++++++++++++++++++++++++++++++++++++------
2 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b542abd..6a3dbd3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2012-10-10 Edgar E. Iglesias <edgar.iglesias@gmail.com>
+
+ * bfd/elf32-microblaze.c: Correct adjustment of global symbols
+ after linker relaxation
+
2012-09-20 Walter Lee <walt@tilera.com>
* elf32-tilepro.c (tilepro_elf_relocate_section): Adjust got
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index 27b569e..487977e 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -1256,6 +1256,31 @@ microblaze_elf_relocate_section (bfd *output_bfd,
/* Calculate fixup value for reference. */
+#define D(x)
+
+static int
+calc_size_fixup (bfd_vma start, bfd_vma size, asection *sec)
+{
+ bfd_vma end = start + size;
+ int i, fixup = 0;
+
+ if (sec == NULL || sec->relax == NULL)
+ return 0;
+
+ /* Look for addr in relax table, total fixup value. */
+ for (i = 0; i < sec->relax_count; i++)
+ {
+ D(fprintf(stderr, "%s: start=%x end=%x reladdr=%x relsize=%d\n", __func__,
+ start, end, sec->relax[i].addr, sec->relax[i].size));
+ if (end < sec->relax[i].addr)
+ break;
+ if (start > sec->relax[i].addr)
+ continue;
+ fixup += sec->relax[i].size;
+ }
+ return fixup;
+}
+
static int
calc_fixup (bfd_vma addr, asection *sec)
{
@@ -1338,6 +1363,7 @@ microblaze_elf_relax_section (bfd *abfd,
irelend = internal_relocs + sec->reloc_count;
rel_count = 0;
+ D(fprintf (stderr, "%s:%s\n", abfd->filename, sec->name));
for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
{
bfd_vma symval;
@@ -1740,23 +1766,38 @@ microblaze_elf_relax_section (bfd *abfd,
isymend = isymbuf + symtab_hdr->sh_info;
for (isym = isymbuf; isym < isymend; isym++)
{
- if (isym->st_shndx == shndx)
- isym->st_value =- calc_fixup (isym->st_value, sec);
+ if (isym->st_shndx == shndx) {
+ int count, count_size;
+
+ count = calc_fixup (isym->st_value, sec);
+ count_size = calc_size_fixup (isym->st_value, isym->st_size, sec);
+ D(fprintf(stderr, "local adjust loc=%x.%d size=%d.%d \n",
+ isym->st_value, -count,
+ isym->st_size, -count_size));
+ isym->st_value -= count;
+ isym->st_size -= count_size;
+ }
}
/* Now adjust the global symbols defined in this section. */
isym = isymbuf + symtab_hdr->sh_info;
- isymend = isymbuf + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
- for (sym_index = 0; isym < isymend; isym++, sym_index++)
+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
+ for (sym_index = 0; sym_index < symcount; sym_index++)
{
sym_hash = elf_sym_hashes (abfd)[sym_index];
- if (isym->st_shndx == shndx
- && (sym_hash->root.type == bfd_link_hash_defined
+ if ((sym_hash->root.type == bfd_link_hash_defined
|| sym_hash->root.type == bfd_link_hash_defweak)
&& sym_hash->root.u.def.section == sec)
{
- sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
- sec);
+ int count, count_size;
+
+ count = calc_fixup (sym_hash->root.u.def.value, sec);
+ count_size = calc_size_fixup (sym_hash->root.u.def.value, sym_hash->size, sec);
+ D(fprintf(stderr, "adjust loc=%x.%d size=%d.%d \n",
+ sym_hash->root.u.def.value, -count,
+ sym_hash->size, -count_size));
+ sym_hash->root.u.def.value -= count;
+ sym_hash->size -= count_size;
}
}
@@ -1771,6 +1812,8 @@ microblaze_elf_relax_section (bfd *abfd,
memmove (contents + dest, contents + src, len);
sec->size -= sec->relax[i].size;
dest += len;
+ D(fprintf(stderr, "relax %x to %x relaxsize=%d secsize=%d\n",
+ src, dest, sec->relax[i].size, sec->size));
}
elf_section_data (sec)->relocs = internal_relocs;
--
1.7.0.4