This is the mail archive of the binutils@sourceware.org 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]
Other format: [Raw text]

[PATCH ARC 2/5]: 24 bit reloc and overflow detection fix


Hi all,

Please review.
This patch fixes 24 bit relocs based by selecting the right replacement
function depending on the endianess of the target.

Fixed overflow detection on 32 bit host execution. Because relocation
values were done using an unsigned type, right shifts used to align the
relocation value where performed non arithmetically. This shift cleared
the most significant bits and made relocation value to be a big positive
value, instead of a small negative one.

Best regards,
Cupertino

bfd/ChangeLog:

Cupertino Miranda  <cmiranda@synopsys.com>
    elf32-arc.c: Defined macro DEBUG.
    (name_for_global_symbol): Changed assert.
    (get_replace_function): Created.:
    (struct arc_relocation_data): Changed to signed types.
    (defines S, L, P, PDATA): Casted to signed type.
    (defines SECTSTART, _SDA_BASE_, TLS_REL): Likewise.
    (PRINT_DEBUG_RELOC_INFO_BEFORE): Changed.
    (arc_do_relocation): Changed.

include/ChangeLog:

Cupertino Miranda  <cmiranda@synopsys.com>
    opcode/arc-func.h (replace_bits24): Changed.
    (replace_bits24_be): Created.

diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index 0c93f7f..e25e9ba 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -28,6 +28,7 @@
 #include "opcode/arc-func.h"
 #include "arc-plt.h"
 
+#define DEBUG
 #ifdef DEBUG
 # define PR_DEBUG(fmt, args...) fprintf (stderr, fmt, ##args)
 #else
@@ -64,7 +65,7 @@ name_for_global_symbol (struct elf_link_hash_entry *h)
     _rel.r_addend = ADDEND;						\
     _rel.r_offset = (_htab->s##SECTION)->output_section->vma		\
       + (_htab->s##SECTION)->output_offset + OFFSET;			\
-    BFD_ASSERT (SYM_IDX != -1);						\
+    BFD_ASSERT ((int) SYM_IDX != -1);						\
     _rel.r_info = ELF32_R_INFO (SYM_IDX, TYPE);				\
     bfd_elf32_swap_reloca_out (BFD, &_rel, _loc);			\
   }
@@ -375,6 +376,29 @@ static const struct arc_reloc_map arc_reloc_map[] =
 };
 #undef ARC_RELOC_HOWTO
 
+typedef ATTRIBUTE_UNUSED bfd_vma (*replace_func) (unsigned, int ATTRIBUTE_UNUSED);
+
+#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+  case TYPE: \
+    func = (void *) RELOC_FUNCTION; \
+    break;
+static replace_func
+get_replace_function (bfd *abfd, unsigned int r_type)
+{
+  void *func = NULL;
+
+  switch (r_type)
+    {
+      #include "elf/arc-reloc.def"
+    }
+
+  if (func == replace_bits24 && bfd_big_endian (abfd))
+    return (replace_func) replace_bits24_be;
+
+  return (replace_func) func;
+}
+#undef ARC_RELOC_HOWTO
+
 static reloc_howto_type *
 arc_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
 				 bfd_reloc_code_real_type code)
@@ -683,20 +707,20 @@ arc_elf_final_write_processing (bfd * abfd,
 
 struct arc_relocation_data
 {
-  bfd_vma	  reloc_offset;
-  bfd_vma	  reloc_addend;
-  bfd_vma	  got_offset_value;
+  bfd_signed_vma  reloc_offset;
+  bfd_signed_vma  reloc_addend;
+  bfd_signed_vma  got_offset_value;
 
-  bfd_vma	  sym_value;
+  bfd_signed_vma  sym_value;
   asection *	  sym_section;
 
   reloc_howto_type *howto;
 
   asection *	  input_section;
 
-  bfd_vma	  sdata_begin_symbol_vma;
+  bfd_signed_vma  sdata_begin_symbol_vma;
   bfd_boolean	  sdata_begin_symbol_vma_set;
-  bfd_vma	  got_symbol_vma;
+  bfd_signed_vma  got_symbol_vma;
 
   bfd_boolean	  should_relocate;
 };
@@ -770,16 +794,14 @@ middle_endian_convert (bfd_vma insn, bfd_boolean do_it)
 #define IS_ME(FORMULA,BFD) ((strstr (FORMULA, "ME") != NULL) \
 			    && (!bfd_big_endian (BFD)))
 
-#define S (reloc_data.sym_value						\
+#define S ((bfd_signed_vma) (reloc_data.sym_value			\
 	   + (reloc_data.sym_section->output_section != NULL ?		\
 	      (reloc_data.sym_section->output_offset			\
-	       + reloc_data.sym_section->output_section->vma) : 0)	\
-	   )
-#define L (reloc_data.sym_value						\
+	       + reloc_data.sym_section->output_section->vma) : 0)))
+#define L ((bfd_signed_vma) (reloc_data.sym_value			\
 	   + (reloc_data.sym_section->output_section != NULL ?		\
 	      (reloc_data.sym_section->output_offset			\
-	      + reloc_data.sym_section->output_section->vma) : 0)	\
-	  )
+	      + reloc_data.sym_section->output_section->vma) : 0)))
 #define A (reloc_data.reloc_addend)
 #define B (0)
 #define G (reloc_data.got_offset_value)
@@ -789,33 +811,32 @@ middle_endian_convert (bfd_vma insn, bfd_boolean do_it)
 #define MES (0)
 	/* P: relative offset to PCL The offset should be to the
 	  current location aligned to 32 bits.  */
-#define P (								\
+#define P ((bfd_signed_vma) (						\
 	   (								\
 	    (reloc_data.input_section->output_section != NULL ?		\
 	     reloc_data.input_section->output_section->vma : 0)		\
 	    + reloc_data.input_section->output_offset			\
-	    + (reloc_data.reloc_offset - (bitsize >= 32 ? 4 : 0))	\
-	    ) & ~0x3)
-#define PDATA ( \
+	    + (reloc_data.reloc_offset - (bitsize >= 32 ? 4 : 0)))	\
+	   & ~0x3))
+#define PDATA ((bfd_signed_vma) ( \
 	    (reloc_data.input_section->output_section->vma \
 	     + reloc_data.input_section->output_offset \
-	     + (reloc_data.reloc_offset) \
-	    ))
-#define SECTSTAR (reloc_data.input_section->output_offset)
-#define SECTSTART (reloc_data.input_section->output_offset)
-#define _SDA_BASE_ (reloc_data.sdata_begin_symbol_vma)
-#define TLS_REL ((elf_hash_table (info))->tls_sec->output_section->vma)
-#define _SDA_BASE_ (reloc_data.sdata_begin_symbol_vma)
+	     + (reloc_data.reloc_offset))))
+#define SECTSTART (bfd_signed_vma) (reloc_data.input_section->output_offset)
+#define _SDA_BASE_ (bfd_signed_vma) (reloc_data.sdata_begin_symbol_vma)
+#define TLS_REL (bfd_signed_vma) \
+  ((elf_hash_table (info))->tls_sec->output_section->vma)
 #define TLS_TBSS (8)
 #define TCB_SIZE (8)
 
 #define none (0)
 
-#define PRINT_DEBUG_RELOC_INFO_BEFORE(FORMULA) \
+#define PRINT_DEBUG_RELOC_INFO_BEFORE(FORMULA, TYPE) \
     {\
       asection *sym_section = reloc_data.sym_section; \
       asection *input_section = reloc_data.input_section; \
-      ARC_DEBUG ("FORMULA = " #FORMULA "\n"); \
+      ARC_DEBUG ("RELOC_TYPE = " TYPE "\n"); \
+      ARC_DEBUG ("FORMULA = " FORMULA "\n"); \
       ARC_DEBUG ("S = 0x%x\n", S); \
       ARC_DEBUG ("A = 0x%x\n", A); \
       ARC_DEBUG ("L = 0x%x\n", L); \
@@ -856,11 +877,11 @@ middle_endian_convert (bfd_vma insn, bfd_boolean do_it)
 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
   case R_##TYPE: \
     { \
-      bfd_vma bitsize ATTRIBUTE_UNUSED = BITSIZE; \
+      bfd_signed_vma bitsize ATTRIBUTE_UNUSED = BITSIZE; \
       relocation = FORMULA  ; \
-      PRINT_DEBUG_RELOC_INFO_BEFORE(FORMULA) \
+      PRINT_DEBUG_RELOC_INFO_BEFORE (#FORMULA, #TYPE); \
       insn = middle_endian_convert (insn, IS_ME (#FORMULA, abfd)); \
-      insn = RELOC_FUNCTION (insn, relocation); \
+      insn = (* get_replace_function (abfd, TYPE)) (insn, relocation); \
       insn = middle_endian_convert (insn, IS_ME (#FORMULA, abfd)); \
       PRINT_DEBUG_RELOC_INFO_AFTER \
     } \
@@ -871,7 +892,7 @@ arc_do_relocation (bfd_byte * contents,
 		   struct arc_relocation_data reloc_data,
 		   struct bfd_link_info *info)
 {
-  bfd_vma relocation = 0;
+  bfd_signed_vma relocation = 0;
   bfd_vma insn;
   bfd_vma orig_insn ATTRIBUTE_UNUSED;
   bfd * abfd = reloc_data.input_section->owner;
diff --git a/include/opcode/arc-func.h b/include/opcode/arc-func.h
index 47451a6..cafb92f 100644
--- a/include/opcode/arc-func.h
+++ b/include/opcode/arc-func.h
@@ -66,13 +66,28 @@ replace_bits16 (unsigned insn, int value ATTRIBUTE_UNUSED)
 ATTRIBUTE_UNUSED static unsigned
 replace_bits24 (unsigned insn, int value ATTRIBUTE_UNUSED)
 {
+  insn = insn & ~0xffffff;
+  insn |= ((value >> 0) & 0xffffff) << 0;
+
+  return insn;
+}
+
+#endif /* REPLACE_bits24 */
+
+/* Special 24 bit replace for big endian.  */
+/* mask  = 111111111111111111111111.  */
+#ifndef REPLACE_bits24_be
+#define REPLACE_bits24_be
+ATTRIBUTE_UNUSED static unsigned
+replace_bits24_be (unsigned insn, int value ATTRIBUTE_UNUSED)
+{
   insn = insn & ~0xffffff00;
   insn |= ((value >> 0) & 0xffffff) << 8;
 
   return insn;
 }
 
-#endif /* REPLACE_bits24 */
+#endif /* REPLACE_bits24_be */
 
 /* mask  = 11111111111111111111111111111111.  */
 #ifndef REPLACE_word32
-- 
1.9.1


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