1 /* Adapteva epiphany specific support for 32-bit ELF 2 Copyright (C) 2000-2019 Free Software Foundation, Inc. 3 Contributed by Embecosm on behalf of Adapteva, Inc. 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "bfd.h" 24 #include "libbfd.h" 25 #include "elf-bfd.h" 26 #include "elf/epiphany.h" 27 #include "libiberty.h" 28 29 /* Struct used to pass miscellaneous paramaters which 30 helps to avoid overly long parameter lists. */ 31 struct misc 32 { 33 Elf_Internal_Shdr * symtab_hdr; 34 Elf_Internal_Rela * irelbase; 35 bfd_byte * contents; 36 Elf_Internal_Sym * isymbuf; 37 }; 38 39 struct epiphany_opcode 40 { 41 unsigned short opcode; 42 unsigned short mask; 43 }; 44 45 static bfd_boolean epiphany_relaxed = FALSE; 46 47 /* Relocation tables. */ 48 static reloc_howto_type epiphany_elf_howto_table [] = 49 { 50 #define AHOW(t,rs,s,bs,pr,bp,co,name,sm,dm) \ 51 HOWTO(t, /* type */ \ 52 rs, /* rightshift */ \ 53 s, /* size (0 = byte, 1 = short, 2 = long) */ \ 54 bs, /* bitsize */ \ 55 pr, /* pc_relative */ \ 56 bp, /* bitpos */ \ 57 co, /* complain_on_overflow */ \ 58 bfd_elf_generic_reloc,/* special_function */ \ 59 name, /* name */ \ 60 FALSE, /* partial_inplace */ \ 61 sm, /* src_mask */ \ 62 dm, /* dst_mask */ \ 63 pr) /* pcrel_offset */ 64 65 /* This reloc does nothing. */ 66 AHOW (R_EPIPHANY_NONE, 0, 3,0, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_NONE", 0, 0), 67 68 /* 8 bit absolute (not likely) */ 69 AHOW (R_EPIPHANY_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_8", 0x000000ff, 0x000000ff), 70 /* 16 bit absolute */ 71 AHOW (R_EPIPHANY_16, 0, 1,16, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_16", 0x0000ffff, 0x00ff1fe0), 72 /* A 32 bit absolute relocation. */ 73 AHOW (R_EPIPHANY_32, 0, 2,32, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_32", 0xffffffff, 0xffffffff), 74 75 /* 8 bit relative relocation */ 76 HOWTO ( R_EPIPHANY_8_PCREL, 0, 0, 8, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE), 77 /* 16 bit relative relocation */ 78 HOWTO ( R_EPIPHANY_16_PCREL, 0, 1, 16, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE), 79 /* 32 bit relative relocation */ 80 HOWTO ( R_EPIPHANY_32_PCREL, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE), 81 82 /* 8 bit pc-relative relocation */ 83 AHOW (R_EPIPHANY_SIMM8, 1, 0, 8, TRUE, 8, complain_overflow_signed, "R_EPIPHANY_SIMM8", 0x000000ff, 0x0000ff00), 84 /* 24 bit pc-relative relocation */ 85 AHOW (R_EPIPHANY_SIMM24, 1, 2,24, TRUE, 8, complain_overflow_signed, "R_EPIPHANY_SIMM24", 0x00ffffff, 0xffffff00), 86 87 /* %HIGH(EA) */ 88 AHOW (R_EPIPHANY_HIGH, 0, 2,16, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_HIGH", 0x0ff01fe0, 0x0ff01fe0), 89 90 /* %LOW(EA) */ 91 AHOW (R_EPIPHANY_LOW, 0, 2,16, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_LOW", 0x0ff01fe0, 0x0ff01fe0), 92 93 /* simm11 */ 94 AHOW (R_EPIPHANY_SIMM11, 0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_SIMM11", 0x00ff0380, 0x00ff0380), 95 /* imm12 - sign-magnitude */ 96 AHOW (R_EPIPHANY_IMM11, 0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_IMM12", 0x00ff0380, 0x00ff0380), 97 /* imm8 */ 98 AHOW (R_EPIPHANY_IMM8, 0, 1, 8, FALSE, 8, complain_overflow_signed, "R_EPIPHANY_IMM8", 0x0000ff00, 0x0000ff00) 99 100 101 }; 102 #undef AHOW 103 104 /* Map BFD reloc types to EPIPHANY ELF reloc types. */ 105 106 static reloc_howto_type * 107 epiphany_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, 108 bfd_reloc_code_real_type code) 109 { 110 /* Note that the epiphany_elf_howto_table is indxed by the R_ 111 constants. Thus, the order that the howto records appear in the 112 table *must* match the order of the relocation types defined in 113 include/elf/epiphany.h. */ 114 115 switch (code) 116 { 117 case BFD_RELOC_NONE: 118 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_NONE]; 119 120 case BFD_RELOC_EPIPHANY_SIMM8: 121 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM8]; 122 case BFD_RELOC_EPIPHANY_SIMM24: 123 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM24]; 124 125 case BFD_RELOC_8_PCREL: 126 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8_PCREL]; 127 case BFD_RELOC_16_PCREL: 128 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16_PCREL]; 129 case BFD_RELOC_32_PCREL: 130 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32_PCREL]; 131 132 case BFD_RELOC_8: 133 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8]; 134 case BFD_RELOC_16: 135 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16]; 136 case BFD_RELOC_32: 137 return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32]; 138 139 case BFD_RELOC_EPIPHANY_HIGH: 140 return & epiphany_elf_howto_table[ (int) R_EPIPHANY_HIGH]; 141 case BFD_RELOC_EPIPHANY_LOW: 142 return & epiphany_elf_howto_table[ (int) R_EPIPHANY_LOW]; 143 144 case BFD_RELOC_EPIPHANY_SIMM11: 145 return & epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM11]; 146 case BFD_RELOC_EPIPHANY_IMM11: 147 return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM11]; 148 149 case BFD_RELOC_EPIPHANY_IMM8: 150 return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM8]; 151 152 default: 153 /* Pacify gcc -Wall. */ 154 return NULL; 155 } 156 return NULL; 157 } 158 159 static reloc_howto_type * 160 epiphany_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 161 { 162 unsigned int i; 163 164 for (i = 0; i < ARRAY_SIZE (epiphany_elf_howto_table); i++) 165 if (epiphany_elf_howto_table[i].name != NULL 166 && strcasecmp (epiphany_elf_howto_table[i].name, r_name) == 0) 167 return &epiphany_elf_howto_table[i]; 168 169 return NULL; 170 } 171 172 #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000) 173 #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset) 174 175 /* This function handles relaxing for the epiphany. 176 Dummy placeholder for future optimizations. */ 177 178 static bfd_boolean 179 epiphany_elf_relax_section (bfd *abfd, asection *sec, 180 struct bfd_link_info *link_info, 181 bfd_boolean *again) 182 { 183 Elf_Internal_Shdr *symtab_hdr; 184 Elf_Internal_Rela *internal_relocs; 185 bfd_byte *contents = NULL; 186 Elf_Internal_Sym *isymbuf = NULL; 187 static asection * first_section = NULL; 188 static unsigned long search_addr; 189 static unsigned long page_start = 0; 190 static unsigned long page_end = 0; 191 static unsigned int pass = 0; 192 static bfd_boolean new_pass = FALSE; 193 static bfd_boolean changed = FALSE; 194 struct misc misc ATTRIBUTE_UNUSED; 195 asection *stab; 196 197 /* Assume nothing changes. */ 198 *again = FALSE; 199 200 if (first_section == NULL) 201 { 202 epiphany_relaxed = TRUE; 203 first_section = sec; 204 } 205 206 if (first_section == sec) 207 { 208 pass++; 209 new_pass = TRUE; 210 } 211 212 /* We don't have to do anything for a relocatable link, 213 if this section does not have relocs, or if this is 214 not a code section. */ 215 if (bfd_link_relocatable (link_info) 216 || (sec->flags & SEC_RELOC) == 0 217 || sec->reloc_count == 0 218 || (sec->flags & SEC_CODE) == 0) 219 return TRUE; 220 221 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 222 223 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, 224 link_info->keep_memory); 225 if (internal_relocs == NULL) 226 goto error_return; 227 228 /* Make sure the stac.rela stuff gets read in. */ 229 stab = bfd_get_section_by_name (abfd, ".stab"); 230 231 if (stab) 232 { 233 /* So stab does exits. */ 234 Elf_Internal_Rela * irelbase ATTRIBUTE_UNUSED; 235 236 irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL, 237 link_info->keep_memory); 238 } 239 240 /* Get section contents cached copy if it exists. */ 241 if (contents == NULL) 242 { 243 /* Get cached copy if it exists. */ 244 if (elf_section_data (sec)->this_hdr.contents != NULL) 245 contents = elf_section_data (sec)->this_hdr.contents; 246 else 247 { 248 /* Go get them off disk. */ 249 if (!bfd_malloc_and_get_section (abfd, sec, &contents)) 250 goto error_return; 251 } 252 } 253 254 /* Read this BFD's symbols cached copy if it exists. */ 255 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 256 { 257 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 258 if (isymbuf == NULL) 259 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 260 symtab_hdr->sh_info, 0, 261 NULL, NULL, NULL); 262 if (isymbuf == NULL) 263 goto error_return; 264 } 265 266 misc.symtab_hdr = symtab_hdr; 267 misc.isymbuf = isymbuf; 268 misc.irelbase = internal_relocs; 269 misc.contents = contents; 270 271 /* This is where all the relaxation actually get done. */ 272 if ((pass == 1) || (new_pass && !changed)) 273 { 274 /* On the first pass we simply search for the lowest page that 275 we havn't relaxed yet. Note that the pass count is reset 276 each time a page is complete in order to move on to the next page. 277 If we can't find any more pages then we are finished. */ 278 if (new_pass) 279 { 280 pass = 1; 281 new_pass = FALSE; 282 changed = TRUE; /* Pre-initialize to break out of pass 1. */ 283 search_addr = 0xFFFFFFFF; 284 } 285 286 if ((BASEADDR (sec) + sec->size < search_addr) 287 && (BASEADDR (sec) + sec->size > page_end)) 288 { 289 if (BASEADDR (sec) <= page_end) 290 search_addr = page_end + 1; 291 else 292 search_addr = BASEADDR (sec); 293 294 /* Found a page => more work to do. */ 295 *again = TRUE; 296 } 297 } 298 else 299 { 300 if (new_pass) 301 { 302 new_pass = FALSE; 303 changed = FALSE; 304 page_start = PAGENO (search_addr); 305 page_end = page_start | 0x00003FFF; 306 } 307 308 /* Only process sections in range. */ 309 if ((BASEADDR (sec) + sec->size >= page_start) 310 && (BASEADDR (sec) <= page_end)) 311 { 312 #if 0 313 if (!epiphany_elf_relax_section_page (abfd, sec, &changed, &misc, 314 page_start, page_end)) 315 #endif 316 return FALSE; 317 } 318 *again = TRUE; 319 } 320 321 /* Perform some house keeping after relaxing the section. */ 322 323 if (isymbuf != NULL 324 && symtab_hdr->contents != (unsigned char *) isymbuf) 325 { 326 if (! link_info->keep_memory) 327 free (isymbuf); 328 else 329 symtab_hdr->contents = (unsigned char *) isymbuf; 330 } 331 332 if (contents != NULL 333 && elf_section_data (sec)->this_hdr.contents != contents) 334 { 335 if (! link_info->keep_memory) 336 free (contents); 337 else 338 { 339 /* Cache the section contents for elf_link_input_bfd. */ 340 elf_section_data (sec)->this_hdr.contents = contents; 341 } 342 } 343 344 if (internal_relocs != NULL 345 && elf_section_data (sec)->relocs != internal_relocs) 346 free (internal_relocs); 347 348 return TRUE; 349 350 error_return: 351 if (isymbuf != NULL 352 && symtab_hdr->contents != (unsigned char *) isymbuf) 353 free (isymbuf); 354 if (contents != NULL 355 && elf_section_data (sec)->this_hdr.contents != contents) 356 free (contents); 357 if (internal_relocs != NULL 358 && elf_section_data (sec)->relocs != internal_relocs) 359 free (internal_relocs); 360 return FALSE; 361 } 362 363 /* Set the howto pointer for a EPIPHANY ELF reloc. */ 364 365 static bfd_boolean 366 epiphany_info_to_howto_rela (bfd * abfd, 367 arelent * cache_ptr, 368 Elf_Internal_Rela * dst) 369 { 370 unsigned int r_type; 371 372 r_type = ELF32_R_TYPE (dst->r_info); 373 if (r_type >= (unsigned int) R_EPIPHANY_max) 374 { 375 /* xgettext:c-format */ 376 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 377 abfd, r_type); 378 bfd_set_error (bfd_error_bad_value); 379 return FALSE; 380 } 381 cache_ptr->howto = & epiphany_elf_howto_table [r_type]; 382 return TRUE; 383 } 384 385 /* Perform a single relocation. 386 By default we use the standard BFD routines. */ 387 388 static bfd_reloc_status_type 389 epiphany_final_link_relocate (reloc_howto_type * howto, 390 bfd * input_bfd, 391 asection * input_section, 392 bfd_byte * contents, 393 Elf_Internal_Rela * rel, 394 bfd_vma relocation) 395 { 396 switch (howto->type) 397 { 398 /* Handle 16 bit immediates. */ 399 case R_EPIPHANY_HIGH: 400 relocation += rel->r_addend; 401 relocation >>= 16; 402 goto common; 403 404 case R_EPIPHANY_LOW: 405 relocation += rel->r_addend; 406 common: 407 relocation = ((relocation & 0xff00L) << 12) 408 | ((relocation & 0x00ffL) << 5); 409 /* Sanity check the address. */ 410 if (rel->r_offset > bfd_get_section_limit (input_bfd, input_section)) 411 return bfd_reloc_outofrange; 412 413 return _bfd_relocate_contents (howto, input_bfd, relocation, 414 contents + rel->r_offset); 415 416 case R_EPIPHANY_SIMM11: 417 relocation += rel->r_addend; 418 /* Check signed overflow. */ 419 if ((int)relocation > 1023 || (int)relocation < -1024) 420 return bfd_reloc_outofrange; 421 goto disp11; 422 423 case R_EPIPHANY_IMM11: 424 relocation += rel->r_addend; 425 if ((unsigned int) relocation > 0x7ff) 426 return bfd_reloc_outofrange; 427 /* Fall through. */ 428 disp11: 429 relocation = (((relocation & 7) << 5) 430 | ((relocation & 0x7f8 ) << 13)); 431 return _bfd_relocate_contents (howto, input_bfd, relocation, 432 contents + rel->r_offset); 433 434 /* Pass others through. */ 435 default: 436 break; 437 } 438 439 /* Only install relocation if above tests did not disqualify it. */ 440 return _bfd_final_link_relocate (howto, input_bfd, input_section, 441 contents, rel->r_offset, 442 relocation, rel->r_addend); 443 } 444 445 /* Relocate an EPIPHANY ELF section. 446 447 The RELOCATE_SECTION function is called by the new ELF backend linker 448 to handle the relocations for a section. 449 450 The relocs are always passed as Rela structures; if the section 451 actually uses Rel structures, the r_addend field will always be 452 zero. 453 454 This function is responsible for adjusting the section contents as 455 necessary, and (if using Rela relocs and generating a relocatable 456 output file) adjusting the reloc addend as necessary. 457 458 This function does not have to worry about setting the reloc 459 address or the reloc symbol index. 460 461 LOCAL_SYMS is a pointer to the swapped in local symbols. 462 463 LOCAL_SECTIONS is an array giving the section in the input file 464 corresponding to the st_shndx field of each local symbol. 465 466 The global hash table entry for the global symbols can be found 467 via elf_sym_hashes (input_bfd). 468 469 When generating relocatable output, this function must handle 470 STB_LOCAL/STT_SECTION symbols specially. The output symbol is 471 going to be the section symbol corresponding to the output 472 section, which means that the addend must be adjusted 473 accordingly. */ 474 475 static bfd_boolean 476 epiphany_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, 477 struct bfd_link_info *info, 478 bfd *input_bfd, 479 asection *input_section, 480 bfd_byte *contents, 481 Elf_Internal_Rela *relocs, 482 Elf_Internal_Sym *local_syms, 483 asection **local_sections) 484 { 485 Elf_Internal_Shdr *symtab_hdr; 486 struct elf_link_hash_entry **sym_hashes; 487 Elf_Internal_Rela *rel; 488 Elf_Internal_Rela *relend; 489 490 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 491 sym_hashes = elf_sym_hashes (input_bfd); 492 relend = relocs + input_section->reloc_count; 493 494 for (rel = relocs; rel < relend; rel ++) 495 { 496 reloc_howto_type * howto; 497 unsigned long r_symndx; 498 Elf_Internal_Sym * sym; 499 asection * sec; 500 struct elf_link_hash_entry * h; 501 bfd_vma relocation; 502 bfd_reloc_status_type r; 503 const char * name = NULL; 504 int r_type ATTRIBUTE_UNUSED; 505 506 r_type = ELF32_R_TYPE (rel->r_info); 507 r_symndx = ELF32_R_SYM (rel->r_info); 508 howto = epiphany_elf_howto_table + ELF32_R_TYPE (rel->r_info); 509 h = NULL; 510 sym = NULL; 511 sec = NULL; 512 513 if (r_symndx < symtab_hdr->sh_info) 514 { 515 sym = local_syms + r_symndx; 516 sec = local_sections [r_symndx]; 517 relocation = BASEADDR (sec) + sym->st_value; 518 519 name = bfd_elf_string_from_elf_section 520 (input_bfd, symtab_hdr->sh_link, sym->st_name); 521 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; 522 } 523 else 524 { 525 bfd_boolean warned ATTRIBUTE_UNUSED; 526 bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED; 527 bfd_boolean ignored ATTRIBUTE_UNUSED; 528 529 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 530 r_symndx, symtab_hdr, sym_hashes, 531 h, sec, relocation, 532 unresolved_reloc, warned, ignored); 533 534 name = h->root.root.string; 535 } 536 537 if (sec != NULL && discarded_section (sec)) 538 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 539 rel, 1, relend, howto, 0, contents); 540 541 if (bfd_link_relocatable (info)) 542 continue; 543 544 /* Finally, the sole EPIPHANY-specific part. */ 545 r = epiphany_final_link_relocate (howto, input_bfd, input_section, 546 contents, rel, relocation); 547 548 if (r != bfd_reloc_ok) 549 { 550 const char * msg = NULL; 551 552 switch (r) 553 { 554 case bfd_reloc_overflow: 555 (*info->callbacks->reloc_overflow) 556 (info, (h ? &h->root : NULL), name, howto->name, 557 (bfd_vma) 0, input_bfd, input_section, rel->r_offset); 558 break; 559 560 case bfd_reloc_undefined: 561 (*info->callbacks->undefined_symbol) 562 (info, name, input_bfd, input_section, rel->r_offset, TRUE); 563 break; 564 565 case bfd_reloc_outofrange: 566 msg = _("internal error: out of range error"); 567 break; 568 569 /* This is how epiphany_final_link_relocate tells us of a 570 non-kosher reference between insn & data address spaces. */ 571 case bfd_reloc_notsupported: 572 if (sym != NULL) /* Only if it's not an unresolved symbol. */ 573 msg = _("unsupported relocation between data/insn address spaces"); 574 break; 575 576 case bfd_reloc_dangerous: 577 msg = _("internal error: dangerous relocation"); 578 break; 579 580 default: 581 msg = _("internal error: unknown error"); 582 break; 583 } 584 585 if (msg) 586 (*info->callbacks->warning) (info, msg, name, input_bfd, 587 input_section, rel->r_offset); 588 } 589 } 590 591 return TRUE; 592 } 593 594 /* We only have a little-endian target. */ 595 #define TARGET_LITTLE_SYM epiphany_elf32_vec 596 #define TARGET_LITTLE_NAME "elf32-epiphany" 597 598 #define ELF_ARCH bfd_arch_epiphany 599 #define ELF_MACHINE_CODE EM_ADAPTEVA_EPIPHANY 600 601 #define ELF_MAXPAGESIZE 0x8000 /* No pages on the EPIPHANY. */ 602 603 #define elf_info_to_howto_rel NULL 604 #define elf_info_to_howto epiphany_info_to_howto_rela 605 606 #define elf_backend_can_gc_sections 1 607 #define elf_backend_rela_normal 1 608 #define elf_backend_relocate_section epiphany_elf_relocate_section 609 610 #define elf_symbol_leading_char '_' 611 #define bfd_elf32_bfd_reloc_type_lookup epiphany_reloc_type_lookup 612 #define bfd_elf32_bfd_reloc_name_lookup epiphany_reloc_name_lookup 613 #define bfd_elf32_bfd_relax_section epiphany_elf_relax_section 614 615 #include "elf32-target.h" 616