From: Maciej W. Rozycki Date: Sat, 12 Jul 2025 00:25:53 +0000 (+0100) Subject: PR 19977: MIPS: Add missing pairing for REL PCHI/PCLO relocations X-Git-Tag: binutils-2_45~67 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=68f5cb38c27699e9b4840f22596ede96762c4796;p=thirdparty%2Fbinutils-gdb.git PR 19977: MIPS: Add missing pairing for REL PCHI/PCLO relocations Just as with all HI/LO 16-bit partial relocations the newly-introduced MIPSr6 PC-relative R_MIPS_PCHI16 and R_MIPS_PCLO16 relocations require pairing for correct borrow propagation from the low part to the high part with REL targets, another case for PR 19977. Unlike with absolute relocation, there is a complication here in that both parts represent a calculation that is relative to the PC at the individual relocation's location rather than both referring to the location of the R_MIPS_PCHI16 relocation, normally applied to an AUIPC instruction, the location of which is used for the run-time calculation executed by hardware. To take this semantics into account, the addend of the R_MIPS_PCLO16 relocation matching a given R_MIPS_PCHI16 relocation is expected to be adjusted in the source assembly file for the distance between the two relocations in a single pair, so that once both relocations have been calculated by the linker, the expression calculated at run time is such as if the combined 32-bit immediate was added at the location of the AUIPC instruction. So for matching R_MIPS_PCHI16 and R_MIPS_PCLO16 relocations into pairs GAS needs to check for the distance between the two relocations to be equal to the difference between the addends supplied, and then the linker has to subtract the low part of the distance between the two relocations from the low part in calculating the high part, so as to factor in any borrow. A further complication is that `_bfd_mips_elf_lo16_reloc' handler is supplied with the addend differently depending on whether it has been called by GAS via `bfd_install_relocation', or by the generic linker via `bfd_perform_relocation'. In the former case the addend is supplied with the relocation itself while in the latter one it comes from the field being relocated. We currently ignore the addend supplied with the relocation and it works for calculating absolute high-part relocations, because the same addend has been previously supplied with them when `_bfd_mips_elf_hi16_reloc' was called, however this approach does not work for the PC-relative case because as noted above the low-part addend is different and we need to consistently apply the distance adjustment both with GAS and LD. Since the supplied addend and one retrieved from field being relocated won't ever be both nonzero, just use the sum of the two values. The low-part addend in `mips_elf_add_lo16_rel_addend' always comes from the field being relocated, so there's no complication there, we just need to apply the same adjustment. New linker test cases verify that the same ultimate machine code is produced both for ELF and S-record output formats, ensuring that the both the MIPS/ELF linker and the generic linker behave in the correct way, consistent with each other. --- diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 6fe93a893e8..45856b14af0 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -789,7 +789,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + _bfd_mips_elf_hi16_reloc, /* special_function */ "R_MIPS_PCHI16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -803,7 +803,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + _bfd_mips_elf_lo16_reloc, /* special_function */ "R_MIPS_PCLO16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index 5b5521079e1..29dcadd3230 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -868,7 +868,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] = true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + _bfd_mips_elf_hi16_reloc, /* special_function */ "R_MIPS_PCHI16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -882,7 +882,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] = true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + _bfd_mips_elf_lo16_reloc, /* special_function */ "R_MIPS_PCLO16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index e457bfc9849..d72e2f5236a 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -847,7 +847,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + _bfd_mips_elf_hi16_reloc, /* special_function */ "R_MIPS_PCHI16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -861,7 +861,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + _bfd_mips_elf_lo16_reloc, /* special_function */ "R_MIPS_PCLO16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 6f323289ad6..7d1dff1d721 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2600,20 +2600,22 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, extended. For example, an addend of 0x38000 would have 0x0004 in the high part and 0x8000 (=0xff..f8000) in the low part. To extract the actual addend, calculate - ((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000. - We will be applying (symbol + addend) & 0xffff to the low insn, - and we want to apply (symbol + addend + 0x8000) >> 16 to the - high insn (the +0x8000 adjusting for when the applied low part is - negative). */ + ((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000. */ vallo = _bfd_mips_elf_sign_extend (bfd_get_32 (abfd, location) & 0xffff, 16); _bfd_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, false, location); + /* Add in the separate addend, if any. Since we are REL here this + will have been set and the in-place addend cleared if we have + been called from GAS via `bfd_install_relocation'. */ + vallo += reloc_entry->addend; tdata = mips_elf_tdata (abfd); while (tdata->mips_hi16_list != NULL) { bfd_reloc_status_type ret; struct mips_hi16 *hi; + bfd_vma addhi; + bfd_vma addlo; hi = tdata->mips_hi16_list; @@ -2629,7 +2631,19 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, else if (hi->rel.howto->type == R_MICROMIPS_GOT16) hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MICROMIPS_HI16, false); - hi->rel.addend += vallo; + /* We will be applying (symbol + addend) & 0xffff to the low insn, + and we want to apply (symbol + addend + 0x8000) >> 16 to the + high insn (the +0x8000 adjusting for when the applied low part is + negative). */ + addhi = (hi->rel.addend + 0x8000) & ~(bfd_vma) 0xffff; + addlo = vallo; + + /* For a PC-relative relocation the PCLO16 part of the addend + is relative to its PC and not ours, so we need to adjust it. */ + if (hi->rel.howto->type == R_MIPS_PCHI16) + addlo -= reloc_entry->address - hi->rel.address; + + hi->rel.addend = addhi + _bfd_mips_elf_sign_extend (addlo & 0xffff, 16); ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data, hi->input_section, output_bfd, @@ -8334,6 +8348,10 @@ mips_elf_add_lo16_rel_addend (bfd *abfd, contents); l <<= lo16_howto->rightshift; + /* For a PC-relative relocation the PCLO16 part of the addend + is relative to its PC and not ours, so we need to adjust it. */ + if (r_type == R_MIPS_PCHI16) + l = (l - (lo16_relocation->r_offset - rel->r_offset)) & 0xffff; l = _bfd_mips_elf_sign_extend (l, 16); *addend <<= 16; diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 9134cef96be..7d0d8559115 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -4328,14 +4328,16 @@ got16_reloc_p (bfd_reloc_code_real_type reloc) static inline bool hi16_reloc_p (bfd_reloc_code_real_type reloc) { - return (reloc == BFD_RELOC_HI16_S || reloc == BFD_RELOC_MIPS16_HI16_S + return (reloc == BFD_RELOC_HI16_S || reloc == BFD_RELOC_HI16_S_PCREL + || reloc == BFD_RELOC_MIPS16_HI16_S || reloc == BFD_RELOC_MICROMIPS_HI16_S); } static inline bool lo16_reloc_p (bfd_reloc_code_real_type reloc) { - return (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_MIPS16_LO16 + return (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_LO16_PCREL + || reloc == BFD_RELOC_MIPS16_LO16 || reloc == BFD_RELOC_MICROMIPS_LO16); } @@ -4402,8 +4404,9 @@ static inline bfd_reloc_code_real_type matching_lo_reloc (bfd_reloc_code_real_type reloc) { return (mips16_reloc_p (reloc) ? BFD_RELOC_MIPS16_LO16 - : (micromips_reloc_p (reloc) ? BFD_RELOC_MICROMIPS_LO16 - : BFD_RELOC_LO16)); + : micromips_reloc_p (reloc) ? BFD_RELOC_MICROMIPS_LO16 + : reloc == BFD_RELOC_HI16_S_PCREL ? BFD_RELOC_LO16_PCREL + : BFD_RELOC_LO16); } /* Return true if the given fixup is followed by a matching R_MIPS_LO16 @@ -4415,7 +4418,12 @@ fixup_has_matching_lo_p (fixS *fixp) return (fixp->fx_next != NULL && fixp->fx_next->fx_r_type == matching_lo_reloc (fixp->fx_r_type) && fixp->fx_addsy == fixp->fx_next->fx_addsy - && fixp->fx_offset == fixp->fx_next->fx_offset); + && (fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL + ? (fixp->fx_next->fx_offset - fixp->fx_offset + == ((fixp->fx_next->fx_frag->fr_address + + fixp->fx_next->fx_where) + - (fixp->fx_frag->fr_address + fixp->fx_where))) + : fixp->fx_offset == fixp->fx_next->fx_offset)); } /* Move all labels in LABELS to the current insertion point. TEXT_P @@ -15413,6 +15421,13 @@ mips_frob_file_before_adjust (void) if the user knows that adding 2 to "foo" will not induce a carry to the high 16 bits. + A %pcrel_lo() expression matches a %pcrel_hi() expression if: + + (a) it refers to the same symbol; and + (b) the offset applied in the %pcrel_lo() expression equals + the offset applied in the %pcrel_hi() expression plus the + distance from the location of %pcrel_hi() to %pcrel_lo(). + When several %lo()s match a particular %got() or %hi(), we use the following rules to distinguish them: @@ -15484,9 +15499,14 @@ mips_frob_file (void) if ((*pos)->fx_r_type == looking_for_rtype && symbol_same_p ((*pos)->fx_addsy, l->fixp->fx_addsy) - && (*pos)->fx_offset >= l->fixp->fx_offset + && (l->fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL + ? ((*pos)->fx_offset - l->fixp->fx_offset + == (((*pos)->fx_frag->fr_address + (*pos)->fx_where) + - (l->fixp->fx_frag->fr_address + l->fixp->fx_where))) + : (*pos)->fx_offset >= l->fixp->fx_offset) && (lo_pos == NULL - || (*pos)->fx_offset < (*lo_pos)->fx_offset + || (l->fixp->fx_r_type != BFD_RELOC_HI16_S_PCREL + && (*pos)->fx_offset < (*lo_pos)->fx_offset) || (!matched_lo_p && (*pos)->fx_offset == (*lo_pos)->fx_offset))) lo_pos = pos; @@ -15497,15 +15517,20 @@ mips_frob_file (void) /* If we found a match, remove the high-part relocation from its current position and insert it before the low-part relocation. - Make the offsets match so that fixup_has_matching_lo_p() - will return true. + + For absolute relocations make the offsets match so that + fixup_has_matching_lo_p() will return true. For PC-relative + relocations the distance between the offsets is retained + according to expectations in `fixup_has_matching_lo_p', + `_bfd_mips_elf_lo16_reloc' and `mips_elf_add_lo16_rel_addend'. We don't warn about unmatched high-part relocations since some versions of gcc have been known to emit dead "lui ...%hi(...)" instructions. */ if (lo_pos != NULL) { - l->fixp->fx_offset = (*lo_pos)->fx_offset; + if (l->fixp->fx_r_type != BFD_RELOC_HI16_S_PCREL) + l->fixp->fx_offset = (*lo_pos)->fx_offset; if (l->fixp->fx_next != *lo_pos) { *hi_pos = l->fixp->fx_next; diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index 1a766ffc821..73ea41d59c6 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -1724,6 +1724,13 @@ if { [istarget mips*-*-vxworks*] } { run_dump_test "pcrel-4-n32" run_dump_test "pcrel-4-64" } + run_dump_test "pcrel-hilo-match" + run_dump_test "pcrel-hilo-addend" + run_dump_test "pcrel-hilo" + if $has_newabi { + run_dump_test "pcrel-hilo-n32" + run_dump_test "pcrel-hilo-64" + } run_dump_test "pcrel-reloc-1" run_dump_test "pcrel-reloc-1-r6" diff --git a/gas/testsuite/gas/mips/pcrel-hilo-64.d b/gas/testsuite/gas/mips/pcrel-hilo-64.d new file mode 100644 index 00000000000..92c697ffb42 --- /dev/null +++ b/gas/testsuite/gas/mips/pcrel-hilo-64.d @@ -0,0 +1,79 @@ +#readelf: -r +#name: MIPSr6 PCHI16/PCLO16 relocations (n64) +#as: -mabi=64 -march=mips64r6 -mno-pdr +#source: pcrel-hilo.s + +Relocation section '\.rela\.text' at offset .+ contains 24 entries: + Offset Info Type Sym\. Value Sym\. Name \+ Addend +000000000000 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 7fec + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000004 000900000005 R_MIPS_HI16 0000000000000000 baz \+ 0 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000008 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 7ff8 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +00000000000c 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ fff0 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000010 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 7ffc + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000014 000900000006 R_MIPS_LO16 0000000000000000 baz \+ 0 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000018 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 8008 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +00000000001c 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 10000 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000020 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 800c + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000024 000900000005 R_MIPS_HI16 0000000000000000 baz \+ 0 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000028 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 8018 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +00000000002c 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 10010 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030030 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 3801c + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030034 000900000006 R_MIPS_LO16 0000000000000000 baz \+ 0 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030038 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 38028 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +00000003003c 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 40020 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030040 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 3802c + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030044 000900000006 R_MIPS_LO16 0000000000000000 baz \+ 0 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030048 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 38038 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +00000003004c 000800000041 R_MIPS_PCLO16 0000000000000000 bar \+ 40030 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030050 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 3803c + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030054 000900000005 R_MIPS_HI16 0000000000000000 baz \+ 0 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000030058 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 38048 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +00000003005c 000800000040 R_MIPS_PCHI16 0000000000000000 bar \+ 40040 + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE diff --git a/gas/testsuite/gas/mips/pcrel-hilo-addend.d b/gas/testsuite/gas/mips/pcrel-hilo-addend.d new file mode 100644 index 00000000000..296101cbd5c --- /dev/null +++ b/gas/testsuite/gas/mips/pcrel-hilo-addend.d @@ -0,0 +1,63 @@ +#objdump: -dr --prefix-addresses --show-raw-insn +#name: MIPSr6 PCHI16/PCLO16 in-place addends (o32) +#as: -mabi=32 -mno-pdr +#source: pcrel-hilo.s + +.*: +file format .*mips.* + +Disassembly of section \.text: +00000000 <[^>]*> ec9e0000 auipc a0,0x0 + 0: R_MIPS_PCHI16 bar +00000004 <[^>]*> 3c050000 lui a1,0x0 + 4: R_MIPS_HI16 baz +00000008 <[^>]*> ecde0000 auipc a2,0x0 + 8: R_MIPS_PCHI16 bar +0000000c <[^>]*> ecfe0001 auipc a3,0x1 + c: R_MIPS_PCHI16 bar +00000010 <[^>]*> 24847ffc addiu a0,a0,32764 + 10: R_MIPS_PCLO16 bar +00000014 <[^>]*> 24a50000 addiu a1,a1,0 + 14: R_MIPS_LO16 baz +00000018 <[^>]*> 24c68008 addiu a2,a2,-32760 + 18: R_MIPS_PCLO16 bar +0000001c <[^>]*> 24e70000 addiu a3,a3,0 + 1c: R_MIPS_PCLO16 bar +00000020 <[^>]*> ec9e0001 auipc a0,0x1 + 20: R_MIPS_PCHI16 bar +00000024 <[^>]*> 3c050000 lui a1,0x0 + 24: R_MIPS_HI16 baz +00000028 <[^>]*> ecde0001 auipc a2,0x1 + 28: R_MIPS_PCHI16 bar +0000002c <[^>]*> ecfe0001 auipc a3,0x1 + 2c: R_MIPS_PCHI16 bar + \.\.\. +00030030 <[^>]*> 2484801c addiu a0,a0,-32740 + 30030: R_MIPS_PCLO16 bar +00030034 <[^>]*> 24a50000 addiu a1,a1,0 + 30034: R_MIPS_LO16 baz +00030038 <[^>]*> 24c68028 addiu a2,a2,-32728 + 30038: R_MIPS_PCLO16 bar +0003003c <[^>]*> 24e70020 addiu a3,a3,32 + 3003c: R_MIPS_PCLO16 bar +00030040 <[^>]*> 2410802c li s0,-32724 + 30040: R_MIPS_PCLO16 bar +00030044 <[^>]*> 24110000 li s1,0 + 30044: R_MIPS_LO16 baz +00030048 <[^>]*> 24128038 li s2,-32712 + 30048: R_MIPS_PCLO16 bar +0003004c <[^>]*> 24130030 li s3,48 + 3004c: R_MIPS_PCLO16 bar +00030050 <[^>]*> ec9e0004 auipc a0,0x4 + 30050: R_MIPS_PCHI16 bar +00030054 <[^>]*> 3c050000 lui a1,0x0 + 30054: R_MIPS_HI16 baz +00030058 <[^>]*> ecde0004 auipc a2,0x4 + 30058: R_MIPS_PCHI16 bar +0003005c <[^>]*> ecfe0004 auipc a3,0x4 + 3005c: R_MIPS_PCHI16 bar +00030060 <[^>]*> 00902021 addu a0,a0,s0 +00030064 <[^>]*> 00b12821 addu a1,a1,s1 +00030068 <[^>]*> 00d23021 addu a2,a2,s2 +0003006c <[^>]*> 00f33821 addu a3,a3,s3 +00030070 <[^>]*> d81f0000 jrc ra + \.\.\. diff --git a/gas/testsuite/gas/mips/pcrel-hilo-match.d b/gas/testsuite/gas/mips/pcrel-hilo-match.d new file mode 100644 index 00000000000..5ff66c255c4 --- /dev/null +++ b/gas/testsuite/gas/mips/pcrel-hilo-match.d @@ -0,0 +1,28 @@ +#objdump: -r +#as: -mabi=32 -mno-pdr +#name: MIPS pcrel-hilo-match + +.*: +file format .*mips.* + +RELOCATION RECORDS FOR \[\.text\]: +OFFSET +TYPE +VALUE +00000010 R_MIPS_PCHI16 var4 +00000018 R_MIPS_PCLO16 var4 +00000008 R_MIPS_PCHI16 __var1 +00000020 R_MIPS_PCLO16 __var1 +0000001c R_MIPS_PCHI16 .sbss +0000002c R_MIPS_PCLO16 .sbss +00000028 R_MIPS_PCHI16 __var3 +00000034 R_MIPS_PCLO16 __var3 +00000030 R_MIPS_PCHI16 func4 +00000038 R_MIPS_PCLO16 func4 +00000024 R_MIPS_PCHI16 hilo_match +0000003c R_MIPS_PCLO16 hilo_match +00000040 R_MIPS_PCHI16 .bss +00000048 R_MIPS_PCLO16 .bss +00000044 R_MIPS_PCHI16 .bss +0000004c R_MIPS_PCLO16 .bss +00000050 R_MIPS_PCHI16 hilo_match +00000058 R_MIPS_PCLO16 hilo_match +00000054 R_MIPS_PCHI16 func3 +0000005c R_MIPS_PCLO16 func3 diff --git a/gas/testsuite/gas/mips/pcrel-hilo-match.s b/gas/testsuite/gas/mips/pcrel-hilo-match.s new file mode 100644 index 00000000000..dfc8a80680b --- /dev/null +++ b/gas/testsuite/gas/mips/pcrel-hilo-match.s @@ -0,0 +1,81 @@ + .module mips64r6 + + .align 2 + .globl _pinit + .ent _pinit +_pinit: + lw $3,8($23) + li $5,1 +10: auipc $2,%pcrel_hi(__var1) + ori $3,$3,0x1 +11: auipc $4,%pcrel_hi(var4) + sw $3,8($23) +12: addiu $4,$4,%pcrel_lo(var4 + (12b - 11b)) +13: auipc $3,%pcrel_hi(var5) +14: sw $5,%pcrel_lo(__var1 + (14b - 10b))($2) +15: auipc $19,%pcrel_hi(hilo_match) +16: auipc $2,%pcrel_hi(__var3) +17: sw $5,%pcrel_lo(var5 + (17b - 13b))($3) +18: auipc $25,%pcrel_hi(func4) +19: sw $5,%pcrel_lo(__var3 + (19b - 16b))($2) +20: jialc $25,%pcrel_lo(func4 + (20b - 18b)) +21: lw $17,%pcrel_lo(hilo_match + (21b - 15b))($19) +22: auipc $2,%pcrel_hi(var6) +23: auipc $3,%pcrel_hi(var6+704) +24: addiu $16,$2,%pcrel_lo(var6 + (24b - 22b)) +25: addiu $18,$3,%pcrel_lo(var6+704 + (25b - 23b)) +26: auipc $19,%pcrel_hi(hilo_match) +28: auipc $25,%pcrel_hi(func3) +27: sw $2,%pcrel_lo(hilo_match + (27b - 26b))($19) +29: jialc $25,%pcrel_lo(func3 + (29b - 28b)) + .end _pinit + .size _pinit, .-_pinit + + .align 2 + .weak __var3 + .section .sbss,"aw",@nobits + .align 2 + .type __var3, @object + .size __var3, 4 +__var3: + .space 4 + .weak __var1 + .align 2 + .type __var1, @object + .size __var1, 4 +__var1: + .space 4 + .data + .align 2 + .weak __hilo_match + .align 2 + .type __hilo_match, @object + .size __hilo_match, 4 +__hilo_match: + .space 4 + .data + .align 2 + .align 2 + .type var2, @object + .size var2, 32 +var2: + .word 0 + .word -1 + .word 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .word 0 + .word 0 + .half 0 + .space 6 + .align 2 + .rdata + .align 2 + .space 8 + .local var5 + .comm var5,4,4 + .align 2 + .local var6 + .comm var6,704,4 diff --git a/gas/testsuite/gas/mips/pcrel-hilo-n32.d b/gas/testsuite/gas/mips/pcrel-hilo-n32.d new file mode 100644 index 00000000000..aed204a5517 --- /dev/null +++ b/gas/testsuite/gas/mips/pcrel-hilo-n32.d @@ -0,0 +1,31 @@ +#readelf: -r +#name: MIPSr6 PCHI16/PCLO16 relocations (n32) +#as: -mabi=n32 -march=mips64r6 -mno-pdr +#source: pcrel-hilo.s + +Relocation section '\.rela\.text' at offset .+ contains 24 entries: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +00000000 00000840 R_MIPS_PCHI16 00000000 bar \+ 7fec +00000004 00000905 R_MIPS_HI16 00000000 baz \+ 0 +00000008 00000840 R_MIPS_PCHI16 00000000 bar \+ 7ff8 +0000000c 00000840 R_MIPS_PCHI16 00000000 bar \+ fff0 +00000010 00000841 R_MIPS_PCLO16 00000000 bar \+ 7ffc +00000014 00000906 R_MIPS_LO16 00000000 baz \+ 0 +00000018 00000841 R_MIPS_PCLO16 00000000 bar \+ 8008 +0000001c 00000841 R_MIPS_PCLO16 00000000 bar \+ 10000 +00000020 00000840 R_MIPS_PCHI16 00000000 bar \+ 800c +00000024 00000905 R_MIPS_HI16 00000000 baz \+ 0 +00000028 00000840 R_MIPS_PCHI16 00000000 bar \+ 8018 +0000002c 00000840 R_MIPS_PCHI16 00000000 bar \+ 10010 +00030030 00000841 R_MIPS_PCLO16 00000000 bar \+ 3801c +00030034 00000906 R_MIPS_LO16 00000000 baz \+ 0 +00030038 00000841 R_MIPS_PCLO16 00000000 bar \+ 38028 +0003003c 00000841 R_MIPS_PCLO16 00000000 bar \+ 40020 +00030040 00000841 R_MIPS_PCLO16 00000000 bar \+ 3802c +00030044 00000906 R_MIPS_LO16 00000000 baz \+ 0 +00030048 00000841 R_MIPS_PCLO16 00000000 bar \+ 38038 +0003004c 00000841 R_MIPS_PCLO16 00000000 bar \+ 40030 +00030050 00000840 R_MIPS_PCHI16 00000000 bar \+ 3803c +00030054 00000905 R_MIPS_HI16 00000000 baz \+ 0 +00030058 00000840 R_MIPS_PCHI16 00000000 bar \+ 38048 +0003005c 00000840 R_MIPS_PCHI16 00000000 bar \+ 40040 diff --git a/gas/testsuite/gas/mips/pcrel-hilo.d b/gas/testsuite/gas/mips/pcrel-hilo.d new file mode 100644 index 00000000000..a96e4f2375e --- /dev/null +++ b/gas/testsuite/gas/mips/pcrel-hilo.d @@ -0,0 +1,30 @@ +#readelf: -r +#name: MIPSr6 PCHI16/PCLO16 relocations (o32) +#as: -mabi=32 -mno-pdr + +Relocation section '\.rel\.text' at offset .+ contains 24 entries: + Offset Info Type Sym\.Value Sym\. Name +00030050 00000840 R_MIPS_PCHI16 00000000 bar +00000000 00000840 R_MIPS_PCHI16 00000000 bar +00000010 00000841 R_MIPS_PCLO16 00000000 bar +00000004 00000905 R_MIPS_HI16 00000000 baz +00000014 00000906 R_MIPS_LO16 00000000 baz +00030058 00000840 R_MIPS_PCHI16 00000000 bar +00000028 00000840 R_MIPS_PCHI16 00000000 bar +00000008 00000840 R_MIPS_PCHI16 00000000 bar +00000018 00000841 R_MIPS_PCLO16 00000000 bar +0003005c 00000840 R_MIPS_PCHI16 00000000 bar +0000002c 00000840 R_MIPS_PCHI16 00000000 bar +0000000c 00000840 R_MIPS_PCHI16 00000000 bar +0000001c 00000841 R_MIPS_PCLO16 00000000 bar +00000020 00000840 R_MIPS_PCHI16 00000000 bar +00030030 00000841 R_MIPS_PCLO16 00000000 bar +00000024 00000905 R_MIPS_HI16 00000000 baz +00030034 00000906 R_MIPS_LO16 00000000 baz +00030038 00000841 R_MIPS_PCLO16 00000000 bar +0003003c 00000841 R_MIPS_PCLO16 00000000 bar +00030040 00000841 R_MIPS_PCLO16 00000000 bar +00030054 00000905 R_MIPS_HI16 00000000 baz +00030044 00000906 R_MIPS_LO16 00000000 baz +00030048 00000841 R_MIPS_PCLO16 00000000 bar +0003004c 00000841 R_MIPS_PCLO16 00000000 bar diff --git a/gas/testsuite/gas/mips/pcrel-hilo.s b/gas/testsuite/gas/mips/pcrel-hilo.s new file mode 100644 index 00000000000..4a8278f1b24 --- /dev/null +++ b/gas/testsuite/gas/mips/pcrel-hilo.s @@ -0,0 +1,48 @@ + .module mips64r6 + + .text + .align 16 + .globl foo + .ent foo +foo: +0: auipc $4, %pcrel_hi(bar + 0x7fec) +1: lui $5, %hi(baz) +2: auipc $6, %pcrel_hi(bar + 0x7ff8) +3: auipc $7, %pcrel_hi(bar + 0xfff0) +4: addiu $4, %pcrel_lo(bar + 0x7fec + (4b - 0b)) +5: addiu $5, %lo(baz) +6: addiu $6, %pcrel_lo(bar + 0x7ff8 + (6b - 2b)) +7: addiu $7, %pcrel_lo(bar + 0xfff0 + (7b - 3b)) +10: auipc $4, %pcrel_hi(bar + 0x800c) +11: lui $5, %hi(baz) +12: auipc $6, %pcrel_hi(bar + 0x8018) +13: auipc $7, %pcrel_hi(bar + 0x10010) + .rept 49152 + nop + .endr +14: addiu $4, %pcrel_lo(bar + 0x800c + (14b - 10b)) +15: addiu $5, %lo(baz) +16: addiu $6, %pcrel_lo(bar + 0x8018 + (16b - 12b)) +17: addiu $7, %pcrel_lo(bar + 0x10010 + (17b - 13b)) +24: addiu $16, $0, %pcrel_lo(bar + 0x3803c + (24b - 20f)) +25: addiu $17, $0, %lo(baz) +26: addiu $18, $0, %pcrel_lo(bar + 0x38048 + (26b - 22f)) +27: addiu $19, $0, %pcrel_lo(bar + 0x40040 + (27b - 23f)) +20: auipc $4, %pcrel_hi(bar + 0x3803c) +21: lui $5, %hi(baz) +22: auipc $6, %pcrel_hi(bar + 0x38048) +23: auipc $7, %pcrel_hi(bar + 0x40040) + addu $4, $4, $16 + addu $5, $5, $17 + addu $6, $6, $18 + addu $7, $7, $19 + jrc $31 + .end foo + + .data + .align 16 + .globl bar + .type bar, @object +bar: + .space 0x18000 + .size bar, . - bar diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index e95f1e739cd..6fc960dfc10 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -855,6 +855,17 @@ run_dump_test_n32 "micromips-hilo-srec" \ run_dump_test_n64 "micromips-hilo-srec-n64" \ [list noarch \ [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]] +run_dump_test_o32 "pcrel-hilo" +run_dump_test_n32 "pcrel-hilo" [list [list name (n32)]] +run_dump_test_n64 "pcrel-hilo" [list [list name (n64)]] +run_dump_test_o32 "pcrel-hilo-srec" \ + [list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]] +run_dump_test_n32 "pcrel-hilo-srec" \ + [list [list name (n32)] \ + [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]] +run_dump_test_n64 "pcrel-hilo-srec" \ + [list [list name (n64)] \ + [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]] if { $linux_gnu } { run_dump_test_n32 "textrel-1" diff --git a/ld/testsuite/ld-mips-elf/pcrel-hilo-srec.d b/ld/testsuite/ld-mips-elf/pcrel-hilo-srec.d new file mode 100644 index 00000000000..e9b09567f4a --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pcrel-hilo-srec.d @@ -0,0 +1,6 @@ +#name: MIPSr6 PCHI16/PCLO16 relocations srec +#as: -mno-pdr +#ld: -e 0 --defsym=baz=0xfedcba98 -T pcrel-hilo.ld --oformat=srec +#objdump: -m mips:isa64r6 -D -j .sec1 +#source: ../../../gas/testsuite/gas/mips/pcrel-hilo.s +#dump: pcrel-hilo.d diff --git a/ld/testsuite/ld-mips-elf/pcrel-hilo.d b/ld/testsuite/ld-mips-elf/pcrel-hilo.d new file mode 100644 index 00000000000..ae5d0522229 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pcrel-hilo.d @@ -0,0 +1,42 @@ +#name: MIPSr6 PCHI16/PCLO16 relocations +#as: -mno-pdr +#ld: -e 0 --defsym=baz=0xfedcba98 -T pcrel-hilo.ld +#objdump: -m mips:isa64r6 -d +#source: ../../../gas/testsuite/gas/mips/pcrel-hilo.s + +.*: +file format (?:.*mips.*|srec) + +Disassembly of section \.(?:text|sec1): + +0*10000000 <[^>]*>: + *10000000: ec9e2456 auipc a0,0x2456 + *10000004: 3c05fedd lui a1,0xfedd + *10000008: ecde2456 auipc a2,0x2456 + *1000000c: ecfe2457 auipc a3,0x2457 + *10000010: 24847fec addiu a0,a0,32748 + *10000014: 24a5ba98 addiu a1,a1,-17768 + *10000018: 24c67ff0 addiu a2,a2,32752 + *1000001c: 24e7ffe4 addiu a3,a3,-28 + *10000020: ec9e2456 auipc a0,0x2456 + *10000024: 3c05fedd lui a1,0xfedd + *10000028: ecde2456 auipc a2,0x2456 + *1000002c: ecfe2457 auipc a3,0x2457 + \.\.\. + *10030030: 24847fec addiu a0,a0,32748 + *10030034: 24a5ba98 addiu a1,a1,-17768 + *10030038: 24c67ff0 addiu a2,a2,32752 + *1003003c: 24e7ffe4 addiu a3,a3,-28 + *10030040: 24107fec li s0,32748 + *10030044: 2411ba98 li s1,-17768 + *10030048: 24127ff0 li s2,32752 + *1003004c: 2413ffe4 li s3,-28 + *10030050: ec9e2456 auipc a0,0x2456 + *10030054: 3c05fedd lui a1,0xfedd + *10030058: ecde2456 auipc a2,0x2456 + *1003005c: ecfe2457 auipc a3,0x2457 + *10030060: 00902021 addu a0,a0,s0 + *10030064: 00b12821 addu a1,a1,s1 + *10030068: 00d23021 addu a2,a2,s2 + *1003006c: 00f33821 addu a3,a3,s3 + *10030070: d81f0000 jrc ra + \.\.\. diff --git a/ld/testsuite/ld-mips-elf/pcrel-hilo.ld b/ld/testsuite/ld-mips-elf/pcrel-hilo.ld new file mode 100644 index 00000000000..77d361d9317 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pcrel-hilo.ld @@ -0,0 +1,14 @@ +MEMORY +{ + text (rx) : ORIGIN = 0x10000000, LENGTH = 0x40000 + data (w) : ORIGIN = 0x34560000, LENGTH = 0x40000 +} +SECTIONS +{ + .text : { *(.text) } >text + .data : { *(.data) } >data + .symtab : { *(.symtab) } + .strtab : { *(.strtab) } + .shstrtab : { *(.shstrtab) } + /DISCARD/ : { *(*) } +}