From b3645961a3714e92706f75ab6031e6f5e66e91df Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Thu, 17 Nov 2011 23:44:38 +0100 Subject: [PATCH] bfd/ * bfd/elf32-microblaze.c: Correct adjustment of global symbols 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 Signed-off-by: David Holsgrove --- bfd/elf32-microblaze.c | 46 ++++++++++++++++++++++----- gas/testsuite/gas/microblaze/relax_size.elf | 32 +++++++++++++++++++ gas/testsuite/gas/microblaze/relax_size.exp | 22 +++++++++++++ gas/testsuite/gas/microblaze/relax_size.s | 7 ++++ 4 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 gas/testsuite/gas/microblaze/relax_size.elf create mode 100644 gas/testsuite/gas/microblaze/relax_size.exp create mode 100644 gas/testsuite/gas/microblaze/relax_size.s diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c index be2de13..71daa3c 100644 --- a/bfd/elf32-microblaze.c +++ b/bfd/elf32-microblaze.c @@ -1273,6 +1273,27 @@ microblaze_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd) /* Calculate fixup value for reference. */ 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++) + { + 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) { int i, fixup = 0; @@ -1784,23 +1805,32 @@ 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); + 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); + sym_hash->root.u.def.value -= count; + sym_hash->size -= count_size; } } diff --git a/gas/testsuite/gas/microblaze/relax_size.elf b/gas/testsuite/gas/microblaze/relax_size.elf new file mode 100644 index 0000000..cf23ea6 --- /dev/null +++ b/gas/testsuite/gas/microblaze/relax_size.elf @@ -0,0 +1,32 @@ + +Symbol table '.symtab' contains 29 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 00000000 0 NOTYPE LOCAL DEFAULT UND + 1: 00000050 0 SECTION LOCAL DEFAULT 1 + 2: 00000058 0 SECTION LOCAL DEFAULT 2 + 3: 00000000 0 FILE LOCAL DEFAULT ABS relax_size.o + 4: 00000050 8 NOTYPE LOCAL DEFAULT 1 func + 5: 00000058 0 NOTYPE LOCAL DEFAULT 1 label + 6: 00000000 0 FILE LOCAL DEFAULT ABS + 7: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _fdata + 8: 00000058 0 NOTYPE GLOBAL DEFAULT 1 _etext + 9: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _essrw + 10: 00000058 0 NOTYPE GLOBAL DEFAULT 1 _heap_end + 11: 00000058 0 NOTYPE GLOBAL DEFAULT 1 _heap_start + 12: 00000000 0 NOTYPE GLOBAL DEFAULT ABS _ssro_size + 13: 00000050 0 NOTYPE GLOBAL DEFAULT 1 _ftext + 14: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _essro + 15: 00000400 0 NOTYPE GLOBAL DEFAULT ABS _STACK_SIZE + 16: 00000000 0 NOTYPE GLOBAL DEFAULT ABS _HEAP_SIZE + 17: 00000000 0 NOTYPE GLOBAL DEFAULT ABS _ssrw_size + 18: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _stack_end + 19: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _edata + 20: 00000458 0 NOTYPE GLOBAL DEFAULT 2 _end + 21: 00000058 0 NOTYPE GLOBAL DEFAULT 1 _heap + 22: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _ssro + 23: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _ssrw + 24: 00000458 0 NOTYPE GLOBAL DEFAULT 2 _stack + 25: 00000050 0 NOTYPE GLOBAL DEFAULT ABS _TEXT_START_ADDR + 26: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _frodata + 27: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _fbss + 28: 00000058 0 NOTYPE GLOBAL DEFAULT 2 _erodata diff --git a/gas/testsuite/gas/microblaze/relax_size.exp b/gas/testsuite/gas/microblaze/relax_size.exp new file mode 100644 index 0000000..16ef447 --- /dev/null +++ b/gas/testsuite/gas/microblaze/relax_size.exp @@ -0,0 +1,22 @@ + +proc ld_test { objects ldflags dest test } { + set ld_output [target_link $objects $dest $ldflags] +} + +proc readelf_test { exec flags dest test } { + set readelf [find_binutils_prog readelf] + verbose -log "$readelf $flags $exec > $dest" + catch "exec $readelf $flags $exec > $dest" readelf_output +} + +proc regexp_test { file1 file2 test } { + if [regexp_diff $file1 $file2] then { fail $test } else { pass $test } +} + +global srcdir subdir +if [istarget microblaze*-*-elf] { + gas_test "relax_size.s" {-o relax_size.o} {} {assembling relax_size} + ld_test {relax_size.o } {-e 0 -N -relax } {relax_size.x} {linking relax_size.x} + readelf_test {relax_size.x} {-s} {relax_size.elf} {readelf -s relax_size.x } + regexp_test {relax_size.elf} "$srcdir/$subdir/relax_size.elf" {matching readelf} +} diff --git a/gas/testsuite/gas/microblaze/relax_size.s b/gas/testsuite/gas/microblaze/relax_size.s new file mode 100644 index 0000000..6b25977 --- /dev/null +++ b/gas/testsuite/gas/microblaze/relax_size.s @@ -0,0 +1,7 @@ + .org 0 + .section .text +func: + braid label + nop +label: + .size func, . - func -- 1.7.9.5