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