elf32-visium.c revision 1.1.1.9 1 1.1 christos /* Visium-specific support for 32-bit ELF.
2 1.1 christos
3 1.1.1.9 christos Copyright (C) 2003-2026 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 1.1 christos Boston, MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1 christos #include "bfd.h"
24 1.1 christos #include "sysdep.h"
25 1.1 christos #include "libbfd.h"
26 1.1 christos #include "elf-bfd.h"
27 1.1 christos #include "elf/visium.h"
28 1.1.1.4 christos #include "libiberty.h"
29 1.1 christos
30 1.1 christos static bfd_reloc_status_type visium_elf_howto_parity_reloc
31 1.1.1.6 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
32 1.1 christos
33 1.1 christos static reloc_howto_type visium_elf_howto_table[] = {
34 1.1 christos /* This reloc does nothing. */
35 1.1 christos HOWTO (R_VISIUM_NONE, /* type */
36 1.1 christos 0, /* rightshift */
37 1.1.1.6 christos 0, /* size */
38 1.1 christos 0, /* bitsize */
39 1.1.1.6 christos false, /* pc_relative */
40 1.1 christos 0, /* bitpos */
41 1.1 christos complain_overflow_dont, /* complain_on_overflow */
42 1.1 christos bfd_elf_generic_reloc, /* special_function */
43 1.1 christos "R_VISIUM_NONE", /* name */
44 1.1.1.6 christos false, /* partial_inplace */
45 1.1 christos 0, /* src_mask */
46 1.1 christos 0, /* dst_mask */
47 1.1.1.6 christos false), /* pcrel_offset */
48 1.1 christos
49 1.1 christos /* A 8 bit absolute relocation. */
50 1.1 christos HOWTO (R_VISIUM_8, /* type */
51 1.1 christos 0, /* rightshift */
52 1.1.1.6 christos 1, /* size */
53 1.1 christos 8, /* bitsize */
54 1.1.1.6 christos false, /* pc_relative */
55 1.1 christos 0, /* bitpos */
56 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
57 1.1 christos bfd_elf_generic_reloc, /* special_function */
58 1.1 christos "R_VISIUM_8", /* name */
59 1.1.1.6 christos false, /* partial_inplace */
60 1.1 christos 0x00, /* src_mask */
61 1.1 christos 0xff, /* dst_mask */
62 1.1.1.6 christos false), /* pcrel_offset */
63 1.1 christos
64 1.1 christos /* A 16 bit absolute relocation. */
65 1.1 christos HOWTO (R_VISIUM_16, /* type */
66 1.1 christos 0, /* rightshift */
67 1.1.1.6 christos 2, /* size */
68 1.1 christos 16, /* bitsize */
69 1.1.1.6 christos false, /* pc_relative */
70 1.1 christos 0, /* bitpos */
71 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
72 1.1 christos bfd_elf_generic_reloc, /* special_function */
73 1.1 christos "R_VISIUM_16", /* name */
74 1.1.1.6 christos false, /* partial_inplace */
75 1.1 christos 0x0000, /* src_mask */
76 1.1 christos 0xffff, /* dst_mask */
77 1.1.1.6 christos false), /* pcrel_offset */
78 1.1 christos
79 1.1 christos /* A 32 bit absolute relocation. */
80 1.1 christos HOWTO (R_VISIUM_32, /* type */
81 1.1 christos 0, /* rightshift */
82 1.1.1.6 christos 4, /* size */
83 1.1 christos 32, /* bitsize */
84 1.1.1.6 christos false, /* pc_relative */
85 1.1 christos 0, /* bitpos */
86 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
87 1.1 christos bfd_elf_generic_reloc, /* special_function */
88 1.1 christos "R_VISIUM_32", /* name */
89 1.1.1.6 christos false, /* partial_inplace */
90 1.1 christos 0x00000000, /* src_mask */
91 1.1 christos 0xffffffff, /* dst_mask */
92 1.1.1.6 christos false), /* pcrel_offset */
93 1.1 christos
94 1.1 christos
95 1.1 christos /* A 8 bit PC relative relocation. */
96 1.1 christos HOWTO (R_VISIUM_8_PCREL, /* type */
97 1.1 christos 0, /* rightshift */
98 1.1.1.6 christos 1, /* size */
99 1.1 christos 8, /* bitsize */
100 1.1.1.6 christos true, /* pc_relative */
101 1.1 christos 0, /* bitpos */
102 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
103 1.1 christos bfd_elf_generic_reloc, /* special_function */
104 1.1 christos "R_VISIUM_8_PCREL", /* name */
105 1.1.1.6 christos false, /* partial_inplace */
106 1.1 christos 0x00, /* src_mask */
107 1.1 christos 0xff, /* dst_mask */
108 1.1.1.6 christos true), /* pcrel_offset */
109 1.1 christos
110 1.1 christos /* A 16 bit PC relative relocation. */
111 1.1 christos HOWTO (R_VISIUM_16_PCREL, /* type */
112 1.1 christos 0, /* rightshift */
113 1.1.1.6 christos 2, /* size */
114 1.1 christos 16, /* bitsize */
115 1.1.1.6 christos true, /* pc_relative */
116 1.1 christos 0, /* bitpos */
117 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
118 1.1 christos bfd_elf_generic_reloc, /* special_function */
119 1.1 christos "R_VISIUM_16_PCREL", /* name */
120 1.1.1.6 christos false, /* partial inplace */
121 1.1 christos 0x0000, /* src_mask */
122 1.1 christos 0xffff, /* dst_mask */
123 1.1.1.6 christos true), /* pcrel_offset */
124 1.1 christos
125 1.1 christos /* A 32-bit PC relative relocation. */
126 1.1 christos HOWTO (R_VISIUM_32_PCREL, /* type */
127 1.1 christos 0, /* rightshift */
128 1.1.1.6 christos 4, /* size */
129 1.1 christos 32, /* bitsize */
130 1.1.1.6 christos true, /* pc_relative */
131 1.1 christos 0, /* bitpos */
132 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
133 1.1 christos bfd_elf_generic_reloc, /* special_function */
134 1.1 christos "R_VISIUM_32_PCREL", /* name */
135 1.1.1.6 christos false, /* partial_inplace */
136 1.1 christos 0, /* src_mask */
137 1.1 christos 0xffffffff, /* dst_mask */
138 1.1.1.6 christos true), /* pcrel_offset */
139 1.1 christos
140 1.1 christos /* A 16-bit PC word relative offset, relative to start of instruction
141 1.1 christos and always in the second half of the instruction. */
142 1.1 christos HOWTO (R_VISIUM_PC16, /* type */
143 1.1 christos 2, /* rightshift */
144 1.1.1.6 christos 4, /* size */
145 1.1 christos 16, /* bitsize */
146 1.1.1.6 christos true, /* pc_relative */
147 1.1 christos 0, /* bitpos */
148 1.1 christos complain_overflow_signed, /* complain_on_overflow */
149 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
150 1.1 christos "R_VISIUM_PC16", /* name */
151 1.1.1.6 christos false, /* partial_inplace */
152 1.1 christos 0x00000000, /* src_mask */
153 1.1 christos 0x0000ffff, /* dst_mask */
154 1.1.1.6 christos true), /* pcrel_offset */
155 1.1 christos
156 1.1 christos /* The high 16 bits of symbol value. */
157 1.1 christos HOWTO (R_VISIUM_HI16, /* type */
158 1.1 christos 16, /* rightshift */
159 1.1.1.6 christos 4, /* size */
160 1.1 christos 16, /* bitsize */
161 1.1.1.6 christos false, /* pc_relative */
162 1.1 christos 0, /* bitpos */
163 1.1 christos complain_overflow_dont, /* complain_on_overflow */
164 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
165 1.1 christos "R_VISIUM_HI16", /* name */
166 1.1.1.6 christos false, /* partial_inplace */
167 1.1 christos 0x00000000, /* src_mask */
168 1.1 christos 0x0000ffff, /* dst_mask */
169 1.1.1.6 christos false), /* pcrel_offset */
170 1.1 christos
171 1.1 christos /* The low 16 bits of symbol value. */
172 1.1 christos HOWTO (R_VISIUM_LO16, /* type */
173 1.1 christos 0, /* rightshift */
174 1.1.1.6 christos 4, /* size */
175 1.1 christos 16, /* bitsize */
176 1.1.1.6 christos false, /* pc_relative */
177 1.1 christos 0, /* bitpos */
178 1.1 christos complain_overflow_dont, /* complain_on_overflow */
179 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
180 1.1 christos "R_VISIUM_LO16", /* name */
181 1.1.1.6 christos false, /* partial_inplace */
182 1.1 christos 0x00000000, /* src_mask */
183 1.1 christos 0x0000ffff, /* dst_mask */
184 1.1.1.6 christos false), /* pcrel_offset */
185 1.1 christos
186 1.1 christos /* A 16 bit immediate value. */
187 1.1 christos HOWTO (R_VISIUM_IM16, /* type */
188 1.1 christos 0, /* rightshift */
189 1.1.1.6 christos 4, /* size */
190 1.1 christos 16, /* bitsize */
191 1.1.1.6 christos false, /* pc_relative */
192 1.1 christos 0, /* bitpos */
193 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
194 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
195 1.1 christos "R_VISIUM_IM16", /* name */
196 1.1.1.6 christos false, /* partial_inplace */
197 1.1 christos 0x0000000, /* src_mask */
198 1.1 christos 0x000ffff, /* dst_mask */
199 1.1.1.6 christos false), /* pcrel_offset */
200 1.1 christos
201 1.1 christos /* The high 16 bits of symbol value, pc relative. */
202 1.1 christos HOWTO (R_VISIUM_HI16_PCREL, /* type */
203 1.1 christos 16, /* rightshift */
204 1.1.1.6 christos 4, /* size */
205 1.1 christos 16, /* bitsize */
206 1.1.1.6 christos true, /* pc_relative */
207 1.1 christos 0, /* bitpos */
208 1.1 christos complain_overflow_dont, /* complain_on_overflow */
209 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
210 1.1 christos "R_VISIUM_HI16_PCREL", /* name */
211 1.1.1.6 christos false, /* partial_inplace */
212 1.1 christos 0x00000000, /* src_mask */
213 1.1 christos 0x0000ffff, /* dst_mask */
214 1.1.1.6 christos true), /* pcrel_offset */
215 1.1 christos
216 1.1 christos /* The low 16 bits of symbol value, pc relative. */
217 1.1 christos HOWTO (R_VISIUM_LO16_PCREL, /* type */
218 1.1 christos 0, /* rightshift */
219 1.1.1.6 christos 4, /* size */
220 1.1 christos 16, /* bitsize */
221 1.1.1.6 christos true, /* pc_relative */
222 1.1 christos 0, /* bitpos */
223 1.1 christos complain_overflow_dont, /* complain_on_overflow */
224 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
225 1.1 christos "R_VISIUM_LO16_PCREL", /* name */
226 1.1.1.6 christos false, /* partial_inplace */
227 1.1 christos 0x00000000, /* src_mask */
228 1.1 christos 0x0000ffff, /* dst_mask */
229 1.1.1.6 christos true), /* pcrel_offset */
230 1.1 christos
231 1.1 christos /* A 16 bit immediate value, pc relative. */
232 1.1 christos HOWTO (R_VISIUM_IM16_PCREL, /* type */
233 1.1 christos 0, /* rightshift */
234 1.1.1.6 christos 4, /* size */
235 1.1 christos 16, /* bitsize */
236 1.1.1.6 christos true, /* pc_relative */
237 1.1 christos 0, /* bitpos */
238 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
239 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
240 1.1 christos "R_VISIUM_IM16_PCREL", /* name */
241 1.1.1.6 christos false, /* partial_inplace */
242 1.1 christos 0x0000000, /* src_mask */
243 1.1 christos 0x000ffff, /* dst_mask */
244 1.1.1.6 christos true), /* pcrel_offset */
245 1.1 christos
246 1.1 christos };
247 1.1 christos
248 1.1 christos /* GNU extension to record C++ vtable hierarchy. */
249 1.1 christos static reloc_howto_type visium_elf_vtinherit_howto =
250 1.1 christos HOWTO (R_VISIUM_GNU_VTINHERIT, /* type */
251 1.1 christos 0, /* rightshift */
252 1.1.1.6 christos 4, /* size */
253 1.1 christos 0, /* bitsize */
254 1.1.1.6 christos false, /* pc_relative */
255 1.1 christos 0, /* bitpos */
256 1.1 christos complain_overflow_dont, /* complain_on_overflow */
257 1.1 christos NULL, /* special_function */
258 1.1 christos "R_VISIUM_GNU_VTINHERIT", /* name */
259 1.1.1.6 christos false, /* partial_inplace */
260 1.1 christos 0, /* src_mask */
261 1.1 christos 0, /* dst_mask */
262 1.1.1.6 christos false); /* pcrel_offset */
263 1.1 christos
264 1.1 christos /* GNU extension to record C++ vtable member usage. */
265 1.1 christos static reloc_howto_type visium_elf_vtentry_howto =
266 1.1 christos HOWTO (R_VISIUM_GNU_VTENTRY, /* type */
267 1.1 christos 0, /* rightshift */
268 1.1.1.6 christos 4, /* size */
269 1.1 christos 0, /* bitsize */
270 1.1.1.6 christos false, /* pc_relative */
271 1.1 christos 0, /* bitpos */
272 1.1 christos complain_overflow_dont, /* complain_on_overflow */
273 1.1 christos NULL, /* special_function */
274 1.1 christos "R_VISIUM_GNU_VTENTRY", /* name */
275 1.1.1.6 christos false, /* partial_inplace */
276 1.1 christos 0, /* src_mask */
277 1.1 christos 0, /* dst_mask */
278 1.1.1.6 christos false); /* pcrel_offset */
279 1.1 christos
280 1.1 christos /* Return the parity bit for INSN shifted to its final position. */
281 1.1 christos
282 1.1 christos static bfd_vma
283 1.1 christos visium_parity_bit (bfd_vma insn)
284 1.1 christos {
285 1.1 christos bfd_vma p = 0;
286 1.1 christos int i;
287 1.1 christos
288 1.1 christos for (i = 0; i < 31; i++)
289 1.1 christos {
290 1.1 christos p ^= (insn & 1);
291 1.1 christos insn >>= 1;
292 1.1 christos }
293 1.1 christos
294 1.1 christos return p << 31;
295 1.1 christos }
296 1.1 christos
297 1.1 christos /* This "special function" will only be used when the input and
298 1.1 christos output files have different formats ie. when generating S-records
299 1.1 christos directly using "--oformat srec". Otherwise we use
300 1.1 christos _bfd_final_link_relocate which uses a howto structure, but does
301 1.1 christos not use the special_function field.
302 1.1 christos
303 1.1 christos It sets instruction parity to even. This cannot be done by a howto. */
304 1.1 christos
305 1.1 christos static bfd_reloc_status_type
306 1.1 christos visium_elf_howto_parity_reloc (bfd * input_bfd, arelent *reloc_entry,
307 1.1.1.6 christos asymbol *symbol, void *data,
308 1.1 christos asection *input_section, bfd *output_bfd,
309 1.1 christos char **error_message ATTRIBUTE_UNUSED)
310 1.1 christos {
311 1.1 christos bfd_reloc_status_type ret;
312 1.1 christos bfd_vma relocation;
313 1.1 christos bfd_byte *inplace_address;
314 1.1 christos bfd_vma insn;
315 1.1 christos
316 1.1 christos /* This part is from bfd_elf_generic_reloc.
317 1.1 christos If we're relocating, and this an external symbol, we don't want
318 1.1 christos to change anything. */
319 1.1 christos if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0)
320 1.1 christos {
321 1.1 christos reloc_entry->address += input_section->output_offset;
322 1.1 christos return bfd_reloc_ok;
323 1.1 christos }
324 1.1 christos
325 1.1 christos /* Now do the reloc in the usual way. */
326 1.1 christos
327 1.1 christos /* Sanity check the address (offset in section). */
328 1.1 christos if (reloc_entry->address > bfd_get_section_limit (input_bfd, input_section))
329 1.1 christos return bfd_reloc_outofrange;
330 1.1 christos
331 1.1 christos ret = bfd_reloc_ok;
332 1.1 christos if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL)
333 1.1 christos ret = bfd_reloc_undefined;
334 1.1 christos
335 1.1 christos if (bfd_is_com_section (symbol->section) || output_bfd != (bfd *) NULL)
336 1.1 christos relocation = 0;
337 1.1 christos else
338 1.1 christos relocation = symbol->value;
339 1.1 christos
340 1.1 christos /* Only do this for a final link. */
341 1.1 christos if (output_bfd == (bfd *) NULL)
342 1.1 christos {
343 1.1 christos relocation += symbol->section->output_section->vma;
344 1.1 christos relocation += symbol->section->output_offset;
345 1.1 christos }
346 1.1 christos
347 1.1 christos relocation += reloc_entry->addend;
348 1.1 christos inplace_address = (bfd_byte *) data + reloc_entry->address;
349 1.1 christos insn = bfd_get_32 (input_bfd, inplace_address);
350 1.1 christos
351 1.1 christos if (reloc_entry->howto->pc_relative)
352 1.1 christos {
353 1.1.1.5 christos relocation -= input_section->output_section->vma;
354 1.1.1.5 christos relocation -= input_section->output_offset;
355 1.1 christos relocation -= reloc_entry->address;
356 1.1 christos }
357 1.1 christos
358 1.1 christos switch (reloc_entry->howto->type)
359 1.1 christos {
360 1.1 christos case R_VISIUM_PC16:
361 1.1.1.5 christos if (ret == bfd_reloc_ok
362 1.1.1.5 christos && ((bfd_signed_vma) relocation < -0x20000
363 1.1.1.5 christos || (bfd_signed_vma) relocation > 0x1ffff))
364 1.1 christos ret = bfd_reloc_overflow;
365 1.1.1.5 christos relocation = (relocation >> 2) & 0xffff;
366 1.1 christos break;
367 1.1 christos case R_VISIUM_HI16:
368 1.1 christos case R_VISIUM_HI16_PCREL:
369 1.1 christos relocation = (relocation >> 16) & 0xffff;
370 1.1 christos break;
371 1.1 christos case R_VISIUM_LO16:
372 1.1 christos case R_VISIUM_LO16_PCREL:
373 1.1 christos relocation &= 0xffff;
374 1.1 christos break;
375 1.1 christos case R_VISIUM_IM16:
376 1.1 christos case R_VISIUM_IM16_PCREL:
377 1.1 christos if (ret == bfd_reloc_ok && (relocation & 0xffff0000) != 0)
378 1.1 christos ret = bfd_reloc_overflow;
379 1.1 christos relocation &= 0xffff;
380 1.1 christos break;
381 1.1 christos }
382 1.1 christos insn = (insn & 0x7fff0000) | relocation;
383 1.1 christos insn |= visium_parity_bit (insn);
384 1.1 christos bfd_put_32 (input_bfd, insn, inplace_address);
385 1.1 christos
386 1.1 christos if (output_bfd != (bfd *) NULL)
387 1.1 christos reloc_entry->address += input_section->output_offset;
388 1.1 christos
389 1.1 christos return ret;
390 1.1 christos }
391 1.1 christos
392 1.1 christos static reloc_howto_type *
393 1.1 christos visium_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
394 1.1 christos bfd_reloc_code_real_type code)
395 1.1 christos {
396 1.1 christos /* Note that the visium_elf_howto_table is indexed by the R_
397 1.1 christos constants. Thus, the order that the howto records appear in the
398 1.1 christos table *must* match the order of the relocation types defined in
399 1.1 christos include/elf/visium.h. */
400 1.1 christos switch (code)
401 1.1 christos {
402 1.1 christos case BFD_RELOC_NONE:
403 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_NONE];
404 1.1 christos case BFD_RELOC_8:
405 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_8];
406 1.1 christos case BFD_RELOC_16:
407 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_16];
408 1.1 christos case BFD_RELOC_32:
409 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_32];
410 1.1 christos case BFD_RELOC_8_PCREL:
411 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_8_PCREL];
412 1.1 christos case BFD_RELOC_16_PCREL:
413 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_16_PCREL];
414 1.1 christos case BFD_RELOC_32_PCREL:
415 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_32_PCREL];
416 1.1 christos case BFD_RELOC_VISIUM_REL16:
417 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_PC16];
418 1.1 christos case BFD_RELOC_VISIUM_HI16:
419 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_HI16];
420 1.1 christos case BFD_RELOC_VISIUM_LO16:
421 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_LO16];
422 1.1 christos case BFD_RELOC_VISIUM_IM16:
423 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_IM16];
424 1.1 christos case BFD_RELOC_VISIUM_HI16_PCREL:
425 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_HI16_PCREL];
426 1.1 christos case BFD_RELOC_VISIUM_LO16_PCREL:
427 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_LO16_PCREL];
428 1.1 christos case BFD_RELOC_VISIUM_IM16_PCREL:
429 1.1 christos return &visium_elf_howto_table[(int) R_VISIUM_IM16_PCREL];
430 1.1 christos case BFD_RELOC_VTABLE_INHERIT:
431 1.1 christos return &visium_elf_vtinherit_howto;
432 1.1 christos case BFD_RELOC_VTABLE_ENTRY:
433 1.1 christos return &visium_elf_vtentry_howto;
434 1.1 christos default:
435 1.1 christos return NULL;
436 1.1 christos }
437 1.1 christos }
438 1.1 christos
439 1.1 christos static reloc_howto_type *
440 1.1 christos visium_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
441 1.1 christos {
442 1.1 christos unsigned int i;
443 1.1 christos
444 1.1 christos for (i = 0;
445 1.1 christos i < (sizeof (visium_elf_howto_table)
446 1.1 christos / sizeof (visium_elf_howto_table[0])); i++)
447 1.1 christos if (visium_elf_howto_table[i].name != NULL
448 1.1 christos && strcasecmp (visium_elf_howto_table[i].name, r_name) == 0)
449 1.1 christos return &visium_elf_howto_table[i];
450 1.1 christos
451 1.1 christos if (strcasecmp (visium_elf_vtinherit_howto.name, r_name) == 0)
452 1.1 christos return &visium_elf_vtinherit_howto;
453 1.1 christos if (strcasecmp (visium_elf_vtentry_howto.name, r_name) == 0)
454 1.1 christos return &visium_elf_vtentry_howto;
455 1.1 christos
456 1.1 christos return NULL;
457 1.1 christos }
458 1.1 christos
459 1.1 christos /* Set the howto pointer for a VISIUM ELF reloc. */
460 1.1 christos
461 1.1.1.6 christos static bool
462 1.1.1.4 christos visium_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
463 1.1 christos Elf_Internal_Rela *dst)
464 1.1 christos {
465 1.1 christos unsigned int r_type = ELF32_R_TYPE (dst->r_info);
466 1.1 christos
467 1.1 christos switch (r_type)
468 1.1 christos {
469 1.1 christos case R_VISIUM_GNU_VTINHERIT:
470 1.1 christos cache_ptr->howto = &visium_elf_vtinherit_howto;
471 1.1 christos break;
472 1.1 christos
473 1.1 christos case R_VISIUM_GNU_VTENTRY:
474 1.1 christos cache_ptr->howto = &visium_elf_vtentry_howto;
475 1.1 christos break;
476 1.1 christos
477 1.1 christos default:
478 1.1.1.4 christos if (r_type >= ARRAY_SIZE (visium_elf_howto_table))
479 1.1 christos {
480 1.1.1.3 christos /* xgettext:c-format */
481 1.1.1.4 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
482 1.1.1.4 christos abfd, r_type);
483 1.1.1.4 christos bfd_set_error (bfd_error_bad_value);
484 1.1.1.6 christos return false;
485 1.1 christos }
486 1.1 christos cache_ptr->howto = &visium_elf_howto_table[r_type];
487 1.1 christos break;
488 1.1 christos }
489 1.1.1.6 christos return true;
490 1.1 christos }
491 1.1 christos
492 1.1 christos /* Look through the relocs for a section during the first phase.
493 1.1 christos Since we don't do .gots or .plts, we just need to consider the
494 1.1 christos virtual table relocs for gc. */
495 1.1 christos
496 1.1.1.6 christos static bool
497 1.1 christos visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
498 1.1 christos asection *sec, const Elf_Internal_Rela *relocs)
499 1.1 christos {
500 1.1 christos Elf_Internal_Shdr *symtab_hdr;
501 1.1 christos struct elf_link_hash_entry **sym_hashes;
502 1.1 christos const Elf_Internal_Rela *rel;
503 1.1 christos const Elf_Internal_Rela *rel_end;
504 1.1 christos
505 1.1 christos if (bfd_link_relocatable (info))
506 1.1.1.6 christos return true;
507 1.1 christos
508 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
509 1.1 christos sym_hashes = elf_sym_hashes (abfd);
510 1.1 christos
511 1.1 christos rel_end = relocs + sec->reloc_count;
512 1.1 christos for (rel = relocs; rel < rel_end; rel++)
513 1.1 christos {
514 1.1 christos struct elf_link_hash_entry *h;
515 1.1 christos unsigned long r_symndx;
516 1.1 christos
517 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
518 1.1 christos if (r_symndx < symtab_hdr->sh_info)
519 1.1 christos h = NULL;
520 1.1 christos else
521 1.1 christos {
522 1.1 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info];
523 1.1 christos while (h->root.type == bfd_link_hash_indirect
524 1.1 christos || h->root.type == bfd_link_hash_warning)
525 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link;
526 1.1 christos }
527 1.1 christos
528 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
529 1.1 christos {
530 1.1 christos /* This relocation describes the C++ object vtable hierarchy.
531 1.1 christos Reconstruct it for later use during GC. */
532 1.1 christos case R_VISIUM_GNU_VTINHERIT:
533 1.1 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
534 1.1.1.6 christos return false;
535 1.1 christos break;
536 1.1 christos
537 1.1 christos /* This relocation describes which C++ vtable entries are actually
538 1.1 christos used. Record for later use during GC. */
539 1.1 christos case R_VISIUM_GNU_VTENTRY:
540 1.1 christos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
541 1.1.1.6 christos return false;
542 1.1 christos break;
543 1.1 christos }
544 1.1 christos }
545 1.1 christos
546 1.1.1.6 christos return true;
547 1.1 christos }
548 1.1 christos
549 1.1 christos /* Relocate a VISIUM ELF section. */
550 1.1 christos
551 1.1.1.6 christos static int
552 1.1 christos visium_elf_relocate_section (bfd *output_bfd,
553 1.1 christos struct bfd_link_info *info, bfd *input_bfd,
554 1.1 christos asection *input_section, bfd_byte *contents,
555 1.1 christos Elf_Internal_Rela *relocs,
556 1.1 christos Elf_Internal_Sym *local_syms,
557 1.1 christos asection **local_sections)
558 1.1 christos {
559 1.1 christos Elf_Internal_Shdr *symtab_hdr;
560 1.1 christos struct elf_link_hash_entry **sym_hashes;
561 1.1 christos Elf_Internal_Rela *rel;
562 1.1 christos Elf_Internal_Rela *relend;
563 1.1 christos
564 1.1 christos symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
565 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
566 1.1 christos relend = relocs + input_section->reloc_count;
567 1.1 christos
568 1.1 christos for (rel = relocs; rel < relend; rel++)
569 1.1 christos {
570 1.1 christos reloc_howto_type *howto;
571 1.1 christos unsigned long r_symndx;
572 1.1 christos Elf_Internal_Sym *sym;
573 1.1 christos asection *sec;
574 1.1 christos struct elf_link_hash_entry *h;
575 1.1 christos bfd_vma relocation;
576 1.1 christos bfd_reloc_status_type r;
577 1.1 christos const char *name = NULL;
578 1.1 christos int r_type;
579 1.1 christos bfd_vma insn;
580 1.1 christos
581 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
582 1.1 christos
583 1.1 christos if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY)
584 1.1 christos continue;
585 1.1 christos
586 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
587 1.1 christos
588 1.1 christos howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info);
589 1.1 christos h = NULL;
590 1.1 christos sym = NULL;
591 1.1 christos sec = NULL;
592 1.1 christos
593 1.1 christos if (r_symndx < symtab_hdr->sh_info)
594 1.1 christos {
595 1.1 christos /* This is a local symbol. */
596 1.1 christos sym = local_syms + r_symndx;
597 1.1 christos sec = local_sections[r_symndx];
598 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
599 1.1 christos
600 1.1 christos name = bfd_elf_string_from_elf_section
601 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
602 1.1.1.5 christos name = name == NULL ? bfd_section_name (sec) : name;
603 1.1 christos }
604 1.1 christos else
605 1.1 christos {
606 1.1.1.6 christos bool unresolved_reloc;
607 1.1.1.6 christos bool warned, ignored;
608 1.1 christos
609 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
610 1.1 christos r_symndx, symtab_hdr, sym_hashes,
611 1.1 christos h, sec, relocation,
612 1.1 christos unresolved_reloc, warned, ignored);
613 1.1 christos
614 1.1 christos name = h->root.root.string;
615 1.1 christos }
616 1.1 christos
617 1.1 christos if (sec != NULL && discarded_section (sec))
618 1.1.1.9 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
619 1.1.1.9 christos rel, 1, relend, R_VISIUM_NONE,
620 1.1.1.9 christos howto, 0, contents);
621 1.1 christos
622 1.1 christos if (bfd_link_relocatable (info))
623 1.1 christos continue;
624 1.1 christos
625 1.1 christos switch (r_type)
626 1.1 christos {
627 1.1 christos case R_VISIUM_PC16:
628 1.1 christos case R_VISIUM_HI16:
629 1.1 christos case R_VISIUM_LO16:
630 1.1 christos case R_VISIUM_IM16:
631 1.1 christos case R_VISIUM_HI16_PCREL:
632 1.1 christos case R_VISIUM_LO16_PCREL:
633 1.1 christos case R_VISIUM_IM16_PCREL:
634 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
635 1.1 christos contents, rel->r_offset,
636 1.1 christos relocation, rel->r_addend);
637 1.1 christos
638 1.1 christos /* For instruction relocations, the parity needs correcting. */
639 1.1 christos if (r == bfd_reloc_ok)
640 1.1 christos {
641 1.1 christos insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
642 1.1 christos insn = (insn & 0x7fffffff) | visium_parity_bit (insn);
643 1.1 christos bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
644 1.1 christos }
645 1.1 christos break;
646 1.1 christos
647 1.1 christos default:
648 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
649 1.1 christos contents, rel->r_offset,
650 1.1 christos relocation, rel->r_addend);
651 1.1 christos break;
652 1.1 christos }
653 1.1 christos
654 1.1 christos if (r != bfd_reloc_ok)
655 1.1 christos {
656 1.1 christos const char *msg = (const char *) NULL;
657 1.1 christos
658 1.1 christos switch (r)
659 1.1 christos {
660 1.1 christos case bfd_reloc_overflow:
661 1.1.1.2 christos (*info->callbacks->reloc_overflow)
662 1.1 christos (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
663 1.1 christos input_bfd, input_section, rel->r_offset);
664 1.1 christos break;
665 1.1 christos
666 1.1 christos case bfd_reloc_undefined:
667 1.1.1.2 christos (*info->callbacks->undefined_symbol)
668 1.1.1.6 christos (info, name, input_bfd, input_section, rel->r_offset, true);
669 1.1 christos break;
670 1.1 christos
671 1.1 christos case bfd_reloc_outofrange:
672 1.1 christos msg = _("internal error: out of range error");
673 1.1 christos break;
674 1.1 christos
675 1.1 christos case bfd_reloc_notsupported:
676 1.1 christos msg = _("internal error: unsupported relocation error");
677 1.1 christos break;
678 1.1 christos
679 1.1 christos case bfd_reloc_dangerous:
680 1.1 christos msg = _("internal error: dangerous relocation");
681 1.1 christos break;
682 1.1 christos
683 1.1 christos default:
684 1.1 christos msg = _("internal error: unknown error");
685 1.1 christos break;
686 1.1 christos }
687 1.1 christos
688 1.1 christos if (msg)
689 1.1.1.2 christos (*info->callbacks->warning) (info, msg, name, input_bfd,
690 1.1.1.2 christos input_section, rel->r_offset);
691 1.1 christos }
692 1.1 christos }
693 1.1 christos
694 1.1.1.6 christos return true;
695 1.1 christos }
696 1.1 christos
697 1.1 christos /* This function is called during section gc to discover the section a
698 1.1 christos to which a particular relocation refers. Return the section that
699 1.1 christos should be marked against GC for a given relocation. */
700 1.1 christos
701 1.1 christos static asection *
702 1.1 christos visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
703 1.1.1.9 christos struct elf_reloc_cookie *cookie,
704 1.1.1.9 christos struct elf_link_hash_entry *h,
705 1.1.1.9 christos unsigned int symndx)
706 1.1 christos {
707 1.1 christos if (h != NULL)
708 1.1.1.9 christos switch (ELF32_R_TYPE (cookie->rel->r_info))
709 1.1 christos {
710 1.1 christos case R_VISIUM_GNU_VTINHERIT:
711 1.1 christos case R_VISIUM_GNU_VTENTRY:
712 1.1 christos return NULL;
713 1.1 christos }
714 1.1 christos
715 1.1.1.9 christos return _bfd_elf_gc_mark_hook (sec, info, cookie, h, symndx);
716 1.1 christos }
717 1.1 christos
718 1.1.1.6 christos static bool
719 1.1.1.5 christos visium_elf_init_file_header (bfd *abfd, struct bfd_link_info *info)
720 1.1 christos {
721 1.1.1.5 christos Elf_Internal_Ehdr *i_ehdrp;
722 1.1.1.5 christos
723 1.1.1.5 christos if (!_bfd_elf_init_file_header (abfd, info))
724 1.1.1.6 christos return false;
725 1.1.1.5 christos
726 1.1.1.5 christos i_ehdrp = elf_elfheader (abfd);
727 1.1 christos i_ehdrp->e_ident[EI_ABIVERSION] = 1;
728 1.1.1.6 christos return true;
729 1.1 christos }
730 1.1 christos
731 1.1 christos /* Function to set the ELF flag bits. */
732 1.1 christos
733 1.1.1.6 christos static bool
734 1.1 christos visium_elf_set_private_flags (bfd *abfd, flagword flags)
735 1.1 christos {
736 1.1 christos elf_elfheader (abfd)->e_flags = flags;
737 1.1.1.6 christos elf_flags_init (abfd) = true;
738 1.1.1.6 christos return true;
739 1.1 christos }
740 1.1 christos
741 1.1 christos /* Copy backend specific data from one object module to another. */
742 1.1 christos
743 1.1.1.6 christos static bool
744 1.1 christos visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
745 1.1 christos {
746 1.1.1.9 christos if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
747 1.1.1.6 christos return true;
748 1.1 christos
749 1.1 christos BFD_ASSERT (!elf_flags_init (obfd)
750 1.1 christos || elf_elfheader (obfd)->e_flags ==
751 1.1 christos elf_elfheader (ibfd)->e_flags);
752 1.1 christos
753 1.1 christos elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
754 1.1.1.6 christos elf_flags_init (obfd) = true;
755 1.1 christos
756 1.1 christos /* Copy object attributes. */
757 1.1 christos _bfd_elf_copy_obj_attributes (ibfd, obfd);
758 1.1 christos
759 1.1.1.6 christos return true;
760 1.1 christos }
761 1.1 christos
762 1.1 christos /* Merge backend specific data from an object
763 1.1 christos file to the output object file when linking. */
764 1.1 christos
765 1.1.1.6 christos static bool
766 1.1.1.3 christos visium_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
767 1.1 christos {
768 1.1.1.3 christos bfd *obfd = info->output_bfd;
769 1.1 christos flagword old_flags;
770 1.1 christos flagword new_flags;
771 1.1 christos flagword mismatch;
772 1.1 christos const char *opt_arch = NULL;
773 1.1 christos const char *new_opt_with = NULL;
774 1.1 christos const char *old_opt_with = NULL;
775 1.1 christos const char *with = "with";
776 1.1 christos const char *without = "without";
777 1.1 christos const char *mcm = "mcm";
778 1.1 christos const char *mcm24 = "mcm24";
779 1.1 christos const char *gr6 = "gr6";
780 1.1 christos
781 1.1.1.9 christos if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
782 1.1.1.9 christos return true;
783 1.1.1.9 christos
784 1.1 christos new_flags = elf_elfheader (ibfd)->e_flags;
785 1.1 christos old_flags = elf_elfheader (obfd)->e_flags;
786 1.1 christos
787 1.1 christos if (!elf_flags_init (obfd))
788 1.1 christos {
789 1.1 christos /* First call, no flags set. */
790 1.1.1.6 christos elf_flags_init (obfd) = true;
791 1.1 christos elf_elfheader (obfd)->e_flags = new_flags;
792 1.1 christos }
793 1.1 christos else
794 1.1 christos {
795 1.1 christos mismatch = (new_flags ^ old_flags)
796 1.1 christos & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6);
797 1.1 christos if (mismatch & EF_VISIUM_ARCH_GR6)
798 1.1 christos {
799 1.1 christos opt_arch = gr6;
800 1.1 christos new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without;
801 1.1 christos old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without;
802 1.1 christos }
803 1.1 christos else if (mismatch & EF_VISIUM_ARCH_MCM)
804 1.1 christos {
805 1.1 christos opt_arch = mcm;
806 1.1 christos new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without;
807 1.1 christos old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without;
808 1.1 christos }
809 1.1 christos else if (mismatch & EF_VISIUM_ARCH_MCM24)
810 1.1 christos {
811 1.1 christos opt_arch = mcm24;
812 1.1 christos new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
813 1.1 christos old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
814 1.1 christos }
815 1.1 christos
816 1.1 christos if (mismatch)
817 1.1 christos _bfd_error_handler
818 1.1.1.3 christos /* xgettext:c-format */
819 1.1.1.4 christos (_("%pB: compiled %s -mtune=%s and linked with modules"
820 1.1.1.3 christos " compiled %s -mtune=%s"),
821 1.1.1.3 christos ibfd, new_opt_with, opt_arch, old_opt_with, opt_arch);
822 1.1 christos }
823 1.1 christos
824 1.1.1.6 christos return true;
825 1.1 christos }
826 1.1 christos
827 1.1.1.6 christos static bool
828 1.1 christos visium_elf_print_private_bfd_data (bfd *abfd, void *ptr)
829 1.1 christos {
830 1.1 christos FILE *file = (FILE *) ptr;
831 1.1 christos flagword flags;
832 1.1 christos
833 1.1 christos BFD_ASSERT (abfd != NULL && ptr != NULL);
834 1.1 christos
835 1.1 christos /* Print normal ELF private data. */
836 1.1 christos _bfd_elf_print_private_bfd_data (abfd, ptr);
837 1.1 christos
838 1.1 christos flags = elf_elfheader (abfd)->e_flags;
839 1.1 christos fprintf (file, _("private flags = 0x%lx:"), (long) flags);
840 1.1 christos
841 1.1 christos if (flags & EF_VISIUM_ARCH_GR6)
842 1.1 christos fprintf (file, " -mtune=gr6");
843 1.1 christos else if (flags & EF_VISIUM_ARCH_MCM)
844 1.1 christos fprintf (file, " -mtune=mcm");
845 1.1 christos else if (flags & EF_VISIUM_ARCH_MCM24)
846 1.1 christos fprintf (file, " -mtune=mcm24");
847 1.1 christos
848 1.1 christos fputc ('\n', file);
849 1.1.1.6 christos return true;
850 1.1 christos }
851 1.1 christos
852 1.1 christos #define ELF_ARCH bfd_arch_visium
853 1.1 christos #define ELF_MACHINE_CODE EM_VISIUM
854 1.1.1.5 christos #define ELF_OSABI ELFOSABI_STANDALONE
855 1.1.1.9 christos #define ELF_OSABI_EXACT 1
856 1.1 christos #define ELF_MAXPAGESIZE 1
857 1.1 christos
858 1.1 christos #define TARGET_BIG_SYM visium_elf32_vec
859 1.1 christos #define TARGET_BIG_NAME "elf32-visium"
860 1.1 christos
861 1.1 christos #define elf_info_to_howto_rel NULL
862 1.1 christos #define elf_info_to_howto visium_info_to_howto_rela
863 1.1 christos #define elf_backend_relocate_section visium_elf_relocate_section
864 1.1 christos #define elf_backend_gc_mark_hook visium_elf_gc_mark_hook
865 1.1 christos #define elf_backend_check_relocs visium_elf_check_relocs
866 1.1 christos #define elf_backend_rela_normal 1
867 1.1 christos
868 1.1 christos #define elf_backend_can_gc_sections 1
869 1.1 christos
870 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup
871 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup
872 1.1 christos
873 1.1 christos #define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags
874 1.1 christos #define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data
875 1.1 christos #define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data
876 1.1 christos #define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data
877 1.1.1.5 christos #define elf_backend_init_file_header visium_elf_init_file_header
878 1.1 christos
879 1.1 christos #include "elf32-target.h"
880