This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
R_ARC_B22_PCREL relocs busted?
- To: binutils at sourceware dot cygnus dot com
- Subject: R_ARC_B22_PCREL relocs busted?
- From: Andre Paquette <APaquette at Catena dot com>
- Date: Thu, 20 Sep 2001 10:30:44 -0400
Folks,
In the ARC target, it looks like pc-relative branches fixed during linking
are busted. Note that I did pick up the recent fixes to enable
partial_inplace and disable pcrel_offset in bfd/elf32-arc.c.
To reproduce, take the two source files below and assemble separately, then
link.
1.s:
===
.extern _myfunc
.global main
.text
main:
nop
nop
bl _myfunc
b main
2.s:
===
.text
.global _myfunc
_myfunc:
j.f [blink]
Here is the resulting disassembly:
a.out: file format elf32-littlearc
Disassembly of section .text:
00000074 <main>:
74: ff ff ff 7f 7fffffff nop
78: ff ff ff 7f 7fffffff nop
7c: 80 01 00 28 28000180 bl 8c <_myfunc+0x8>
80: 00 fe ff 27 27fffe00 b 74 <main>
00000084 <_myfunc>:
84: 00 81 0f 38 380f8100 j.f [blink]
I have come up with a patch for this but I'm certain that I'm just
addressing the symptom, not the root of the problem. Perhaps a coordinated
change between the assembler and linker would be better. Also, I'm not
certain if I've caught all the appropriate conditions under which the addend
fudge needs to be applied. If those in the know (Nick?) could have a look
and determine the correct solution, it would be appreciated.
Thanks,
Andre Paquette
Index: elf32-arc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arc.c,v
retrieving revision 1.8
diff -C3 -r1.8 elf32-arc.c
*** elf32-arc.c 2001/09/18 09:57:23 1.8
--- elf32-arc.c 2001/09/20 14:34:29
***************
*** 32,37 ****
--- 32,39 ----
PARAMS ((bfd *));
static void arc_elf_final_write_processing
PARAMS ((bfd *, boolean));
+ static bfd_reloc_status_type arc_elf_pcrel_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
/* Try to minimize the amount of space occupied by relocation tables
on the ROM (not that the ROM won't be swamped by other ELF overhead).
*/
***************
*** 93,99 ****
true, /* pc_relative */
7, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
! bfd_elf_generic_reloc, /* special_function */
"R_ARC_B22_PCREL", /* name */
true, /* partial_inplace */
0x07ffff80, /* src_mask */
--- 95,101 ----
true, /* pc_relative */
7, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
! arc_elf_pcrel_reloc, /* special_function */
"R_ARC_B22_PCREL", /* name */
true, /* partial_inplace */
0x07ffff80, /* src_mask */
***************
*** 101,106 ****
--- 103,144 ----
false), /* pcrel_offset */
};
+
+ /* Taken from elf.c, bfd_elf_generic_reloc with the exception that
+ * the addend gets fudged when passed to the linker. */
+
+ bfd_reloc_status_type
+ arc_elf_pcrel_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data ATTRIBUTE_UNUSED;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message ATTRIBUTE_UNUSED;
+ {
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && (! reloc_entry->howto->partial_inplace
+ || reloc_entry->addend == 0))
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* If linking, back up the final symbol address by the address
+ of the reloc. */
+ if (output_bfd == (bfd *) NULL)
+ reloc_entry->addend -= reloc_entry->address;
+
+ return bfd_reloc_continue;
+ }
/* Map BFD reloc types to ARC ELF reloc types. */