diff options
Diffstat (limited to 'recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch')
-rw-r--r-- | recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch b/recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch new file mode 100644 index 00000000..0623e945 --- /dev/null +++ b/recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch @@ -0,0 +1,228 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Date: Mon, 4 Feb 2013 12:15:22 +1000 +Subject: Fixup debug_loc sections after linker relaxation + +Adds a new reloctype R_MICROBLAZE_32_NONE, used for passing +reloc info from the assembler to the linker when the linker +manages to fully resolve a local symbol reference. + +This is a workaround for design flaws in the assembler to +linker interface with regards to linker relaxation. + +Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending +--- + bfd/bfd-in2.h | 5 +++++ + bfd/elf32-microblaze.c | 45 +++++++++++++++++++++++++++++++++++++-------- + bfd/libbfd.h | 1 + + bfd/reloc.c | 6 ++++++ + binutils/readelf.c | 4 ++++ + gas/config/tc-microblaze.c | 3 +++ + include/elf/microblaze.h | 1 + + 7 files changed, 57 insertions(+), 8 deletions(-) + +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 8b7f2ee..de38907 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -5449,6 +5449,11 @@ value relative to the read-write small data area anchor */ + expressions of the form "Symbol Op Symbol" */ + BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM, + ++/* This is a 32 bit reloc that stores the 32 bit pc relative ++value in two words (with an imm instruction). No relocation is ++done here - only used for relaxing */ ++ BFD_RELOC_MICROBLAZE_32_NONE, ++ + /* This is a 64 bit reloc that stores the 32 bit pc relative + value in two words (with an imm instruction). No relocation is + done here - only used for relaxing */ +diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c +index f90df47..d440084 100644 +--- a/bfd/elf32-microblaze.c ++++ b/bfd/elf32-microblaze.c +@@ -177,6 +177,20 @@ static reloc_howto_type microblaze_elf_howto_raw[] = + FALSE), /* PC relative offset? */ + + /* This reloc does nothing. Used for relaxation. */ ++ HOWTO (R_MICROBLAZE_32_NONE, /* Type. */ ++ 0, /* Rightshift. */ ++ 2, /* Size (0 = byte, 1 = short, 2 = long). */ ++ 32, /* Bitsize. */ ++ TRUE, /* PC_relative. */ ++ 0, /* Bitpos. */ ++ complain_overflow_bitfield, /* Complain on overflow. */ ++ NULL, /* Special Function. */ ++ "R_MICROBLAZE_32_NONE",/* Name. */ ++ FALSE, /* Partial Inplace. */ ++ 0, /* Source Mask. */ ++ 0, /* Dest Mask. */ ++ FALSE), /* PC relative offset? */ ++ + HOWTO (R_MICROBLAZE_64_NONE, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ +@@ -532,7 +546,10 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, + case BFD_RELOC_NONE: + microblaze_reloc = R_MICROBLAZE_NONE; + break; +- case BFD_RELOC_MICROBLAZE_64_NONE: ++ case BFD_RELOC_MICROBLAZE_32_NONE: ++ microblaze_reloc = R_MICROBLAZE_32_NONE; ++ break; ++ case BFD_RELOC_MICROBLAZE_64_NONE: + microblaze_reloc = R_MICROBLAZE_64_NONE; + break; + case BFD_RELOC_32: +@@ -1913,14 +1930,22 @@ microblaze_elf_relax_section (bfd *abfd, + } + break; + case R_MICROBLAZE_NONE: ++ case R_MICROBLAZE_32_NONE: + { + /* This was a PC-relative instruction that was + completely resolved. */ + int sfix, efix; ++ unsigned int val; + bfd_vma target_address; + target_address = irel->r_addend + irel->r_offset; + sfix = calc_fixup (irel->r_offset, 0, sec); + efix = calc_fixup (target_address, 0, sec); ++ ++ /* Validate the in-band val. */ ++ val = bfd_get_32 (abfd, contents + irel->r_offset); ++ if (val != irel->r_addend && ELF32_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) { ++ fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, (unsigned long)irel->r_addend); ++ } + irel->r_addend -= (efix - sfix); + /* Should use HOWTO. */ + microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset, +@@ -1968,12 +1993,16 @@ microblaze_elf_relax_section (bfd *abfd, + irelscanend = irelocs + o->reloc_count; + for (irelscan = irelocs; irelscan < irelscanend; irelscan++) + { +- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_NONE) ++ if (1 && ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_NONE) + { + unsigned int val; + + isym = isymbuf + ELF32_R_SYM (irelscan->r_info); + ++ /* hax: We only do the following fixup for debug location lists. */ ++ if (strcmp(".debug_loc", o->name)) ++ continue; ++ + /* This was a PC-relative instruction that was completely resolved. */ + if (ocontents == NULL) + { +@@ -1998,15 +2027,15 @@ microblaze_elf_relax_section (bfd *abfd, + } + } + +- irelscan->r_addend -= calc_fixup (irelscan->r_addend +- + isym->st_value, sec); + val = bfd_get_32 (abfd, ocontents + irelscan->r_offset); ++ if (val != irelscan->r_addend) { ++ fprintf(stderr, "%d: CORRUPT relax reloc! %x %lx\n", __LINE__, val, (unsigned long)irelscan->r_addend); ++ } ++ ++ irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec); + microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset, + irelscan->r_addend); + } +- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_NONE) { +- fprintf(stderr, "Unhandled NONE 64\n"); +- } + if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32) + { + isym = isymbuf + ELF32_R_SYM (irelscan->r_info); +@@ -2066,7 +2095,7 @@ microblaze_elf_relax_section (bfd *abfd, + elf_section_data (o)->this_hdr.contents = ocontents; + } + } +- irelscan->r_addend -= calc_fixup (irel->r_addend ++ irelscan->r_addend -= calc_fixup (irelscan->r_addend + + isym->st_value, + 0, + sec); +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index 09f307f..840c662 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -2644,6 +2644,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_MICROBLAZE_32_ROSDA", + "BFD_RELOC_MICROBLAZE_32_RWSDA", + "BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM", ++ "BFD_RELOC_MICROBLAZE_32_NONE", + "BFD_RELOC_MICROBLAZE_64_NONE", + "BFD_RELOC_MICROBLAZE_64_GOTPC", + "BFD_RELOC_MICROBLAZE_64_GOT", +diff --git a/bfd/reloc.c b/bfd/reloc.c +index 7f46c58..5bcd52d 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -6396,6 +6396,12 @@ ENUMDOC + This is a 32 bit reloc for the microblaze to handle + expressions of the form "Symbol Op Symbol" + ENUM ++ BFD_RELOC_MICROBLAZE_32_NONE ++ENUMDOC ++ This is a 32 bit reloc that stores the 32 bit pc relative ++ value in two words (with an imm instruction). No relocation is ++ done here - only used for relaxing ++ENUM + BFD_RELOC_MICROBLAZE_64_NONE + ENUMDOC + This is a 64 bit reloc that stores the 32 bit pc relative +diff --git a/binutils/readelf.c b/binutils/readelf.c +index af6463e..343eb61 100644 +--- a/binutils/readelf.c ++++ b/binutils/readelf.c +@@ -10821,6 +10821,10 @@ is_none_reloc (unsigned int reloc_type) + || reloc_type == 19 /* R_XTENSA_DIFF32. */); + case EM_METAG: + return reloc_type == 3; /* R_METAG_NONE. */ ++ case EM_MICROBLAZE: ++ return reloc_type == 30 /* R_MICROBLAZE_32_NONE. */ ++ || reloc_type == 0 /* R_MICROBLAZE_NONE. */ ++ || reloc_type == 9; /* R_MICROBLAZE_64_NONE. */ + } + return FALSE; + } +diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c +index 12ad616..46d61db 100644 +--- a/gas/config/tc-microblaze.c ++++ b/gas/config/tc-microblaze.c +@@ -2167,6 +2167,8 @@ md_apply_fix (fixS * fixP, + moves code around due to relaxing. */ + if (fixP->fx_r_type == BFD_RELOC_64_PCREL) + fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE; ++ else if (fixP->fx_r_type == BFD_RELOC_32) ++ fixP->fx_r_type = BFD_RELOC_MICROBLAZE_32_NONE; + else + fixP->fx_r_type = BFD_RELOC_NONE; + fixP->fx_addsy = section_symbol (absolute_section); +@@ -2388,6 +2390,7 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) + switch (fixp->fx_r_type) + { + case BFD_RELOC_NONE: ++ case BFD_RELOC_MICROBLAZE_32_NONE: + case BFD_RELOC_MICROBLAZE_64_NONE: + case BFD_RELOC_32: + case BFD_RELOC_MICROBLAZE_32_LO: +diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h +index effca20..f8420dc 100644 +--- a/include/elf/microblaze.h ++++ b/include/elf/microblaze.h +@@ -58,6 +58,7 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type) + RELOC_NUMBER (R_MICROBLAZE_TLSDTPREL64, 27) /* TLS Offset Within TLS Block */ + RELOC_NUMBER (R_MICROBLAZE_TLSGOTTPREL32, 28) /* TLS Offset From Thread Pointer */ + RELOC_NUMBER (R_MICROBLAZE_TLSTPREL32, 29) /* TLS Offset From Thread Pointer */ ++ RELOC_NUMBER (R_MICROBLAZE_32_NONE, 30) + + END_RELOC_NUMBERS (R_MICROBLAZE_max) + +-- +1.9.0 + |