Home | History | Annotate | Line # | Download | only in bfd
elf32-dlx.c revision 1.11
      1   1.1  christos /* DLX specific support for 32-bit ELF
      2  1.11  christos    Copyright (C) 2002-2024 Free Software Foundation, Inc.
      3   1.1  christos 
      4   1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      5   1.1  christos 
      6   1.1  christos    This program is free software; you can redistribute it and/or modify
      7   1.1  christos    it under the terms of the GNU General Public License as published by
      8   1.1  christos    the Free Software Foundation; either version 3 of the License, or
      9   1.1  christos    (at your option) any later version.
     10   1.1  christos 
     11   1.1  christos    This program is distributed in the hope that it will be useful,
     12   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.1  christos    GNU General Public License for more details.
     15   1.1  christos 
     16   1.1  christos    You should have received a copy of the GNU General Public License
     17   1.1  christos    along with this program; if not, write to the Free Software
     18   1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19   1.1  christos    MA 02110-1301, USA.  */
     20   1.1  christos 
     21   1.1  christos #include "sysdep.h"
     22   1.1  christos #include "bfd.h"
     23   1.1  christos #include "libbfd.h"
     24   1.1  christos #include "elf-bfd.h"
     25   1.1  christos #include "elf/dlx.h"
     26   1.6  christos #include "elf32-dlx.h"
     27   1.1  christos 
     28   1.1  christos #define USE_REL 1
     29   1.1  christos 
     30   1.1  christos #define bfd_elf32_bfd_reloc_type_lookup elf32_dlx_reloc_type_lookup
     31   1.1  christos #define bfd_elf32_bfd_reloc_name_lookup elf32_dlx_reloc_name_lookup
     32   1.8  christos #define elf_info_to_howto		elf32_dlx_info_to_howto
     33   1.8  christos #define elf_info_to_howto_rel		elf32_dlx_info_to_howto_rel
     34   1.8  christos #define elf_backend_check_relocs	elf32_dlx_check_relocs
     35   1.1  christos 
     36   1.1  christos /* The gas default behavior is not to preform the %hi modifier so that the
     37   1.1  christos    GNU assembler can have the lower 16 bits offset placed in the insn, BUT
     38   1.1  christos    we do like the gas to indicate it is %hi reloc type so when we in the link
     39   1.1  christos    loader phase we can have the corrected hi16 vale replace the buggous lo16
     40   1.1  christos    value that was placed there by gas.  */
     41   1.1  christos 
     42   1.1  christos static int skip_dlx_elf_hi16_reloc = 0;
     43   1.1  christos 
     44   1.1  christos int
     45   1.1  christos set_dlx_skip_hi16_flag (int flag)
     46   1.1  christos {
     47   1.1  christos   skip_dlx_elf_hi16_reloc = flag;
     48   1.1  christos   return flag;
     49   1.1  christos }
     50   1.1  christos 
     51   1.1  christos static bfd_reloc_status_type
     52   1.1  christos _bfd_dlx_elf_hi16_reloc (bfd *abfd,
     53   1.1  christos 			 arelent *reloc_entry,
     54   1.1  christos 			 asymbol *symbol,
     55   1.1  christos 			 void * data,
     56   1.1  christos 			 asection *input_section,
     57   1.1  christos 			 bfd *output_bfd,
     58   1.1  christos 			 char **error_message)
     59   1.1  christos {
     60   1.1  christos   bfd_reloc_status_type ret;
     61   1.1  christos   bfd_vma relocation;
     62   1.1  christos 
     63   1.1  christos   /* If the skip flag is set then we simply do the generic relocating, this
     64   1.1  christos      is more of a hack for dlx gas/gld, so we do not need to do the %hi/%lo
     65   1.1  christos      fixup like mips gld did.   */
     66   1.1  christos   if (skip_dlx_elf_hi16_reloc)
     67   1.1  christos     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
     68   1.8  christos 			  input_section, output_bfd, error_message);
     69   1.1  christos 
     70   1.1  christos   /* If we're relocating, and this an external symbol, we don't want
     71   1.1  christos      to change anything.  */
     72   1.1  christos   if (output_bfd != (bfd *) NULL
     73   1.1  christos       && (symbol->flags & BSF_SECTION_SYM) == 0
     74   1.1  christos       && reloc_entry->addend == 0)
     75   1.1  christos     {
     76   1.1  christos       reloc_entry->address += input_section->output_offset;
     77   1.1  christos       return bfd_reloc_ok;
     78   1.1  christos     }
     79   1.1  christos 
     80   1.1  christos   ret = bfd_reloc_ok;
     81   1.1  christos 
     82   1.1  christos   if (bfd_is_und_section (symbol->section)
     83   1.1  christos       && output_bfd == (bfd *) NULL)
     84   1.1  christos     ret = bfd_reloc_undefined;
     85   1.1  christos 
     86   1.1  christos   relocation = (bfd_is_com_section (symbol->section)) ? 0 : symbol->value;
     87   1.1  christos   relocation += symbol->section->output_section->vma;
     88   1.1  christos   relocation += symbol->section->output_offset;
     89   1.1  christos   relocation += reloc_entry->addend;
     90   1.1  christos   relocation += bfd_get_16 (abfd, (bfd_byte *)data + reloc_entry->address);
     91   1.1  christos 
     92   1.1  christos   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     93   1.1  christos     return bfd_reloc_outofrange;
     94   1.1  christos 
     95   1.1  christos   bfd_put_16 (abfd, (short)((relocation >> 16) & 0xFFFF),
     96   1.8  christos 	      (bfd_byte *)data + reloc_entry->address);
     97   1.1  christos 
     98   1.1  christos   return ret;
     99   1.1  christos }
    100   1.1  christos 
    101   1.1  christos /* ELF relocs are against symbols.  If we are producing relocatable
    102   1.1  christos    output, and the reloc is against an external symbol, and nothing
    103   1.1  christos    has given us any additional addend, the resulting reloc will also
    104   1.1  christos    be against the same symbol.  In such a case, we don't want to
    105   1.1  christos    change anything about the way the reloc is handled, since it will
    106   1.1  christos    all be done at final link time.  Rather than put special case code
    107   1.1  christos    into bfd_perform_relocation, all the reloc types use this howto
    108   1.1  christos    function.  It just short circuits the reloc if producing
    109   1.1  christos    relocatable output against an external symbol.  */
    110   1.1  christos 
    111   1.1  christos static bfd_reloc_status_type
    112   1.1  christos elf32_dlx_relocate16 (bfd *abfd,
    113   1.1  christos 		      arelent *reloc_entry,
    114   1.1  christos 		      asymbol *symbol,
    115   1.1  christos 		      void * data,
    116   1.1  christos 		      asection *input_section,
    117   1.1  christos 		      bfd *output_bfd,
    118   1.1  christos 		      char **error_message ATTRIBUTE_UNUSED)
    119   1.1  christos {
    120   1.1  christos   unsigned long insn, vallo, allignment;
    121   1.8  christos   int		val;
    122   1.1  christos 
    123   1.1  christos   /* HACK: I think this first condition is necessary when producing
    124   1.1  christos      relocatable output.  After the end of HACK, the code is identical
    125   1.1  christos      to bfd_elf_generic_reloc().  I would _guess_ the first change
    126   1.1  christos      belongs there rather than here.  martindo 1998-10-23.  */
    127   1.1  christos 
    128   1.1  christos   if (skip_dlx_elf_hi16_reloc)
    129   1.1  christos     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
    130   1.8  christos 				 input_section, output_bfd, error_message);
    131   1.1  christos 
    132   1.1  christos   /* Check undefined section and undefined symbols.  */
    133   1.1  christos   if (bfd_is_und_section (symbol->section)
    134   1.1  christos       && output_bfd == (bfd *) NULL)
    135   1.1  christos     return bfd_reloc_undefined;
    136   1.1  christos 
    137   1.1  christos   /* Can not support a long jump to sections other then .text.  */
    138   1.1  christos   if (strcmp (input_section->name, symbol->section->output_section->name) != 0)
    139   1.1  christos     {
    140   1.7  christos       _bfd_error_handler
    141   1.8  christos 	(_("branch (PC rel16) to section (%s) not supported"),
    142   1.7  christos 	 symbol->section->output_section->name);
    143   1.1  christos       return bfd_reloc_undefined;
    144   1.1  christos     }
    145   1.1  christos 
    146   1.1  christos   insn  = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
    147   1.1  christos   allignment = 1 << (input_section->output_section->alignment_power - 1);
    148   1.1  christos   vallo = insn & 0x0000FFFF;
    149   1.1  christos 
    150   1.1  christos   if (vallo & 0x8000)
    151   1.1  christos     vallo = ~(vallo | 0xFFFF0000) + 1;
    152   1.1  christos 
    153   1.1  christos   /* vallo points to the vma of next instruction.  */
    154   1.1  christos   vallo += (((unsigned long)(input_section->output_section->vma +
    155   1.8  christos 			   input_section->output_offset) +
    156   1.8  christos 	    allignment) & ~allignment);
    157   1.1  christos 
    158   1.1  christos   /* val is the displacement (PC relative to next instruction).  */
    159   1.1  christos   val =  (symbol->section->output_offset +
    160   1.1  christos 	  symbol->section->output_section->vma +
    161   1.1  christos 	  symbol->value) - vallo;
    162   1.1  christos 
    163   1.1  christos   if (abs ((int) val) > 0x00007FFF)
    164   1.1  christos     return bfd_reloc_outofrange;
    165   1.1  christos 
    166   1.1  christos   insn  = (insn & 0xFFFF0000) | (val & 0x0000FFFF);
    167   1.1  christos 
    168   1.1  christos   bfd_put_32 (abfd, insn,
    169   1.8  christos 	      (bfd_byte *) data + reloc_entry->address);
    170   1.1  christos 
    171   1.1  christos   return bfd_reloc_ok;
    172   1.1  christos }
    173   1.1  christos 
    174   1.1  christos static bfd_reloc_status_type
    175   1.1  christos elf32_dlx_relocate26 (bfd *abfd,
    176   1.1  christos 		      arelent *reloc_entry,
    177   1.1  christos 		      asymbol *symbol,
    178   1.1  christos 		      void * data,
    179   1.1  christos 		      asection *input_section,
    180   1.1  christos 		      bfd *output_bfd,
    181   1.1  christos 		      char **error_message ATTRIBUTE_UNUSED)
    182   1.1  christos {
    183   1.1  christos   unsigned long insn, vallo, allignment;
    184   1.8  christos   int		val;
    185   1.1  christos 
    186   1.1  christos   /* HACK: I think this first condition is necessary when producing
    187   1.1  christos      relocatable output.  After the end of HACK, the code is identical
    188   1.1  christos      to bfd_elf_generic_reloc().  I would _guess_ the first change
    189   1.1  christos      belongs there rather than here.  martindo 1998-10-23.  */
    190   1.1  christos 
    191   1.1  christos   if (skip_dlx_elf_hi16_reloc)
    192   1.1  christos     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
    193   1.8  christos 				 input_section, output_bfd, error_message);
    194   1.1  christos 
    195   1.1  christos   /* Check undefined section and undefined symbols.  */
    196   1.1  christos   if (bfd_is_und_section (symbol->section)
    197   1.1  christos       && output_bfd == (bfd *) NULL)
    198   1.1  christos     return bfd_reloc_undefined;
    199   1.1  christos 
    200   1.1  christos   /* Can not support a long jump to sections other then .text   */
    201   1.1  christos   if (strcmp (input_section->name, symbol->section->output_section->name) != 0)
    202   1.1  christos     {
    203   1.7  christos       _bfd_error_handler
    204   1.8  christos 	(_("jump (PC rel26) to section (%s) not supported"),
    205   1.7  christos 	 symbol->section->output_section->name);
    206   1.1  christos       return bfd_reloc_undefined;
    207   1.1  christos     }
    208   1.1  christos 
    209   1.1  christos   insn  = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
    210   1.1  christos   allignment = 1 << (input_section->output_section->alignment_power - 1);
    211   1.1  christos   vallo = insn & 0x03FFFFFF;
    212   1.1  christos 
    213   1.1  christos   if (vallo & 0x03000000)
    214   1.1  christos     vallo = ~(vallo | 0xFC000000) + 1;
    215   1.1  christos 
    216   1.1  christos   /* vallo is the vma for the next instruction.  */
    217   1.1  christos   vallo += (((unsigned long) (input_section->output_section->vma +
    218   1.1  christos 			      input_section->output_offset) +
    219   1.1  christos 	     allignment) & ~allignment);
    220   1.1  christos 
    221   1.1  christos   /* val is the displacement (PC relative to next instruction).  */
    222   1.1  christos   val = (symbol->section->output_offset +
    223   1.1  christos 	 symbol->section->output_section->vma + symbol->value)
    224   1.1  christos     - vallo;
    225   1.1  christos 
    226   1.1  christos   if (abs ((int) val) > 0x01FFFFFF)
    227   1.1  christos     return bfd_reloc_outofrange;
    228   1.1  christos 
    229   1.1  christos   insn  = (insn & 0xFC000000) | (val & 0x03FFFFFF);
    230   1.1  christos   bfd_put_32 (abfd, insn,
    231   1.8  christos 	      (bfd_byte *) data + reloc_entry->address);
    232   1.1  christos 
    233   1.1  christos   return bfd_reloc_ok;
    234   1.1  christos }
    235   1.1  christos 
    236   1.1  christos static reloc_howto_type dlx_elf_howto_table[]=
    237   1.1  christos {
    238   1.1  christos   /* No relocation.  */
    239   1.8  christos   HOWTO (R_DLX_NONE,		/* Type. */
    240   1.8  christos 	 0,			/* Rightshift.  */
    241  1.10  christos 	 0,			/* size.  */
    242   1.8  christos 	 0,			/* Bitsize.  */
    243  1.10  christos 	 false,			/* PC_relative.  */
    244   1.8  christos 	 0,			/* Bitpos.  */
    245   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    246   1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    247   1.8  christos 	 "R_DLX_NONE",		/* Name.  */
    248  1.10  christos 	 false,			/* Partial_inplace.  */
    249   1.8  christos 	 0,			/* Src_mask.  */
    250   1.8  christos 	 0,			/* Dst_mask.  */
    251  1.10  christos 	 false),		/* PCrel_offset.  */
    252   1.1  christos 
    253   1.1  christos   /* 8 bit relocation.  */
    254   1.8  christos   HOWTO (R_DLX_RELOC_8,		/* Type. */
    255   1.8  christos 	 0,			/* Rightshift.  */
    256  1.10  christos 	 1,			/* Size.  */
    257   1.8  christos 	 8,			/* Bitsize.  */
    258  1.10  christos 	 false,			/* PC_relative.  */
    259   1.8  christos 	 0,			/* Bitpos.  */
    260   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    261   1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    262   1.8  christos 	 "R_DLX_RELOC_8",	/* Name.  */
    263  1.10  christos 	 true,			/* Partial_inplace.  */
    264   1.8  christos 	 0xff,			/* Src_mask.  */
    265   1.8  christos 	 0xff,			/* Dst_mask.  */
    266  1.10  christos 	 false),		/* PCrel_offset.  */
    267   1.1  christos 
    268   1.1  christos   /* 16 bit relocation.  */
    269   1.8  christos   HOWTO (R_DLX_RELOC_16,	/* Type. */
    270   1.8  christos 	 0,			/* Rightshift.  */
    271  1.10  christos 	 2,			/* Size.  */
    272   1.8  christos 	 16,			/* Bitsize.  */
    273  1.10  christos 	 false,			/* PC_relative.  */
    274   1.8  christos 	 0,			/* Bitpos.  */
    275   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    276   1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    277   1.8  christos 	 "R_DLX_RELOC_16",	/* Name.  */
    278  1.10  christos 	 true,			/* Partial_inplace.  */
    279   1.8  christos 	 0xffff,		/* Src_mask.  */
    280   1.8  christos 	 0xffff,		/* Dst_mask.  */
    281  1.10  christos 	 false),		/* PCrel_offset.  */
    282   1.1  christos 
    283   1.1  christos   /* 32 bit relocation.  */
    284   1.8  christos   HOWTO (R_DLX_RELOC_32,	/* Type. */
    285   1.8  christos 	 0,			/* Rightshift.  */
    286  1.10  christos 	 4,			/* Size.  */
    287   1.8  christos 	 32,			/* Bitsize.  */
    288  1.10  christos 	 false,			/* PC_relative.  */
    289   1.8  christos 	 0,			/* Bitpos.  */
    290   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    291   1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    292   1.8  christos 	 "R_DLX_RELOC_32",	/* Name.  */
    293  1.10  christos 	 true,			/* Partial_inplace.  */
    294   1.8  christos 	 0xffffffff,		/* Src_mask.  */
    295   1.8  christos 	 0xffffffff,		/* Dst_mask.  */
    296  1.10  christos 	 false),		/* PCrel_offset.  */
    297   1.1  christos 
    298   1.1  christos   /* GNU extension to record C++ vtable hierarchy.  */
    299   1.8  christos   HOWTO (R_DLX_GNU_VTINHERIT,	/* Type. */
    300   1.1  christos 	 0,			/* Rightshift.  */
    301  1.10  christos 	 4,			/* Size.  */
    302   1.1  christos 	 0,			/* Bitsize.  */
    303  1.10  christos 	 false,			/* PC_relative.  */
    304   1.1  christos 	 0,			/* Bitpos.  */
    305   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    306   1.1  christos 	 NULL,			/* Special_function.  */
    307   1.1  christos 	 "R_DLX_GNU_VTINHERIT", /* Name.  */
    308  1.10  christos 	 false,			/* Partial_inplace.  */
    309   1.1  christos 	 0,			/* Src_mask.  */
    310   1.1  christos 	 0,			/* Dst_mask.  */
    311  1.10  christos 	 false),		/* PCrel_offset.  */
    312   1.1  christos 
    313   1.1  christos   /* GNU extension to record C++ vtable member usage.  */
    314   1.8  christos   HOWTO (R_DLX_GNU_VTENTRY,	/* Type. */
    315   1.1  christos 	 0,			/* Rightshift.  */
    316  1.10  christos 	 4,			/* Size.  */
    317   1.1  christos 	 0,			/* Bitsize.  */
    318  1.10  christos 	 false,			/* PC_relative.  */
    319   1.1  christos 	 0,			/* Bitpos.  */
    320   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    321   1.1  christos 	 _bfd_elf_rel_vtable_reloc_fn,/* Special_function.  */
    322   1.1  christos 	 "R_DLX_GNU_VTENTRY",	/* Name.  */
    323  1.10  christos 	 false,			/* Partial_inplace.  */
    324   1.1  christos 	 0,			/* Src_mask.  */
    325   1.1  christos 	 0,			/* Dst_mask.  */
    326  1.10  christos 	 false)			/* PCrel_offset.  */
    327   1.1  christos };
    328   1.1  christos 
    329   1.1  christos /* 16 bit offset for pc-relative branches.  */
    330   1.1  christos static reloc_howto_type elf_dlx_gnu_rel16_s2 =
    331   1.8  christos   HOWTO (R_DLX_RELOC_16_PCREL,	/* Type. */
    332   1.8  christos 	 0,			/* Rightshift.  */
    333  1.10  christos 	 2,			/* Size.  */
    334   1.8  christos 	 16,			/* Bitsize.  */
    335  1.10  christos 	 true,			/* PC_relative.  */
    336   1.8  christos 	 0,			/* Bitpos.  */
    337   1.1  christos 	 complain_overflow_signed, /* Complain_on_overflow.  */
    338   1.8  christos 	 elf32_dlx_relocate16,	/* Special_function.  */
    339   1.1  christos 	 "R_DLX_RELOC_16_PCREL",/* Name.  */
    340  1.10  christos 	 true,			/* Partial_inplace.  */
    341   1.8  christos 	 0xffff,		/* Src_mask.  */
    342   1.8  christos 	 0xffff,		/* Dst_mask.  */
    343  1.10  christos 	 true);			/* PCrel_offset.  */
    344   1.1  christos 
    345   1.1  christos /* 26 bit offset for pc-relative branches.  */
    346   1.1  christos static reloc_howto_type elf_dlx_gnu_rel26_s2 =
    347   1.8  christos   HOWTO (R_DLX_RELOC_26_PCREL,	/* Type. */
    348   1.8  christos 	 0,			/* Rightshift.  */
    349  1.10  christos 	 4,			/* Size.  */
    350   1.8  christos 	 26,			/* Bitsize.  */
    351  1.10  christos 	 true,			/* PC_relative.  */
    352   1.8  christos 	 0,			/* Bitpos.  */
    353   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    354   1.8  christos 	 elf32_dlx_relocate26,	/* Special_function.  */
    355   1.1  christos 	 "R_DLX_RELOC_26_PCREL",/* Name.  */
    356  1.10  christos 	 true,			/* Partial_inplace.  */
    357   1.8  christos 	 0xffff,		/* Src_mask.  */
    358   1.8  christos 	 0xffff,		/* Dst_mask.  */
    359  1.10  christos 	 true);			/* PCrel_offset.  */
    360   1.1  christos 
    361   1.1  christos /* High 16 bits of symbol value.  */
    362   1.1  christos static reloc_howto_type elf_dlx_reloc_16_hi =
    363   1.8  christos   HOWTO (R_DLX_RELOC_16_HI,	/* Type. */
    364   1.8  christos 	 16,			/* Rightshift.  */
    365  1.10  christos 	 4,			/* Size.  */
    366   1.8  christos 	 32,			/* Bitsize.  */
    367  1.10  christos 	 false,			/* PC_relative.  */
    368   1.8  christos 	 0,			/* Bitpos.  */
    369   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    370   1.1  christos 	 _bfd_dlx_elf_hi16_reloc,/* Special_function.  */
    371   1.8  christos 	 "R_DLX_RELOC_16_HI",	/* Name.  */
    372  1.10  christos 	 true,			/* Partial_inplace.  */
    373   1.8  christos 	 0xFFFF,		/* Src_mask.  */
    374   1.8  christos 	 0xffff,		/* Dst_mask.  */
    375  1.10  christos 	 false);		/* PCrel_offset.  */
    376   1.1  christos 
    377   1.1  christos   /* Low 16 bits of symbol value.  */
    378   1.1  christos static reloc_howto_type elf_dlx_reloc_16_lo =
    379   1.8  christos   HOWTO (R_DLX_RELOC_16_LO,	/* Type. */
    380   1.8  christos 	 0,			/* Rightshift.  */
    381  1.10  christos 	 2,			/* Size.  */
    382   1.8  christos 	 16,			/* Bitsize.  */
    383  1.10  christos 	 false,			/* PC_relative.  */
    384   1.8  christos 	 0,			/* Bitpos.  */
    385   1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    386   1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    387   1.8  christos 	 "R_DLX_RELOC_16_LO",	/* Name.  */
    388  1.10  christos 	 true,			/* Partial_inplace.  */
    389   1.8  christos 	 0xffff,		/* Src_mask.  */
    390   1.8  christos 	 0xffff,		/* Dst_mask.  */
    391  1.10  christos 	 false);		/* PCrel_offset.  */
    392   1.1  christos 
    393   1.1  christos /* A mapping from BFD reloc types to DLX ELF reloc types.
    394   1.1  christos    Stolen from elf32-mips.c.
    395   1.1  christos 
    396   1.1  christos    More about this table - for dlx elf relocation we do not really
    397   1.1  christos    need this table, if we have a rtype defined in this table will
    398   1.1  christos    caused tc_gen_relocate confused and die on us, but if we remove
    399   1.1  christos    this table it will caused more problem, so for now simple solution
    400   1.1  christos    is to remove those entries which may cause problem.  */
    401   1.1  christos struct elf_reloc_map
    402   1.1  christos {
    403   1.1  christos   bfd_reloc_code_real_type bfd_reloc_val;
    404   1.1  christos   enum elf_dlx_reloc_type elf_reloc_val;
    405   1.1  christos };
    406   1.1  christos 
    407   1.1  christos static const struct elf_reloc_map dlx_reloc_map[] =
    408   1.1  christos {
    409   1.8  christos   { BFD_RELOC_NONE,	      R_DLX_NONE },
    410   1.8  christos   { BFD_RELOC_16,	      R_DLX_RELOC_16 },
    411   1.8  christos   { BFD_RELOC_32,	      R_DLX_RELOC_32 },
    412   1.1  christos   { BFD_RELOC_DLX_HI16_S,     R_DLX_RELOC_16_HI },
    413   1.8  christos   { BFD_RELOC_DLX_LO16,	      R_DLX_RELOC_16_LO },
    414   1.1  christos   { BFD_RELOC_VTABLE_INHERIT,	R_DLX_GNU_VTINHERIT },
    415   1.1  christos   { BFD_RELOC_VTABLE_ENTRY,	R_DLX_GNU_VTENTRY }
    416   1.1  christos };
    417   1.1  christos 
    418   1.1  christos /* Look through the relocs for a section during the first phase.
    419   1.1  christos    Since we don't do .gots or .plts, we just need to consider the
    420   1.1  christos    virtual table relocs for gc.  */
    421   1.1  christos 
    422  1.10  christos static bool
    423   1.1  christos elf32_dlx_check_relocs (bfd *abfd,
    424   1.1  christos 			struct bfd_link_info *info,
    425   1.1  christos 			asection *sec,
    426   1.1  christos 			const Elf_Internal_Rela *relocs)
    427   1.1  christos {
    428   1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    429   1.1  christos   struct elf_link_hash_entry **sym_hashes;
    430   1.1  christos   const Elf_Internal_Rela *rel;
    431   1.1  christos   const Elf_Internal_Rela *rel_end;
    432   1.1  christos 
    433   1.6  christos   if (bfd_link_relocatable (info))
    434  1.10  christos     return true;
    435   1.1  christos 
    436   1.1  christos   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    437   1.1  christos   sym_hashes = elf_sym_hashes (abfd);
    438   1.1  christos 
    439   1.1  christos   rel_end = relocs + sec->reloc_count;
    440   1.1  christos   for (rel = relocs; rel < rel_end; rel++)
    441   1.1  christos     {
    442   1.1  christos       struct elf_link_hash_entry *h;
    443   1.1  christos       unsigned long r_symndx;
    444   1.1  christos 
    445   1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    446   1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    447   1.8  christos 	h = NULL;
    448   1.1  christos       else
    449   1.1  christos 	{
    450   1.1  christos 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    451   1.1  christos 	  while (h->root.type == bfd_link_hash_indirect
    452   1.1  christos 		 || h->root.type == bfd_link_hash_warning)
    453   1.1  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    454   1.1  christos 	}
    455   1.1  christos 
    456   1.1  christos       switch (ELF32_R_TYPE (rel->r_info))
    457   1.8  christos 	{
    458   1.8  christos 	/* This relocation describes the C++ object vtable hierarchy.
    459   1.8  christos 	   Reconstruct it for later use during GC.  */
    460   1.8  christos 	case R_DLX_GNU_VTINHERIT:
    461   1.8  christos 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
    462  1.10  christos 	    return false;
    463   1.8  christos 	  break;
    464   1.8  christos 
    465   1.8  christos 	/* This relocation describes which C++ vtable entries are actually
    466   1.8  christos 	   used.  Record for later use during GC.  */
    467   1.8  christos 	case R_DLX_GNU_VTENTRY:
    468   1.9  christos 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
    469  1.10  christos 	    return false;
    470   1.8  christos 	  break;
    471   1.8  christos 	}
    472   1.1  christos     }
    473   1.1  christos 
    474  1.10  christos   return true;
    475   1.1  christos }
    476   1.1  christos 
    477   1.1  christos /* Given a BFD reloc type, return a howto structure.  */
    478   1.1  christos 
    479   1.1  christos static reloc_howto_type *
    480   1.1  christos elf32_dlx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    481   1.1  christos 			     bfd_reloc_code_real_type code)
    482   1.1  christos {
    483   1.1  christos   unsigned int i;
    484   1.1  christos 
    485   1.1  christos   for (i = 0; i < sizeof (dlx_reloc_map) / sizeof (struct elf_reloc_map); i++)
    486   1.1  christos     if (dlx_reloc_map[i].bfd_reloc_val == code)
    487   1.1  christos       return &dlx_elf_howto_table[(int) dlx_reloc_map[i].elf_reloc_val];
    488   1.1  christos 
    489   1.1  christos   switch (code)
    490   1.1  christos     {
    491   1.1  christos     default:
    492   1.1  christos       bfd_set_error (bfd_error_bad_value);
    493   1.1  christos       return NULL;
    494   1.1  christos     case BFD_RELOC_16_PCREL_S2:
    495   1.1  christos       return &elf_dlx_gnu_rel16_s2;
    496   1.1  christos     case BFD_RELOC_DLX_JMP26:
    497   1.1  christos       return &elf_dlx_gnu_rel26_s2;
    498   1.1  christos     case BFD_RELOC_HI16_S:
    499   1.1  christos       return &elf_dlx_reloc_16_hi;
    500   1.1  christos     case BFD_RELOC_LO16:
    501   1.1  christos       return &elf_dlx_reloc_16_lo;
    502   1.1  christos     }
    503   1.1  christos }
    504   1.1  christos 
    505   1.1  christos static reloc_howto_type *
    506   1.1  christos elf32_dlx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    507   1.1  christos 			     const char *r_name)
    508   1.1  christos {
    509   1.1  christos   unsigned int i;
    510   1.1  christos 
    511   1.1  christos   for (i = 0;
    512   1.1  christos        i < sizeof (dlx_elf_howto_table) / sizeof (dlx_elf_howto_table[0]);
    513   1.1  christos        i++)
    514   1.1  christos     if (dlx_elf_howto_table[i].name != NULL
    515   1.1  christos 	&& strcasecmp (dlx_elf_howto_table[i].name, r_name) == 0)
    516   1.1  christos       return &dlx_elf_howto_table[i];
    517   1.1  christos 
    518   1.1  christos   if (strcasecmp (elf_dlx_gnu_rel16_s2.name, r_name) == 0)
    519   1.1  christos     return &elf_dlx_gnu_rel16_s2;
    520   1.1  christos   if (strcasecmp (elf_dlx_gnu_rel26_s2.name, r_name) == 0)
    521   1.1  christos     return &elf_dlx_gnu_rel26_s2;
    522   1.1  christos   if (strcasecmp (elf_dlx_reloc_16_hi.name, r_name) == 0)
    523   1.1  christos     return &elf_dlx_reloc_16_hi;
    524   1.1  christos   if (strcasecmp (elf_dlx_reloc_16_lo.name, r_name) == 0)
    525   1.1  christos     return &elf_dlx_reloc_16_lo;
    526   1.1  christos 
    527   1.1  christos   return NULL;
    528   1.1  christos }
    529   1.1  christos 
    530   1.1  christos static reloc_howto_type *
    531   1.8  christos dlx_rtype_to_howto (bfd *abfd, unsigned int r_type)
    532   1.1  christos {
    533   1.1  christos   switch (r_type)
    534   1.1  christos     {
    535   1.1  christos     case R_DLX_RELOC_16_PCREL:
    536   1.1  christos       return & elf_dlx_gnu_rel16_s2;
    537   1.1  christos     case R_DLX_RELOC_26_PCREL:
    538   1.1  christos       return & elf_dlx_gnu_rel26_s2;
    539   1.1  christos     case R_DLX_RELOC_16_HI:
    540   1.1  christos       return & elf_dlx_reloc_16_hi;
    541   1.1  christos     case R_DLX_RELOC_16_LO:
    542   1.1  christos       return & elf_dlx_reloc_16_lo;
    543   1.1  christos     default:
    544   1.3  christos       if (r_type >= (unsigned int) R_DLX_max)
    545   1.3  christos 	{
    546   1.8  christos 	  _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    547   1.8  christos 			      abfd, r_type);
    548   1.8  christos 	  bfd_set_error (bfd_error_bad_value);
    549   1.8  christos 	  return NULL;
    550   1.3  christos 	}
    551   1.1  christos       return & dlx_elf_howto_table[r_type];
    552   1.1  christos     }
    553   1.1  christos }
    554   1.1  christos 
    555  1.10  christos static bool
    556   1.1  christos elf32_dlx_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
    557   1.1  christos 			 arelent * cache_ptr ATTRIBUTE_UNUSED,
    558   1.1  christos 			 Elf_Internal_Rela * dst ATTRIBUTE_UNUSED)
    559   1.1  christos {
    560  1.10  christos   return false;
    561   1.1  christos }
    562   1.1  christos 
    563  1.10  christos static bool
    564   1.8  christos elf32_dlx_info_to_howto_rel (bfd *abfd,
    565   1.1  christos 			     arelent *cache_ptr,
    566   1.1  christos 			     Elf_Internal_Rela *dst)
    567   1.1  christos {
    568   1.1  christos   unsigned int r_type;
    569   1.1  christos 
    570   1.1  christos   r_type = ELF32_R_TYPE (dst->r_info);
    571   1.8  christos   cache_ptr->howto = dlx_rtype_to_howto (abfd, r_type);
    572   1.8  christos   return cache_ptr->howto != NULL;
    573   1.1  christos }
    574   1.1  christos 
    575   1.8  christos #define TARGET_BIG_SYM		dlx_elf32_be_vec
    576   1.8  christos #define TARGET_BIG_NAME		"elf32-dlx"
    577   1.8  christos #define ELF_ARCH		bfd_arch_dlx
    578   1.8  christos #define ELF_MACHINE_CODE	EM_DLX
    579   1.8  christos #define ELF_MAXPAGESIZE		1 /* FIXME: This number is wrong,  It should be the page size in bytes.  */
    580   1.1  christos 
    581   1.1  christos #include "elf32-target.h"
    582