This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

sh-elf: the substraction of two symbols


Hi,

I have a problem with the sh-elf toolchain. Current as/ld for sh-elf
doesn't handle the substraction of two symbols correctly, if these
two symbols are in different sections.
For example, foo.s

        .little
        .text
        .align 5
f:
	rts
	 nop
        .section .text.foo,"aw",@progbits
        .align 5
        .global ff
ff:
	nop
	nop
	nop
	nop
L:	
	rts
	 nop
        .align 2
        .long   f-L	! <- This

is assembled to foo.o:

Disassembly of section .text
[snip]
Disassembly of section .text.foo:

00000000 <ff>:
   0:   09 00           .word 0x0900
   2:   09 00           .word 0x0900
   4:   09 00           .word 0x0900
   6:   09 00           .word 0x0900

00000008 <L>:
   8:   0b 00           .word 0x0b00
   a:   09 00           .word 0x0900
   c:   f8 ff           .word 0xf8ff
   e:   ff ff           .word 0xffff

and readelf shows that there is a relocation

Relocation section '.rela.text.foo' at offset 0x2a8 contains 1 entries:
  Offset    Info  Type            Symbol's Value  Symbol's Name          Addend
  0000000c  00102 R_SH_REL32            00000000  .text                     + 0

Then ld -EL outputs the following result from foo.o:

Disassembly of section .text:

00000340 <f>:
 340:   0b 00           rts     
 342:   09 00           nop     
        ...

00000360 <ff>:
 360:   09 00           nop     
 362:   09 00           nop     
 364:   09 00           nop     
 366:   09 00           nop     

00000368 <L>:
 368:   0b 00           rts     
 36a:   09 00           nop     
 36c:   d4 ff           .word 0xffd4
 36e:   ff ff           .word 0xffff

and there is no relocation at 0x36c.
Here we get 0xffffffd4 in the word at 0x36c instead of
  f - L = 0x340 - 0x368 = 0xffffffd8.

The relocation type R_SH_REL32 wants the relocation by
  (the value of symbol) - (the position of object) + (the value of reloc)
and in the above case, this is
  f (== .text) - (L + 4) + (the value of reloc). So the value of
reloc must to be 4 in foo.o. It seems that we need a hack in
md_apply_fix like i386 backend does for BFD_RELLOC_32_PCREL in
md_apply_fix3 to get correct in-place relocation.

The second point is that sh-elf ld ignores in-place relocation
for R_SH_REL32, though it seems the assembler gives in-place value
for this type of relocation.

One more another problem occurs when generating a relocateable object
from multiple objects which include R_SH_REL32 relocations for the
section symbol. An simple example can be get from a.s

	.text
	nop
	nop
	nop
	nop

and ld -EL -r -o afoo.ro a.o foo.o.
The linker applies _bfd_final_link_relocate in sh_elf_relocate_section
to wind up the relocation from foo.o since the symbol f becomes not
equal to .text in the output section.
But _bfd_final_link_relocate treats pc_rel relocations specially
which is wrong operation in this case. It seems that we have to call
_bfd_relocate_contents directly.

Under these changes, the results of small tests looks good and some
shared libraries which didn't work can run in sh-linux now.
But I suspect that these changes may break something. Anyway, I'd
like to append my patch to clarify my point.
Thoughts?

	kaz
--
--- cvs/src/gas/config/tc-sh.c  Sat Nov 18 00:50:50 2000
+++ binutils-current/gas/config/tc-sh.c Tue Nov 28 06:57:47 2000
@@ -2779,6 +2779,11 @@
       && fixP->fx_addsy != NULL
       && S_IS_WEAK (fixP->fx_addsy))
     val -= S_GET_VALUE  (fixP->fx_addsy);
+
+  if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+      && fixP->fx_r_type == BFD_RELOC_32_PCREL
+      && fixP->fx_addsy != NULL)
+    val += fixP->fx_where + fixP->fx_frag->fr_address;
 #endif
 
 #ifndef BFD_ASSEMBLER

--- cvs/src/bfd/elf32-sh.c	Sun Nov 12 00:50:20 2000
+++ binutils-current/bfd/elf32-sh.c	Mon Jan  1 12:10:57 2001
@@ -120,8 +120,8 @@
 	 complain_overflow_signed, /* complain_on_overflow */
 	 sh_elf_ignore_reloc,	/* special_function */
 	 "R_SH_REL32",		/* name */
-	 false,			/* partial_inplace */
-	 0,			/* src_mask */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
 
@@ -2940,7 +2940,11 @@
 		 section symbol winds up in the output section.  */
 	      sym = local_syms + r_symndx;
 	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-		goto final_link_relocate;
+		{
+		  r = _bfd_relocate_contents (howto, input_bfd, relocation,
+					      contents + rel->r_offset);
+		  goto relocation_done;
+		}
 
 	      continue;
 	    }
@@ -3331,6 +3335,7 @@
 	  }
 	}
 
+    relocation_done:
       if (r != bfd_reloc_ok)
 	{
 	  switch (r)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]