gdb: Force use of float version of log10
[deliverable/binutils-gdb.git] / bfd / elf32-pru.c
CommitLineData
889294f6 1/* 32-bit ELF support for TI PRU.
82704155 2 Copyright (C) 2014-2019 Free Software Foundation, Inc.
889294f6
DD
3 Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
4 Based on elf32-nios2.c
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23/* This file handles TI PRU ELF targets. */
24
25#include "sysdep.h"
26#include "bfd.h"
27#include "libbfd.h"
28#include "bfdlink.h"
29#include "genlink.h"
30#include "elf-bfd.h"
31#include "elf/pru.h"
32#include "opcode/pru.h"
f3185997 33#include "libiberty.h"
889294f6
DD
34
35#define SWAP_VALS(A,B) \
36 do { \
37 (A) ^= (B); \
38 (B) ^= (A); \
39 (A) ^= (B); \
40 } while (0)
41
42/* Enable debugging printout at stdout with this variable. */
43static bfd_boolean debug_relax = FALSE;
44
45/* Forward declarations. */
46static bfd_reloc_status_type pru_elf32_pmem_relocate
47 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
48static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate
49 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
50static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate
51 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
52static bfd_reloc_status_type pru_elf32_ldi32_relocate
53 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
54static bfd_reloc_status_type bfd_elf_pru_diff_relocate
55 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
56
57/* Target vector. */
58extern const bfd_target pru_elf32_vec;
59
60/* The relocation table used for SHT_REL sections. */
61static reloc_howto_type elf_pru_howto_table_rel[] = {
62 /* No relocation. */
63 HOWTO (R_PRU_NONE, /* type */
64 0, /* rightshift */
65 0, /* size (0 = byte, 1 = short, 2 = long) */
66 3, /* bitsize */
67 FALSE, /* pc_relative */
68 0, /* bitpos */
69 complain_overflow_dont,/* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_PRU_NONE", /* name */
72 FALSE, /* partial_inplace */
73 0, /* src_mask */
74 0, /* dst_mask */
75 FALSE), /* pcrel_offset */
76
77 HOWTO (R_PRU_16_PMEM,
78 2,
79 1, /* short */
80 32,
81 FALSE,
82 0,
83 complain_overflow_dont,
84 bfd_elf_generic_reloc,
85 "R_PRU_16_PMEM",
86 FALSE,
87 0, /* src_mask */
88 0xffff,
89 FALSE),
90
91 HOWTO (R_PRU_U16_PMEMIMM,
92 2,
93 2,
94 32,
95 FALSE,
96 8,
97 complain_overflow_unsigned,
98 pru_elf32_pmem_relocate,
99 "R_PRU_U16_PMEMIMM",
100 FALSE,
101 0, /* src_mask */
102 0x00ffff00,
103 FALSE),
104
105 HOWTO (R_PRU_BFD_RELOC_16,
106 0,
107 1, /* short */
108 16,
109 FALSE,
110 0,
111 complain_overflow_bitfield,
112 bfd_elf_generic_reloc,
113 "R_PRU_BFD_RELOC16",
114 FALSE,
115 0, /* src_mask */
116 0x0000ffff,
117 FALSE),
118
119 /* 16-bit unsigned immediate relocation. */
120 HOWTO (R_PRU_U16, /* type */
121 0, /* rightshift */
122 2, /* size (0 = byte, 1 = short, 2 = long) */
123 16, /* bitsize */
124 FALSE, /* pc_relative */
125 8, /* bitpos */
126 complain_overflow_unsigned, /* complain on overflow */
127 bfd_elf_generic_reloc, /* special function */
128 "R_PRU_U16", /* name */
129 FALSE, /* partial_inplace */
130 0, /* src_mask */
131 0x00ffff00, /* dest_mask */
132 FALSE), /* pcrel_offset */
133
134 HOWTO (R_PRU_32_PMEM,
135 2,
136 2, /* long */
137 32,
138 FALSE,
139 0,
140 complain_overflow_dont,
141 pru_elf32_pmem_relocate,
142 "R_PRU_32_PMEM",
143 FALSE,
144 0, /* src_mask */
145 0xffffffff,
146 FALSE),
147
148 HOWTO (R_PRU_BFD_RELOC_32,
149 0,
150 2, /* long */
151 32,
152 FALSE,
153 0,
154 complain_overflow_dont,
155 bfd_elf_generic_reloc,
156 "R_PRU_BFD_RELOC32",
157 FALSE,
158 0, /* src_mask */
159 0xffffffff,
160 FALSE),
161
162 HOWTO (R_PRU_S10_PCREL,
163 2,
164 2,
165 10,
166 TRUE,
167 0,
168 complain_overflow_bitfield,
169 pru_elf32_s10_pcrel_relocate,
170 "R_PRU_S10_PCREL",
171 FALSE,
172 0, /* src_mask */
173 0x060000ff,
174 TRUE),
175
176 HOWTO (R_PRU_U8_PCREL,
177 2,
178 2,
179 8,
180 TRUE,
181 0,
182 complain_overflow_unsigned,
183 pru_elf32_u8_pcrel_relocate,
184 "R_PRU_U8_PCREL",
185 FALSE,
186 0, /* src_mask */
187 0x000000ff,
188 TRUE),
189
190 HOWTO (R_PRU_LDI32,
191 0, /* rightshift */
192 4, /* size (4 = 8bytes) */
193 32, /* bitsize */
194 FALSE, /* pc_relative */
195 0, /* bitpos */
196 complain_overflow_unsigned, /* complain on overflow */
197 pru_elf32_ldi32_relocate, /* special function */
198 "R_PRU_LDI32", /* name */
199 FALSE, /* partial_inplace */
200 0, /* src_mask */
201 0xffffffff, /* dest_mask */
202 FALSE), /* pcrel_offset */
203
204 /* GNU-specific relocations. */
205 HOWTO (R_PRU_GNU_BFD_RELOC_8,
206 0,
207 0, /* byte */
208 8,
209 FALSE,
210 0,
211 complain_overflow_bitfield,
212 bfd_elf_generic_reloc,
213 "R_PRU_BFD_RELOC8",
214 FALSE,
215 0, /* src_mask */
216 0x000000ff,
217 FALSE),
218
219 HOWTO (R_PRU_GNU_DIFF8, /* type */
220 0, /* rightshift */
07d6d2b8
AM
221 0, /* size (0 = byte, 1 = short, 2 = long) */
222 8, /* bitsize */
889294f6
DD
223 FALSE, /* pc_relative */
224 0, /* bitpos */
225 complain_overflow_bitfield, /* complain_on_overflow */
226 bfd_elf_pru_diff_relocate, /* special_function */
07d6d2b8 227 "R_PRU_DIFF8", /* name */
889294f6
DD
228 FALSE, /* partial_inplace */
229 0, /* src_mask */
230 0xff, /* dst_mask */
231 FALSE), /* pcrel_offset */
232
07d6d2b8 233 HOWTO (R_PRU_GNU_DIFF16, /* type */
889294f6
DD
234 0, /* rightshift */
235 1, /* size (0 = byte, 1 = short, 2 = long) */
236 16, /* bitsize */
237 FALSE, /* pc_relative */
238 0, /* bitpos */
239 complain_overflow_bitfield, /* complain_on_overflow */
240 bfd_elf_pru_diff_relocate,/* special_function */
07d6d2b8 241 "R_PRU_DIFF16", /* name */
889294f6
DD
242 FALSE, /* partial_inplace */
243 0, /* src_mask */
244 0xffff, /* dst_mask */
245 FALSE), /* pcrel_offset */
246
07d6d2b8 247 HOWTO (R_PRU_GNU_DIFF32, /* type */
889294f6
DD
248 0, /* rightshift */
249 2, /* size (0 = byte, 1 = short, 2 = long) */
250 32, /* bitsize */
251 FALSE, /* pc_relative */
252 0, /* bitpos */
253 complain_overflow_bitfield, /* complain_on_overflow */
254 bfd_elf_pru_diff_relocate,/* special_function */
07d6d2b8 255 "R_PRU_DIFF32", /* name */
889294f6
DD
256 FALSE, /* partial_inplace */
257 0, /* src_mask */
07d6d2b8 258 0xffffffff, /* dst_mask */
889294f6
DD
259 FALSE), /* pcrel_offset */
260
261 HOWTO (R_PRU_GNU_DIFF16_PMEM, /* type */
262 0, /* rightshift */
263 1, /* size (0 = byte, 1 = short, 2 = long) */
264 16, /* bitsize */
265 FALSE, /* pc_relative */
266 0, /* bitpos */
267 complain_overflow_bitfield, /* complain_on_overflow */
268 bfd_elf_pru_diff_relocate,/* special_function */
07d6d2b8 269 "R_PRU_DIFF16_PMEM", /* name */
889294f6
DD
270 FALSE, /* partial_inplace */
271 0, /* src_mask */
272 0xffff, /* dst_mask */
273 FALSE), /* pcrel_offset */
274
275 HOWTO (R_PRU_GNU_DIFF32_PMEM, /* type */
276 0, /* rightshift */
277 2, /* size (0 = byte, 1 = short, 2 = long) */
278 32, /* bitsize */
279 FALSE, /* pc_relative */
280 0, /* bitpos */
281 complain_overflow_bitfield, /* complain_on_overflow */
282 bfd_elf_pru_diff_relocate,/* special_function */
07d6d2b8 283 "R_PRU_DIFF32_PMEM", /* name */
889294f6
DD
284 FALSE, /* partial_inplace */
285 0, /* src_mask */
286 0xffffffff, /* dst_mask */
287 FALSE), /* pcrel_offset */
288
289/* Add other relocations here. */
290};
291
292static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1];
293
294/* Return the howto for relocation RTYPE. */
f3185997 295
889294f6
DD
296static reloc_howto_type *
297lookup_howto (unsigned int rtype)
298{
f3185997 299 static bfd_boolean initialized = FALSE;
889294f6
DD
300 int i;
301 int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel)
302 / sizeof (elf_pru_howto_table_rel[0]));
303
f3185997 304 if (! initialized)
889294f6 305 {
f3185997 306 initialized = TRUE;
889294f6
DD
307 memset (elf_code_to_howto_index, 0xff,
308 sizeof (elf_code_to_howto_index));
309 for (i = 0; i < howto_tbl_size; i++)
310 elf_code_to_howto_index[elf_pru_howto_table_rel[i].type] = i;
311 }
312
f3185997
NC
313 if (rtype > R_PRU_ILLEGAL)
314 return NULL;
889294f6
DD
315 i = elf_code_to_howto_index[rtype];
316 if (i >= howto_tbl_size)
f3185997 317 return NULL;
889294f6
DD
318 return elf_pru_howto_table_rel + i;
319}
320
321/* Map for converting BFD reloc types to PRU reloc types. */
f3185997 322
889294f6
DD
323struct elf_reloc_map
324{
325 bfd_reloc_code_real_type bfd_val;
326 enum elf_pru_reloc_type elf_val;
327};
328
f3185997
NC
329static const struct elf_reloc_map pru_reloc_map[] =
330{
889294f6
DD
331 {BFD_RELOC_NONE, R_PRU_NONE},
332 {BFD_RELOC_PRU_16_PMEM, R_PRU_16_PMEM},
333 {BFD_RELOC_PRU_U16_PMEMIMM, R_PRU_U16_PMEMIMM},
334 {BFD_RELOC_16, R_PRU_BFD_RELOC_16},
335 {BFD_RELOC_PRU_U16, R_PRU_U16},
336 {BFD_RELOC_PRU_32_PMEM, R_PRU_32_PMEM},
337 {BFD_RELOC_32, R_PRU_BFD_RELOC_32},
338 {BFD_RELOC_PRU_S10_PCREL, R_PRU_S10_PCREL},
339 {BFD_RELOC_PRU_U8_PCREL, R_PRU_U8_PCREL},
340 {BFD_RELOC_PRU_LDI32, R_PRU_LDI32},
341
342 {BFD_RELOC_8, R_PRU_GNU_BFD_RELOC_8},
343 {BFD_RELOC_PRU_GNU_DIFF8, R_PRU_GNU_DIFF8},
344 {BFD_RELOC_PRU_GNU_DIFF16, R_PRU_GNU_DIFF16},
345 {BFD_RELOC_PRU_GNU_DIFF32, R_PRU_GNU_DIFF32},
346 {BFD_RELOC_PRU_GNU_DIFF16_PMEM, R_PRU_GNU_DIFF16_PMEM},
347 {BFD_RELOC_PRU_GNU_DIFF32_PMEM, R_PRU_GNU_DIFF32_PMEM},
348};
349
350
351/* Assorted hash table functions. */
352
353/* Create an entry in a PRU ELF linker hash table. */
f3185997 354
889294f6
DD
355static struct bfd_hash_entry *
356link_hash_newfunc (struct bfd_hash_entry *entry,
357 struct bfd_hash_table *table, const char *string)
358{
359 /* Allocate the structure if it has not already been allocated by a
360 subclass. */
361 if (entry == NULL)
362 {
363 entry = bfd_hash_allocate (table,
364 sizeof (struct elf_link_hash_entry));
365 if (entry == NULL)
366 return entry;
367 }
368
369 /* Call the allocation method of the superclass. */
370 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
371
372 return entry;
373}
374
375/* Implement bfd_elf32_bfd_reloc_type_lookup:
376 Given a BFD reloc type, return a howto structure. */
f3185997 377
889294f6
DD
378static reloc_howto_type *
379pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
380 bfd_reloc_code_real_type code)
381{
f3185997
NC
382 unsigned int i;
383
384 for (i = 0; i < ARRAY_SIZE (pru_reloc_map); ++i)
889294f6
DD
385 if (pru_reloc_map[i].bfd_val == code)
386 return lookup_howto ((unsigned int) pru_reloc_map[i].elf_val);
387 return NULL;
388}
389
390/* Implement bfd_elf32_bfd_reloc_name_lookup:
391 Given a reloc name, return a howto structure. */
f3185997 392
889294f6
DD
393static reloc_howto_type *
394pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
395 const char *r_name)
396{
397 unsigned int i;
f3185997
NC
398
399 for (i = 0; i < ARRAY_SIZE (elf_pru_howto_table_rel); i++)
889294f6
DD
400 if (elf_pru_howto_table_rel[i].name
401 && strcasecmp (elf_pru_howto_table_rel[i].name, r_name) == 0)
402 return &elf_pru_howto_table_rel[i];
403
404 return NULL;
405}
406
407/* Implement elf_info_to_howto:
408 Given a ELF32 relocation, fill in a arelent structure. */
f3185997
NC
409
410static bfd_boolean
411pru_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr,
889294f6
DD
412 Elf_Internal_Rela *dst)
413{
414 unsigned int r_type;
415
416 r_type = ELF32_R_TYPE (dst->r_info);
f3185997
NC
417 if (r_type >= R_PRU_ILLEGAL)
418 {
419 /* xgettext:c-format */
420 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
421 bfd_set_error (bfd_error_bad_value);
422 return FALSE;
423 }
4b24dd1a 424
889294f6 425 cache_ptr->howto = lookup_howto (r_type);
f3185997 426 return cache_ptr->howto != NULL;
889294f6
DD
427}
428
429/* Do the relocations that require special handling. */
430/* Produce a word address for program memory. Linker scripts will put .text
431 at a high offset in order to differentiate it from .data. So here we also
432 mask the high bits of PMEM address.
433
434 But why 1MB when internal Program Memory much smaller? We want to catch
435 unintended overflows.
436
437 Why not use (1<<31) as an offset and a mask? Sitara DDRAM usually resides
438 there, and users might want to put some shared carveout memory region in
439 their linker scripts. So 0x80000000 might be a valid .data address.
440
441 Note that we still keep and pass down the original howto. This way we
442 can reuse this function for several different relocations. */
443static bfd_reloc_status_type
444pru_elf32_do_pmem_relocate (bfd *abfd, reloc_howto_type *howto,
445 asection *input_section,
446 bfd_byte *data, bfd_vma offset,
447 bfd_vma symbol_value, bfd_vma addend)
448{
449 symbol_value = symbol_value + addend;
450 addend = 0;
451 symbol_value &= 0x3fffff;
452 return _bfd_final_link_relocate (howto, abfd, input_section,
453 data, offset, symbol_value, addend);
454}
455
456/* Direct copy of _bfd_final_link_relocate, but with special
457 "fill-in". This copy-paste mumbo jumbo is only needed because BFD
458 cannot deal correctly with non-contiguous bit fields. */
459static bfd_reloc_status_type
460pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto,
461 asection *input_section,
462 bfd_byte *contents, bfd_vma address,
463 bfd_vma relocation, bfd_vma addend)
464{
465 bfd_byte *location;
466 bfd_vma x = 0;
467 bfd_vma qboff;
468 bfd_reloc_status_type flag = bfd_reloc_ok;
469
470 /* Sanity check the address. */
471 if (address > bfd_get_section_limit (input_bfd, input_section))
472 return bfd_reloc_outofrange;
473
474 BFD_ASSERT (howto->pc_relative);
475 BFD_ASSERT (howto->pcrel_offset);
476
477 relocation = relocation + addend - (input_section->output_section->vma
478 + input_section->output_offset) - address;
479
480 location = contents + address;
481
482 /* Get the value we are going to relocate. */
483 BFD_ASSERT (bfd_get_reloc_size (howto) == 4);
484 x = bfd_get_32 (input_bfd, location);
485
486 qboff = GET_BROFF_SIGNED (x) << howto->rightshift;
487 relocation += qboff;
488
489 BFD_ASSERT (howto->complain_on_overflow == complain_overflow_bitfield);
490
491 if (relocation > 2047 && relocation < (bfd_vma)-2048l)
492 flag = bfd_reloc_overflow;
493
494 /* Check that target address is word-aligned. */
495 if (relocation & ((1 << howto->rightshift) - 1))
496 flag = bfd_reloc_outofrange;
497
498 relocation >>= (bfd_vma) howto->rightshift;
499
500 /* Fill-in the RELOCATION to the right bits of X. */
501 SET_BROFF_URAW (x, relocation);
502
503 bfd_put_32 (input_bfd, x, location);
504
505 return flag;
506}
507
508static bfd_reloc_status_type
509pru_elf32_do_u8_pcrel_relocate (bfd *abfd, reloc_howto_type *howto,
510 asection *input_section,
511 bfd_byte *data, bfd_vma offset,
512 bfd_vma symbol_value, bfd_vma addend)
513{
514 bfd_vma relocation;
515
516 BFD_ASSERT (howto->pc_relative);
517 BFD_ASSERT (howto->pcrel_offset);
518
519 relocation = symbol_value + addend - (input_section->output_section->vma
520 + input_section->output_offset) - offset;
521 relocation >>= howto->rightshift;
522
523 /* 0 and 1 are invalid target labels for LOOP. We cannot
524 encode this info in HOWTO, so catch such cases here. */
525 if (relocation < 2)
526 return bfd_reloc_outofrange;
527
528 return _bfd_final_link_relocate (howto, abfd, input_section,
529 data, offset, symbol_value, addend);
530}
531
532/* Idea and code taken from elf32-d30v. */
533static bfd_reloc_status_type
534pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
535 asection *input_section,
536 bfd_byte *data, bfd_vma offset,
537 bfd_vma symbol_value, bfd_vma addend)
538{
539 bfd_signed_vma relocation;
540 bfd_size_type octets = offset * bfd_octets_per_byte (abfd);
541 bfd_byte *location;
493ffac5 542 unsigned long in1, in2;
889294f6
DD
543
544 /* A hacked-up version of _bfd_final_link_relocate() follows. */
545
546 /* Sanity check the address. */
547 if (octets + bfd_get_reloc_size (howto)
548 > bfd_get_section_limit_octets (abfd, input_section))
549 return bfd_reloc_outofrange;
550
551 /* This function assumes that we are dealing with a basic relocation
552 against a symbol. We want to compute the value of the symbol to
553 relocate to. This is just VALUE, the value of the symbol, plus
554 ADDEND, any addend associated with the reloc. */
555 relocation = symbol_value + addend;
556
557 BFD_ASSERT (!howto->pc_relative);
558
559 /* A hacked-up version of _bfd_relocate_contents() follows. */
560 location = data + offset * bfd_octets_per_byte (abfd);
561
562 BFD_ASSERT (!howto->pc_relative);
563
564 in1 = bfd_get_32 (abfd, location);
565 in2 = bfd_get_32 (abfd, location + 4);
566
493ffac5
DD
567 SET_INSN_FIELD (IMM16, in1, relocation >> 16);
568 SET_INSN_FIELD (IMM16, in2, relocation & 0xffff);
889294f6
DD
569
570 bfd_put_32 (abfd, in1, location);
571 bfd_put_32 (abfd, in2, location + 4);
572
493ffac5
DD
573 /* Old GAS and LD versions have a bug, where the two
574 LDI instructions are swapped. Detect such object
575 files and bail. */
576 if (GET_INSN_FIELD (RDSEL, in1) != RSEL_31_16)
577 {
578 /* xgettext:c-format */
579 _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
580 abfd);
581 return bfd_reloc_notsupported;
582 }
583
889294f6
DD
584 return bfd_reloc_ok;
585}
586
587/* HOWTO handlers for relocations that require special handling. */
588
589static bfd_reloc_status_type
590pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
591 asymbol *symbol, void *data,
592 asection *input_section, bfd *output_bfd,
593 char **error_message)
594{
595 /* If this is a relocatable link (output_bfd test tells us), just
596 call the generic function. Any adjustment will be done at final
597 link time. */
598 if (output_bfd != NULL)
599 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
600 input_section, output_bfd, error_message);
601
493ffac5 602 BFD_ASSERT (0);
889294f6
DD
603 return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
604 input_section,
605 data, reloc_entry->address,
606 (symbol->value
607 + symbol->section->output_section->vma
608 + symbol->section->output_offset),
609 reloc_entry->addend);
610}
611
612static bfd_reloc_status_type
613pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry,
614 asymbol *symbol, void *data,
615 asection *input_section, bfd *output_bfd,
616 char **error_message)
617{
618 /* If this is a relocatable link (output_bfd test tells us), just
619 call the generic function. Any adjustment will be done at final
620 link time. */
621 if (output_bfd != NULL)
622 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
623 input_section, output_bfd, error_message);
624
625 return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
626 input_section, data,
627 reloc_entry->address,
628 (symbol->value
629 + symbol->section->output_section->vma
630 + symbol->section->output_offset),
631 reloc_entry->addend);
632}
633
634static bfd_reloc_status_type
635pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
636 void *data, asection *input_section,
637 bfd *output_bfd,
638 char **error_message)
639{
640 /* If this is a relocatable link (output_bfd test tells us), just
641 call the generic function. Any adjustment will be done at final
642 link time. */
643 if (output_bfd != NULL)
644 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
645 input_section, output_bfd, error_message);
646
647 return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
648 input_section,
649 data, reloc_entry->address,
650 (symbol->value
651 + symbol->section->output_section->vma
652 + symbol->section->output_offset),
653 reloc_entry->addend);
654}
655
656static bfd_reloc_status_type
657pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
658 void *data, asection *input_section,
659 bfd *output_bfd,
660 char **error_message)
661{
662 /* If this is a relocatable link (output_bfd test tells us), just
663 call the generic function. Any adjustment will be done at final
664 link time. */
665 if (output_bfd != NULL)
666 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
667 input_section, output_bfd, error_message);
668
669 return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
670 input_section,
671 data, reloc_entry->address,
672 (symbol->value
673 + symbol->section->output_section->vma
674 + symbol->section->output_offset),
675 reloc_entry->addend);
676}
677
678
679/* Implement elf_backend_relocate_section. */
680static bfd_boolean
681pru_elf32_relocate_section (bfd *output_bfd,
682 struct bfd_link_info *info,
683 bfd *input_bfd,
684 asection *input_section,
685 bfd_byte *contents,
686 Elf_Internal_Rela *relocs,
687 Elf_Internal_Sym *local_syms,
688 asection **local_sections)
689{
493ffac5 690 struct bfd_elf_section_data * esd = elf_section_data (input_section);
889294f6
DD
691 Elf_Internal_Shdr *symtab_hdr;
692 struct elf_link_hash_entry **sym_hashes;
693 Elf_Internal_Rela *rel;
694 Elf_Internal_Rela *relend;
493ffac5 695 bfd_boolean is_rel_reloc;
889294f6
DD
696
697 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
698 sym_hashes = elf_sym_hashes (input_bfd);
699 relend = relocs + input_section->reloc_count;
700
493ffac5
DD
701 /* See if we have a REL type relocation. */
702 is_rel_reloc = (esd->rel.hdr != NULL);
703 /* Sanity check - only one type of relocation per section.
704 FIXME: Theoretically it is possible to have both types,
705 but if that happens how can we distinguish between the two ? */
706 BFD_ASSERT (! is_rel_reloc || ! esd->rela.hdr);
707
889294f6
DD
708 for (rel = relocs; rel < relend; rel++)
709 {
710 reloc_howto_type *howto;
711 unsigned long r_symndx;
712 Elf_Internal_Sym *sym;
713 asection *sec;
714 struct elf_link_hash_entry *h;
715 bfd_vma relocation;
716 bfd_reloc_status_type r = bfd_reloc_ok;
717 const char *name = NULL;
718 const char* msg = (const char*) NULL;
719 bfd_boolean unresolved_reloc;
493ffac5
DD
720 bfd_vma addend;
721
722 /* If we are using a REL relocation then the addend should be empty. */
723 BFD_ASSERT (! is_rel_reloc || rel->r_addend == 0);
889294f6
DD
724
725 r_symndx = ELF32_R_SYM (rel->r_info);
726
727 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
728 h = NULL;
729 sym = NULL;
730 sec = NULL;
731
732 if (r_symndx < symtab_hdr->sh_info)
733 {
734 sym = local_syms + r_symndx;
735 sec = local_sections[r_symndx];
736 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
737 }
738 else
739 {
740 bfd_boolean warned, ignored;
741
742 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
743 r_symndx, symtab_hdr, sym_hashes,
744 h, sec, relocation,
745 unresolved_reloc, warned, ignored);
746 }
747
748 if (sec && discarded_section (sec))
749 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
750 rel, 1, relend, howto, 0, contents);
751
752 /* Nothing more to do unless this is a final link. */
753 if (bfd_link_relocatable (info))
754 continue;
755
756 if (howto)
757 {
758 switch (howto->type)
759 {
760 case R_PRU_NONE:
761 /* We don't need to find a value for this symbol. It's just a
762 marker. */
763 r = bfd_reloc_ok;
764 break;
765
493ffac5
DD
766 case R_PRU_U16:
767 if (is_rel_reloc)
768 {
769 unsigned long insn;
770 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
771 addend = GET_INSN_FIELD (IMM16, insn);
772 }
773 else
774 addend = rel->r_addend;
775 r = _bfd_final_link_relocate (howto, input_bfd,
776 input_section, contents,
777 rel->r_offset, relocation,
778 addend);
779 break;
780
889294f6
DD
781 case R_PRU_U16_PMEMIMM:
782 case R_PRU_32_PMEM:
783 case R_PRU_16_PMEM:
493ffac5
DD
784 if (is_rel_reloc && howto->type == R_PRU_U16_PMEMIMM)
785 {
786 unsigned long insn;
787 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
788 addend = GET_INSN_FIELD (IMM16, insn) << 2;
789 }
790 else if (is_rel_reloc && howto->type == R_PRU_32_PMEM)
791 {
792 addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
793 addend <<= 2;
794 }
795 else if (is_rel_reloc && howto->type == R_PRU_16_PMEM)
796 {
797 addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
798 addend <<= 2;
799 }
800 else
801 {
802 BFD_ASSERT (!is_rel_reloc);
803 addend = rel->r_addend;
804 }
889294f6
DD
805 r = pru_elf32_do_pmem_relocate (input_bfd, howto,
806 input_section,
807 contents, rel->r_offset,
493ffac5 808 relocation, addend);
889294f6
DD
809 break;
810 case R_PRU_S10_PCREL:
493ffac5 811 BFD_ASSERT (! is_rel_reloc);
889294f6
DD
812 r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
813 input_section,
814 contents,
815 rel->r_offset,
816 relocation,
817 rel->r_addend);
818 break;
819 case R_PRU_U8_PCREL:
493ffac5 820 BFD_ASSERT (! is_rel_reloc);
889294f6
DD
821 r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
822 input_section,
823 contents,
824 rel->r_offset,
825 relocation,
826 rel->r_addend);
827 break;
828 case R_PRU_LDI32:
493ffac5
DD
829 if (is_rel_reloc)
830 {
831 unsigned long in1, in2;
832 in1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
833 in2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
834 addend = (GET_INSN_FIELD (IMM16, in1) << 16)
835 | GET_INSN_FIELD (IMM16, in2);
836 }
837 else
838 {
839 addend = rel->r_addend;
840 }
889294f6
DD
841 r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
842 input_section,
843 contents,
844 rel->r_offset,
845 relocation,
493ffac5 846 addend);
889294f6
DD
847 break;
848 case R_PRU_GNU_DIFF8:
849 case R_PRU_GNU_DIFF16:
850 case R_PRU_GNU_DIFF32:
851 case R_PRU_GNU_DIFF16_PMEM:
852 case R_PRU_GNU_DIFF32_PMEM:
493ffac5
DD
853 /* GNU extensions support only rela. */
854 BFD_ASSERT (! is_rel_reloc);
889294f6
DD
855 /* Nothing to do here, as contents already contain the
856 diff value. */
857 r = bfd_reloc_ok;
858 break;
859
493ffac5
DD
860 case R_PRU_BFD_RELOC_16:
861 if (is_rel_reloc)
862 addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
863 else
864 addend = rel->r_addend;
865 r = _bfd_final_link_relocate (howto, input_bfd,
866 input_section, contents,
867 rel->r_offset, relocation,
868 addend);
869 break;
870
871 case R_PRU_BFD_RELOC_32:
872 if (is_rel_reloc)
873 addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
874 else
875 addend = rel->r_addend;
876 r = _bfd_final_link_relocate (howto, input_bfd,
877 input_section, contents,
878 rel->r_offset, relocation,
879 addend);
880 break;
881
882 case R_PRU_GNU_BFD_RELOC_8:
883 BFD_ASSERT (! is_rel_reloc);
889294f6
DD
884 r = _bfd_final_link_relocate (howto, input_bfd,
885 input_section, contents,
886 rel->r_offset, relocation,
887 rel->r_addend);
888 break;
493ffac5
DD
889
890 default:
891 BFD_ASSERT (0);
892 break;
889294f6
DD
893 }
894 }
895 else
896 r = bfd_reloc_notsupported;
897
898 if (r != bfd_reloc_ok)
899 {
900 if (h != NULL)
901 name = h->root.root.string;
902 else
903 {
904 name = bfd_elf_string_from_elf_section (input_bfd,
905 symtab_hdr->sh_link,
906 sym->st_name);
907 if (name == NULL || *name == '\0')
908 name = bfd_section_name (input_bfd, sec);
909 }
910
911 switch (r)
912 {
913 case bfd_reloc_overflow:
914 (*info->callbacks->reloc_overflow) (info, NULL, name,
915 howto->name, (bfd_vma) 0,
916 input_bfd, input_section,
917 rel->r_offset);
918 break;
919
920 case bfd_reloc_undefined:
921 (*info->callbacks->undefined_symbol) (info, name, input_bfd,
922 input_section,
923 rel->r_offset, TRUE);
924 break;
925
926 case bfd_reloc_outofrange:
927 if (msg == NULL)
928 msg = _("relocation out of range");
929 break;
930
931 case bfd_reloc_notsupported:
932 if (msg == NULL)
933 msg = _("unsupported relocation");
934 break;
935
936 case bfd_reloc_dangerous:
937 if (msg == NULL)
938 msg = _("dangerous relocation");
939 break;
940
941 default:
942 if (msg == NULL)
943 msg = _("unknown error");
944 break;
945 }
946
947 if (msg)
948 {
949 (*info->callbacks->warning) (info, msg, name, input_bfd,
950 input_section, rel->r_offset);
951 return FALSE;
952 }
953 }
954 }
955 return TRUE;
956}
957
958\f
959/* Perform a diff relocation. Nothing to do, as the difference value is
960 already written into the section's contents. */
961
962static bfd_reloc_status_type
963bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
964 arelent *reloc_entry ATTRIBUTE_UNUSED,
965 asymbol *symbol ATTRIBUTE_UNUSED,
966 void *data ATTRIBUTE_UNUSED,
967 asection *input_section ATTRIBUTE_UNUSED,
968 bfd *output_bfd ATTRIBUTE_UNUSED,
969 char **error_message ATTRIBUTE_UNUSED)
970{
971 return bfd_reloc_ok;
972}
973
974
975/* Returns whether the relocation type passed is a diff reloc. */
976
977static bfd_boolean
978elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
979{
980 return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
981 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
982 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
983 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
984 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
985}
986
987/* Reduce the diff value written in the section by count if the shrinked
988 insn address happens to fall between the two symbols for which this
989 diff reloc was emitted. */
990
991static void
992elf32_pru_adjust_diff_reloc_value (bfd *abfd,
993 struct bfd_section *isec,
994 Elf_Internal_Rela *irel,
995 bfd_vma symval,
996 bfd_vma shrinked_insn_address,
997 int count)
998{
999 unsigned char *reloc_contents = NULL;
1000 unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
1001 if (isec_contents == NULL)
1002 {
1003 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
1004 return;
1005
1006 elf_section_data (isec)->this_hdr.contents = isec_contents;
1007 }
1008
1009 reloc_contents = isec_contents + irel->r_offset;
1010
1011 /* Read value written in object file. */
1012 bfd_signed_vma x = 0;
1013 switch (ELF32_R_TYPE (irel->r_info))
1014 {
1015 case R_PRU_GNU_DIFF8:
1016 {
1017 x = bfd_get_signed_8 (abfd, reloc_contents);
1018 break;
1019 }
1020 case R_PRU_GNU_DIFF16:
1021 {
1022 x = bfd_get_signed_16 (abfd, reloc_contents);
1023 break;
1024 }
1025 case R_PRU_GNU_DIFF32:
1026 {
1027 x = bfd_get_signed_32 (abfd, reloc_contents);
1028 break;
1029 }
1030 case R_PRU_GNU_DIFF16_PMEM:
1031 {
1032 x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
1033 break;
1034 }
1035 case R_PRU_GNU_DIFF32_PMEM:
1036 {
1037 x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
1038 break;
1039 }
1040 default:
1041 {
1042 BFD_FAIL ();
1043 }
1044 }
1045
1046 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
1047 into the object file at the reloc offset. sym2's logical value is
1048 symval (<start_of_section>) + reloc addend. Compute the start and end
1049 addresses and check if the shrinked insn falls between sym1 and sym2. */
1050
1051 bfd_vma end_address = symval + irel->r_addend;
1052 bfd_vma start_address = end_address - x;
1053
1054 /* Shrink the absolute DIFF value (get the to labels "closer"
1055 together), because we have removed data between labels. */
1056 if (x < 0)
1057 {
1058 x += count;
1059 /* In case the signed x is negative, restore order. */
1060 SWAP_VALS (end_address, start_address);
1061 }
1062 else
1063 {
1064 x -= count;
1065 }
1066
1067 /* Reduce the diff value by count bytes and write it back into section
1068 contents. */
1069
1070 if (shrinked_insn_address >= start_address
1071 && shrinked_insn_address <= end_address)
1072 {
1073 switch (ELF32_R_TYPE (irel->r_info))
1074 {
1075 case R_PRU_GNU_DIFF8:
1076 {
1077 bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
1078 break;
1079 }
1080 case R_PRU_GNU_DIFF16:
1081 {
1082 bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
1083 break;
1084 }
1085 case R_PRU_GNU_DIFF32:
1086 {
1087 bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
1088 break;
1089 }
1090 case R_PRU_GNU_DIFF16_PMEM:
1091 {
1092 bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
1093 break;
1094 }
1095 case R_PRU_GNU_DIFF32_PMEM:
1096 {
1097 bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
1098 break;
1099 }
1100 default:
1101 {
1102 BFD_FAIL ();
1103 }
1104 }
1105
1106 }
1107}
1108
1109/* Delete some bytes from a section while changing the size of an instruction.
1110 The parameter "addr" denotes the section-relative offset pointing just
1111 behind the shrinked instruction. "addr+count" point at the first
1112 byte just behind the original unshrinked instruction.
1113
1114 Idea copied from the AVR port. */
1115
1116static bfd_boolean
1117pru_elf_relax_delete_bytes (bfd *abfd,
1118 asection *sec,
1119 bfd_vma addr,
1120 int count)
1121{
1122 Elf_Internal_Shdr *symtab_hdr;
1123 unsigned int sec_shndx;
1124 bfd_byte *contents;
1125 Elf_Internal_Rela *irel, *irelend;
1126 Elf_Internal_Sym *isym;
1127 Elf_Internal_Sym *isymbuf = NULL;
1128 bfd_vma toaddr;
1129 struct elf_link_hash_entry **sym_hashes;
1130 struct elf_link_hash_entry **end_hashes;
1131 unsigned int symcount;
1132
1133 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1134 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1135 contents = elf_section_data (sec)->this_hdr.contents;
1136
1137 toaddr = sec->size;
1138
1139 irel = elf_section_data (sec)->relocs;
1140 irelend = irel + sec->reloc_count;
1141
1142 /* Actually delete the bytes. */
1143 if (toaddr - addr - count > 0)
1144 memmove (contents + addr, contents + addr + count,
1145 (size_t) (toaddr - addr - count));
1146 sec->size -= count;
1147
1148 /* Adjust all the reloc addresses. */
1149 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1150 {
1151 bfd_vma old_reloc_address;
1152
1153 old_reloc_address = (sec->output_section->vma
1154 + sec->output_offset + irel->r_offset);
1155
1156 /* Get the new reloc address. */
1157 if ((irel->r_offset > addr
1158 && irel->r_offset < toaddr))
1159 {
1160 if (debug_relax)
1161 printf ("Relocation at address 0x%x needs to be moved.\n"
1162 "Old section offset: 0x%x, New section offset: 0x%x \n",
1163 (unsigned int) old_reloc_address,
1164 (unsigned int) irel->r_offset,
1165 (unsigned int) ((irel->r_offset) - count));
1166
1167 irel->r_offset -= count;
1168 }
1169
1170 }
1171
1172 /* The reloc's own addresses are now ok. However, we need to readjust
1173 the reloc's addend, i.e. the reloc's value if two conditions are met:
1174 1.) the reloc is relative to a symbol in this section that
1175 is located in front of the shrinked instruction
1176 2.) symbol plus addend end up behind the shrinked instruction.
1177
1178 The most common case where this happens are relocs relative to
1179 the section-start symbol.
1180
1181 This step needs to be done for all of the sections of the bfd. */
1182
1183 {
1184 struct bfd_section *isec;
1185
1186 for (isec = abfd->sections; isec; isec = isec->next)
1187 {
1188 bfd_vma symval;
1189 bfd_vma shrinked_insn_address;
1190
1191 if (isec->reloc_count == 0)
1192 continue;
1193
1194 shrinked_insn_address = (sec->output_section->vma
493ffac5 1195 + sec->output_offset + addr);
889294f6
DD
1196
1197 irel = elf_section_data (isec)->relocs;
1198 /* PR 12161: Read in the relocs for this section if necessary. */
1199 if (irel == NULL)
1200 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
1201
1202 for (irelend = irel + isec->reloc_count;
1203 irel < irelend;
1204 irel++)
1205 {
1206 /* Read this BFD's local symbols if we haven't done
1207 so already. */
1208 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1209 {
1210 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1211 if (isymbuf == NULL)
1212 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1213 symtab_hdr->sh_info, 0,
1214 NULL, NULL, NULL);
1215 if (isymbuf == NULL)
1216 return FALSE;
1217 }
1218
1219 /* Get the value of the symbol referred to by the reloc. */
1220 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1221 {
1222 /* A local symbol. */
1223 asection *sym_sec;
1224
1225 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1226 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1227 symval = isym->st_value;
1228 /* If the reloc is absolute, it will not have
1229 a symbol or section associated with it. */
1230 if (sym_sec == sec)
1231 {
1232 symval += sym_sec->output_section->vma
1233 + sym_sec->output_offset;
1234
1235 if (debug_relax)
1236 printf ("Checking if the relocation's "
1237 "addend needs corrections.\n"
1238 "Address of anchor symbol: 0x%x \n"
1239 "Address of relocation target: 0x%x \n"
1240 "Address of relaxed insn: 0x%x \n",
1241 (unsigned int) symval,
1242 (unsigned int) (symval + irel->r_addend),
1243 (unsigned int) shrinked_insn_address);
1244
1245 /* Shrink the special DIFF relocations. */
1246 if (elf32_pru_is_diff_reloc (irel))
1247 {
1248 elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1249 symval,
1250 shrinked_insn_address,
1251 count);
1252 }
1253
1254 /* Fix the addend, if it is affected. */
1255 if (symval <= shrinked_insn_address
1256 && (symval + irel->r_addend) > shrinked_insn_address)
1257 {
1258
1259 irel->r_addend -= count;
1260
1261 if (debug_relax)
1262 printf ("Relocation's addend needed to be fixed \n");
1263 }
1264 }
1265 /* else...Reference symbol is absolute.
1266 No adjustment needed. */
1267 }
1268 /* else...Reference symbol is extern. No need for adjusting
1269 the addend. */
1270 }
1271 }
1272 }
1273
1274 /* Adjust the local symbols defined in this section. */
1275 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1276 /* Fix PR 9841, there may be no local symbols. */
1277 if (isym != NULL)
1278 {
1279 Elf_Internal_Sym *isymend;
1280
1281 isymend = isym + symtab_hdr->sh_info;
1282 for (; isym < isymend; isym++)
1283 {
1284 if (isym->st_shndx == sec_shndx)
1285 {
1286 if (isym->st_value > addr
1287 && isym->st_value <= toaddr)
1288 isym->st_value -= count;
1289
1290 if (isym->st_value <= addr
1291 && isym->st_value + isym->st_size > addr)
1292 {
1293 /* If this assert fires then we have a symbol that ends
1294 part way through an instruction. Does that make
1295 sense? */
1296 BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1297 isym->st_size -= count;
1298 }
1299 }
1300 }
1301 }
1302
1303 /* Now adjust the global symbols defined in this section. */
1304 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1305 - symtab_hdr->sh_info);
1306 sym_hashes = elf_sym_hashes (abfd);
1307 end_hashes = sym_hashes + symcount;
1308 for (; sym_hashes < end_hashes; sym_hashes++)
1309 {
1310 struct elf_link_hash_entry *sym_hash = *sym_hashes;
1311 if ((sym_hash->root.type == bfd_link_hash_defined
1312 || sym_hash->root.type == bfd_link_hash_defweak)
1313 && sym_hash->root.u.def.section == sec)
1314 {
1315 if (sym_hash->root.u.def.value > addr
1316 && sym_hash->root.u.def.value <= toaddr)
1317 sym_hash->root.u.def.value -= count;
1318
1319 if (sym_hash->root.u.def.value <= addr
1320 && (sym_hash->root.u.def.value + sym_hash->size > addr))
1321 {
1322 /* If this assert fires then we have a symbol that ends
1323 part way through an instruction. Does that make
1324 sense? */
1325 BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1326 >= addr + count);
1327 sym_hash->size -= count;
1328 }
1329 }
1330 }
1331
1332 return TRUE;
1333}
1334
1335static bfd_boolean
1336pru_elf32_relax_section (bfd * abfd, asection * sec,
1337 struct bfd_link_info * link_info,
1338 bfd_boolean * again)
1339{
1340 Elf_Internal_Shdr * symtab_hdr;
1341 Elf_Internal_Rela * internal_relocs;
1342 Elf_Internal_Rela * irel;
1343 Elf_Internal_Rela * irelend;
1344 bfd_byte * contents = NULL;
1345 Elf_Internal_Sym * isymbuf = NULL;
1346
1347 /* Assume nothing changes. */
1348 *again = FALSE;
1349
1350 /* We don't have to do anything for a relocatable link, if
1351 this section does not have relocs, or if this is not a
1352 code section. */
1353 if (bfd_link_relocatable (link_info)
1354 || (sec->flags & SEC_RELOC) == 0
1355 || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1356 return TRUE;
1357
1358 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1359
1360 /* Get a copy of the native relocations. */
1361 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1362 link_info->keep_memory);
1363 if (internal_relocs == NULL)
1364 goto error_return;
1365
1366 /* Walk through them looking for relaxing opportunities. */
1367 irelend = internal_relocs + sec->reloc_count;
1368
1369 for (irel = internal_relocs; irel < irelend; irel++)
1370 {
1371 bfd_vma symval;
1372
1373 /* Get the section contents if we haven't done so already. */
1374 if (contents == NULL)
1375 {
1376 /* Get cached copy if it exists. */
1377 if (elf_section_data (sec)->this_hdr.contents != NULL)
1378 contents = elf_section_data (sec)->this_hdr.contents;
1379 else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1380 goto error_return;
1381 }
1382
1383 /* Read this BFD's local symbols if we haven't done so already. */
1384 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1385 {
1386 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1387 if (isymbuf == NULL)
1388 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1389 symtab_hdr->sh_info, 0,
1390 NULL, NULL, NULL);
1391 if (isymbuf == NULL)
1392 goto error_return;
1393 }
1394
1395 /* Get the value of the symbol referred to by the reloc. */
1396 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1397 {
1398 /* A local symbol. */
1399 Elf_Internal_Sym *isym;
1400 asection *sym_sec;
1401
1402 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1403 if (isym->st_shndx == SHN_UNDEF)
1404 sym_sec = bfd_und_section_ptr;
1405 else if (isym->st_shndx == SHN_ABS)
1406 sym_sec = bfd_abs_section_ptr;
1407 else if (isym->st_shndx == SHN_COMMON)
1408 sym_sec = bfd_com_section_ptr;
1409 else
1410 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1411 symval = (isym->st_value
1412 + sym_sec->output_section->vma + sym_sec->output_offset);
1413 }
1414 else
1415 {
1416 unsigned long indx;
1417 struct elf_link_hash_entry *h;
1418
1419 /* An external symbol. */
1420 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1421 h = elf_sym_hashes (abfd)[indx];
1422 BFD_ASSERT (h != NULL);
1423
1424 if (h->root.type != bfd_link_hash_defined
1425 && h->root.type != bfd_link_hash_defweak)
1426 /* This appears to be a reference to an undefined
1427 symbol. Just ignore it--it will be caught by the
1428 regular reloc processing. */
1429 continue;
1430
1431 symval = (h->root.u.def.value
1432 + h->root.u.def.section->output_section->vma
1433 + h->root.u.def.section->output_offset);
1434 }
1435
1436 /* For simplicity of coding, we are going to modify the section
1437 contents, the section relocs, and the BFD symbol table. We
1438 must tell the rest of the code not to free up this
1439 information. It would be possible to instead create a table
1440 of changes which have to be made, as is done in coff-mips.c;
1441 that would be more work, but would require less memory when
1442 the linker is run. */
1443
1444 /* Check if we can remove an LDI instruction from the LDI32
1445 pseudo instruction if the upper 16 operand bits are zero. */
1446 if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1447 {
1448 bfd_vma value = symval + irel->r_addend;
1449
1450 if (debug_relax)
1451 printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1452
1453 if ((long) value >> 16 == 0)
1454 {
493ffac5
DD
1455 unsigned long insn;
1456
889294f6
DD
1457 /* Note that we've changed the relocs, section contents. */
1458 elf_section_data (sec)->relocs = internal_relocs;
1459 elf_section_data (sec)->this_hdr.contents = contents;
1460 symtab_hdr->contents = (unsigned char *) isymbuf;
1461
493ffac5
DD
1462 /* Make the second instruction load the 16-bit constant
1463 into the full 32-bit register. */
1464 insn = bfd_get_32 (abfd, contents + irel->r_offset + 4);
1465
1466 /* Old GAS and LD versions have a bug, where the two
1467 LDI instructions are swapped. Detect such object
1468 files and bail. */
1469 if (GET_INSN_FIELD (RDSEL, insn) != RSEL_15_0)
1470 {
1471 /* xgettext:c-format */
1472 _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
1473 abfd);
1474 goto error_return;
1475 }
1476
1477 SET_INSN_FIELD (RDSEL, insn, RSEL_31_0);
1478 bfd_put_32 (abfd, insn, contents + irel->r_offset + 4);
1479
1480 /* Delete the first LDI instruction. Note that there should
1481 be no relocations or symbols pointing to the second LDI
1482 instruction. */
1483 if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 4))
889294f6
DD
1484 goto error_return;
1485
493ffac5
DD
1486 /* We're done with deletion of the first instruction.
1487 Set a regular LDI relocation for the second instruction
889294f6
DD
1488 we left to load the 16-bit value into the 32-bit
1489 register. */
1490 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1491 R_PRU_U16);
1492
1493 /* That will change things, so, we should relax again.
1494 Note that this is not required, and it may be slow. */
1495 *again = TRUE;
1496 }
1497 }
1498 }
1499
1500 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1501 {
1502 if (!link_info->keep_memory)
1503 free (isymbuf);
1504 else
1505 {
1506 /* Cache the symbols for elf_link_input_bfd. */
1507 symtab_hdr->contents = (unsigned char *) isymbuf;
1508 }
1509 }
1510
1511 if (contents != NULL
1512 && elf_section_data (sec)->this_hdr.contents != contents)
1513 {
1514 if (!link_info->keep_memory)
1515 free (contents);
1516 else
1517 {
1518 /* Cache the section contents for elf_link_input_bfd. */
1519 elf_section_data (sec)->this_hdr.contents = contents;
1520 }
1521 }
1522
1523 if (internal_relocs != NULL
1524 && elf_section_data (sec)->relocs != internal_relocs)
1525 free (internal_relocs);
1526
1527 return TRUE;
1528
1529error_return:
1530 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1531 free (isymbuf);
1532 if (contents != NULL
1533 && elf_section_data (sec)->this_hdr.contents != contents)
1534 free (contents);
1535 if (internal_relocs != NULL
1536 && elf_section_data (sec)->relocs != internal_relocs)
1537 free (internal_relocs);
1538
1539 return FALSE;
1540}
1541
1542/* Free the derived linker hash table. */
1543static void
1544pru_elf32_link_hash_table_free (bfd *obfd)
1545{
1546 _bfd_elf_link_hash_table_free (obfd);
1547}
1548
1549/* Implement bfd_elf32_bfd_link_hash_table_create. */
1550static struct bfd_link_hash_table *
1551pru_elf32_link_hash_table_create (bfd *abfd)
1552{
1553 struct elf_link_hash_table *ret;
1554 bfd_size_type amt = sizeof (struct elf_link_hash_table);
1555
1556 ret = bfd_zmalloc (amt);
1557 if (ret == NULL)
1558 return NULL;
1559
1560 if (!_bfd_elf_link_hash_table_init (ret, abfd,
1561 link_hash_newfunc,
1562 sizeof (struct
1563 elf_link_hash_entry),
1564 PRU_ELF_DATA))
1565 {
1566 free (ret);
1567 return NULL;
1568 }
1569
1570 ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1571
1572 return &ret->root;
1573}
1574
1575#define ELF_ARCH bfd_arch_pru
1576#define ELF_TARGET_ID PRU_ELF_DATA
1577#define ELF_MACHINE_CODE EM_TI_PRU
1578
1579#define ELF_MAXPAGESIZE 1
1580
1581#define bfd_elf32_bfd_link_hash_table_create \
1582 pru_elf32_link_hash_table_create
1583
1584/* Relocation table lookup macros. */
1585
1586#define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup
1587#define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup
1588
889294f6 1589#define elf_info_to_howto pru_elf32_info_to_howto
493ffac5 1590#define elf_info_to_howto_rel NULL
889294f6
DD
1591
1592/* elf backend functions. */
1593
493ffac5
DD
1594/* TI folks like to use a mix of REL and RELA relocations. See also
1595 the MSP430 and TI C6X backends. */
1596#define elf_backend_may_use_rel_p 1
1597#define elf_backend_may_use_rela_p 1
1598#define elf_backend_default_use_rela_p 1
1599
889294f6
DD
1600#define elf_backend_rela_normal 1
1601
1602#define elf_backend_relocate_section pru_elf32_relocate_section
1603#define bfd_elf32_bfd_relax_section pru_elf32_relax_section
1604
1605#define TARGET_LITTLE_SYM pru_elf32_vec
1606#define TARGET_LITTLE_NAME "elf32-pru"
1607
1608#include "elf32-target.h"
This page took 0.237216 seconds and 4 git commands to generate.