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