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