elf32-visium.c revision 1.4 1 1.1 christos /* Visium-specific support for 32-bit ELF.
2 1.1 christos
3 1.4 christos Copyright (C) 2003-2016 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 christos
29 1.1 christos static bfd_reloc_status_type visium_elf_howto_parity_reloc
30 1.1 christos (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
31 1.1 christos
32 1.1 christos static reloc_howto_type visium_elf_howto_table[] = {
33 1.1 christos /* This reloc does nothing. */
34 1.1 christos HOWTO (R_VISIUM_NONE, /* type */
35 1.1 christos 0, /* rightshift */
36 1.3 christos 3, /* size (0 = byte, 1 = short, 2 = long) */
37 1.3 christos 0, /* bitsize */
38 1.1 christos FALSE, /* pc_relative */
39 1.1 christos 0, /* bitpos */
40 1.3 christos complain_overflow_dont, /* complain_on_overflow */
41 1.1 christos bfd_elf_generic_reloc, /* special_function */
42 1.1 christos "R_VISIUM_NONE", /* name */
43 1.1 christos FALSE, /* partial_inplace */
44 1.1 christos 0, /* src_mask */
45 1.1 christos 0, /* dst_mask */
46 1.1 christos FALSE), /* pcrel_offset */
47 1.1 christos
48 1.1 christos /* A 8 bit absolute relocation. */
49 1.1 christos HOWTO (R_VISIUM_8, /* type */
50 1.1 christos 0, /* rightshift */
51 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
52 1.1 christos 8, /* bitsize */
53 1.1 christos FALSE, /* pc_relative */
54 1.1 christos 0, /* bitpos */
55 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
56 1.1 christos bfd_elf_generic_reloc, /* special_function */
57 1.1 christos "R_VISIUM_8", /* name */
58 1.1 christos FALSE, /* partial_inplace */
59 1.1 christos 0x00, /* src_mask */
60 1.1 christos 0xff, /* dst_mask */
61 1.1 christos FALSE), /* pcrel_offset */
62 1.1 christos
63 1.1 christos /* A 16 bit absolute relocation. */
64 1.1 christos HOWTO (R_VISIUM_16, /* type */
65 1.1 christos 0, /* rightshift */
66 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
67 1.1 christos 16, /* bitsize */
68 1.1 christos FALSE, /* pc_relative */
69 1.1 christos 0, /* bitpos */
70 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
71 1.1 christos bfd_elf_generic_reloc, /* special_function */
72 1.1 christos "R_VISIUM_16", /* name */
73 1.1 christos FALSE, /* partial_inplace */
74 1.1 christos 0x0000, /* src_mask */
75 1.1 christos 0xffff, /* dst_mask */
76 1.1 christos FALSE), /* pcrel_offset */
77 1.1 christos
78 1.1 christos /* A 32 bit absolute relocation. */
79 1.1 christos HOWTO (R_VISIUM_32, /* type */
80 1.1 christos 0, /* rightshift */
81 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
82 1.1 christos 32, /* bitsize */
83 1.1 christos FALSE, /* pc_relative */
84 1.1 christos 0, /* bitpos */
85 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
86 1.1 christos bfd_elf_generic_reloc, /* special_function */
87 1.1 christos "R_VISIUM_32", /* name */
88 1.1 christos FALSE, /* partial_inplace */
89 1.1 christos 0x00000000, /* src_mask */
90 1.1 christos 0xffffffff, /* dst_mask */
91 1.1 christos FALSE), /* pcrel_offset */
92 1.1 christos
93 1.1 christos
94 1.1 christos /* A 8 bit PC relative relocation. */
95 1.1 christos HOWTO (R_VISIUM_8_PCREL, /* type */
96 1.1 christos 0, /* rightshift */
97 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
98 1.1 christos 8, /* bitsize */
99 1.1 christos TRUE, /* pc_relative */
100 1.1 christos 0, /* bitpos */
101 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
102 1.1 christos bfd_elf_generic_reloc, /* special_function */
103 1.1 christos "R_VISIUM_8_PCREL", /* name */
104 1.1 christos FALSE, /* partial_inplace */
105 1.1 christos 0x00, /* src_mask */
106 1.1 christos 0xff, /* dst_mask */
107 1.1 christos TRUE), /* pcrel_offset */
108 1.1 christos
109 1.1 christos /* A 16 bit PC relative relocation. */
110 1.1 christos HOWTO (R_VISIUM_16_PCREL, /* type */
111 1.1 christos 0, /* rightshift */
112 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
113 1.1 christos 16, /* bitsize */
114 1.1 christos TRUE, /* pc_relative */
115 1.1 christos 0, /* bitpos */
116 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
117 1.1 christos bfd_elf_generic_reloc, /* special_function */
118 1.1 christos "R_VISIUM_16_PCREL", /* name */
119 1.1 christos FALSE, /* partial inplace */
120 1.1 christos 0x0000, /* src_mask */
121 1.1 christos 0xffff, /* dst_mask */
122 1.1 christos TRUE), /* pcrel_offset */
123 1.1 christos
124 1.1 christos /* A 32-bit PC relative relocation. */
125 1.1 christos HOWTO (R_VISIUM_32_PCREL, /* type */
126 1.1 christos 0, /* rightshift */
127 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
128 1.1 christos 32, /* bitsize */
129 1.1 christos TRUE, /* pc_relative */
130 1.1 christos 0, /* bitpos */
131 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
132 1.1 christos bfd_elf_generic_reloc, /* special_function */
133 1.1 christos "R_VISIUM_32_PCREL", /* name */
134 1.1 christos FALSE, /* partial_inplace */
135 1.1 christos 0, /* src_mask */
136 1.1 christos 0xffffffff, /* dst_mask */
137 1.1 christos TRUE), /* pcrel_offset */
138 1.1 christos
139 1.1 christos /* A 16-bit PC word relative offset, relative to start of instruction
140 1.1 christos and always in the second half of the instruction. */
141 1.1 christos HOWTO (R_VISIUM_PC16, /* type */
142 1.1 christos 2, /* rightshift */
143 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
144 1.1 christos 16, /* bitsize */
145 1.1 christos TRUE, /* pc_relative */
146 1.1 christos 0, /* bitpos */
147 1.1 christos complain_overflow_signed, /* complain_on_overflow */
148 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
149 1.1 christos "R_VISIUM_PC16", /* name */
150 1.1 christos FALSE, /* partial_inplace */
151 1.1 christos 0x00000000, /* src_mask */
152 1.1 christos 0x0000ffff, /* dst_mask */
153 1.1 christos TRUE), /* pcrel_offset */
154 1.1 christos
155 1.1 christos /* The high 16 bits of symbol value. */
156 1.1 christos HOWTO (R_VISIUM_HI16, /* type */
157 1.1 christos 16, /* rightshift */
158 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
159 1.1 christos 16, /* bitsize */
160 1.1 christos FALSE, /* pc_relative */
161 1.1 christos 0, /* bitpos */
162 1.1 christos complain_overflow_dont, /* complain_on_overflow */
163 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
164 1.1 christos "R_VISIUM_HI16", /* name */
165 1.1 christos FALSE, /* partial_inplace */
166 1.1 christos 0x00000000, /* src_mask */
167 1.1 christos 0x0000ffff, /* dst_mask */
168 1.1 christos FALSE), /* pcrel_offset */
169 1.1 christos
170 1.1 christos /* The low 16 bits of symbol value. */
171 1.1 christos HOWTO (R_VISIUM_LO16, /* type */
172 1.1 christos 0, /* rightshift */
173 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
174 1.1 christos 16, /* bitsize */
175 1.1 christos FALSE, /* pc_relative */
176 1.1 christos 0, /* bitpos */
177 1.1 christos complain_overflow_dont, /* complain_on_overflow */
178 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
179 1.1 christos "R_VISIUM_LO16", /* name */
180 1.1 christos FALSE, /* partial_inplace */
181 1.1 christos 0x00000000, /* src_mask */
182 1.1 christos 0x0000ffff, /* dst_mask */
183 1.1 christos FALSE), /* pcrel_offset */
184 1.1 christos
185 1.1 christos /* A 16 bit immediate value. */
186 1.1 christos HOWTO (R_VISIUM_IM16, /* type */
187 1.1 christos 0, /* rightshift */
188 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
189 1.1 christos 16, /* bitsize */
190 1.1 christos FALSE, /* pc_relative */
191 1.1 christos 0, /* bitpos */
192 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
193 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
194 1.1 christos "R_VISIUM_IM16", /* name */
195 1.1 christos FALSE, /* partial_inplace */
196 1.1 christos 0x0000000, /* src_mask */
197 1.1 christos 0x000ffff, /* dst_mask */
198 1.1 christos FALSE), /* pcrel_offset */
199 1.1 christos
200 1.1 christos /* The high 16 bits of symbol value, pc relative. */
201 1.1 christos HOWTO (R_VISIUM_HI16_PCREL, /* type */
202 1.1 christos 16, /* rightshift */
203 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
204 1.1 christos 16, /* bitsize */
205 1.1 christos TRUE, /* pc_relative */
206 1.1 christos 0, /* bitpos */
207 1.1 christos complain_overflow_dont, /* complain_on_overflow */
208 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
209 1.1 christos "R_VISIUM_HI16_PCREL", /* name */
210 1.1 christos FALSE, /* partial_inplace */
211 1.1 christos 0x00000000, /* src_mask */
212 1.1 christos 0x0000ffff, /* dst_mask */
213 1.1 christos TRUE), /* pcrel_offset */
214 1.1 christos
215 1.1 christos /* The low 16 bits of symbol value, pc relative. */
216 1.1 christos HOWTO (R_VISIUM_LO16_PCREL, /* type */
217 1.1 christos 0, /* rightshift */
218 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
219 1.1 christos 16, /* bitsize */
220 1.1 christos TRUE, /* pc_relative */
221 1.1 christos 0, /* bitpos */
222 1.1 christos complain_overflow_dont, /* complain_on_overflow */
223 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
224 1.1 christos "R_VISIUM_LO16_PCREL", /* name */
225 1.1 christos FALSE, /* partial_inplace */
226 1.1 christos 0x00000000, /* src_mask */
227 1.1 christos 0x0000ffff, /* dst_mask */
228 1.1 christos TRUE), /* pcrel_offset */
229 1.1 christos
230 1.1 christos /* A 16 bit immediate value, pc relative. */
231 1.1 christos HOWTO (R_VISIUM_IM16_PCREL, /* type */
232 1.1 christos 0, /* rightshift */
233 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
234 1.1 christos 16, /* bitsize */
235 1.1 christos TRUE, /* pc_relative */
236 1.1 christos 0, /* bitpos */
237 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
238 1.1 christos visium_elf_howto_parity_reloc, /* special_function */
239 1.1 christos "R_VISIUM_IM16_PCREL", /* name */
240 1.1 christos FALSE, /* partial_inplace */
241 1.1 christos 0x0000000, /* src_mask */
242 1.1 christos 0x000ffff, /* dst_mask */
243 1.1 christos TRUE), /* pcrel_offset */
244 1.1 christos
245 1.1 christos };
246 1.1 christos
247 1.1 christos /* GNU extension to record C++ vtable hierarchy. */
248 1.1 christos static reloc_howto_type visium_elf_vtinherit_howto =
249 1.1 christos HOWTO (R_VISIUM_GNU_VTINHERIT, /* type */
250 1.1 christos 0, /* rightshift */
251 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
252 1.1 christos 0, /* bitsize */
253 1.1 christos FALSE, /* pc_relative */
254 1.1 christos 0, /* bitpos */
255 1.1 christos complain_overflow_dont, /* complain_on_overflow */
256 1.1 christos NULL, /* special_function */
257 1.1 christos "R_VISIUM_GNU_VTINHERIT", /* name */
258 1.1 christos FALSE, /* partial_inplace */
259 1.1 christos 0, /* src_mask */
260 1.1 christos 0, /* dst_mask */
261 1.1 christos FALSE); /* pcrel_offset */
262 1.1 christos
263 1.1 christos /* GNU extension to record C++ vtable member usage. */
264 1.1 christos static reloc_howto_type visium_elf_vtentry_howto =
265 1.1 christos HOWTO (R_VISIUM_GNU_VTENTRY, /* type */
266 1.1 christos 0, /* rightshift */
267 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
268 1.1 christos 0, /* bitsize */
269 1.1 christos FALSE, /* pc_relative */
270 1.1 christos 0, /* bitpos */
271 1.1 christos complain_overflow_dont, /* complain_on_overflow */
272 1.1 christos NULL, /* special_function */
273 1.1 christos "R_VISIUM_GNU_VTENTRY", /* name */
274 1.1 christos FALSE, /* partial_inplace */
275 1.1 christos 0, /* src_mask */
276 1.1 christos 0, /* dst_mask */
277 1.1 christos FALSE); /* pcrel_offset */
278 1.1 christos
279 1.1 christos /* Return the parity bit for INSN shifted to its final position. */
280 1.1 christos
281 1.1 christos static bfd_vma
282 1.1 christos visium_parity_bit (bfd_vma insn)
283 1.1 christos {
284 1.1 christos bfd_vma p = 0;
285 1.1 christos int i;
286 1.1 christos
287 1.1 christos for (i = 0; i < 31; i++)
288 1.1 christos {
289 1.1 christos p ^= (insn & 1);
290 1.1 christos insn >>= 1;
291 1.1 christos }
292 1.1 christos
293 1.1 christos return p << 31;
294 1.1 christos }
295 1.1 christos
296 1.1 christos /* This "special function" will only be used when the input and
297 1.1 christos output files have different formats ie. when generating S-records
298 1.1 christos directly using "--oformat srec". Otherwise we use
299 1.1 christos _bfd_final_link_relocate which uses a howto structure, but does
300 1.1 christos not use the special_function field.
301 1.1 christos
302 1.1 christos It sets instruction parity to even. This cannot be done by a howto. */
303 1.1 christos
304 1.1 christos static bfd_reloc_status_type
305 1.1 christos visium_elf_howto_parity_reloc (bfd * input_bfd, arelent *reloc_entry,
306 1.1 christos asymbol *symbol, PTR data,
307 1.1 christos asection *input_section, bfd *output_bfd,
308 1.1 christos char **error_message ATTRIBUTE_UNUSED)
309 1.1 christos {
310 1.1 christos bfd_reloc_status_type ret;
311 1.1 christos bfd_vma relocation;
312 1.1 christos bfd_byte *inplace_address;
313 1.1 christos bfd_vma insn;
314 1.1 christos const bfd_vma signmask = 0xffff8000;
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 christos relocation -= input_section->output_section->vma
354 1.1 christos + 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 christos relocation >>= 2;
362 1.1 christos if (ret == bfd_reloc_ok && (relocation & signmask) != 0
363 1.1 christos && (relocation & signmask) != signmask)
364 1.1 christos ret = bfd_reloc_overflow;
365 1.1 christos relocation &= 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 christos static void
462 1.1 christos visium_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, 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 christos if (r_type >= (unsigned int) R_VISIUM_max)
479 1.1 christos {
480 1.3 christos _bfd_error_handler (_("%B: invalid Visium reloc number: %d"), abfd, r_type);
481 1.1 christos r_type = 0;
482 1.1 christos }
483 1.1 christos cache_ptr->howto = &visium_elf_howto_table[r_type];
484 1.1 christos break;
485 1.1 christos }
486 1.1 christos }
487 1.1 christos
488 1.1 christos /* Look through the relocs for a section during the first phase.
489 1.1 christos Since we don't do .gots or .plts, we just need to consider the
490 1.1 christos virtual table relocs for gc. */
491 1.1 christos
492 1.1 christos static bfd_boolean
493 1.1 christos visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
494 1.1 christos asection *sec, const Elf_Internal_Rela *relocs)
495 1.1 christos {
496 1.1 christos Elf_Internal_Shdr *symtab_hdr;
497 1.1 christos struct elf_link_hash_entry **sym_hashes;
498 1.1 christos const Elf_Internal_Rela *rel;
499 1.1 christos const Elf_Internal_Rela *rel_end;
500 1.1 christos
501 1.4 christos if (bfd_link_relocatable (info))
502 1.1 christos return TRUE;
503 1.1 christos
504 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
505 1.1 christos sym_hashes = elf_sym_hashes (abfd);
506 1.1 christos
507 1.1 christos rel_end = relocs + sec->reloc_count;
508 1.1 christos for (rel = relocs; rel < rel_end; rel++)
509 1.1 christos {
510 1.1 christos struct elf_link_hash_entry *h;
511 1.1 christos unsigned long r_symndx;
512 1.1 christos
513 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
514 1.1 christos if (r_symndx < symtab_hdr->sh_info)
515 1.1 christos h = NULL;
516 1.1 christos else
517 1.1 christos {
518 1.1 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info];
519 1.1 christos while (h->root.type == bfd_link_hash_indirect
520 1.1 christos || h->root.type == bfd_link_hash_warning)
521 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link;
522 1.1 christos }
523 1.1 christos
524 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
525 1.1 christos {
526 1.1 christos /* This relocation describes the C++ object vtable hierarchy.
527 1.1 christos Reconstruct it for later use during GC. */
528 1.1 christos case R_VISIUM_GNU_VTINHERIT:
529 1.1 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
530 1.1 christos return FALSE;
531 1.1 christos break;
532 1.1 christos
533 1.1 christos /* This relocation describes which C++ vtable entries are actually
534 1.1 christos used. Record for later use during GC. */
535 1.1 christos case R_VISIUM_GNU_VTENTRY:
536 1.1 christos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
537 1.1 christos return FALSE;
538 1.1 christos break;
539 1.1 christos }
540 1.1 christos }
541 1.1 christos
542 1.1 christos return TRUE;
543 1.1 christos }
544 1.1 christos
545 1.1 christos /* Relocate a VISIUM ELF section. */
546 1.1 christos
547 1.1 christos static bfd_boolean
548 1.1 christos visium_elf_relocate_section (bfd *output_bfd,
549 1.1 christos struct bfd_link_info *info, bfd *input_bfd,
550 1.1 christos asection *input_section, bfd_byte *contents,
551 1.1 christos Elf_Internal_Rela *relocs,
552 1.1 christos Elf_Internal_Sym *local_syms,
553 1.1 christos asection **local_sections)
554 1.1 christos {
555 1.1 christos Elf_Internal_Shdr *symtab_hdr;
556 1.1 christos struct elf_link_hash_entry **sym_hashes;
557 1.1 christos Elf_Internal_Rela *rel;
558 1.1 christos Elf_Internal_Rela *relend;
559 1.1 christos
560 1.1 christos symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
561 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
562 1.1 christos relend = relocs + input_section->reloc_count;
563 1.1 christos
564 1.1 christos for (rel = relocs; rel < relend; rel++)
565 1.1 christos {
566 1.1 christos reloc_howto_type *howto;
567 1.1 christos unsigned long r_symndx;
568 1.1 christos Elf_Internal_Sym *sym;
569 1.1 christos asection *sec;
570 1.1 christos struct elf_link_hash_entry *h;
571 1.1 christos bfd_vma relocation;
572 1.1 christos bfd_reloc_status_type r;
573 1.1 christos const char *name = NULL;
574 1.1 christos int r_type;
575 1.1 christos bfd_vma insn;
576 1.1 christos
577 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
578 1.1 christos
579 1.1 christos if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY)
580 1.1 christos continue;
581 1.1 christos
582 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
583 1.1 christos
584 1.1 christos howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info);
585 1.1 christos h = NULL;
586 1.1 christos sym = NULL;
587 1.1 christos sec = NULL;
588 1.1 christos
589 1.1 christos if (r_symndx < symtab_hdr->sh_info)
590 1.1 christos {
591 1.1 christos /* This is a local symbol. */
592 1.1 christos sym = local_syms + r_symndx;
593 1.1 christos sec = local_sections[r_symndx];
594 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
595 1.1 christos
596 1.1 christos name = bfd_elf_string_from_elf_section
597 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
598 1.1 christos name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
599 1.1 christos }
600 1.1 christos else
601 1.1 christos {
602 1.1 christos bfd_boolean unresolved_reloc;
603 1.1 christos bfd_boolean warned, ignored;
604 1.1 christos
605 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
606 1.1 christos r_symndx, symtab_hdr, sym_hashes,
607 1.1 christos h, sec, relocation,
608 1.1 christos unresolved_reloc, warned, ignored);
609 1.1 christos
610 1.1 christos name = h->root.root.string;
611 1.1 christos }
612 1.1 christos
613 1.1 christos if (sec != NULL && discarded_section (sec))
614 1.1 christos {
615 1.1 christos /* For relocs against symbols from removed linkonce sections,
616 1.1 christos or sections discarded by a linker script, we just want the
617 1.1 christos section contents zeroed. Avoid any special processing. */
618 1.1 christos _bfd_clear_contents (howto, input_bfd, input_section,
619 1.1 christos contents + rel->r_offset);
620 1.1 christos
621 1.1 christos rel->r_info = 0;
622 1.1 christos rel->r_addend = 0;
623 1.1 christos continue;
624 1.1 christos }
625 1.1 christos
626 1.4 christos if (bfd_link_relocatable (info))
627 1.1 christos continue;
628 1.1 christos
629 1.1 christos switch (r_type)
630 1.1 christos {
631 1.1 christos case R_VISIUM_PC16:
632 1.1 christos case R_VISIUM_HI16:
633 1.1 christos case R_VISIUM_LO16:
634 1.1 christos case R_VISIUM_IM16:
635 1.1 christos case R_VISIUM_HI16_PCREL:
636 1.1 christos case R_VISIUM_LO16_PCREL:
637 1.1 christos case R_VISIUM_IM16_PCREL:
638 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
639 1.1 christos contents, rel->r_offset,
640 1.1 christos relocation, rel->r_addend);
641 1.1 christos
642 1.1 christos /* For instruction relocations, the parity needs correcting. */
643 1.1 christos if (r == bfd_reloc_ok)
644 1.1 christos {
645 1.1 christos insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
646 1.1 christos insn = (insn & 0x7fffffff) | visium_parity_bit (insn);
647 1.1 christos bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
648 1.1 christos }
649 1.1 christos break;
650 1.1 christos
651 1.1 christos default:
652 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
653 1.1 christos contents, rel->r_offset,
654 1.1 christos relocation, rel->r_addend);
655 1.1 christos break;
656 1.1 christos }
657 1.1 christos
658 1.1 christos if (r != bfd_reloc_ok)
659 1.1 christos {
660 1.1 christos const char *msg = (const char *) NULL;
661 1.1 christos
662 1.1 christos switch (r)
663 1.1 christos {
664 1.1 christos case bfd_reloc_overflow:
665 1.4 christos (*info->callbacks->reloc_overflow)
666 1.1 christos (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
667 1.1 christos input_bfd, input_section, rel->r_offset);
668 1.1 christos break;
669 1.1 christos
670 1.1 christos case bfd_reloc_undefined:
671 1.4 christos (*info->callbacks->undefined_symbol)
672 1.1 christos (info, name, input_bfd, input_section, rel->r_offset, TRUE);
673 1.1 christos break;
674 1.1 christos
675 1.1 christos case bfd_reloc_outofrange:
676 1.1 christos msg = _("internal error: out of range error");
677 1.1 christos break;
678 1.1 christos
679 1.1 christos case bfd_reloc_notsupported:
680 1.1 christos msg = _("internal error: unsupported relocation error");
681 1.1 christos break;
682 1.1 christos
683 1.1 christos case bfd_reloc_dangerous:
684 1.1 christos msg = _("internal error: dangerous relocation");
685 1.1 christos break;
686 1.1 christos
687 1.1 christos default:
688 1.1 christos msg = _("internal error: unknown error");
689 1.1 christos break;
690 1.1 christos }
691 1.1 christos
692 1.1 christos if (msg)
693 1.4 christos (*info->callbacks->warning) (info, msg, name, input_bfd,
694 1.4 christos input_section, rel->r_offset);
695 1.1 christos }
696 1.1 christos }
697 1.1 christos
698 1.1 christos return TRUE;
699 1.1 christos }
700 1.1 christos
701 1.1 christos /* This function is called during section gc to discover the section a
702 1.1 christos to which a particular relocation refers. Return the section that
703 1.1 christos should be marked against GC for a given relocation. */
704 1.1 christos
705 1.1 christos static asection *
706 1.1 christos visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
707 1.1 christos Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
708 1.1 christos Elf_Internal_Sym *sym)
709 1.1 christos {
710 1.1 christos if (h != NULL)
711 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
712 1.1 christos {
713 1.1 christos case R_VISIUM_GNU_VTINHERIT:
714 1.1 christos case R_VISIUM_GNU_VTENTRY:
715 1.1 christos return NULL;
716 1.1 christos }
717 1.1 christos
718 1.1 christos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
719 1.1 christos }
720 1.1 christos
721 1.1 christos static void
722 1.1 christos visium_elf_post_process_headers (bfd *abfd,
723 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED)
724 1.1 christos {
725 1.1 christos Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
726 1.1 christos i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
727 1.1 christos i_ehdrp->e_ident[EI_ABIVERSION] = 1;
728 1.1 christos }
729 1.1 christos
730 1.1 christos /* Function to set the ELF flag bits. */
731 1.1 christos
732 1.1 christos static bfd_boolean
733 1.1 christos visium_elf_set_private_flags (bfd *abfd, flagword flags)
734 1.1 christos {
735 1.1 christos elf_elfheader (abfd)->e_flags = flags;
736 1.1 christos elf_flags_init (abfd) = TRUE;
737 1.1 christos return TRUE;
738 1.1 christos }
739 1.1 christos
740 1.1 christos /* Copy backend specific data from one object module to another. */
741 1.1 christos
742 1.1 christos static bfd_boolean
743 1.1 christos visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
744 1.1 christos {
745 1.1 christos if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
746 1.1 christos || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
747 1.1 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 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 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 christos static bfd_boolean
766 1.1 christos visium_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
767 1.1 christos {
768 1.1 christos flagword old_flags;
769 1.1 christos flagword new_flags;
770 1.1 christos flagword mismatch;
771 1.1 christos const char *opt_arch = NULL;
772 1.1 christos const char *new_opt_with = NULL;
773 1.1 christos const char *old_opt_with = NULL;
774 1.1 christos const char *with = "with";
775 1.1 christos const char *without = "without";
776 1.1 christos const char *mcm = "mcm";
777 1.1 christos const char *mcm24 = "mcm24";
778 1.1 christos const char *gr6 = "gr6";
779 1.1 christos
780 1.1 christos new_flags = elf_elfheader (ibfd)->e_flags;
781 1.1 christos old_flags = elf_elfheader (obfd)->e_flags;
782 1.1 christos
783 1.1 christos if (!elf_flags_init (obfd))
784 1.1 christos {
785 1.1 christos /* First call, no flags set. */
786 1.1 christos elf_flags_init (obfd) = TRUE;
787 1.1 christos elf_elfheader (obfd)->e_flags = new_flags;
788 1.1 christos }
789 1.1 christos else
790 1.1 christos {
791 1.1 christos mismatch = (new_flags ^ old_flags)
792 1.1 christos & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6);
793 1.1 christos if (mismatch & EF_VISIUM_ARCH_GR6)
794 1.1 christos {
795 1.1 christos opt_arch = gr6;
796 1.1 christos new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without;
797 1.1 christos old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without;
798 1.1 christos }
799 1.1 christos else if (mismatch & EF_VISIUM_ARCH_MCM)
800 1.1 christos {
801 1.1 christos opt_arch = mcm;
802 1.1 christos new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without;
803 1.1 christos old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without;
804 1.1 christos }
805 1.1 christos else if (mismatch & EF_VISIUM_ARCH_MCM24)
806 1.1 christos {
807 1.1 christos opt_arch = mcm24;
808 1.1 christos new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
809 1.1 christos old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
810 1.1 christos }
811 1.1 christos
812 1.1 christos if (mismatch)
813 1.1 christos _bfd_error_handler
814 1.1 christos (_
815 1.1 christos ("%s: compiled %s -mtune=%s and linked with modules"
816 1.1 christos " compiled %s -mtune=%s"),
817 1.1 christos bfd_get_filename (ibfd), new_opt_with, opt_arch, old_opt_with,
818 1.1 christos opt_arch);
819 1.1 christos }
820 1.1 christos
821 1.1 christos return TRUE;
822 1.1 christos }
823 1.1 christos
824 1.1 christos static bfd_boolean
825 1.1 christos visium_elf_print_private_bfd_data (bfd *abfd, void *ptr)
826 1.1 christos {
827 1.1 christos FILE *file = (FILE *) ptr;
828 1.1 christos flagword flags;
829 1.1 christos
830 1.1 christos BFD_ASSERT (abfd != NULL && ptr != NULL);
831 1.1 christos
832 1.1 christos /* Print normal ELF private data. */
833 1.1 christos _bfd_elf_print_private_bfd_data (abfd, ptr);
834 1.1 christos
835 1.1 christos flags = elf_elfheader (abfd)->e_flags;
836 1.1 christos fprintf (file, _("private flags = 0x%lx:"), (long) flags);
837 1.1 christos
838 1.1 christos if (flags & EF_VISIUM_ARCH_GR6)
839 1.1 christos fprintf (file, " -mtune=gr6");
840 1.1 christos else if (flags & EF_VISIUM_ARCH_MCM)
841 1.1 christos fprintf (file, " -mtune=mcm");
842 1.1 christos else if (flags & EF_VISIUM_ARCH_MCM24)
843 1.1 christos fprintf (file, " -mtune=mcm24");
844 1.1 christos
845 1.1 christos fputc ('\n', file);
846 1.1 christos return TRUE;
847 1.1 christos }
848 1.1 christos
849 1.1 christos #define ELF_ARCH bfd_arch_visium
850 1.1 christos #define ELF_MACHINE_CODE EM_VISIUM
851 1.1 christos #define ELF_MAXPAGESIZE 1
852 1.1 christos
853 1.1 christos #define TARGET_BIG_SYM visium_elf32_vec
854 1.1 christos #define TARGET_BIG_NAME "elf32-visium"
855 1.1 christos
856 1.1 christos #define elf_info_to_howto_rel NULL
857 1.1 christos #define elf_info_to_howto visium_info_to_howto_rela
858 1.1 christos #define elf_backend_relocate_section visium_elf_relocate_section
859 1.1 christos #define elf_backend_gc_mark_hook visium_elf_gc_mark_hook
860 1.1 christos #define elf_backend_check_relocs visium_elf_check_relocs
861 1.1 christos #define elf_backend_rela_normal 1
862 1.1 christos
863 1.1 christos #define elf_backend_can_gc_sections 1
864 1.1 christos
865 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup
866 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup
867 1.1 christos
868 1.1 christos #define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags
869 1.1 christos #define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data
870 1.1 christos #define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data
871 1.1 christos #define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data
872 1.1 christos #define elf_backend_post_process_headers visium_elf_post_process_headers
873 1.1 christos
874 1.1 christos #include "elf32-target.h"
875