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