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