This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: [PATCH] Fix handling of R_MIPS_PC16 relocations
- To: binutils at sources dot redhat dot com
- Subject: Re: [PATCH] Fix handling of R_MIPS_PC16 relocations
- From: Thiemo Seufer <ica2_ts at csv dot ica dot uni-stuttgart dot de>
- Date: Fri, 7 Sep 2001 00:59:55 +0200
- References: <20010826233029.F13086@rembrandt.csv.ica.uni-stuttgart.de>
Thiemo Seufer wrote:
[snip]
> /bfd/ChangeLog (elf_mips_howto_table): Fix rightshift for R_MIPS_PC16.
> (mips_reloc_map): Map R_MIPS_PC16 to the BFD_RELOC_16_PCREL_S2.
> (mips_elf_calculate_relocation): Fix handling of R_MIPS_PC16.
> (_bfd_mips_elf_relocate_section): Likewise.
This patch was wrong. The R_MIPS_PC16 relocation actually spans an
offset of only 16 bit while the hardware (and internal branches
without a reloc) can do 18 bit. I have no explanation why this was
defined this way. The appended patch adds handling for R_MIPS_PC16
to gas and bfd. Tested for mips64-linux and mips-elf.
Thiemo
2001-09-07 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
/bfd/ChangeLog
* elf32-mips.c (mips_elf_calculate_relocation): Fix overflow handling
of R_MIPS_PC16.
/gas/ChangeLog
* config/tc-mips.c (append_insn): Handle BFD_RELOC_16_PCREL.
(macro_build): Use BFD_RELOC_16_PCREL_S2 only for embedded
PIC, BFD_RELOC_16_PCREL for the rest.
(mips_ip): Likewise.
(md_pcrel_from): return the right offset for the differently shifted
pcrel relocs.
(md_apply_fix): Handle BFD_RELOC_16_PCREL.
/gas/testsuite/ChangeLog
* gas/mips/beq.d: Check branches to external labels.
* gas/mips/beq.s: Likewise.
* gas/mips/bge.d: Likewise.
* gas/mips/bge.s: Likewise.
* gas/mips/bgeu.d: Likewise.
* gas/mips/bgeu.s: Likewise.
* gas/mips/blt.d: Likewise.
* gas/mips/blt.s: Likewise.
* gas/mips/bltu.d: Likewise.
* gas/mips/bltu.s: Likewise.
* gas/mips/elempic.d: Switch from R_MIPS_GNU_REL16_S2 to R_MIPS_PC16.
* gas/mips/empic.d: Likewise.
* gas/mips/empic.s: Likewise.
* gas/mips/telempic.d: Likewise.
* gas/mips/tempic.d: Likewise.
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/bfd/elf32-mips.c src/bfd/elf32-mips.c
--- src-orig/bfd/elf32-mips.c Fri Aug 31 21:59:55 2001
+++ src/bfd/elf32-mips.c Thu Sep 6 21:11:29 2001
@@ -6488,8 +6488,8 @@ mips_elf_calculate_relocation (abfd,
case R_MIPS_PC16:
value = mips_elf_sign_extend (addend, 16) + symbol - p;
- value = (bfd_vma) ((bfd_signed_vma) value / 4);
overflowed_p = mips_elf_overflow_p (value, 16);
+ value = (bfd_vma) ((bfd_signed_vma) value / 4);
break;
case R_MIPS_GOT_HI16:
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/config/tc-mips.c src/gas/config/tc-mips.c
--- src-orig/gas/config/tc-mips.c Fri Aug 31 22:00:08 2001
+++ src/gas/config/tc-mips.c Thu Sep 6 21:58:05 2001
@@ -1898,6 +1978,10 @@ append_insn (place, ip, address_expr, re
| ((address_expr->X_add_number & 0x3fffc) >> 2));
break;
+ case BFD_RELOC_16_PCREL:
+ ip->insn_opcode |= (address_expr->X_add_number >> 2) & 0xffff;
+ break;
+
case BFD_RELOC_16_PCREL_S2:
goto need_reloc;
@@ -1914,7 +1998,8 @@ append_insn (place, ip, address_expr, re
{
fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
address_expr,
- reloc_type == BFD_RELOC_16_PCREL_S2,
+ (reloc_type == BFD_RELOC_16_PCREL
+ || reloc_type == BFD_RELOC_16_PCREL_S2),
reloc_type);
if (unmatched_hi)
{
@@ -2699,7 +2804,10 @@ macro_build (place, counter, ep, name, f
ep = NULL;
}
else
- r = BFD_RELOC_16_PCREL_S2;
+ if (mips_pic == EMBEDDED_PIC)
+ r = BFD_RELOC_16_PCREL_S2;
+ else
+ r = BFD_RELOC_16_PCREL;
continue;
case 'a':
@@ -7791,7 +8131,10 @@ mips_ip (str, ip)
continue;
case 'p': /* pc relative offset */
- offset_reloc = BFD_RELOC_16_PCREL_S2;
+ if (mips_pic == EMBEDDED_PIC)
+ offset_reloc = BFD_RELOC_16_PCREL_S2;
+ else
+ offset_reloc = BFD_RELOC_16_PCREL;
my_getExpression (&offset_expr, s);
s = expr_end;
continue;
@@ -9427,9 +9836,16 @@ md_pcrel_from (fixP)
&& fixP->fx_addsy != (symbolS *) NULL
&& ! S_IS_DEFINED (fixP->fx_addsy))
{
- /* This makes a branch to an undefined symbol be a branch to the
- current location. */
- return 4;
+ if (mips_pic == EMBEDDED_PIC)
+ {
+ /* This makes a branch to an undefined symbol be a branch to the
+ current location. */
+ return 4;
+ }
+ else
+ {
+ return 1;
+ }
}
/* return the address of the delay slot */
@@ -9666,7 +10102,8 @@ md_apply_fix (fixP, valueP)
/* BFD's REL handling, for MIPS, is _very_ weird.
This gives the right results, but it can't possibly
be the way things are supposed to work. */
- if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
+ if ((fixP->fx_r_type != BFD_RELOC_16_PCREL
+ && fixP->fx_r_type != BFD_RELOC_16_PCREL_S2)
|| S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
value += fixP->fx_frag->fr_address + fixP->fx_where;
}
@@ -9812,15 +10268,18 @@ md_apply_fix (fixP, valueP)
break;
case BFD_RELOC_16_PCREL_S2:
+ if ((value & 0x3) != 0)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Branch to odd address (%lx)"), (long) value);
+
+ /* Fall through. */
+
+ case BFD_RELOC_16_PCREL:
/*
* We need to save the bits in the instruction since fixup_segment()
* might be deleting the relocation entry (i.e., a branch within
* the current segment).
*/
- if ((value & 0x3) != 0)
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("Branch to odd address (%lx)"), (long) value);
-
if (!fixP->fx_done && value != 0)
break;
/* If 'value' is zero, the remaining reloc code won't actually
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/beq.d src/gas/testsuite/gas/mips/beq.d
--- src-orig/gas/testsuite/gas/mips/beq.d Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/beq.d Fri Aug 31 23:01:41 2001
@@ -37,4 +37,10 @@ Disassembly of section .text:
0+2006c <[^>]*> nop
0+20070 <[^>]*> jal 0+0000 <text_label>
[ ]*20070: (MIPS_JMP|JMPADDR|R_MIPS_26) .text
+0+20074 <[^>]*> nop
+0+20078 <[^>]*> b 0+20078 <text_label\+0x20078>
+[ ]*20078: R_MIPS_PC16 external_label
+0+2007c <[^>]*> nop
+0+20080 <[^>]*> bal 0+20080 <text_label\+0x20080>
+[ ]*20080: R_MIPS_PC16 external_label
...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/beq.s src/gas/testsuite/gas/mips/beq.s
--- src-orig/gas/testsuite/gas/mips/beq.s Mon May 3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/beq.s Fri Aug 31 23:01:41 2001
@@ -22,7 +22,9 @@ text_label:
b text_label
bal text_label
+# Branch to an external label.
+ b external_label
+ bal external_label
+
# Round to a 16 byte boundary, for ease in testing multiple targets.
- nop
- nop
nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bge.d src/gas/testsuite/gas/mips/bge.d
--- src-orig/gas/testsuite/gas/mips/bge.d Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/bge.d Fri Aug 31 23:01:41 2001
@@ -50,4 +50,20 @@ Disassembly of section .text:
0+00a4 <[^>]*> nop
0+00a8 <[^>]*> slt at,a1,a0
0+00ac <[^>]*> bnezl at,0+0000 <text_label>
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> slt at,a0,a1
+0+00b8 <[^>]*> beqz at,000000b8 <text_label\+0xb8>
+[ ]*b8: R_MIPS_PC16 external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> slt at,a1,a0
+0+00c4 <[^>]*> bnez at,000000c4 <text_label\+0xc4>
+[ ]*c4: R_MIPS_PC16 external_label
+0+00c8 <[^>]*> nop
+0+00cc <[^>]*> slt at,a0,a1
+0+00d0 <[^>]*> beqzl at,000000d0 <text_label\+0xd0>
+[ ]*d0: R_MIPS_PC16 external_label
+0+00d4 <[^>]*> nop
+0+00d8 <[^>]*> slt at,a1,a0
+0+00dc <[^>]*> bnezl at,000000dc <text_label\+0xdc>
+[ ]*dc: R_MIPS_PC16 external_label
...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bge.s src/gas/testsuite/gas/mips/bge.s
--- src-orig/gas/testsuite/gas/mips/bge.s Mon May 3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/bge.s Fri Aug 31 23:01:41 2001
@@ -24,6 +24,12 @@ text_label:
bgel $4,$5,text_label
bgtl $4,$5,text_label
+# Branch to an external label.
+ bge $4,$5,external_label
+ bgt $4,$5,external_label
+ bgel $4,$5,external_label
+ bgtl $4,$5,external_label
+
# Round to a 16 byte boundary, for ease in testing multiple targets.
nop
nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bgeu.d src/gas/testsuite/gas/mips/bgeu.d
--- src-orig/gas/testsuite/gas/mips/bgeu.d Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/bgeu.d Fri Aug 31 23:01:41 2001
@@ -44,4 +44,20 @@ Disassembly of section .text:
0+008c <[^>]*> nop
0+0090 <[^>]*> sltu at,a1,a0
0+0094 <[^>]*> bnezl at,0+0000 <text_label>
+0+0098 <[^>]*> nop
+0+009c <[^>]*> sltu at,a0,a1
+0+00a0 <[^>]*> beqz at,000000a0 <text_label\+0xa0>
+[ ]*a0: R_MIPS_PC16 external_label
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> sltu at,a1,a0
+0+00ac <[^>]*> bnez at,000000ac <text_label\+0xac>
+[ ]*ac: R_MIPS_PC16 external_label
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> sltu at,a0,a1
+0+00b8 <[^>]*> beqzl at,000000b8 <text_label\+0xb8>
+[ ]*b8: R_MIPS_PC16 external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> sltu at,a1,a0
+0+00c4 <[^>]*> bnezl at,000000c4 <text_label\+0xc4>
+[ ]*c4: R_MIPS_PC16 external_label
...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bgeu.s src/gas/testsuite/gas/mips/bgeu.s
--- src-orig/gas/testsuite/gas/mips/bgeu.s Mon May 3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/bgeu.s Fri Aug 31 23:01:41 2001
@@ -22,6 +22,12 @@ text_label:
bgeul $4,$5,text_label
bgtul $4,$5,text_label
+# Branch to an external label.
+ bgeu $4,$5,external_label
+ bgtu $4,$5,external_label
+ bgeul $4,$5,external_label
+ bgtul $4,$5,external_label
+
# Round to a 16 byte boundary, for ease in testing multiple targets.
nop
nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/blt.d src/gas/testsuite/gas/mips/blt.d
--- src-orig/gas/testsuite/gas/mips/blt.d Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/blt.d Fri Aug 31 23:01:41 2001
@@ -50,4 +50,20 @@ Disassembly of section .text:
0+00a4 <[^>]*> nop
0+00a8 <[^>]*> slt at,a1,a0
0+00ac <[^>]*> beqzl at,0+0000 <text_label>
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> slt at,a0,a1
+0+00b8 <[^>]*> bnez at,000000b8 <text_label\+0xb8>
+[ ]*b8: R_MIPS_PC16 external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> slt at,a1,a0
+0+00c4 <[^>]*> beqz at,000000c4 <text_label\+0xc4>
+[ ]*c4: R_MIPS_PC16 external_label
+0+00c8 <[^>]*> nop
+0+00cc <[^>]*> slt at,a0,a1
+0+00d0 <[^>]*> bnezl at,000000d0 <text_label\+0xd0>
+[ ]*d0: R_MIPS_PC16 external_label
+0+00d4 <[^>]*> nop
+0+00d8 <[^>]*> slt at,a1,a0
+0+00dc <[^>]*> beqzl at,000000dc <text_label\+0xdc>
+[ ]*dc: R_MIPS_PC16 external_label
...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/blt.s src/gas/testsuite/gas/mips/blt.s
--- src-orig/gas/testsuite/gas/mips/blt.s Mon May 3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/blt.s Fri Aug 31 23:01:41 2001
@@ -24,6 +24,12 @@ text_label:
bltl $4,$5,text_label
blel $4,$5,text_label
+# Branch to an external label.
+ blt $4,$5,external_label
+ ble $4,$5,external_label
+ bltl $4,$5,external_label
+ blel $4,$5,external_label
+
# Round to a 16 byte boundary, for ease in testing multiple targets.
nop
nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bltu.d src/gas/testsuite/gas/mips/bltu.d
--- src-orig/gas/testsuite/gas/mips/bltu.d Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/bltu.d Fri Aug 31 23:01:41 2001
@@ -44,4 +44,20 @@ Disassembly of section .text:
0+008c <[^>]*> nop
0+0090 <[^>]*> sltu at,a1,a0
0+0094 <[^>]*> beqzl at,0+0000 <text_label>
+0+0098 <[^>]*> nop
+0+009c <[^>]*> sltu at,a0,a1
+0+00a0 <[^>]*> bnez at,000000a0 <text_label\+0xa0>
+[ ]*a0: R_MIPS_PC16 external_label
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> sltu at,a1,a0
+0+00ac <[^>]*> beqz at,000000ac <text_label\+0xac>
+[ ]*ac: R_MIPS_PC16 external_label
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> sltu at,a0,a1
+0+00b8 <[^>]*> bnezl at,000000b8 <text_label\+0xb8>
+[ ]*b8: R_MIPS_PC16 external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> sltu at,a1,a0
+0+00c4 <[^>]*> beqzl at,000000c4 <text_label\+0xc4>
+[ ]*c4: R_MIPS_PC16 external_label
...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bltu.s src/gas/testsuite/gas/mips/bltu.s
--- src-orig/gas/testsuite/gas/mips/bltu.s Mon May 3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/bltu.s Fri Aug 31 23:01:41 2001
@@ -22,6 +22,12 @@ text_label:
bltul $4,$5,text_label
bleul $4,$5,text_label
+# Branch to an external label.
+ bltu $4,$5,external_label
+ bleu $4,$5,external_label
+ bltul $4,$5,external_label
+ bleul $4,$5,external_label
+
# Round to a 16 byte boundary, for ease in testing multiple targets.
nop
nop