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