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