elf32-pru.c revision 1.1.1.2 1 /* 32-bit ELF support for TI PRU.
2 Copyright (C) 2014-2019 Free Software Foundation, Inc.
3 Contributed by Dimitar Dimitrov <dimitar (at) 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"
33 #include "libiberty.h"
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. */
43 static bfd_boolean debug_relax = FALSE;
44
45 /* Forward declarations. */
46 static bfd_reloc_status_type pru_elf32_pmem_relocate
47 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
48 static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate
49 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
50 static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate
51 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
52 static bfd_reloc_status_type pru_elf32_ldi32_relocate
53 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
54 static bfd_reloc_status_type bfd_elf_pru_diff_relocate
55 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
56
57 /* Target vector. */
58 extern const bfd_target pru_elf32_vec;
59
60 /* The relocation table used for SHT_REL sections. */
61 static 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 */
221 0, /* size (0 = byte, 1 = short, 2 = long) */
222 8, /* bitsize */
223 FALSE, /* pc_relative */
224 0, /* bitpos */
225 complain_overflow_bitfield, /* complain_on_overflow */
226 bfd_elf_pru_diff_relocate, /* special_function */
227 "R_PRU_DIFF8", /* name */
228 FALSE, /* partial_inplace */
229 0, /* src_mask */
230 0xff, /* dst_mask */
231 FALSE), /* pcrel_offset */
232
233 HOWTO (R_PRU_GNU_DIFF16, /* type */
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 */
241 "R_PRU_DIFF16", /* name */
242 FALSE, /* partial_inplace */
243 0, /* src_mask */
244 0xffff, /* dst_mask */
245 FALSE), /* pcrel_offset */
246
247 HOWTO (R_PRU_GNU_DIFF32, /* type */
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 */
255 "R_PRU_DIFF32", /* name */
256 FALSE, /* partial_inplace */
257 0, /* src_mask */
258 0xffffffff, /* dst_mask */
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 */
269 "R_PRU_DIFF16_PMEM", /* name */
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 */
283 "R_PRU_DIFF32_PMEM", /* name */
284 FALSE, /* partial_inplace */
285 0, /* src_mask */
286 0xffffffff, /* dst_mask */
287 FALSE), /* pcrel_offset */
288
289 /* Add other relocations here. */
290 };
291
292 static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1];
293
294 /* Return the howto for relocation RTYPE. */
295
296 static reloc_howto_type *
297 lookup_howto (unsigned int rtype)
298 {
299 static bfd_boolean initialized = FALSE;
300 int i;
301 int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel)
302 / sizeof (elf_pru_howto_table_rel[0]));
303
304 if (! initialized)
305 {
306 initialized = TRUE;
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
313 if (rtype > R_PRU_ILLEGAL)
314 return NULL;
315 i = elf_code_to_howto_index[rtype];
316 if (i >= howto_tbl_size)
317 return NULL;
318 return elf_pru_howto_table_rel + i;
319 }
320
321 /* Map for converting BFD reloc types to PRU reloc types. */
322
323 struct elf_reloc_map
324 {
325 bfd_reloc_code_real_type bfd_val;
326 enum elf_pru_reloc_type elf_val;
327 };
328
329 static const struct elf_reloc_map pru_reloc_map[] =
330 {
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. */
354
355 static struct bfd_hash_entry *
356 link_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. */
377
378 static reloc_howto_type *
379 pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
380 bfd_reloc_code_real_type code)
381 {
382 unsigned int i;
383
384 for (i = 0; i < ARRAY_SIZE (pru_reloc_map); ++i)
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. */
392
393 static reloc_howto_type *
394 pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
395 const char *r_name)
396 {
397 unsigned int i;
398
399 for (i = 0; i < ARRAY_SIZE (elf_pru_howto_table_rel); i++)
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. */
409
410 static bfd_boolean
411 pru_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr,
412 Elf_Internal_Rela *dst)
413 {
414 unsigned int r_type;
415
416 r_type = ELF32_R_TYPE (dst->r_info);
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 }
424
425 cache_ptr->howto = lookup_howto (r_type);
426 return cache_ptr->howto != NULL;
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. */
443 static bfd_reloc_status_type
444 pru_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. */
459 static bfd_reloc_status_type
460 pru_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
508 static bfd_reloc_status_type
509 pru_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. */
533 static bfd_reloc_status_type
534 pru_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;
542 unsigned long in1, in2;
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
567 SET_INSN_FIELD (IMM16, in1, relocation >> 16);
568 SET_INSN_FIELD (IMM16, in2, relocation & 0xffff);
569
570 bfd_put_32 (abfd, in1, location);
571 bfd_put_32 (abfd, in2, location + 4);
572
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
584 return bfd_reloc_ok;
585 }
586
587 /* HOWTO handlers for relocations that require special handling. */
588
589 static bfd_reloc_status_type
590 pru_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
602 BFD_ASSERT (0);
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
612 static bfd_reloc_status_type
613 pru_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
634 static bfd_reloc_status_type
635 pru_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
656 static bfd_reloc_status_type
657 pru_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. */
680 static bfd_boolean
681 pru_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 {
690 struct bfd_elf_section_data * esd = elf_section_data (input_section);
691 Elf_Internal_Shdr *symtab_hdr;
692 struct elf_link_hash_entry **sym_hashes;
693 Elf_Internal_Rela *rel;
694 Elf_Internal_Rela *relend;
695 bfd_boolean is_rel_reloc;
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
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
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;
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);
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
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
781 case R_PRU_U16_PMEMIMM:
782 case R_PRU_32_PMEM:
783 case R_PRU_16_PMEM:
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 }
805 r = pru_elf32_do_pmem_relocate (input_bfd, howto,
806 input_section,
807 contents, rel->r_offset,
808 relocation, addend);
809 break;
810 case R_PRU_S10_PCREL:
811 BFD_ASSERT (! is_rel_reloc);
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:
820 BFD_ASSERT (! is_rel_reloc);
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:
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 }
841 r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
842 input_section,
843 contents,
844 rel->r_offset,
845 relocation,
846 addend);
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:
853 /* GNU extensions support only rela. */
854 BFD_ASSERT (! is_rel_reloc);
855 /* Nothing to do here, as contents already contain the
856 diff value. */
857 r = bfd_reloc_ok;
858 break;
859
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);
884 r = _bfd_final_link_relocate (howto, input_bfd,
885 input_section, contents,
886 rel->r_offset, relocation,
887 rel->r_addend);
888 break;
889
890 default:
891 BFD_ASSERT (0);
892 break;
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
959 /* Perform a diff relocation. Nothing to do, as the difference value is
961 already written into the section's contents. */
962
963 static bfd_reloc_status_type
964 bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
965 arelent *reloc_entry ATTRIBUTE_UNUSED,
966 asymbol *symbol ATTRIBUTE_UNUSED,
967 void *data ATTRIBUTE_UNUSED,
968 asection *input_section ATTRIBUTE_UNUSED,
969 bfd *output_bfd ATTRIBUTE_UNUSED,
970 char **error_message ATTRIBUTE_UNUSED)
971 {
972 return bfd_reloc_ok;
973 }
974
975
976 /* Returns whether the relocation type passed is a diff reloc. */
977
978 static bfd_boolean
979 elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
980 {
981 return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
982 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
983 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
984 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
985 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
986 }
987
988 /* Reduce the diff value written in the section by count if the shrinked
989 insn address happens to fall between the two symbols for which this
990 diff reloc was emitted. */
991
992 static void
993 elf32_pru_adjust_diff_reloc_value (bfd *abfd,
994 struct bfd_section *isec,
995 Elf_Internal_Rela *irel,
996 bfd_vma symval,
997 bfd_vma shrinked_insn_address,
998 int count)
999 {
1000 unsigned char *reloc_contents = NULL;
1001 unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
1002 if (isec_contents == NULL)
1003 {
1004 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
1005 return;
1006
1007 elf_section_data (isec)->this_hdr.contents = isec_contents;
1008 }
1009
1010 reloc_contents = isec_contents + irel->r_offset;
1011
1012 /* Read value written in object file. */
1013 bfd_signed_vma x = 0;
1014 switch (ELF32_R_TYPE (irel->r_info))
1015 {
1016 case R_PRU_GNU_DIFF8:
1017 {
1018 x = bfd_get_signed_8 (abfd, reloc_contents);
1019 break;
1020 }
1021 case R_PRU_GNU_DIFF16:
1022 {
1023 x = bfd_get_signed_16 (abfd, reloc_contents);
1024 break;
1025 }
1026 case R_PRU_GNU_DIFF32:
1027 {
1028 x = bfd_get_signed_32 (abfd, reloc_contents);
1029 break;
1030 }
1031 case R_PRU_GNU_DIFF16_PMEM:
1032 {
1033 x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
1034 break;
1035 }
1036 case R_PRU_GNU_DIFF32_PMEM:
1037 {
1038 x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
1039 break;
1040 }
1041 default:
1042 {
1043 BFD_FAIL ();
1044 }
1045 }
1046
1047 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
1048 into the object file at the reloc offset. sym2's logical value is
1049 symval (<start_of_section>) + reloc addend. Compute the start and end
1050 addresses and check if the shrinked insn falls between sym1 and sym2. */
1051
1052 bfd_vma end_address = symval + irel->r_addend;
1053 bfd_vma start_address = end_address - x;
1054
1055 /* Shrink the absolute DIFF value (get the to labels "closer"
1056 together), because we have removed data between labels. */
1057 if (x < 0)
1058 {
1059 x += count;
1060 /* In case the signed x is negative, restore order. */
1061 SWAP_VALS (end_address, start_address);
1062 }
1063 else
1064 {
1065 x -= count;
1066 }
1067
1068 /* Reduce the diff value by count bytes and write it back into section
1069 contents. */
1070
1071 if (shrinked_insn_address >= start_address
1072 && shrinked_insn_address <= end_address)
1073 {
1074 switch (ELF32_R_TYPE (irel->r_info))
1075 {
1076 case R_PRU_GNU_DIFF8:
1077 {
1078 bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
1079 break;
1080 }
1081 case R_PRU_GNU_DIFF16:
1082 {
1083 bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
1084 break;
1085 }
1086 case R_PRU_GNU_DIFF32:
1087 {
1088 bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
1089 break;
1090 }
1091 case R_PRU_GNU_DIFF16_PMEM:
1092 {
1093 bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
1094 break;
1095 }
1096 case R_PRU_GNU_DIFF32_PMEM:
1097 {
1098 bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
1099 break;
1100 }
1101 default:
1102 {
1103 BFD_FAIL ();
1104 }
1105 }
1106
1107 }
1108 }
1109
1110 /* Delete some bytes from a section while changing the size of an instruction.
1111 The parameter "addr" denotes the section-relative offset pointing just
1112 behind the shrinked instruction. "addr+count" point at the first
1113 byte just behind the original unshrinked instruction.
1114
1115 Idea copied from the AVR port. */
1116
1117 static bfd_boolean
1118 pru_elf_relax_delete_bytes (bfd *abfd,
1119 asection *sec,
1120 bfd_vma addr,
1121 int count)
1122 {
1123 Elf_Internal_Shdr *symtab_hdr;
1124 unsigned int sec_shndx;
1125 bfd_byte *contents;
1126 Elf_Internal_Rela *irel, *irelend;
1127 Elf_Internal_Sym *isym;
1128 Elf_Internal_Sym *isymbuf = NULL;
1129 bfd_vma toaddr;
1130 struct elf_link_hash_entry **sym_hashes;
1131 struct elf_link_hash_entry **end_hashes;
1132 unsigned int symcount;
1133
1134 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1135 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1136 contents = elf_section_data (sec)->this_hdr.contents;
1137
1138 toaddr = sec->size;
1139
1140 irel = elf_section_data (sec)->relocs;
1141 irelend = irel + sec->reloc_count;
1142
1143 /* Actually delete the bytes. */
1144 if (toaddr - addr - count > 0)
1145 memmove (contents + addr, contents + addr + count,
1146 (size_t) (toaddr - addr - count));
1147 sec->size -= count;
1148
1149 /* Adjust all the reloc addresses. */
1150 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1151 {
1152 bfd_vma old_reloc_address;
1153
1154 old_reloc_address = (sec->output_section->vma
1155 + sec->output_offset + irel->r_offset);
1156
1157 /* Get the new reloc address. */
1158 if ((irel->r_offset > addr
1159 && irel->r_offset < toaddr))
1160 {
1161 if (debug_relax)
1162 printf ("Relocation at address 0x%x needs to be moved.\n"
1163 "Old section offset: 0x%x, New section offset: 0x%x \n",
1164 (unsigned int) old_reloc_address,
1165 (unsigned int) irel->r_offset,
1166 (unsigned int) ((irel->r_offset) - count));
1167
1168 irel->r_offset -= count;
1169 }
1170
1171 }
1172
1173 /* The reloc's own addresses are now ok. However, we need to readjust
1174 the reloc's addend, i.e. the reloc's value if two conditions are met:
1175 1.) the reloc is relative to a symbol in this section that
1176 is located in front of the shrinked instruction
1177 2.) symbol plus addend end up behind the shrinked instruction.
1178
1179 The most common case where this happens are relocs relative to
1180 the section-start symbol.
1181
1182 This step needs to be done for all of the sections of the bfd. */
1183
1184 {
1185 struct bfd_section *isec;
1186
1187 for (isec = abfd->sections; isec; isec = isec->next)
1188 {
1189 bfd_vma symval;
1190 bfd_vma shrinked_insn_address;
1191
1192 if (isec->reloc_count == 0)
1193 continue;
1194
1195 shrinked_insn_address = (sec->output_section->vma
1196 + sec->output_offset + addr);
1197
1198 irel = elf_section_data (isec)->relocs;
1199 /* PR 12161: Read in the relocs for this section if necessary. */
1200 if (irel == NULL)
1201 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
1202
1203 for (irelend = irel + isec->reloc_count;
1204 irel < irelend;
1205 irel++)
1206 {
1207 /* Read this BFD's local symbols if we haven't done
1208 so already. */
1209 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1210 {
1211 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1212 if (isymbuf == NULL)
1213 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1214 symtab_hdr->sh_info, 0,
1215 NULL, NULL, NULL);
1216 if (isymbuf == NULL)
1217 return FALSE;
1218 }
1219
1220 /* Get the value of the symbol referred to by the reloc. */
1221 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1222 {
1223 /* A local symbol. */
1224 asection *sym_sec;
1225
1226 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1227 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1228 symval = isym->st_value;
1229 /* If the reloc is absolute, it will not have
1230 a symbol or section associated with it. */
1231 if (sym_sec == sec)
1232 {
1233 symval += sym_sec->output_section->vma
1234 + sym_sec->output_offset;
1235
1236 if (debug_relax)
1237 printf ("Checking if the relocation's "
1238 "addend needs corrections.\n"
1239 "Address of anchor symbol: 0x%x \n"
1240 "Address of relocation target: 0x%x \n"
1241 "Address of relaxed insn: 0x%x \n",
1242 (unsigned int) symval,
1243 (unsigned int) (symval + irel->r_addend),
1244 (unsigned int) shrinked_insn_address);
1245
1246 /* Shrink the special DIFF relocations. */
1247 if (elf32_pru_is_diff_reloc (irel))
1248 {
1249 elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1250 symval,
1251 shrinked_insn_address,
1252 count);
1253 }
1254
1255 /* Fix the addend, if it is affected. */
1256 if (symval <= shrinked_insn_address
1257 && (symval + irel->r_addend) > shrinked_insn_address)
1258 {
1259
1260 irel->r_addend -= count;
1261
1262 if (debug_relax)
1263 printf ("Relocation's addend needed to be fixed \n");
1264 }
1265 }
1266 /* else...Reference symbol is absolute.
1267 No adjustment needed. */
1268 }
1269 /* else...Reference symbol is extern. No need for adjusting
1270 the addend. */
1271 }
1272 }
1273 }
1274
1275 /* Adjust the local symbols defined in this section. */
1276 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1277 /* Fix PR 9841, there may be no local symbols. */
1278 if (isym != NULL)
1279 {
1280 Elf_Internal_Sym *isymend;
1281
1282 isymend = isym + symtab_hdr->sh_info;
1283 for (; isym < isymend; isym++)
1284 {
1285 if (isym->st_shndx == sec_shndx)
1286 {
1287 if (isym->st_value > addr
1288 && isym->st_value <= toaddr)
1289 isym->st_value -= count;
1290
1291 if (isym->st_value <= addr
1292 && isym->st_value + isym->st_size > addr)
1293 {
1294 /* If this assert fires then we have a symbol that ends
1295 part way through an instruction. Does that make
1296 sense? */
1297 BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1298 isym->st_size -= count;
1299 }
1300 }
1301 }
1302 }
1303
1304 /* Now adjust the global symbols defined in this section. */
1305 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1306 - symtab_hdr->sh_info);
1307 sym_hashes = elf_sym_hashes (abfd);
1308 end_hashes = sym_hashes + symcount;
1309 for (; sym_hashes < end_hashes; sym_hashes++)
1310 {
1311 struct elf_link_hash_entry *sym_hash = *sym_hashes;
1312 if ((sym_hash->root.type == bfd_link_hash_defined
1313 || sym_hash->root.type == bfd_link_hash_defweak)
1314 && sym_hash->root.u.def.section == sec)
1315 {
1316 if (sym_hash->root.u.def.value > addr
1317 && sym_hash->root.u.def.value <= toaddr)
1318 sym_hash->root.u.def.value -= count;
1319
1320 if (sym_hash->root.u.def.value <= addr
1321 && (sym_hash->root.u.def.value + sym_hash->size > addr))
1322 {
1323 /* If this assert fires then we have a symbol that ends
1324 part way through an instruction. Does that make
1325 sense? */
1326 BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1327 >= addr + count);
1328 sym_hash->size -= count;
1329 }
1330 }
1331 }
1332
1333 return TRUE;
1334 }
1335
1336 static bfd_boolean
1337 pru_elf32_relax_section (bfd * abfd, asection * sec,
1338 struct bfd_link_info * link_info,
1339 bfd_boolean * again)
1340 {
1341 Elf_Internal_Shdr * symtab_hdr;
1342 Elf_Internal_Rela * internal_relocs;
1343 Elf_Internal_Rela * irel;
1344 Elf_Internal_Rela * irelend;
1345 bfd_byte * contents = NULL;
1346 Elf_Internal_Sym * isymbuf = NULL;
1347
1348 /* Assume nothing changes. */
1349 *again = FALSE;
1350
1351 /* We don't have to do anything for a relocatable link, if
1352 this section does not have relocs, or if this is not a
1353 code section. */
1354 if (bfd_link_relocatable (link_info)
1355 || (sec->flags & SEC_RELOC) == 0
1356 || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1357 return TRUE;
1358
1359 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1360
1361 /* Get a copy of the native relocations. */
1362 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1363 link_info->keep_memory);
1364 if (internal_relocs == NULL)
1365 goto error_return;
1366
1367 /* Walk through them looking for relaxing opportunities. */
1368 irelend = internal_relocs + sec->reloc_count;
1369
1370 for (irel = internal_relocs; irel < irelend; irel++)
1371 {
1372 bfd_vma symval;
1373
1374 /* Get the section contents if we haven't done so already. */
1375 if (contents == NULL)
1376 {
1377 /* Get cached copy if it exists. */
1378 if (elf_section_data (sec)->this_hdr.contents != NULL)
1379 contents = elf_section_data (sec)->this_hdr.contents;
1380 else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1381 goto error_return;
1382 }
1383
1384 /* Read this BFD's local symbols if we haven't done so already. */
1385 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1386 {
1387 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1388 if (isymbuf == NULL)
1389 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1390 symtab_hdr->sh_info, 0,
1391 NULL, NULL, NULL);
1392 if (isymbuf == NULL)
1393 goto error_return;
1394 }
1395
1396 /* Get the value of the symbol referred to by the reloc. */
1397 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1398 {
1399 /* A local symbol. */
1400 Elf_Internal_Sym *isym;
1401 asection *sym_sec;
1402
1403 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1404 if (isym->st_shndx == SHN_UNDEF)
1405 sym_sec = bfd_und_section_ptr;
1406 else if (isym->st_shndx == SHN_ABS)
1407 sym_sec = bfd_abs_section_ptr;
1408 else if (isym->st_shndx == SHN_COMMON)
1409 sym_sec = bfd_com_section_ptr;
1410 else
1411 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1412 symval = (isym->st_value
1413 + sym_sec->output_section->vma + sym_sec->output_offset);
1414 }
1415 else
1416 {
1417 unsigned long indx;
1418 struct elf_link_hash_entry *h;
1419
1420 /* An external symbol. */
1421 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1422 h = elf_sym_hashes (abfd)[indx];
1423 BFD_ASSERT (h != NULL);
1424
1425 if (h->root.type != bfd_link_hash_defined
1426 && h->root.type != bfd_link_hash_defweak)
1427 /* This appears to be a reference to an undefined
1428 symbol. Just ignore it--it will be caught by the
1429 regular reloc processing. */
1430 continue;
1431
1432 symval = (h->root.u.def.value
1433 + h->root.u.def.section->output_section->vma
1434 + h->root.u.def.section->output_offset);
1435 }
1436
1437 /* For simplicity of coding, we are going to modify the section
1438 contents, the section relocs, and the BFD symbol table. We
1439 must tell the rest of the code not to free up this
1440 information. It would be possible to instead create a table
1441 of changes which have to be made, as is done in coff-mips.c;
1442 that would be more work, but would require less memory when
1443 the linker is run. */
1444
1445 /* Check if we can remove an LDI instruction from the LDI32
1446 pseudo instruction if the upper 16 operand bits are zero. */
1447 if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1448 {
1449 bfd_vma value = symval + irel->r_addend;
1450
1451 if (debug_relax)
1452 printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1453
1454 if ((long) value >> 16 == 0)
1455 {
1456 unsigned long insn;
1457
1458 /* Note that we've changed the relocs, section contents. */
1459 elf_section_data (sec)->relocs = internal_relocs;
1460 elf_section_data (sec)->this_hdr.contents = contents;
1461 symtab_hdr->contents = (unsigned char *) isymbuf;
1462
1463 /* Make the second instruction load the 16-bit constant
1464 into the full 32-bit register. */
1465 insn = bfd_get_32 (abfd, contents + irel->r_offset + 4);
1466
1467 /* Old GAS and LD versions have a bug, where the two
1468 LDI instructions are swapped. Detect such object
1469 files and bail. */
1470 if (GET_INSN_FIELD (RDSEL, insn) != RSEL_15_0)
1471 {
1472 /* xgettext:c-format */
1473 _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
1474 abfd);
1475 goto error_return;
1476 }
1477
1478 SET_INSN_FIELD (RDSEL, insn, RSEL_31_0);
1479 bfd_put_32 (abfd, insn, contents + irel->r_offset + 4);
1480
1481 /* Delete the first LDI instruction. Note that there should
1482 be no relocations or symbols pointing to the second LDI
1483 instruction. */
1484 if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 4))
1485 goto error_return;
1486
1487 /* We're done with deletion of the first instruction.
1488 Set a regular LDI relocation for the second instruction
1489 we left to load the 16-bit value into the 32-bit
1490 register. */
1491 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1492 R_PRU_U16);
1493
1494 /* That will change things, so, we should relax again.
1495 Note that this is not required, and it may be slow. */
1496 *again = TRUE;
1497 }
1498 }
1499 }
1500
1501 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1502 {
1503 if (!link_info->keep_memory)
1504 free (isymbuf);
1505 else
1506 {
1507 /* Cache the symbols for elf_link_input_bfd. */
1508 symtab_hdr->contents = (unsigned char *) isymbuf;
1509 }
1510 }
1511
1512 if (contents != NULL
1513 && elf_section_data (sec)->this_hdr.contents != contents)
1514 {
1515 if (!link_info->keep_memory)
1516 free (contents);
1517 else
1518 {
1519 /* Cache the section contents for elf_link_input_bfd. */
1520 elf_section_data (sec)->this_hdr.contents = contents;
1521 }
1522 }
1523
1524 if (internal_relocs != NULL
1525 && elf_section_data (sec)->relocs != internal_relocs)
1526 free (internal_relocs);
1527
1528 return TRUE;
1529
1530 error_return:
1531 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1532 free (isymbuf);
1533 if (contents != NULL
1534 && elf_section_data (sec)->this_hdr.contents != contents)
1535 free (contents);
1536 if (internal_relocs != NULL
1537 && elf_section_data (sec)->relocs != internal_relocs)
1538 free (internal_relocs);
1539
1540 return FALSE;
1541 }
1542
1543 /* Free the derived linker hash table. */
1544 static void
1545 pru_elf32_link_hash_table_free (bfd *obfd)
1546 {
1547 _bfd_elf_link_hash_table_free (obfd);
1548 }
1549
1550 /* Implement bfd_elf32_bfd_link_hash_table_create. */
1551 static struct bfd_link_hash_table *
1552 pru_elf32_link_hash_table_create (bfd *abfd)
1553 {
1554 struct elf_link_hash_table *ret;
1555 bfd_size_type amt = sizeof (struct elf_link_hash_table);
1556
1557 ret = bfd_zmalloc (amt);
1558 if (ret == NULL)
1559 return NULL;
1560
1561 if (!_bfd_elf_link_hash_table_init (ret, abfd,
1562 link_hash_newfunc,
1563 sizeof (struct
1564 elf_link_hash_entry),
1565 PRU_ELF_DATA))
1566 {
1567 free (ret);
1568 return NULL;
1569 }
1570
1571 ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1572
1573 return &ret->root;
1574 }
1575
1576 #define ELF_ARCH bfd_arch_pru
1577 #define ELF_TARGET_ID PRU_ELF_DATA
1578 #define ELF_MACHINE_CODE EM_TI_PRU
1579
1580 #define ELF_MAXPAGESIZE 1
1581
1582 #define bfd_elf32_bfd_link_hash_table_create \
1583 pru_elf32_link_hash_table_create
1584
1585 /* Relocation table lookup macros. */
1586
1587 #define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup
1588 #define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup
1589
1590 #define elf_info_to_howto pru_elf32_info_to_howto
1591 #define elf_info_to_howto_rel NULL
1592
1593 /* elf backend functions. */
1594
1595 /* TI folks like to use a mix of REL and RELA relocations. See also
1596 the MSP430 and TI C6X backends. */
1597 #define elf_backend_may_use_rel_p 1
1598 #define elf_backend_may_use_rela_p 1
1599 #define elf_backend_default_use_rela_p 1
1600
1601 #define elf_backend_rela_normal 1
1602
1603 #define elf_backend_relocate_section pru_elf32_relocate_section
1604 #define bfd_elf32_bfd_relax_section pru_elf32_relax_section
1605
1606 #define TARGET_LITTLE_SYM pru_elf32_vec
1607 #define TARGET_LITTLE_NAME "elf32-pru"
1608
1609 #include "elf32-target.h"
1610