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
set_dlx_skip_hi16_flag(flag)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
_bfd_dlx_elf_hi16_reloc(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)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
elf32_dlx_relocate16(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)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
elf32_dlx_relocate26(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)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
elf32_dlx_check_relocs(abfd,info,sec,relocs)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 *
elf32_dlx_reloc_type_lookup(abfd,code)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 *
dlx_rtype_to_howto(r_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
elf32_dlx_info_to_howto(abfd,cache_ptr,dst)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
elf32_dlx_info_to_howto_rel(abfd,cache_ptr,dst)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"
661