xtensa: fix XTENSA_NDIFF handling for PR ld/25861
[deliverable/binutils-gdb.git] / bfd / elf32-z80.c
index 888606e7b5cc4bf643668424d51203340dd34530..89089f5eaab69da7128417ba84efba5f3e607959 100644 (file)
 /* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
 #define OCTETS_PER_BYTE(ABFD, SEC) 1
 
-/* Relocation functions.  */
-static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
-  (bfd *, bfd_reloc_code_real_type);
-static bfd_boolean z80_info_to_howto_rel
-  (bfd *, arelent *, Elf_Internal_Rela *);
-
 typedef struct {
   bfd_reloc_code_real_type r_type;
   reloc_howto_type howto;
@@ -44,6 +38,11 @@ typedef struct {
 #define BFD_EMPTY_HOWTO(rt,x) {rt, EMPTY_HOWTO(x)}
 #define BFD_HOWTO(rt,a,b,c,d,e,f,g,h,i,j,k,l,m) {rt, HOWTO(a,b,c,d,e,f,g,h,i,j,k,l,m)}
 
+static bfd_reloc_status_type
+z80_elf_16_be_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                    void *data, asection *input_section, bfd *output_bfd,
+                    char **error_message);
+
 static const
 bfd_howto_type elf_z80_howto_table[] =
 {
@@ -253,11 +252,27 @@ bfd_howto_type elf_z80_howto_table[] =
         0,                     /* src_mask */
         0xffff,                /* dst_mask */
         FALSE),                /* pcrel_offset */
+
+  /* An 16 bit big endian absolute relocation */
+  BFD_HOWTO (BFD_RELOC_Z80_16_BE,
+        R_Z80_16_BE,           /* type */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield,    /* complain_on_overflow */
+        z80_elf_16_be_reloc,   /* special_function */
+        "r_imm16be",           /* name */
+        FALSE,                 /* partial_inplace */
+        0x00000000,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 };
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
-                                 bfd_reloc_code_real_type code)
+z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                      bfd_reloc_code_real_type code)
 {
   enum
     {
@@ -268,16 +283,16 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   for (i = 0; i < table_size; i++)
     {
       if (elf_z80_howto_table[i].r_type == code)
-          return &elf_z80_howto_table[i].howto;
+         return &elf_z80_howto_table[i].howto;
     }
 
-  printf ("%s:%d Not found type %d\n", __FILE__, __LINE__, code);
+  printf ("%s:%d Not found BFD reloc type %d\n", __FILE__, __LINE__, code);
 
   return NULL;
 }
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
+z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
 {
   enum
     {
@@ -288,82 +303,308 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
   for (i = 0; i < table_size; i++)
     {
       if (elf_z80_howto_table[i].howto.name != NULL
-          && strcasecmp (elf_z80_howto_table[i].howto.name, r_name) == 0)
-        return &elf_z80_howto_table[i].howto;
+         && strcasecmp (elf_z80_howto_table[i].howto.name, r_name) == 0)
+       return &elf_z80_howto_table[i].howto;
     }
 
+  printf ("%s:%d Not found ELF reloc name `%s'\n", __FILE__, __LINE__, r_name);
+
   return NULL;
 }
 
-/* Set the howto pointer for an z80 ELF reloc.  */
-
-static bfd_boolean
-z80_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
+static reloc_howto_type *
+z80_rtype_to_howto (bfd *abfd, unsigned r_type)
 {
   enum
     {
       table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0])
     };
-  unsigned int  i;
-  unsigned int  r_type = ELF32_R_TYPE (dst->r_info);
+  unsigned int i;
 
   for (i = 0; i < table_size; i++)
     {
       if (elf_z80_howto_table[i].howto.type == r_type)
-        {
-          cache_ptr->howto = &elf_z80_howto_table[i].howto;
-          return TRUE;
-        }
+         return &elf_z80_howto_table[i].howto;
     }
 
   /* xgettext:c-format */
   _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
-                      abfd, r_type);
+                     abfd, r_type);
+  return NULL;
+} 
+
+/* Set the howto pointer for an z80 ELF reloc.  */
+
+static bfd_boolean
+z80_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
+{
+  unsigned int  r_type = ELF32_R_TYPE (dst->r_info);
+  reloc_howto_type *howto = z80_rtype_to_howto (abfd, r_type);
+  if (howto != NULL)
+    {
+      cache_ptr->howto = howto;
+      return TRUE;
+    }
   bfd_set_error (bfd_error_bad_value);
   return FALSE;
 }
 
+static bfd_reloc_status_type
+z80_elf_final_link_relocate (unsigned long r_type,
+                            bfd *input_bfd,
+                            bfd *output_bfd ATTRIBUTE_UNUSED,
+                            asection *input_section ATTRIBUTE_UNUSED,
+                            bfd_byte *contents,
+                            bfd_vma offset,
+                            bfd_vma value,
+                            bfd_vma addend,
+                            struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                            asection *sym_sec ATTRIBUTE_UNUSED,
+                            int is_local ATTRIBUTE_UNUSED)
+{
+  bfd_boolean r;
+  reloc_howto_type *howto;
+
+  switch (r_type)
+    {
+    case R_Z80_16_BE:
+      value += addend;
+      bfd_put_8 (input_bfd, value >> 8, contents + offset + 0);
+      bfd_put_8 (input_bfd, value >> 0, contents + offset + 1);
+      return bfd_reloc_ok;
+    }
+
+  howto = z80_rtype_to_howto (input_bfd, r_type);
+  if (howto == NULL)
+    return bfd_reloc_notsupported;
+
+  r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
+                               offset, value, addend);
+  return r ? bfd_reloc_ok : bfd_reloc_notsupported;
+}
+
+static bfd_boolean
+z80_elf_relocate_section (bfd *output_bfd,
+                         struct bfd_link_info *info,
+                         bfd *input_bfd,
+                         asection *input_section,
+                         bfd_byte *contents,
+                         Elf_Internal_Rela *relocs,
+                         Elf_Internal_Sym *local_syms,
+                         asection **local_sections)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  Elf_Internal_Rela *rel, *relend;
+
+  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (input_bfd);
+
+  rel = relocs;
+  relend = relocs + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      unsigned int r_type;
+      unsigned long r_symndx;
+      Elf_Internal_Sym *sym;
+      asection *sec;
+      struct elf_link_hash_entry *h;
+      bfd_vma relocation;
+
+      /* This is a final link.  */
+      r_symndx = ELF32_R_SYM (rel->r_info);
+      r_type = ELF32_R_TYPE (rel->r_info);
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+      if (r_symndx < symtab_hdr->sh_info)
+       {
+         sym = local_syms + r_symndx;
+         sec = local_sections[r_symndx];
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+       }
+      else
+       {
+         bfd_boolean unresolved_reloc, warned, ignored;
+
+         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                  r_symndx, symtab_hdr, sym_hashes,
+                                  h, sec, relocation,
+                                  unresolved_reloc, warned, ignored);
+       }
+
+      if (sec != NULL && discarded_section (sec))
+       {
+         /* For relocs against symbols from removed linkonce sections,
+            or sections discarded by a linker script, we just want the
+            section contents cleared.  Avoid any special processing.  */
+         reloc_howto_type *howto;
+         howto = z80_rtype_to_howto (input_bfd, r_type);
+         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                          rel, 1, relend, howto, 0, contents);
+       }
+
+      if (bfd_link_relocatable (info))
+       continue;
+
+
+      z80_elf_final_link_relocate (r_type, input_bfd, output_bfd,
+                                  input_section,
+                                  contents, rel->r_offset,
+                                  relocation, rel->r_addend,
+                                  info, sec, h == NULL);
+    }
+
+  return TRUE;
+}
+
+/* The final processing done just before writing out a Z80 ELF object
+   file.  This gets the Z80 architecture right based on the machine
+   number.  */
+
 static bfd_boolean
-z80_elf_set_mach_from_flags (bfd *abfd)
+z80_elf_final_write_processing (bfd *abfd)
 {
-  int mach;
-  switch (elf_elfheader (abfd)->e_flags)
+  unsigned long val = bfd_get_mach (abfd);
+
+  switch (val)
     {
-    case EF_Z80_MACH_GBZ80:
-      mach = bfd_mach_gbz80;
+    default:
+      _bfd_error_handler (_("%pB: unsupported bfd mach %#lx"),
+                         abfd, val);
+      /* fall through */
+    case bfd_mach_z80:
+    case bfd_mach_z80full:
+    case bfd_mach_z80strict:
+      val = EF_Z80_MACH_Z80;
       break;
-    case EF_Z80_MACH_Z80:
-      mach = bfd_mach_z80;
+    case bfd_mach_gbz80:
+      val = EF_Z80_MACH_GBZ80;
       break;
-    case EF_Z80_MACH_Z180:
-      mach = bfd_mach_z180;
+    case bfd_mach_z80n:
+      val = EF_Z80_MACH_Z80N;
       break;
-    case EF_Z80_MACH_EZ80_Z80:
-      mach = bfd_mach_ez80_z80;
+    case bfd_mach_z180:
+      val = EF_Z80_MACH_Z180;
       break;
-    case EF_Z80_MACH_EZ80_ADL:
-      mach = bfd_mach_ez80_adl;
+    case bfd_mach_ez80_z80:
+      val = EF_Z80_MACH_EZ80_Z80;
       break;
-    case EF_Z80_MACH_R800:
-      mach = bfd_mach_r800;
+    case bfd_mach_ez80_adl:
+      val = EF_Z80_MACH_EZ80_ADL;
       break;
-    default:
-      mach = bfd_mach_z80;
+    case bfd_mach_r800:
+      val = EF_Z80_MACH_R800;
       break;
     }
+  elf_elfheader (abfd)->e_machine = EM_Z80;
+  elf_elfheader (abfd)->e_flags &= ~EF_Z80_MACH_MSK;
+  elf_elfheader (abfd)->e_flags |= val;
+  return _bfd_elf_final_write_processing (abfd);
+}
 
-  bfd_default_set_arch_mach (abfd, bfd_arch_z80, mach);
-  return TRUE;
+/* Set the right machine number.  */
+static bfd_boolean
+z80_elf_object_p (bfd *abfd)
+{
+  unsigned int mach;
+
+  if (elf_elfheader (abfd)->e_machine == EM_Z80)
+    {
+      int e_mach = elf_elfheader (abfd)->e_flags & EF_Z80_MACH_MSK;
+      switch (e_mach)
+       {
+       default:
+         _bfd_error_handler (_("%pB: unsupported mach %#x"),
+                             abfd, e_mach);
+         /* fall through */
+       case EF_Z80_MACH_Z80:
+         mach = bfd_mach_z80;
+         break;
+       case EF_Z80_MACH_GBZ80:
+         mach = bfd_mach_gbz80;
+         break;
+       case EF_Z80_MACH_Z180:
+         mach = bfd_mach_z180;
+         break;
+       case EF_Z80_MACH_EZ80_Z80:
+         mach = bfd_mach_ez80_z80;
+         break;
+       case EF_Z80_MACH_EZ80_ADL:
+         mach = bfd_mach_ez80_adl;
+         break;
+       case EF_Z80_MACH_R800:
+         mach = bfd_mach_r800;
+         break;
+       case EF_Z80_MACH_Z80N:
+         mach = bfd_mach_z80n;
+         break;
+       }
+    }
+  else
+    {
+      _bfd_error_handler (_("%pB: unsupported arch %#x"),
+                         abfd, elf_elfheader (abfd)->e_machine);
+      mach = bfd_mach_z80;
+    }
+  return bfd_default_set_arch_mach (abfd, bfd_arch_z80, mach);
 }
 
 static int
-z80_is_local_label_name (bfd *        abfd ATTRIBUTE_UNUSED,
-                         const char * name)
+z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
+                        const char * name)
 {
   return (name[0] == '.' && name[1] == 'L') ||
-         _bfd_elf_is_local_label_name (abfd, name);
+        _bfd_elf_is_local_label_name (abfd, name);
 }
 
+static bfd_reloc_status_type
+z80_elf_16_be_reloc (bfd *abfd,
+                    arelent *reloc_entry,
+                    asymbol *symbol,
+                    void *data,
+                    asection *input_section,
+                    bfd *output_bfd,
+                    char **error_message)
+{
+  bfd_vma val;
+  long x;
+  bfd_size_type octets = (reloc_entry->address
+                         * OCTETS_PER_BYTE (abfd, input_section));
+
+  /* If this is a relocatable link (output_bfd test tells us), just
+     call the generic function.  Any adjustment will be done at final
+     link time.  */
+  if (output_bfd != NULL)
+    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+                                 input_section, output_bfd, error_message);
+
+  /* Get symbol value.  */
+  val = 0;
+  if (!bfd_is_com_section (symbol->section))
+    val = symbol->value;
+  val += symbol->section->output_offset + input_section->output_offset;
+  if (symbol->section->output_section)
+    val += symbol->section->output_section->vma;
+
+  val += reloc_entry->addend;
+  if (reloc_entry->howto->partial_inplace)
+    {
+      x = bfd_get_8 (abfd, (bfd_byte *) data + octets + 0) * 0x100;
+      x += bfd_get_8 (abfd, (bfd_byte *) data + octets + 1);
+      x &= ~reloc_entry->howto->src_mask;
+    }
+  else
+    x = 0;
+
+  x |= val & reloc_entry->howto->dst_mask;
+  if (x < -0x8000 || x >= 0x10000)
+    return bfd_reloc_outofrange;
+
+  bfd_put_8 (abfd, x >> 8, (bfd_byte *) data + octets + 0);
+  bfd_put_8 (abfd, x >> 0, (bfd_byte *) data + octets + 1);
+  return bfd_reloc_ok;
+}
 
 #define ELF_ARCH               bfd_arch_z80
 #define ELF_MACHINE_CODE       EM_Z80
@@ -372,9 +613,20 @@ z80_is_local_label_name (bfd *        abfd ATTRIBUTE_UNUSED,
 #define TARGET_LITTLE_SYM              z80_elf32_vec
 #define TARGET_LITTLE_NAME             "elf32-z80"
 
-#define elf_info_to_howto                      NULL
-#define elf_info_to_howto_rel                  z80_info_to_howto_rel
-#define elf_backend_object_p                   z80_elf_set_mach_from_flags
+#define elf_backend_can_refcount               1
+#define elf_backend_can_gc_sections            1
+#define elf_backend_stack_align                        1
+#define elf_backend_rela_normal                        1
+
+#define elf_info_to_howto                      z80_info_to_howto_rela
+#define elf_info_to_howto_rel                  z80_info_to_howto_rela
+
+#define elf_backend_final_write_processing     z80_elf_final_write_processing
+#define elf_backend_object_p                   z80_elf_object_p
+#define elf_backend_relocate_section           z80_elf_relocate_section
+
+#define bfd_elf32_bfd_reloc_type_lookup                z80_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup                z80_reloc_name_lookup
 #define bfd_elf32_bfd_is_local_label_name      z80_is_local_label_name
 
 #include "elf32-target.h"
This page took 0.02907 seconds and 4 git commands to generate.