gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / coff-z80.c
index 6af3e190bff602f718ea3d105a53b6862ff0cbc2..8913fb5bf956fa6cc353318eeaa710b35d647fd3 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for Zilog Z80 COFF binaries.
-   Copyright 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+   Copyright (C) 2005-2020 Free Software Foundation, Inc.
    Contributed by Arnold Metselaar <arnold_m@operamail.com>
 
    This file is part of BFD, the Binary File Descriptor library.
 #include "coff/z80.h"
 #include "coff/internal.h"
 #include "libcoff.h"
+#include "libiberty.h"
 
 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
 
-static reloc_howto_type r_imm32 =
-HOWTO (R_IMM32, 0, 2, 32, FALSE, 0,
-       complain_overflow_dont, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff,
-       FALSE);
+typedef struct {
+  bfd_reloc_code_real_type r_type;
+  reloc_howto_type howto;
+} bfd_howto_type;
 
-static reloc_howto_type r_imm24 =
-HOWTO (R_IMM24, 0, 1, 24, FALSE, 0,
-       complain_overflow_dont, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff,
-       FALSE);
-
-static reloc_howto_type r_imm16 =
-HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
-       complain_overflow_dont, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff,
-       FALSE);
-
-static reloc_howto_type r_imm8 =
-HOWTO (R_IMM8, 0, 0, 8, FALSE, 0,
-       complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff,
-       FALSE);
-
-static reloc_howto_type r_jr =
-HOWTO (R_JR, 0, 0, 8, TRUE, 0,
-       complain_overflow_signed, 0, "r_jr", FALSE, 0, 0xFF,
-       FALSE);
-
-static reloc_howto_type r_off8 =
-HOWTO (R_OFF8, 0, 0, 8, FALSE, 0,
-       complain_overflow_signed, 0,"r_off8", FALSE, 0, 0xff,
-       FALSE);
+#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_howto_type howto_table[] =
+{
+  BFD_EMPTY_HOWTO (BFD_RELOC_NONE, 0),
+
+  BFD_HOWTO (BFD_RELOC_32,
+     R_IMM32,          /* type */
+     0,                        /* rightshift */
+     2,                        /* size (0 = byte, 1 = short, 2 = long) */
+     32,               /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_bitfield, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_imm32",                /* name */
+     FALSE,            /* partial_inplace */
+     0xffffffff,       /* src_mask */
+     0xffffffff,       /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_24,
+     R_IMM24,          /* type */
+     0,                        /* rightshift */
+     1,                        /* size (0 = byte, 1 = short, 2 = long) */
+     24,               /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_bitfield, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_imm24",                /* name */
+     FALSE,            /* partial_inplace */
+     0x00ffffff,       /* src_mask */
+     0x00ffffff,       /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_16,
+     R_IMM16,          /* type */
+     0,                        /* rightshift */
+     1,                        /* size (0 = byte, 1 = short, 2 = long) */
+     16,               /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_bitfield, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_imm16",                /* name */
+     FALSE,            /* partial_inplace */
+     0x0000ffff,       /* src_mask */
+     0x0000ffff,       /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_8,
+     R_IMM8,           /* type */
+     0,                        /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     8,                        /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_bitfield, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_imm8",         /* name */
+     FALSE,            /* partial_inplace */
+     0x000000ff,       /* src_mask */
+     0x000000ff,       /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_8_PCREL,
+     R_JR,             /* type */
+     0,                        /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     8,                        /* bitsize */
+     TRUE,             /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_signed, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_jr",           /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xFF,             /* dst_mask */
+     TRUE),            /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_DISP8,
+     R_OFF8,           /* type */
+     0,                        /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     8,                        /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_signed, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_off8",         /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xff,             /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_BYTE0,
+     R_BYTE0,          /* type */
+     0,                        /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     8,                        /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_dont, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_byte0",                /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xff,             /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_BYTE1,
+     R_BYTE1,          /* type */
+     8,                        /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     8,                        /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_dont, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_byte1",                /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xff,             /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_BYTE2,
+     R_BYTE2,          /* type */
+     16,               /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     8,                        /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_dont, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_byte2",                /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xff,             /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_BYTE3,
+     R_BYTE3,          /* type */
+     24,               /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     8,                        /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_dont, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_byte3",                /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xff,             /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_WORD0,
+     R_WORD0,          /* type */
+     0,                        /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     16,               /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_dont, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_word0",                /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xffff,           /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_WORD1,
+     R_WORD1,          /* type */
+     16,               /* rightshift */
+     0,                        /* size (0 = byte, 1 = short, 2 = long) */
+     16,               /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_dont, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_word1",                /* name */
+     FALSE,            /* partial_inplace */
+     0,                        /* src_mask */
+     0xffff,           /* dst_mask */
+     FALSE),           /* pcrel_offset */
+
+  BFD_HOWTO (BFD_RELOC_Z80_16_BE,
+     R_IMM16BE,                /* type */
+     0,                        /* rightshift */
+     1,                        /* size (0 = byte, 1 = short, 2 = long) */
+     16,               /* bitsize */
+     FALSE,            /* pc_relative */
+     0,                        /* bitpos */
+     complain_overflow_bitfield, /* complain_on_overflow */
+     0,                        /* special_function */
+     "r_imm16be",      /* name */
+     FALSE,            /* partial_inplace */
+     0x0000ffff,       /* src_mask */
+     0x0000ffff,       /* dst_mask */
+     FALSE),           /* pcrel_offset */
+};
+
+#define NUM_HOWTOS ARRAY_SIZE (howto_table)
 
 #define BADMAG(x) Z80BADMAG(x)
 #define Z80 1                  /* Customize coffcode.h.  */
@@ -74,34 +254,19 @@ HOWTO (R_OFF8, 0, 0, 8, FALSE, 0,
   dst->r_stuff[1] = 'C';
 
 /* Code to turn a r_type into a howto ptr, uses the above howto table.  */
-
 static void
 rtype2howto (arelent *internal, struct internal_reloc *dst)
 {
-  switch (dst->r_type)
+  unsigned i;
+  for (i = 0; i < NUM_HOWTOS; i++)
     {
-    default:
-      abort ();
-      break;
-    case R_IMM8:
-      internal->howto = &r_imm8;
-      break;
-    case R_IMM16:
-      internal->howto = &r_imm16;
-      break;
-    case R_IMM24:
-      internal->howto = &r_imm24;
-      break;
-    case R_IMM32:
-      internal->howto = &r_imm32;
-      break;
-    case R_JR:
-      internal->howto = &r_jr;
-      break;
-    case R_OFF8:
-      internal->howto = &r_off8;
-      break;
+      if (howto_table[i].howto.type == dst->r_type)
+        {
+          internal->howto = &howto_table[i].howto;
+          return;
+        }
     }
+  internal->howto = NULL;
 }
 
 #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
@@ -110,35 +275,23 @@ static reloc_howto_type *
 coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
                            bfd_reloc_code_real_type code)
 {
-  switch (code)
-    {
-    case BFD_RELOC_8:          return & r_imm8;
-    case BFD_RELOC_16:         return & r_imm16;
-    case BFD_RELOC_24:         return & r_imm24;
-    case BFD_RELOC_32:         return & r_imm32;
-    case BFD_RELOC_8_PCREL:    return & r_jr;
-    case BFD_RELOC_Z80_DISP8:  return & r_off8;
-    default:                   BFD_FAIL ();
-      return NULL;
-    }
+  unsigned i;
+  for (i = 0; i < NUM_HOWTOS; i++)
+    if (howto_table[i].r_type == code)
+      return &howto_table[i].howto;
+
+  BFD_FAIL ();
+  return NULL;
 }
 
 static reloc_howto_type *
 coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
                            const char *r_name)
 {
-  if (strcasecmp (r_imm8.name, r_name) == 0)
-    return &r_imm8;
-  if (strcasecmp (r_imm16.name, r_name) == 0)
-    return &r_imm16;
-  if (strcasecmp (r_imm24.name, r_name) == 0)
-    return &r_imm24;
-  if (strcasecmp (r_imm32.name, r_name) == 0)
-    return &r_imm32;
-  if (strcasecmp (r_jr.name, r_name) == 0)
-    return &r_jr;
-  if (strcasecmp (r_off8.name, r_name) == 0)
-    return &r_off8;
+  unsigned i;
+  for (i = 0; i < NUM_HOWTOS; i++)
+    if (strcasecmp(howto_table[i].howto.name, r_name) == 0)
+      return &howto_table[i].howto;
 
   return NULL;
 }
@@ -153,10 +306,10 @@ coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 
 static void
 reloc_processing (arelent *relent,
-                  struct internal_reloc *reloc,
-                  asymbol **symbols,
-                  bfd *abfd,
-                  asection *section)
+                 struct internal_reloc *reloc,
+                 asymbol **symbols,
+                 bfd *abfd,
+                 asection *section)
 {
   relent->address = reloc->r_vaddr;
   rtype2howto (relent, reloc);
@@ -172,55 +325,82 @@ reloc_processing (arelent *relent,
 
 static void
 extra_case (bfd *in_abfd,
-            struct bfd_link_info *link_info,
-            struct bfd_link_order *link_order,
-            arelent *reloc,
-            bfd_byte *data,
-            unsigned int *src_ptr,
-            unsigned int *dst_ptr)
+           struct bfd_link_info *link_info,
+           struct bfd_link_order *link_order,
+           arelent *reloc,
+           bfd_byte *data,
+           unsigned int *src_ptr,
+           unsigned int *dst_ptr)
 {
   asection * input_section = link_order->u.indirect.section;
-  int val;
+  int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
   switch (reloc->howto->type)
     {
     case R_OFF8:
-       val = bfd_coff_reloc16_get_value (reloc, link_info,
-                                          input_section);
-       if (val>127 || val<-128) /* Test for overflow.  */
-         {
-           if (! ((*link_info->callbacks->reloc_overflow)
-                  (link_info, NULL,
-                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
-                   reloc->howto->name, reloc->addend, input_section->owner,
-                   input_section, reloc->address)))
-             abort ();
-         }
+      if (reloc->howto->partial_inplace)
+        val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
+                             & reloc->howto->src_mask);
+      if (val>127 || val<-128) /* Test for overflow.  */
+         (*link_info->callbacks->reloc_overflow)
+           (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+            reloc->howto->name, reloc->addend, input_section->owner,
+            input_section, reloc->address);
+
        bfd_put_8 (in_abfd, val, data + *dst_ptr);
        (*dst_ptr) += 1;
        (*src_ptr) += 1;
       break;
 
+    case R_BYTE3:
+      bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
+      (*dst_ptr) += 1;
+      (*src_ptr) += 1;
+      break;
+
+    case R_BYTE2:
+      bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
+      (*dst_ptr) += 1;
+      (*src_ptr) += 1;
+      break;
+
+    case R_BYTE1:
+      bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
+      (*dst_ptr) += 1;
+      (*src_ptr) += 1;
+      break;
+
     case R_IMM8:
-      val = bfd_get_8 ( in_abfd, data+*src_ptr)
-       + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+      if (reloc->howto->partial_inplace)
+        val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+      //fallthrough
+    case R_BYTE0:
       bfd_put_8 (in_abfd, val, data + *dst_ptr);
       (*dst_ptr) += 1;
       (*src_ptr) += 1;
       break;
 
+    case R_WORD1:
+      bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
+      (*dst_ptr) += 2;
+      (*src_ptr) += 2;
+      break;
+
     case R_IMM16:
-      val = bfd_get_16 ( in_abfd, data+*src_ptr)
-       + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+      if (reloc->howto->partial_inplace)
+        val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+      //fallthrough
+    case R_WORD0:
       bfd_put_16 (in_abfd, val, data + *dst_ptr);
       (*dst_ptr) += 2;
       (*src_ptr) += 2;
       break;
 
     case R_IMM24:
-      val = bfd_get_16 ( in_abfd, data+*src_ptr)
-       + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16)
-       + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+      if (reloc->howto->partial_inplace)
+        val += (bfd_get_16 ( in_abfd, data+*src_ptr)
+            + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16))
+            & reloc->howto->src_mask;
       bfd_put_16 (in_abfd, val, data + *dst_ptr);
       bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
       (*dst_ptr) += 3;
@@ -228,8 +408,8 @@ extra_case (bfd *in_abfd,
       break;
 
     case R_IMM32:
-      val = bfd_get_32 ( in_abfd, data+*src_ptr)
-       + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+      if (reloc->howto->partial_inplace)
+        val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
       bfd_put_32 (in_abfd, val, data + *dst_ptr);
       (*dst_ptr) += 4;
       (*src_ptr) += 4;
@@ -237,35 +417,51 @@ extra_case (bfd *in_abfd,
 
     case R_JR:
       {
-       bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
-                                                 input_section);
+        if (reloc->howto->partial_inplace)
+          val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr) 
+                               & reloc->howto->src_mask);
        bfd_vma dot = (*dst_ptr
                       + input_section->output_offset
                       + input_section->output_section->vma);
-       int gap = dst - dot - 1;  /* -1, Since the offset is relative
-                                    to the value of PC after reading
-                                    the offset.  */
-
+       int gap = val - dot;
        if (gap >= 128 || gap < -128)
-         {
-           if (! ((*link_info->callbacks->reloc_overflow)
-                  (link_info, NULL,
-                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
-                   reloc->howto->name, reloc->addend, input_section->owner,
-                   input_section, reloc->address)))
-             abort ();
-         }
+         (*link_info->callbacks->reloc_overflow)
+           (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+            reloc->howto->name, reloc->addend, input_section->owner,
+            input_section, reloc->address);
+
        bfd_put_8 (in_abfd, gap, data + *dst_ptr);
        (*dst_ptr)++;
        (*src_ptr)++;
        break;
       }
 
+    case R_IMM16BE:
+      if (reloc->howto->partial_inplace)
+       val += (bfd_get_8 ( in_abfd, data+*src_ptr+0) * 0x100 +
+               bfd_get_8 ( in_abfd, data+*src_ptr+1)) & reloc->howto->src_mask;
+      
+      bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr+0);
+      bfd_put_8 (in_abfd, val, data + *dst_ptr+1);
+      (*dst_ptr) += 2;
+      (*src_ptr) += 2;
+      break;
+
     default:
       abort ();
     }
 }
 
+static int
+z80_is_local_label_name (bfd *        abfd ATTRIBUTE_UNUSED,
+                         const char * name)
+{
+  return (name[0] == '.' && name[1] == 'L') ||
+         _bfd_coff_is_local_label_name (abfd, name);
+}
+
+#define coff_bfd_is_local_label_name z80_is_local_label_name
+
 #define coff_reloc16_extra_cases    extra_case
 #define coff_bfd_reloc_type_lookup  coff_z80_reloc_type_lookup
 #define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
@@ -283,7 +479,7 @@ extra_case (bfd *in_abfd,
 #undef  coff_bfd_relax_section
 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
 
-CREATE_LITTLE_COFF_TARGET_VEC (z80coff_vec, "coff-z80", 0,
+CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
                               SEC_CODE | SEC_DATA, '\0', NULL,
                               COFF_SWAP_TABLE)
 
This page took 0.029219 seconds and 4 git commands to generate.