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