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