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