[patch] m32r gas relocation processing

Doug Evans dje@transmeta.com
Thu Mar 9 15:14:00 GMT 2000


Catherine Moore writes:
 > I would like to propose the following patch which fixes a problem in
 > gas/cgen.c.  This problem shows up in the m32r port and can be
 > demonstrated with the following test case:
 > 
 >         .global stra
 >         .section .data
 >         .balign 4
 >         .type    stra,@object
 >         .size    stra,4
 > stra:
 >         .word   7
 >         .word   8
 >         .word   9
 >         .global Nest
 >         .weak Nest
 >         .balign 4
 >         .type    Nest,@object
 >         .size    Nest,8
 > Nest:
 >         .word   1
 >         .word   2
 >         .word   3
 >         .word   4
 >         .word   5
 >         .word   6
 >  
 >         .section .text
 >         .balign 4
 >         .global main
 >         .type    main,@function
 > main:
 >         seth r4,#shigh(Nest+4)
 >         ld r1,@(low(Nest+4),r4)
 >         jmp lr
 > 
 >  
 > Disassembly of section .text:
 >  
 > 00000000 <main>:
 >    0:   d4 c0 00 00     seth r4,#0x0
 >                         0: R_M32R_HI16_SLO      Nest
 >    4:   a1 c4 00 10     ld r1,@(16,r4)
 >                         4: R_M32R_LO16  Nest
 >    8:   1f ce f0 00     jmp lr || nop
 > 
 > An objdump -dr on the resulting object files reveals that an offset of
 > 16 has been generated for the second reloc.  This would be correct if
 > we were relocating against the data section.  In this case, we are
 > relocating against the symbol Nest.  The correct offset should be 4.
 > 
 > This problem would probably show up in any port that uses gas/cgen.c
 > and REL type relocations.  I don't know if there is an accepted way
 > to determine that a particular port uses REL relocations in the
 > generic portion of gas.  This patch does this extra processing only
 > if TC_M32R is defined.  I am open to suggestions for coding this in
 > a more target-independent fashion.

How about this instead?
I've been slow in fully testing this [or it would have been installed
already].  Maybe you can help?

2000-03-09  Doug Evans  <dje@casey.transmeta.com>

	* elf32-m32r.c (m32r_elf_lo16_reloc): Rewrite.

Index: elf32-m32r.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m32r.c,v
retrieving revision 1.6
diff -c -p -r1.6 elf32-m32r.c
*** elf32-m32r.c	2000/03/01 19:40:53	1.6
--- elf32-m32r.c	2000/03/09 23:08:03
*************** m32r_elf_relocate_hi16 (input_bfd, type,
*** 498,506 ****
     R_M32R_HI16_[SU]LO relocation described above.  */
  
  bfd_reloc_status_type
! m32r_elf_lo16_reloc (abfd, reloc_entry, symbol, data,
  		     input_section, output_bfd, error_message)
!      bfd *abfd;
       arelent *reloc_entry;
       asymbol *symbol;
       PTR data;
--- 498,506 ----
     R_M32R_HI16_[SU]LO relocation described above.  */
  
  bfd_reloc_status_type
! m32r_elf_lo16_reloc (input_bfd, reloc_entry, symbol, data,
  		     input_section, output_bfd, error_message)
!      bfd *input_bfd;
       arelent *reloc_entry;
       asymbol *symbol;
       PTR data;
*************** m32r_elf_lo16_reloc (abfd, reloc_entry, 
*** 508,513 ****
--- 508,528 ----
       bfd *output_bfd;
       char **error_message;
  {
+   bfd_reloc_status_type ret;
+   bfd_vma relocation;
+   unsigned long insn;
+ 
+   /* This part is from bfd_elf_generic_reloc.
+      If we're relocating, and this an external symbol, we don't want
+      to change anything.  */
+   if (output_bfd != (bfd *) NULL
+       && (symbol->flags & BSF_SECTION_SYM) == 0
+       && reloc_entry->addend == 0)
+     {
+       reloc_entry->address += input_section->output_offset;
+       return bfd_reloc_ok;
+     }
+ 
    if (m32r_hi16_list != NULL)
      {
        struct m32r_hi16 *l;
*************** m32r_elf_lo16_reloc (abfd, reloc_entry, 
*** 523,530 ****
  	  /* Do the HI16 relocation.  Note that we actually don't need
  	     to know anything about the LO16 itself, except where to
  	     find the low 16 bits of the addend needed by the LO16.  */
! 	  insn = bfd_get_32 (abfd, l->addr);
! 	  vallo = ((bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
  		   & 0xffff) ^ 0x8000) - 0x8000;
  	  val = ((insn & 0xffff) << 16) + vallo;
  	  val += l->addend;
--- 538,545 ----
  	  /* Do the HI16 relocation.  Note that we actually don't need
  	     to know anything about the LO16 itself, except where to
  	     find the low 16 bits of the addend needed by the LO16.  */
! 	  insn = bfd_get_32 (input_bfd, l->addr);
! 	  vallo = ((bfd_get_32 (input_bfd, (bfd_byte *) data + reloc_entry->address)
  		   & 0xffff) ^ 0x8000) - 0x8000;
  	  val = ((insn & 0xffff) << 16) + vallo;
  	  val += l->addend;
*************** m32r_elf_lo16_reloc (abfd, reloc_entry, 
*** 534,540 ****
  	    val += 0x10000;
  
  	  insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
! 	  bfd_put_32 (abfd, insn, l->addr);
  
  	  next = l->next;
  	  free (l);
--- 549,555 ----
  	    val += 0x10000;
  
  	  insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
! 	  bfd_put_32 (input_bfd, insn, l->addr);
  
  	  next = l->next;
  	  free (l);
*************** m32r_elf_lo16_reloc (abfd, reloc_entry, 
*** 543,552 ****
  
        m32r_hi16_list = NULL;
      }
  
!   /* Now do the LO16 reloc in the usual way.  */
!   return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
! 				input_section, output_bfd, error_message);
  }
  
  /* Handle the R_M32R_SDA16 reloc.
--- 558,602 ----
  
        m32r_hi16_list = NULL;
      }
+ 
+   /* Now do the LO16 reloc in the usual way.
+      ??? It would be nice to call bfd_elf_generic_reloc here,
+      but we have partial_inplace == TRUE.  bfd_elf_generic_reloc will
+      pass the handling back to bfd_install_relocation which will install
+      a section relative addend which is wrong.  */
+ 
+   /* Sanity check the address (offset in section).  */
+   if (reloc_entry->address > input_section->_cooked_size)
+     return bfd_reloc_outofrange;
+ 
+   ret = bfd_reloc_ok;
+   if (bfd_is_und_section (symbol->section)
+       && output_bfd == (bfd *) NULL)
+     ret = bfd_reloc_undefined;
+ 
+   if (bfd_is_com_section (symbol->section)
+       || output_bfd != (bfd *) NULL)
+     relocation = 0;
+   else
+     relocation = symbol->value;
+ 
+   /* Only do this for a final link.  */
+   if (output_bfd == (bfd *) NULL)
+     {
+       relocation += symbol->section->output_section->vma;
+       relocation += symbol->section->output_offset;
+     }
+ 
+   relocation += reloc_entry->addend;
+ 
+   insn = bfd_get_32 (input_bfd, data + reloc_entry->address);
+   insn = (insn & 0xffff0000) | (relocation & 0xffff);
+   bfd_put_32 (input_bfd, insn, data + reloc_entry->address);
+ 
+   if (output_bfd != (bfd *) NULL)
+     reloc_entry->address += input_section->output_offset;
  
!   return ret;
  }
  
  /* Handle the R_M32R_SDA16 reloc.


More information about the Binutils mailing list