| /* DLX specific support for 32-bit ELF | 
 |    Copyright (C) 2002-2022 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of BFD, the Binary File Descriptor library. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program; if not, write to the Free Software | 
 |    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | 
 |    MA 02110-1301, USA.  */ | 
 |  | 
 | #include "sysdep.h" | 
 | #include "bfd.h" | 
 | #include "libbfd.h" | 
 | #include "elf-bfd.h" | 
 | #include "elf/dlx.h" | 
 | #include "elf32-dlx.h" | 
 |  | 
 | #define USE_REL 1 | 
 |  | 
 | #define bfd_elf32_bfd_reloc_type_lookup elf32_dlx_reloc_type_lookup | 
 | #define bfd_elf32_bfd_reloc_name_lookup elf32_dlx_reloc_name_lookup | 
 | #define elf_info_to_howto		elf32_dlx_info_to_howto | 
 | #define elf_info_to_howto_rel		elf32_dlx_info_to_howto_rel | 
 | #define elf_backend_check_relocs	elf32_dlx_check_relocs | 
 |  | 
 | /* The gas default behavior is not to preform the %hi modifier so that the | 
 |    GNU assembler can have the lower 16 bits offset placed in the insn, BUT | 
 |    we do like the gas to indicate it is %hi reloc type so when we in the link | 
 |    loader phase we can have the corrected hi16 vale replace the buggous lo16 | 
 |    value that was placed there by gas.  */ | 
 |  | 
 | static int skip_dlx_elf_hi16_reloc = 0; | 
 |  | 
 | int | 
 | set_dlx_skip_hi16_flag (int flag) | 
 | { | 
 |   skip_dlx_elf_hi16_reloc = flag; | 
 |   return flag; | 
 | } | 
 |  | 
 | static bfd_reloc_status_type | 
 | _bfd_dlx_elf_hi16_reloc (bfd *abfd, | 
 | 			 arelent *reloc_entry, | 
 | 			 asymbol *symbol, | 
 | 			 void * data, | 
 | 			 asection *input_section, | 
 | 			 bfd *output_bfd, | 
 | 			 char **error_message) | 
 | { | 
 |   bfd_reloc_status_type ret; | 
 |   bfd_vma relocation; | 
 |  | 
 |   /* If the skip flag is set then we simply do the generic relocating, this | 
 |      is more of a hack for dlx gas/gld, so we do not need to do the %hi/%lo | 
 |      fixup like mips gld did.   */ | 
 |   if (skip_dlx_elf_hi16_reloc) | 
 |     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, | 
 | 			  input_section, output_bfd, error_message); | 
 |  | 
 |   /* 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; | 
 |     } | 
 |  | 
 |   ret = bfd_reloc_ok; | 
 |  | 
 |   if (bfd_is_und_section (symbol->section) | 
 |       && output_bfd == (bfd *) NULL) | 
 |     ret = bfd_reloc_undefined; | 
 |  | 
 |   relocation = (bfd_is_com_section (symbol->section)) ? 0 : symbol->value; | 
 |   relocation += symbol->section->output_section->vma; | 
 |   relocation += symbol->section->output_offset; | 
 |   relocation += reloc_entry->addend; | 
 |   relocation += bfd_get_16 (abfd, (bfd_byte *)data + reloc_entry->address); | 
 |  | 
 |   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) | 
 |     return bfd_reloc_outofrange; | 
 |  | 
 |   bfd_put_16 (abfd, (short)((relocation >> 16) & 0xFFFF), | 
 | 	      (bfd_byte *)data + reloc_entry->address); | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | /* ELF relocs are against symbols.  If we are producing relocatable | 
 |    output, and the reloc is against an external symbol, and nothing | 
 |    has given us any additional addend, the resulting reloc will also | 
 |    be against the same symbol.  In such a case, we don't want to | 
 |    change anything about the way the reloc is handled, since it will | 
 |    all be done at final link time.  Rather than put special case code | 
 |    into bfd_perform_relocation, all the reloc types use this howto | 
 |    function.  It just short circuits the reloc if producing | 
 |    relocatable output against an external symbol.  */ | 
 |  | 
 | static bfd_reloc_status_type | 
 | elf32_dlx_relocate16 (bfd *abfd, | 
 | 		      arelent *reloc_entry, | 
 | 		      asymbol *symbol, | 
 | 		      void * data, | 
 | 		      asection *input_section, | 
 | 		      bfd *output_bfd, | 
 | 		      char **error_message ATTRIBUTE_UNUSED) | 
 | { | 
 |   unsigned long insn, vallo, allignment; | 
 |   int		val; | 
 |  | 
 |   /* HACK: I think this first condition is necessary when producing | 
 |      relocatable output.  After the end of HACK, the code is identical | 
 |      to bfd_elf_generic_reloc().  I would _guess_ the first change | 
 |      belongs there rather than here.  martindo 1998-10-23.  */ | 
 |  | 
 |   if (skip_dlx_elf_hi16_reloc) | 
 |     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, | 
 | 				 input_section, output_bfd, error_message); | 
 |  | 
 |   /* Check undefined section and undefined symbols.  */ | 
 |   if (bfd_is_und_section (symbol->section) | 
 |       && output_bfd == (bfd *) NULL) | 
 |     return bfd_reloc_undefined; | 
 |  | 
 |   /* Can not support a long jump to sections other then .text.  */ | 
 |   if (strcmp (input_section->name, symbol->section->output_section->name) != 0) | 
 |     { | 
 |       _bfd_error_handler | 
 | 	(_("branch (PC rel16) to section (%s) not supported"), | 
 | 	 symbol->section->output_section->name); | 
 |       return bfd_reloc_undefined; | 
 |     } | 
 |  | 
 |   insn  = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address); | 
 |   allignment = 1 << (input_section->output_section->alignment_power - 1); | 
 |   vallo = insn & 0x0000FFFF; | 
 |  | 
 |   if (vallo & 0x8000) | 
 |     vallo = ~(vallo | 0xFFFF0000) + 1; | 
 |  | 
 |   /* vallo points to the vma of next instruction.  */ | 
 |   vallo += (((unsigned long)(input_section->output_section->vma + | 
 | 			   input_section->output_offset) + | 
 | 	    allignment) & ~allignment); | 
 |  | 
 |   /* val is the displacement (PC relative to next instruction).  */ | 
 |   val =  (symbol->section->output_offset + | 
 | 	  symbol->section->output_section->vma + | 
 | 	  symbol->value) - vallo; | 
 |  | 
 |   if (abs ((int) val) > 0x00007FFF) | 
 |     return bfd_reloc_outofrange; | 
 |  | 
 |   insn  = (insn & 0xFFFF0000) | (val & 0x0000FFFF); | 
 |  | 
 |   bfd_put_32 (abfd, insn, | 
 | 	      (bfd_byte *) data + reloc_entry->address); | 
 |  | 
 |   return bfd_reloc_ok; | 
 | } | 
 |  | 
 | static bfd_reloc_status_type | 
 | elf32_dlx_relocate26 (bfd *abfd, | 
 | 		      arelent *reloc_entry, | 
 | 		      asymbol *symbol, | 
 | 		      void * data, | 
 | 		      asection *input_section, | 
 | 		      bfd *output_bfd, | 
 | 		      char **error_message ATTRIBUTE_UNUSED) | 
 | { | 
 |   unsigned long insn, vallo, allignment; | 
 |   int		val; | 
 |  | 
 |   /* HACK: I think this first condition is necessary when producing | 
 |      relocatable output.  After the end of HACK, the code is identical | 
 |      to bfd_elf_generic_reloc().  I would _guess_ the first change | 
 |      belongs there rather than here.  martindo 1998-10-23.  */ | 
 |  | 
 |   if (skip_dlx_elf_hi16_reloc) | 
 |     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, | 
 | 				 input_section, output_bfd, error_message); | 
 |  | 
 |   /* Check undefined section and undefined symbols.  */ | 
 |   if (bfd_is_und_section (symbol->section) | 
 |       && output_bfd == (bfd *) NULL) | 
 |     return bfd_reloc_undefined; | 
 |  | 
 |   /* Can not support a long jump to sections other then .text   */ | 
 |   if (strcmp (input_section->name, symbol->section->output_section->name) != 0) | 
 |     { | 
 |       _bfd_error_handler | 
 | 	(_("jump (PC rel26) to section (%s) not supported"), | 
 | 	 symbol->section->output_section->name); | 
 |       return bfd_reloc_undefined; | 
 |     } | 
 |  | 
 |   insn  = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address); | 
 |   allignment = 1 << (input_section->output_section->alignment_power - 1); | 
 |   vallo = insn & 0x03FFFFFF; | 
 |  | 
 |   if (vallo & 0x03000000) | 
 |     vallo = ~(vallo | 0xFC000000) + 1; | 
 |  | 
 |   /* vallo is the vma for the next instruction.  */ | 
 |   vallo += (((unsigned long) (input_section->output_section->vma + | 
 | 			      input_section->output_offset) + | 
 | 	     allignment) & ~allignment); | 
 |  | 
 |   /* val is the displacement (PC relative to next instruction).  */ | 
 |   val = (symbol->section->output_offset + | 
 | 	 symbol->section->output_section->vma + symbol->value) | 
 |     - vallo; | 
 |  | 
 |   if (abs ((int) val) > 0x01FFFFFF) | 
 |     return bfd_reloc_outofrange; | 
 |  | 
 |   insn  = (insn & 0xFC000000) | (val & 0x03FFFFFF); | 
 |   bfd_put_32 (abfd, insn, | 
 | 	      (bfd_byte *) data + reloc_entry->address); | 
 |  | 
 |   return bfd_reloc_ok; | 
 | } | 
 |  | 
 | static reloc_howto_type dlx_elf_howto_table[]= | 
 | { | 
 |   /* No relocation.  */ | 
 |   HOWTO (R_DLX_NONE,		/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 0,			/* size.  */ | 
 | 	 0,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 bfd_elf_generic_reloc, /* Special_function.  */ | 
 | 	 "R_DLX_NONE",		/* Name.  */ | 
 | 	 false,			/* Partial_inplace.  */ | 
 | 	 0,			/* Src_mask.  */ | 
 | 	 0,			/* Dst_mask.  */ | 
 | 	 false),		/* PCrel_offset.  */ | 
 |  | 
 |   /* 8 bit relocation.  */ | 
 |   HOWTO (R_DLX_RELOC_8,		/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 1,			/* Size.  */ | 
 | 	 8,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 bfd_elf_generic_reloc, /* Special_function.  */ | 
 | 	 "R_DLX_RELOC_8",	/* Name.  */ | 
 | 	 true,			/* Partial_inplace.  */ | 
 | 	 0xff,			/* Src_mask.  */ | 
 | 	 0xff,			/* Dst_mask.  */ | 
 | 	 false),		/* PCrel_offset.  */ | 
 |  | 
 |   /* 16 bit relocation.  */ | 
 |   HOWTO (R_DLX_RELOC_16,	/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 2,			/* Size.  */ | 
 | 	 16,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 bfd_elf_generic_reloc, /* Special_function.  */ | 
 | 	 "R_DLX_RELOC_16",	/* Name.  */ | 
 | 	 true,			/* Partial_inplace.  */ | 
 | 	 0xffff,		/* Src_mask.  */ | 
 | 	 0xffff,		/* Dst_mask.  */ | 
 | 	 false),		/* PCrel_offset.  */ | 
 |  | 
 |   /* 32 bit relocation.  */ | 
 |   HOWTO (R_DLX_RELOC_32,	/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 4,			/* Size.  */ | 
 | 	 32,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 bfd_elf_generic_reloc, /* Special_function.  */ | 
 | 	 "R_DLX_RELOC_32",	/* Name.  */ | 
 | 	 true,			/* Partial_inplace.  */ | 
 | 	 0xffffffff,		/* Src_mask.  */ | 
 | 	 0xffffffff,		/* Dst_mask.  */ | 
 | 	 false),		/* PCrel_offset.  */ | 
 |  | 
 |   /* GNU extension to record C++ vtable hierarchy.  */ | 
 |   HOWTO (R_DLX_GNU_VTINHERIT,	/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 4,			/* Size.  */ | 
 | 	 0,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 NULL,			/* Special_function.  */ | 
 | 	 "R_DLX_GNU_VTINHERIT", /* Name.  */ | 
 | 	 false,			/* Partial_inplace.  */ | 
 | 	 0,			/* Src_mask.  */ | 
 | 	 0,			/* Dst_mask.  */ | 
 | 	 false),		/* PCrel_offset.  */ | 
 |  | 
 |   /* GNU extension to record C++ vtable member usage.  */ | 
 |   HOWTO (R_DLX_GNU_VTENTRY,	/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 4,			/* Size.  */ | 
 | 	 0,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 _bfd_elf_rel_vtable_reloc_fn,/* Special_function.  */ | 
 | 	 "R_DLX_GNU_VTENTRY",	/* Name.  */ | 
 | 	 false,			/* Partial_inplace.  */ | 
 | 	 0,			/* Src_mask.  */ | 
 | 	 0,			/* Dst_mask.  */ | 
 | 	 false)			/* PCrel_offset.  */ | 
 | }; | 
 |  | 
 | /* 16 bit offset for pc-relative branches.  */ | 
 | static reloc_howto_type elf_dlx_gnu_rel16_s2 = | 
 |   HOWTO (R_DLX_RELOC_16_PCREL,	/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 2,			/* Size.  */ | 
 | 	 16,			/* Bitsize.  */ | 
 | 	 true,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_signed, /* Complain_on_overflow.  */ | 
 | 	 elf32_dlx_relocate16,	/* Special_function.  */ | 
 | 	 "R_DLX_RELOC_16_PCREL",/* Name.  */ | 
 | 	 true,			/* Partial_inplace.  */ | 
 | 	 0xffff,		/* Src_mask.  */ | 
 | 	 0xffff,		/* Dst_mask.  */ | 
 | 	 true);			/* PCrel_offset.  */ | 
 |  | 
 | /* 26 bit offset for pc-relative branches.  */ | 
 | static reloc_howto_type elf_dlx_gnu_rel26_s2 = | 
 |   HOWTO (R_DLX_RELOC_26_PCREL,	/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 4,			/* Size.  */ | 
 | 	 26,			/* Bitsize.  */ | 
 | 	 true,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 elf32_dlx_relocate26,	/* Special_function.  */ | 
 | 	 "R_DLX_RELOC_26_PCREL",/* Name.  */ | 
 | 	 true,			/* Partial_inplace.  */ | 
 | 	 0xffff,		/* Src_mask.  */ | 
 | 	 0xffff,		/* Dst_mask.  */ | 
 | 	 true);			/* PCrel_offset.  */ | 
 |  | 
 | /* High 16 bits of symbol value.  */ | 
 | static reloc_howto_type elf_dlx_reloc_16_hi = | 
 |   HOWTO (R_DLX_RELOC_16_HI,	/* Type. */ | 
 | 	 16,			/* Rightshift.  */ | 
 | 	 4,			/* Size.  */ | 
 | 	 32,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 _bfd_dlx_elf_hi16_reloc,/* Special_function.  */ | 
 | 	 "R_DLX_RELOC_16_HI",	/* Name.  */ | 
 | 	 true,			/* Partial_inplace.  */ | 
 | 	 0xFFFF,		/* Src_mask.  */ | 
 | 	 0xffff,		/* Dst_mask.  */ | 
 | 	 false);		/* PCrel_offset.  */ | 
 |  | 
 |   /* Low 16 bits of symbol value.  */ | 
 | static reloc_howto_type elf_dlx_reloc_16_lo = | 
 |   HOWTO (R_DLX_RELOC_16_LO,	/* Type. */ | 
 | 	 0,			/* Rightshift.  */ | 
 | 	 2,			/* Size.  */ | 
 | 	 16,			/* Bitsize.  */ | 
 | 	 false,			/* PC_relative.  */ | 
 | 	 0,			/* Bitpos.  */ | 
 | 	 complain_overflow_dont,/* Complain_on_overflow.  */ | 
 | 	 bfd_elf_generic_reloc, /* Special_function.  */ | 
 | 	 "R_DLX_RELOC_16_LO",	/* Name.  */ | 
 | 	 true,			/* Partial_inplace.  */ | 
 | 	 0xffff,		/* Src_mask.  */ | 
 | 	 0xffff,		/* Dst_mask.  */ | 
 | 	 false);		/* PCrel_offset.  */ | 
 |  | 
 | /* A mapping from BFD reloc types to DLX ELF reloc types. | 
 |    Stolen from elf32-mips.c. | 
 |  | 
 |    More about this table - for dlx elf relocation we do not really | 
 |    need this table, if we have a rtype defined in this table will | 
 |    caused tc_gen_relocate confused and die on us, but if we remove | 
 |    this table it will caused more problem, so for now simple solution | 
 |    is to remove those entries which may cause problem.  */ | 
 | struct elf_reloc_map | 
 | { | 
 |   bfd_reloc_code_real_type bfd_reloc_val; | 
 |   enum elf_dlx_reloc_type elf_reloc_val; | 
 | }; | 
 |  | 
 | static const struct elf_reloc_map dlx_reloc_map[] = | 
 | { | 
 |   { BFD_RELOC_NONE,	      R_DLX_NONE }, | 
 |   { BFD_RELOC_16,	      R_DLX_RELOC_16 }, | 
 |   { BFD_RELOC_32,	      R_DLX_RELOC_32 }, | 
 |   { BFD_RELOC_DLX_HI16_S,     R_DLX_RELOC_16_HI }, | 
 |   { BFD_RELOC_DLX_LO16,	      R_DLX_RELOC_16_LO }, | 
 |   { BFD_RELOC_VTABLE_INHERIT,	R_DLX_GNU_VTINHERIT }, | 
 |   { BFD_RELOC_VTABLE_ENTRY,	R_DLX_GNU_VTENTRY } | 
 | }; | 
 |  | 
 | /* Look through the relocs for a section during the first phase. | 
 |    Since we don't do .gots or .plts, we just need to consider the | 
 |    virtual table relocs for gc.  */ | 
 |  | 
 | static bool | 
 | elf32_dlx_check_relocs (bfd *abfd, | 
 | 			struct bfd_link_info *info, | 
 | 			asection *sec, | 
 | 			const Elf_Internal_Rela *relocs) | 
 | { | 
 |   Elf_Internal_Shdr *symtab_hdr; | 
 |   struct elf_link_hash_entry **sym_hashes; | 
 |   const Elf_Internal_Rela *rel; | 
 |   const Elf_Internal_Rela *rel_end; | 
 |  | 
 |   if (bfd_link_relocatable (info)) | 
 |     return true; | 
 |  | 
 |   symtab_hdr = &elf_tdata (abfd)->symtab_hdr; | 
 |   sym_hashes = elf_sym_hashes (abfd); | 
 |  | 
 |   rel_end = relocs + sec->reloc_count; | 
 |   for (rel = relocs; rel < rel_end; rel++) | 
 |     { | 
 |       struct elf_link_hash_entry *h; | 
 |       unsigned long r_symndx; | 
 |  | 
 |       r_symndx = ELF32_R_SYM (rel->r_info); | 
 |       if (r_symndx < symtab_hdr->sh_info) | 
 | 	h = NULL; | 
 |       else | 
 | 	{ | 
 | 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info]; | 
 | 	  while (h->root.type == bfd_link_hash_indirect | 
 | 		 || h->root.type == bfd_link_hash_warning) | 
 | 	    h = (struct elf_link_hash_entry *) h->root.u.i.link; | 
 | 	} | 
 |  | 
 |       switch (ELF32_R_TYPE (rel->r_info)) | 
 | 	{ | 
 | 	/* This relocation describes the C++ object vtable hierarchy. | 
 | 	   Reconstruct it for later use during GC.  */ | 
 | 	case R_DLX_GNU_VTINHERIT: | 
 | 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) | 
 | 	    return false; | 
 | 	  break; | 
 |  | 
 | 	/* This relocation describes which C++ vtable entries are actually | 
 | 	   used.  Record for later use during GC.  */ | 
 | 	case R_DLX_GNU_VTENTRY: | 
 | 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) | 
 | 	    return false; | 
 | 	  break; | 
 | 	} | 
 |     } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | /* Given a BFD reloc type, return a howto structure.  */ | 
 |  | 
 | static reloc_howto_type * | 
 | elf32_dlx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 			     bfd_reloc_code_real_type code) | 
 | { | 
 |   unsigned int i; | 
 |  | 
 |   for (i = 0; i < sizeof (dlx_reloc_map) / sizeof (struct elf_reloc_map); i++) | 
 |     if (dlx_reloc_map[i].bfd_reloc_val == code) | 
 |       return &dlx_elf_howto_table[(int) dlx_reloc_map[i].elf_reloc_val]; | 
 |  | 
 |   switch (code) | 
 |     { | 
 |     default: | 
 |       bfd_set_error (bfd_error_bad_value); | 
 |       return NULL; | 
 |     case BFD_RELOC_16_PCREL_S2: | 
 |       return &elf_dlx_gnu_rel16_s2; | 
 |     case BFD_RELOC_DLX_JMP26: | 
 |       return &elf_dlx_gnu_rel26_s2; | 
 |     case BFD_RELOC_HI16_S: | 
 |       return &elf_dlx_reloc_16_hi; | 
 |     case BFD_RELOC_LO16: | 
 |       return &elf_dlx_reloc_16_lo; | 
 |     } | 
 | } | 
 |  | 
 | static reloc_howto_type * | 
 | elf32_dlx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 			     const char *r_name) | 
 | { | 
 |   unsigned int i; | 
 |  | 
 |   for (i = 0; | 
 |        i < sizeof (dlx_elf_howto_table) / sizeof (dlx_elf_howto_table[0]); | 
 |        i++) | 
 |     if (dlx_elf_howto_table[i].name != NULL | 
 | 	&& strcasecmp (dlx_elf_howto_table[i].name, r_name) == 0) | 
 |       return &dlx_elf_howto_table[i]; | 
 |  | 
 |   if (strcasecmp (elf_dlx_gnu_rel16_s2.name, r_name) == 0) | 
 |     return &elf_dlx_gnu_rel16_s2; | 
 |   if (strcasecmp (elf_dlx_gnu_rel26_s2.name, r_name) == 0) | 
 |     return &elf_dlx_gnu_rel26_s2; | 
 |   if (strcasecmp (elf_dlx_reloc_16_hi.name, r_name) == 0) | 
 |     return &elf_dlx_reloc_16_hi; | 
 |   if (strcasecmp (elf_dlx_reloc_16_lo.name, r_name) == 0) | 
 |     return &elf_dlx_reloc_16_lo; | 
 |  | 
 |   return NULL; | 
 | } | 
 |  | 
 | static reloc_howto_type * | 
 | dlx_rtype_to_howto (bfd *abfd, unsigned int r_type) | 
 | { | 
 |   switch (r_type) | 
 |     { | 
 |     case R_DLX_RELOC_16_PCREL: | 
 |       return & elf_dlx_gnu_rel16_s2; | 
 |     case R_DLX_RELOC_26_PCREL: | 
 |       return & elf_dlx_gnu_rel26_s2; | 
 |     case R_DLX_RELOC_16_HI: | 
 |       return & elf_dlx_reloc_16_hi; | 
 |     case R_DLX_RELOC_16_LO: | 
 |       return & elf_dlx_reloc_16_lo; | 
 |     default: | 
 |       if (r_type >= (unsigned int) R_DLX_max) | 
 | 	{ | 
 | 	  _bfd_error_handler (_("%pB: unsupported relocation type %#x"), | 
 | 			      abfd, r_type); | 
 | 	  bfd_set_error (bfd_error_bad_value); | 
 | 	  return NULL; | 
 | 	} | 
 |       return & dlx_elf_howto_table[r_type]; | 
 |     } | 
 | } | 
 |  | 
 | static bool | 
 | elf32_dlx_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, | 
 | 			 arelent * cache_ptr ATTRIBUTE_UNUSED, | 
 | 			 Elf_Internal_Rela * dst ATTRIBUTE_UNUSED) | 
 | { | 
 |   return false; | 
 | } | 
 |  | 
 | static bool | 
 | elf32_dlx_info_to_howto_rel (bfd *abfd, | 
 | 			     arelent *cache_ptr, | 
 | 			     Elf_Internal_Rela *dst) | 
 | { | 
 |   unsigned int r_type; | 
 |  | 
 |   r_type = ELF32_R_TYPE (dst->r_info); | 
 |   cache_ptr->howto = dlx_rtype_to_howto (abfd, r_type); | 
 |   return cache_ptr->howto != NULL; | 
 | } | 
 |  | 
 | #define TARGET_BIG_SYM		dlx_elf32_be_vec | 
 | #define TARGET_BIG_NAME		"elf32-dlx" | 
 | #define ELF_ARCH		bfd_arch_dlx | 
 | #define ELF_MACHINE_CODE	EM_DLX | 
 | #define ELF_MAXPAGESIZE		1 /* FIXME: This number is wrong,  It should be the page size in bytes.  */ | 
 |  | 
 | #include "elf32-target.h" |