1/* BFD back-end for National Semiconductor's CR16 ELF 2 Copyright 2007 Free Software Foundation, Inc. 3 Written by M R Swami Reddy. 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 2 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 Foundation, 19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20 21#include "sysdep.h" 22#include "bfd.h" 23#include "bfdlink.h" 24#include "libbfd.h" 25#include "libiberty.h" 26#include "elf-bfd.h" 27#include "elf/cr16.h" 28 29/* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type. */ 30 31struct cr16_reloc_map 32{ 33 bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum. */ 34 unsigned short cr16_reloc_type; /* CR16 relocation type. */ 35}; 36 37static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] = 38{ 39 {BFD_RELOC_NONE, R_CR16_NONE}, 40 {BFD_RELOC_CR16_NUM8, R_CR16_NUM8}, 41 {BFD_RELOC_CR16_NUM16, R_CR16_NUM16}, 42 {BFD_RELOC_CR16_NUM32, R_CR16_NUM32}, 43 {BFD_RELOC_CR16_NUM32a, R_CR16_NUM32a}, 44 {BFD_RELOC_CR16_REGREL4, R_CR16_REGREL4}, 45 {BFD_RELOC_CR16_REGREL4a, R_CR16_REGREL4a}, 46 {BFD_RELOC_CR16_REGREL14, R_CR16_REGREL14}, 47 {BFD_RELOC_CR16_REGREL14a, R_CR16_REGREL14a}, 48 {BFD_RELOC_CR16_REGREL16, R_CR16_REGREL16}, 49 {BFD_RELOC_CR16_REGREL20, R_CR16_REGREL20}, 50 {BFD_RELOC_CR16_REGREL20a, R_CR16_REGREL20a}, 51 {BFD_RELOC_CR16_ABS20, R_CR16_ABS20}, 52 {BFD_RELOC_CR16_ABS24, R_CR16_ABS24}, 53 {BFD_RELOC_CR16_IMM4, R_CR16_IMM4}, 54 {BFD_RELOC_CR16_IMM8, R_CR16_IMM8}, 55 {BFD_RELOC_CR16_IMM16, R_CR16_IMM16}, 56 {BFD_RELOC_CR16_IMM20, R_CR16_IMM20}, 57 {BFD_RELOC_CR16_IMM24, R_CR16_IMM24}, 58 {BFD_RELOC_CR16_IMM32, R_CR16_IMM32}, 59 {BFD_RELOC_CR16_IMM32a, R_CR16_IMM32a}, 60 {BFD_RELOC_CR16_DISP4, R_CR16_DISP4}, 61 {BFD_RELOC_CR16_DISP8, R_CR16_DISP8}, 62 {BFD_RELOC_CR16_DISP16, R_CR16_DISP16}, 63 {BFD_RELOC_CR16_DISP24, R_CR16_DISP24}, 64 {BFD_RELOC_CR16_DISP24a, R_CR16_DISP24a} 65}; 66 67static reloc_howto_type cr16_elf_howto_table[] = 68{ 69 HOWTO (R_CR16_NONE, /* type */ 70 0, /* rightshift */ 71 2, /* size */ 72 32, /* bitsize */ 73 FALSE, /* pc_relative */ 74 0, /* bitpos */ 75 complain_overflow_dont, /* complain_on_overflow */ 76 bfd_elf_generic_reloc, /* special_function */ 77 "R_CR16_NONE", /* name */ 78 FALSE, /* partial_inplace */ 79 0, /* src_mask */ 80 0, /* dst_mask */ 81 FALSE), /* pcrel_offset */ 82 83 HOWTO (R_CR16_NUM8, /* type */ 84 0, /* rightshift */ 85 0, /* size */ 86 8, /* bitsize */ 87 FALSE, /* pc_relative */ 88 0, /* bitpos */ 89 complain_overflow_bitfield,/* complain_on_overflow */ 90 bfd_elf_generic_reloc, /* special_function */ 91 "R_CR16_NUM8", /* name */ 92 FALSE, /* partial_inplace */ 93 0xff, /* src_mask */ 94 0xff, /* dst_mask */ 95 FALSE), /* pcrel_offset */ 96 97 HOWTO (R_CR16_NUM16, /* type */ 98 0, /* rightshift */ 99 1, /* size */ 100 16, /* bitsize */ 101 FALSE, /* pc_relative */ 102 0, /* bitpos */ 103 complain_overflow_bitfield,/* complain_on_overflow */ 104 bfd_elf_generic_reloc, /* special_function */ 105 "R_CR16_NUM16", /* name */ 106 FALSE, /* partial_inplace */ 107 0xffff, /* src_mask */ 108 0xffff, /* dst_mask */ 109 FALSE), /* pcrel_offset */ 110 111 HOWTO (R_CR16_NUM32, /* type */ 112 0, /* rightshift */ 113 2, /* size */ 114 32, /* bitsize */ 115 FALSE, /* pc_relative */ 116 0, /* bitpos */ 117 complain_overflow_bitfield,/* complain_on_overflow */ 118 bfd_elf_generic_reloc, /* special_function */ 119 "R_CR16_NUM32", /* name */ 120 FALSE, /* partial_inplace */ 121 0xffffffff, /* src_mask */ 122 0xffffffff, /* dst_mask */ 123 FALSE), /* pcrel_offset */ 124 125 HOWTO (R_CR16_NUM32a, /* type */ 126 1, /* rightshift */ 127 2, /* size */ 128 32, /* bitsize */ 129 FALSE, /* pc_relative */ 130 0, /* bitpos */ 131 complain_overflow_bitfield,/* complain_on_overflow */ 132 bfd_elf_generic_reloc, /* special_function */ 133 "R_CR16_NUM32a", /* name */ 134 FALSE, /* partial_inplace */ 135 0xffffffff, /* src_mask */ 136 0xffffffff, /* dst_mask */ 137 FALSE), /* pcrel_offset */ 138 139 HOWTO (R_CR16_REGREL4, /* type */ 140 0, /* rightshift */ 141 0, /* size */ 142 4, /* bitsize */ 143 FALSE, /* pc_relative */ 144 0, /* bitpos */ 145 complain_overflow_bitfield,/* complain_on_overflow */ 146 bfd_elf_generic_reloc, /* special_function */ 147 "R_CR16_REGREL4", /* name */ 148 FALSE, /* partial_inplace */ 149 0xf, /* src_mask */ 150 0xf, /* dst_mask */ 151 FALSE), /* pcrel_offset */ 152 153 HOWTO (R_CR16_REGREL4a, /* type */ 154 0, /* rightshift */ 155 0, /* size */ 156 4, /* bitsize */ 157 FALSE, /* pc_relative */ 158 0, /* bitpos */ 159 complain_overflow_bitfield,/* complain_on_overflow */ 160 bfd_elf_generic_reloc, /* special_function */ 161 "R_CR16_REGREL4a", /* name */ 162 FALSE, /* partial_inplace */ 163 0xf, /* src_mask */ 164 0xf, /* dst_mask */ 165 FALSE), /* pcrel_offset */ 166 167 HOWTO (R_CR16_REGREL14, /* type */ 168 0, /* rightshift */ 169 1, /* size */ 170 14, /* bitsize */ 171 FALSE, /* pc_relative */ 172 0, /* bitpos */ 173 complain_overflow_bitfield,/* complain_on_overflow */ 174 bfd_elf_generic_reloc, /* special_function */ 175 "R_CR16_REGREL14", /* name */ 176 FALSE, /* partial_inplace */ 177 0x3fff, /* src_mask */ 178 0x3fff, /* dst_mask */ 179 FALSE), /* pcrel_offset */ 180 181 HOWTO (R_CR16_REGREL14a, /* type */ 182 0, /* rightshift */ 183 1, /* size */ 184 14, /* bitsize */ 185 FALSE, /* pc_relative */ 186 0, /* bitpos */ 187 complain_overflow_bitfield,/* complain_on_overflow */ 188 bfd_elf_generic_reloc, /* special_function */ 189 "R_CR16_REGREL14a", /* name */ 190 FALSE, /* partial_inplace */ 191 0x3fff, /* src_mask */ 192 0x3fff, /* dst_mask */ 193 FALSE), /* pcrel_offset */ 194 195 HOWTO (R_CR16_REGREL16, /* type */ 196 0, /* rightshift */ 197 1, /* size */ 198 16, /* bitsize */ 199 FALSE, /* pc_relative */ 200 0, /* bitpos */ 201 complain_overflow_bitfield,/* complain_on_overflow */ 202 bfd_elf_generic_reloc, /* special_function */ 203 "R_CR16_REGREL16", /* name */ 204 FALSE, /* partial_inplace */ 205 0xffff, /* src_mask */ 206 0xffff, /* dst_mask */ 207 FALSE), /* pcrel_offset */ 208 209 HOWTO (R_CR16_REGREL20, /* type */ 210 0, /* rightshift */ 211 2, /* size */ 212 20, /* bitsize */ 213 FALSE, /* pc_relative */ 214 0, /* bitpos */ 215 complain_overflow_bitfield,/* complain_on_overflow */ 216 bfd_elf_generic_reloc, /* special_function */ 217 "R_CR16_REGREL20", /* name */ 218 FALSE, /* partial_inplace */ 219 0xfffff, /* src_mask */ 220 0xfffff, /* dst_mask */ 221 FALSE), /* pcrel_offset */ 222 223 HOWTO (R_CR16_REGREL20a, /* type */ 224 0, /* rightshift */ 225 2, /* size */ 226 20, /* bitsize */ 227 FALSE, /* pc_relative */ 228 0, /* bitpos */ 229 complain_overflow_bitfield,/* complain_on_overflow */ 230 bfd_elf_generic_reloc, /* special_function */ 231 "R_CR16_REGREL20a", /* name */ 232 FALSE, /* partial_inplace */ 233 0xfffff, /* src_mask */ 234 0xfffff, /* dst_mask */ 235 FALSE), /* pcrel_offset */ 236 237 HOWTO (R_CR16_ABS20, /* type */ 238 0, /* rightshift */ 239 2, /* size */ 240 20, /* bitsize */ 241 FALSE, /* pc_relative */ 242 0, /* bitpos */ 243 complain_overflow_bitfield,/* complain_on_overflow */ 244 bfd_elf_generic_reloc, /* special_function */ 245 "R_CR16_ABS20", /* name */ 246 FALSE, /* partial_inplace */ 247 0xfffff, /* src_mask */ 248 0xfffff, /* dst_mask */ 249 FALSE), /* pcrel_offset */ 250 251 HOWTO (R_CR16_ABS24, /* type */ 252 0, /* rightshift */ 253 2, /* size */ 254 24, /* bitsize */ 255 FALSE, /* pc_relative */ 256 0, /* bitpos */ 257 complain_overflow_bitfield,/* complain_on_overflow */ 258 bfd_elf_generic_reloc, /* special_function */ 259 "R_CR16_ABS24", /* name */ 260 FALSE, /* partial_inplace */ 261 0xffffff, /* src_mask */ 262 0xffffff, /* dst_mask */ 263 FALSE), /* pcrel_offset */ 264 265 HOWTO (R_CR16_IMM4, /* type */ 266 0, /* rightshift */ 267 0, /* size */ 268 4, /* bitsize */ 269 FALSE, /* pc_relative */ 270 0, /* bitpos */ 271 complain_overflow_bitfield,/* complain_on_overflow */ 272 bfd_elf_generic_reloc, /* special_function */ 273 "R_CR16_IMM4", /* name */ 274 FALSE, /* partial_inplace */ 275 0xf, /* src_mask */ 276 0xf, /* dst_mask */ 277 FALSE), /* pcrel_offset */ 278 279 HOWTO (R_CR16_IMM8, /* type */ 280 0, /* rightshift */ 281 0, /* size */ 282 8, /* bitsize */ 283 FALSE, /* pc_relative */ 284 0, /* bitpos */ 285 complain_overflow_bitfield,/* complain_on_overflow */ 286 bfd_elf_generic_reloc, /* special_function */ 287 "R_CR16_IMM8", /* name */ 288 FALSE, /* partial_inplace */ 289 0xff, /* src_mask */ 290 0xff, /* dst_mask */ 291 FALSE), /* pcrel_offset */ 292 293 HOWTO (R_CR16_IMM16, /* type */ 294 0, /* rightshift */ 295 1, /* size */ 296 16, /* bitsize */ 297 FALSE, /* pc_relative */ 298 0, /* bitpos */ 299 complain_overflow_bitfield,/* complain_on_overflow */ 300 bfd_elf_generic_reloc, /* special_function */ 301 "R_CR16_IMM16", /* name */ 302 FALSE, /* partial_inplace */ 303 0xffff, /* src_mask */ 304 0xffff, /* dst_mask */ 305 FALSE), /* pcrel_offset */ 306 307 HOWTO (R_CR16_IMM20, /* type */ 308 0, /* rightshift */ 309 2, /* size */ 310 20, /* bitsize */ 311 FALSE, /* pc_relative */ 312 0, /* bitpos */ 313 complain_overflow_bitfield,/* complain_on_overflow */ 314 bfd_elf_generic_reloc, /* special_function */ 315 "R_CR16_IMM20", /* name */ 316 FALSE, /* partial_inplace */ 317 0xfffff, /* src_mask */ 318 0xfffff, /* dst_mask */ 319 FALSE), /* pcrel_offset */ 320 321 HOWTO (R_CR16_IMM24, /* type */ 322 0, /* rightshift */ 323 2, /* size */ 324 24, /* bitsize */ 325 FALSE, /* pc_relative */ 326 0, /* bitpos */ 327 complain_overflow_bitfield,/* complain_on_overflow */ 328 bfd_elf_generic_reloc, /* special_function */ 329 "R_CR16_IMM24", /* name */ 330 FALSE, /* partial_inplace */ 331 0xffffff, /* src_mask */ 332 0xffffff, /* dst_mask */ 333 FALSE), /* pcrel_offset */ 334 335 HOWTO (R_CR16_IMM32, /* type */ 336 0, /* rightshift */ 337 2, /* size */ 338 32, /* bitsize */ 339 FALSE, /* pc_relative */ 340 0, /* bitpos */ 341 complain_overflow_bitfield,/* complain_on_overflow */ 342 bfd_elf_generic_reloc, /* special_function */ 343 "R_CR16_IMM32", /* name */ 344 FALSE, /* partial_inplace */ 345 0xffffffff, /* src_mask */ 346 0xffffffff, /* dst_mask */ 347 FALSE), /* pcrel_offset */ 348 349 HOWTO (R_CR16_IMM32a, /* type */ 350 1, /* rightshift */ 351 2, /* size */ 352 32, /* bitsize */ 353 FALSE, /* pc_relative */ 354 0, /* bitpos */ 355 complain_overflow_bitfield,/* complain_on_overflow */ 356 bfd_elf_generic_reloc, /* special_function */ 357 "R_CR16_IMM32a", /* name */ 358 FALSE, /* partial_inplace */ 359 0xffffffff, /* src_mask */ 360 0xffffffff, /* dst_mask */ 361 FALSE), /* pcrel_offset */ 362 363 HOWTO (R_CR16_DISP4, /* type */ 364 1, /* rightshift */ 365 0, /* size (0 = byte, 1 = short, 2 = long) */ 366 4, /* bitsize */ 367 TRUE, /* pc_relative */ 368 0, /* bitpos */ 369 complain_overflow_unsigned, /* complain_on_overflow */ 370 bfd_elf_generic_reloc, /* special_function */ 371 "R_CR16_DISP4", /* name */ 372 FALSE, /* partial_inplace */ 373 0xf, /* src_mask */ 374 0xf, /* dst_mask */ 375 FALSE), /* pcrel_offset */ 376 377 HOWTO (R_CR16_DISP8, /* type */ 378 1, /* rightshift */ 379 0, /* size (0 = byte, 1 = short, 2 = long) */ 380 8, /* bitsize */ 381 TRUE, /* pc_relative */ 382 0, /* bitpos */ 383 complain_overflow_unsigned, /* complain_on_overflow */ 384 bfd_elf_generic_reloc, /* special_function */ 385 "R_CR16_DISP8", /* name */ 386 FALSE, /* partial_inplace */ 387 0x1ff, /* src_mask */ 388 0x1ff, /* dst_mask */ 389 FALSE), /* pcrel_offset */ 390 391 HOWTO (R_CR16_DISP16, /* type */ 392 0, /* rightshift REVIITS: To sync with WinIDEA*/ 393 1, /* size (0 = byte, 1 = short, 2 = long) */ 394 16, /* bitsize */ 395 TRUE, /* pc_relative */ 396 0, /* bitpos */ 397 complain_overflow_unsigned, /* complain_on_overflow */ 398 bfd_elf_generic_reloc, /* special_function */ 399 "R_CR16_DISP16", /* name */ 400 FALSE, /* partial_inplace */ 401 0x1ffff, /* src_mask */ 402 0x1ffff, /* dst_mask */ 403 FALSE), /* pcrel_offset */ 404 /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc 405 but its not done, to sync with WinIDEA and CR16 4.1 tools */ 406 HOWTO (R_CR16_DISP24, /* type */ 407 0, /* rightshift */ 408 2, /* size (0 = byte, 1 = short, 2 = long) */ 409 24, /* bitsize */ 410 TRUE, /* pc_relative */ 411 0, /* bitpos */ 412 complain_overflow_unsigned, /* complain_on_overflow */ 413 bfd_elf_generic_reloc, /* special_function */ 414 "R_CR16_DISP24", /* name */ 415 FALSE, /* partial_inplace */ 416 0x1ffffff, /* src_mask */ 417 0x1ffffff, /* dst_mask */ 418 FALSE), /* pcrel_offset */ 419 420 HOWTO (R_CR16_DISP24a, /* type */ 421 0, /* rightshift */ 422 2, /* size (0 = byte, 1 = short, 2 = long) */ 423 24, /* bitsize */ 424 TRUE, /* pc_relative */ 425 0, /* bitpos */ 426 complain_overflow_unsigned, /* complain_on_overflow */ 427 bfd_elf_generic_reloc, /* special_function */ 428 "R_CR16_DISP24a", /* name */ 429 FALSE, /* partial_inplace */ 430 0xffffff, /* src_mask */ 431 0xffffff, /* dst_mask */ 432 FALSE) /* pcrel_offset */ 433}; 434 435/* Retrieve a howto ptr using a BFD reloc_code. */ 436 437static reloc_howto_type * 438elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 439 bfd_reloc_code_real_type code) 440{ 441 unsigned int i; 442 443 for (i = 0; i < R_CR16_MAX; i++) 444 if (code == cr16_reloc_map[i].bfd_reloc_enum) 445 return &cr16_elf_howto_table[cr16_reloc_map[i].cr16_reloc_type]; 446 447 _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code); 448 return NULL; 449} 450 451static reloc_howto_type * 452elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 453 const char *r_name) 454{ 455 unsigned int i; 456 457 for (i = 0; ARRAY_SIZE (cr16_elf_howto_table); i++) 458 if (cr16_elf_howto_table[i].name != NULL 459 && strcasecmp (cr16_elf_howto_table[i].name, r_name) == 0) 460 return cr16_elf_howto_table + i; 461 462 return NULL; 463} 464 465/* Retrieve a howto ptr using an internal relocation entry. */ 466 467static void 468elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, 469 Elf_Internal_Rela *dst) 470{ 471 unsigned int r_type = ELF32_R_TYPE (dst->r_info); 472 473 BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX); 474 cache_ptr->howto = &cr16_elf_howto_table[r_type]; 475} 476 477/* Perform a relocation as part of a final link. */ 478 479static bfd_reloc_status_type 480cr16_elf_final_link_relocate (reloc_howto_type *howto, 481 bfd *input_bfd, 482 bfd *output_bfd ATTRIBUTE_UNUSED, 483 asection *input_section, 484 bfd_byte *contents, 485 bfd_vma offset, 486 bfd_vma Rvalue, 487 bfd_vma addend, 488 struct bfd_link_info *info ATTRIBUTE_UNUSED, 489 asection *sec ATTRIBUTE_UNUSED, 490 int is_local ATTRIBUTE_UNUSED) 491{ 492 unsigned short r_type = howto->type; 493 bfd_byte *hit_data = contents + offset; 494 bfd_vma reloc_bits, check, Rvalue1; 495 496 switch (r_type) 497 { 498 case R_CR16_IMM4: 499 case R_CR16_IMM8: 500 case R_CR16_IMM16: 501 case R_CR16_IMM20: 502 case R_CR16_IMM32: 503 case R_CR16_IMM32a: 504 case R_CR16_REGREL4: 505 case R_CR16_REGREL4a: 506 case R_CR16_REGREL14: 507 case R_CR16_REGREL14a: 508 case R_CR16_REGREL16: 509 case R_CR16_REGREL20: 510 case R_CR16_ABS20: 511 case R_CR16_ABS24: 512 case R_CR16_DISP16: 513 case R_CR16_DISP24: 514 /* 'hit_data' is relative to the start of the instruction, not the 515 relocation offset. Advance it to account for the exact offset. */ 516 hit_data += 2; 517 break; 518 519 case R_CR16_NONE: 520 return bfd_reloc_ok; 521 break; 522 523 case R_CR16_DISP4: 524 case R_CR16_DISP8: 525 case R_CR16_DISP24a: 526 /* We only care about the addend, where the difference between 527 expressions is kept. */ 528 if (is_local) Rvalue -= -1; 529 530 default: 531 break; 532 } 533 534 if (howto->pc_relative) 535 { 536 /* Subtract the address of the section containing the location. */ 537 Rvalue -= (input_section->output_section->vma 538 + input_section->output_offset); 539 /* Subtract the position of the location within the section. */ 540 Rvalue -= offset; 541 } 542 543 /* Add in supplied addend. */ 544 Rvalue += addend; 545 546 /* Complain if the bitfield overflows, whether it is considered 547 as signed or unsigned. */ 548 check = Rvalue >> howto->rightshift; 549 550 /* Assumes two's complement. This expression avoids 551 overflow if howto->bitsize is the number of bits in 552 bfd_vma. */ 553 reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; 554 555 if (((bfd_vma) check & ~reloc_bits) != 0 556 && (((bfd_vma) check & ~reloc_bits) 557 != (-(bfd_vma) 1 & ~reloc_bits))) 558 { 559 /* The above right shift is incorrect for a signed 560 value. See if turning on the upper bits fixes the 561 overflow. */ 562 if (howto->rightshift && (bfd_signed_vma) Rvalue < 0) 563 { 564 check |= ((bfd_vma) - 1 565 & ~((bfd_vma) - 1 566 >> howto->rightshift)); 567 568 if (((bfd_vma) check & ~reloc_bits) 569 != (-(bfd_vma) 1 & ~reloc_bits)) 570 return bfd_reloc_overflow; 571 } 572 else 573 return bfd_reloc_overflow; 574 } 575 576 /* Drop unwanted bits from the value we are relocating to. */ 577 Rvalue >>= (bfd_vma) howto->rightshift; 578 579 /* Apply dst_mask to select only relocatable part of the insn. */ 580 Rvalue &= howto->dst_mask; 581 582 switch (howto->size) 583 { 584 case 0: 585 if ((r_type == R_CR16_IMM4) 586 || (r_type == R_CR16_DISP4) 587 || (r_type == R_CR16_DISP8)) 588 { 589 Rvalue1 = bfd_get_16 (input_bfd, hit_data); 590 Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00) 591 | (Rvalue1 & 0x00f0) | (Rvalue & 0xf)); 592 bfd_put_16 (input_bfd, Rvalue, hit_data); 593 } 594 break; 595 596 case 1: 597 if (r_type == R_CR16_DISP16) 598 { 599 Rvalue |= (bfd_get_16 (input_bfd, hit_data)); 600 Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1)); 601 602 bfd_put_16 (input_bfd, Rvalue, hit_data); 603 } 604 break; 605 606 case 2: 607 if (r_type == R_CR16_ABS20) 608 { 609 Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) 610 | (bfd_get_16 (input_bfd, hit_data + 2))) 611 & ~howto->dst_mask); 612 Rvalue |= (bfd_get_16 (input_bfd, hit_data + 2) << 16); 613 614 /* Relocation on INSTRUCTIONS is different : Instructions are 615 word-addressable, that is, each word itself is arranged according 616 to little-endian convention, whereas the words are arranged with 617 respect to one another in BIG ENDIAN fashion. 618 When there is an immediate value that spans a word boundary, 619 it is split in a big-endian way with respect to the words. */ 620 bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data); 621 bfd_put_16 (input_bfd, (Rvalue >> 16)& 0xffff, hit_data + 2); 622 } 623 else if (r_type == R_CR16_ABS24) 624 { 625 Rvalue = ((((Rvalue >> 20)& 0xf) 626 | (((Rvalue >> 16) & 0xf) << 8) 627 | (bfd_get_16 (input_bfd, hit_data))) 628 | ((Rvalue & 0xffff) << 16)); 629 630 bfd_put_32 (input_bfd, Rvalue, hit_data); 631 } 632 else if (r_type == R_CR16_DISP24) 633 { 634 Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf)<<8) 635 | (bfd_get_16 (input_bfd, hit_data))) 636 | (((Rvalue & 0xfffE) | ((Rvalue >> 24) & 0x1)) << 16)); 637 638 bfd_put_32 (input_bfd, Rvalue, hit_data); 639 } 640 else if ((r_type == R_CR16_IMM32) || (r_type == R_CR16_IMM32a)) 641 { 642 Rvalue = (((Rvalue >> 16)& 0xffff) 643 | (bfd_get_16 (input_bfd, hit_data))) 644 | ((Rvalue & 0xffff) << 16); 645 bfd_put_32 (input_bfd, Rvalue, hit_data); 646 } 647 else if (r_type == R_CR16_DISP24a) 648 { 649 Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23))); 650 Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16) 651 | (bfd_get_32 (input_bfd, hit_data)); 652 653 bfd_put_32 (input_bfd, Rvalue, hit_data); 654 } 655 else if ((r_type == R_CR16_NUM32) || (r_type == R_CR16_NUM32a)) 656 { 657 bfd_put_32 (input_bfd, Rvalue, hit_data); 658 } 659 break; 660 661 default: 662 return bfd_reloc_notsupported; 663 } 664 665 return bfd_reloc_ok; 666} 667 668/* Delete some bytes from a section while relaxing. */ 669 670static bfd_boolean 671elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd, 672 asection *sec, bfd_vma addr, int count) 673{ 674 Elf_Internal_Shdr *symtab_hdr; 675 unsigned int sec_shndx; 676 bfd_byte *contents; 677 Elf_Internal_Rela *irel, *irelend; 678 Elf_Internal_Rela *irelalign; 679 bfd_vma toaddr; 680 Elf_Internal_Sym *isym; 681 Elf_Internal_Sym *isymend; 682 struct elf_link_hash_entry **sym_hashes; 683 struct elf_link_hash_entry **end_hashes; 684 struct elf_link_hash_entry **start_hashes; 685 unsigned int symcount; 686 687 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); 688 689 contents = elf_section_data (sec)->this_hdr.contents; 690 691 /* The deletion must stop at the next ALIGN reloc for an aligment 692 power larger than the number of bytes we are deleting. */ 693 irelalign = NULL; 694 toaddr = sec->size; 695 696 irel = elf_section_data (sec)->relocs; 697 irelend = irel + sec->reloc_count; 698 699 /* Actually delete the bytes. */ 700 memmove (contents + addr, contents + addr + count, 701 (size_t) (toaddr - addr - count)); 702 sec->size -= count; 703 704 /* Adjust all the relocs. */ 705 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) 706 /* Get the new reloc address. */ 707 if ((irel->r_offset > addr && irel->r_offset < toaddr)) 708 irel->r_offset -= count; 709 710 /* Adjust the local symbols defined in this section. */ 711 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 712 isym = (Elf_Internal_Sym *) symtab_hdr->contents; 713 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) 714 { 715 if (isym->st_shndx == sec_shndx 716 && isym->st_value > addr 717 && isym->st_value < toaddr) 718 { 719 /* Adjust the addend of SWITCH relocations in this section, 720 which reference this local symbol. */ 721 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) 722 { 723 unsigned long r_symndx; 724 Elf_Internal_Sym *rsym; 725 bfd_vma addsym, subsym; 726 727 r_symndx = ELF32_R_SYM (irel->r_info); 728 rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx; 729 730 /* Skip if not the local adjusted symbol. */ 731 if (rsym != isym) 732 continue; 733 734 addsym = isym->st_value; 735 subsym = addsym - irel->r_addend; 736 737 /* Fix the addend only when -->> (addsym > addr >= subsym). */ 738 if (subsym <= addr) 739 irel->r_addend -= count; 740 else 741 continue; 742 } 743 744 isym->st_value -= count; 745 } 746 } 747 748 /* Now adjust the global symbols defined in this section. */ 749 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) 750 - symtab_hdr->sh_info); 751 sym_hashes = start_hashes = elf_sym_hashes (abfd); 752 end_hashes = sym_hashes + symcount; 753 754 for (; sym_hashes < end_hashes; sym_hashes++) 755 { 756 struct elf_link_hash_entry *sym_hash = *sym_hashes; 757 758 /* The '--wrap SYMBOL' option is causing a pain when the object file, 759 containing the definition of __wrap_SYMBOL, includes a direct 760 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference 761 the same symbol (which is __wrap_SYMBOL), but still exist as two 762 different symbols in 'sym_hashes', we don't want to adjust 763 the global symbol __wrap_SYMBOL twice. 764 This check is only relevant when symbols are being wrapped. */ 765 if (link_info->wrap_hash != NULL) 766 { 767 struct elf_link_hash_entry **cur_sym_hashes; 768 769 /* Loop only over the symbols whom been already checked. */ 770 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes; 771 cur_sym_hashes++) 772 /* If the current symbol is identical to 'sym_hash', that means 773 the symbol was already adjusted (or at least checked). */ 774 if (*cur_sym_hashes == sym_hash) 775 break; 776 777 /* Don't adjust the symbol again. */ 778 if (cur_sym_hashes < sym_hashes) 779 continue; 780 } 781 782 if ((sym_hash->root.type == bfd_link_hash_defined 783 || sym_hash->root.type == bfd_link_hash_defweak) 784 && sym_hash->root.u.def.section == sec 785 && sym_hash->root.u.def.value > addr 786 && sym_hash->root.u.def.value < toaddr) 787 sym_hash->root.u.def.value -= count; 788 } 789 790 return TRUE; 791} 792 793/* Relocate a CR16 ELF section. */ 794 795static bfd_boolean 796elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info, 797 bfd *input_bfd, asection *input_section, 798 bfd_byte *contents, Elf_Internal_Rela *relocs, 799 Elf_Internal_Sym *local_syms, 800 asection **local_sections) 801{ 802 Elf_Internal_Shdr *symtab_hdr; 803 struct elf_link_hash_entry **sym_hashes; 804 Elf_Internal_Rela *rel, *relend; 805 806 if (info->relocatable) 807 return TRUE; 808 809 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 810 sym_hashes = elf_sym_hashes (input_bfd); 811 812 rel = relocs; 813 relend = relocs + input_section->reloc_count; 814 for (; rel < relend; rel++) 815 { 816 int r_type; 817 reloc_howto_type *howto; 818 unsigned long r_symndx; 819 Elf_Internal_Sym *sym; 820 asection *sec; 821 struct elf_link_hash_entry *h; 822 bfd_vma relocation; 823 bfd_reloc_status_type r; 824 825 r_symndx = ELF32_R_SYM (rel->r_info); 826 r_type = ELF32_R_TYPE (rel->r_info); 827 howto = cr16_elf_howto_table + (r_type); 828 829 h = NULL; 830 sym = NULL; 831 sec = NULL; 832 if (r_symndx < symtab_hdr->sh_info) 833 { 834 sym = local_syms + r_symndx; 835 sec = local_sections[r_symndx]; 836 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 837 } 838 else 839 { 840 bfd_boolean unresolved_reloc, warned; 841 842 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 843 r_symndx, symtab_hdr, sym_hashes, 844 h, sec, relocation, 845 unresolved_reloc, warned); 846 } 847 848 r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd, 849 input_section, 850 contents, rel->r_offset, 851 relocation, rel->r_addend, 852 info, sec, h == NULL); 853 854 if (r != bfd_reloc_ok) 855 { 856 const char *name; 857 const char *msg = NULL; 858 859 if (h != NULL) 860 name = h->root.root.string; 861 else 862 { 863 name = (bfd_elf_string_from_elf_section 864 (input_bfd, symtab_hdr->sh_link, sym->st_name)); 865 if (name == NULL || *name == '\0') 866 name = bfd_section_name (input_bfd, sec); 867 } 868 869 switch (r) 870 { 871 case bfd_reloc_overflow: 872 if (!((*info->callbacks->reloc_overflow) 873 (info, (h ? &h->root : NULL), name, howto->name, 874 (bfd_vma) 0, input_bfd, input_section, 875 rel->r_offset))) 876 return FALSE; 877 break; 878 879 case bfd_reloc_undefined: 880 if (!((*info->callbacks->undefined_symbol) 881 (info, name, input_bfd, input_section, 882 rel->r_offset, TRUE))) 883 return FALSE; 884 break; 885 886 case bfd_reloc_outofrange: 887 msg = _("internal error: out of range error"); 888 goto common_error; 889 890 case bfd_reloc_notsupported: 891 msg = _("internal error: unsupported relocation error"); 892 goto common_error; 893 894 case bfd_reloc_dangerous: 895 msg = _("internal error: dangerous error"); 896 goto common_error; 897 898 default: 899 msg = _("internal error: unknown error"); 900 /* Fall through. */ 901 902 common_error: 903 if (!((*info->callbacks->warning) 904 (info, msg, name, input_bfd, input_section, 905 rel->r_offset))) 906 return FALSE; 907 break; 908 } 909 } 910 } 911 912 return TRUE; 913} 914 915/* This is a version of bfd_generic_get_relocated_section_contents 916 which uses elf32_cr16_relocate_section. */ 917 918static bfd_byte * 919elf32_cr16_get_relocated_section_contents (bfd *output_bfd, 920 struct bfd_link_info *link_info, 921 struct bfd_link_order *link_order, 922 bfd_byte *data, 923 bfd_boolean relocatable, 924 asymbol **symbols) 925{ 926 Elf_Internal_Shdr *symtab_hdr; 927 asection *input_section = link_order->u.indirect.section; 928 bfd *input_bfd = input_section->owner; 929 asection **sections = NULL; 930 Elf_Internal_Rela *internal_relocs = NULL; 931 Elf_Internal_Sym *isymbuf = NULL; 932 933 /* We only need to handle the case of relaxing, or of having a 934 particular set of section contents, specially. */ 935 if (relocatable 936 || elf_section_data (input_section)->this_hdr.contents == NULL) 937 return bfd_generic_get_relocated_section_contents (output_bfd, link_info, 938 link_order, data, 939 relocatable, 940 symbols); 941 942 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 943 944 memcpy (data, elf_section_data (input_section)->this_hdr.contents, 945 (size_t) input_section->size); 946 947 if ((input_section->flags & SEC_RELOC) != 0 948 && input_section->reloc_count > 0) 949 { 950 Elf_Internal_Sym *isym; 951 Elf_Internal_Sym *isymend; 952 asection **secpp; 953 bfd_size_type amt; 954 955 internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section, 956 NULL, NULL, FALSE); 957 if (internal_relocs == NULL) 958 goto error_return; 959 960 if (symtab_hdr->sh_info != 0) 961 { 962 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 963 if (isymbuf == NULL) 964 isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, 965 symtab_hdr->sh_info, 0, 966 NULL, NULL, NULL); 967 if (isymbuf == NULL) 968 goto error_return; 969 } 970 971 amt = symtab_hdr->sh_info; 972 amt *= sizeof (asection *); 973 sections = bfd_malloc (amt); 974 if (sections == NULL && amt != 0) 975 goto error_return; 976 977 isymend = isymbuf + symtab_hdr->sh_info; 978 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) 979 { 980 asection *isec; 981 982 if (isym->st_shndx == SHN_UNDEF) 983 isec = bfd_und_section_ptr; 984 else if (isym->st_shndx == SHN_ABS) 985 isec = bfd_abs_section_ptr; 986 else if (isym->st_shndx == SHN_COMMON) 987 isec = bfd_com_section_ptr; 988 else 989 isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); 990 991 *secpp = isec; 992 } 993 994 if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd, 995 input_section, data, internal_relocs, 996 isymbuf, sections)) 997 goto error_return; 998 999 if (sections != NULL) 1000 free (sections); 1001 if (isymbuf != NULL 1002 && symtab_hdr->contents != (unsigned char *) isymbuf) 1003 free (isymbuf); 1004 if (elf_section_data (input_section)->relocs != internal_relocs) 1005 free (internal_relocs); 1006 } 1007 1008 return data; 1009 1010 error_return: 1011 if (sections != NULL) 1012 free (sections); 1013 if (isymbuf != NULL 1014 && symtab_hdr->contents != (unsigned char *) isymbuf) 1015 free (isymbuf); 1016 if (internal_relocs != NULL 1017 && elf_section_data (input_section)->relocs != internal_relocs) 1018 free (internal_relocs); 1019 return NULL; 1020} 1021 1022/* This function handles relaxing for the CR16. 1023 1024 There's quite a few relaxing opportunites available on the CR16: 1025 1026 * bcond:24 -> bcond:16 2 bytes 1027 * bcond:16 -> bcond:8 2 bytes 1028 * arithmetic imm32 -> arithmetic imm16 2 bytes 1029 1030 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */ 1031 1032static bfd_boolean 1033elf32_cr16_relax_section (bfd *abfd, asection *sec, 1034 struct bfd_link_info *link_info, bfd_boolean *again) 1035{ 1036 Elf_Internal_Shdr *symtab_hdr; 1037 Elf_Internal_Rela *internal_relocs; 1038 Elf_Internal_Rela *irel, *irelend; 1039 bfd_byte *contents = NULL; 1040 Elf_Internal_Sym *isymbuf = NULL; 1041 1042 /* Assume nothing changes. */ 1043 *again = FALSE; 1044 1045 /* We don't have to do anything for a relocatable link, if 1046 this section does not have relocs, or if this is not a 1047 code section. */ 1048 if (link_info->relocatable 1049 || (sec->flags & SEC_RELOC) == 0 1050 || sec->reloc_count == 0 1051 || (sec->flags & SEC_CODE) == 0) 1052 return TRUE; 1053 1054 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 1055 1056 /* Get a copy of the native relocations. */ 1057 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, 1058 link_info->keep_memory); 1059 if (internal_relocs == NULL) 1060 goto error_return; 1061 1062 /* Walk through them looking for relaxing opportunities. */ 1063 irelend = internal_relocs + sec->reloc_count; 1064 for (irel = internal_relocs; irel < irelend; irel++) 1065 { 1066 bfd_vma symval; 1067 1068 /* If this isn't something that can be relaxed, then ignore 1069 this reloc. */ 1070 if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16 1071 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24) 1072 continue; 1073 1074 /* Get the section contents if we haven't done so already. */ 1075 if (contents == NULL) 1076 { 1077 /* Get cached copy if it exists. */ 1078 if (elf_section_data (sec)->this_hdr.contents != NULL) 1079 contents = elf_section_data (sec)->this_hdr.contents; 1080 /* Go get them off disk. */ 1081 else if (!bfd_malloc_and_get_section (abfd, sec, &contents)) 1082 goto error_return; 1083 } 1084 1085 /* Read this BFD's local symbols if we haven't done so already. */ 1086 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 1087 { 1088 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 1089 if (isymbuf == NULL) 1090 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 1091 symtab_hdr->sh_info, 0, 1092 NULL, NULL, NULL); 1093 if (isymbuf == NULL) 1094 goto error_return; 1095 } 1096 1097 /* Get the value of the symbol referred to by the reloc. */ 1098 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 1099 { 1100 /* A local symbol. */ 1101 Elf_Internal_Sym *isym; 1102 asection *sym_sec; 1103 1104 isym = isymbuf + ELF32_R_SYM (irel->r_info); 1105 if (isym->st_shndx == SHN_UNDEF) 1106 sym_sec = bfd_und_section_ptr; 1107 else if (isym->st_shndx == SHN_ABS) 1108 sym_sec = bfd_abs_section_ptr; 1109 else if (isym->st_shndx == SHN_COMMON) 1110 sym_sec = bfd_com_section_ptr; 1111 else 1112 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 1113 symval = (isym->st_value 1114 + sym_sec->output_section->vma 1115 + sym_sec->output_offset); 1116 } 1117 else 1118 { 1119 unsigned long indx; 1120 struct elf_link_hash_entry *h; 1121 1122 /* An external symbol. */ 1123 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; 1124 h = elf_sym_hashes (abfd)[indx]; 1125 BFD_ASSERT (h != NULL); 1126 1127 if (h->root.type != bfd_link_hash_defined 1128 && h->root.type != bfd_link_hash_defweak) 1129 /* This appears to be a reference to an undefined 1130 symbol. Just ignore it--it will be caught by the 1131 regular reloc processing. */ 1132 continue; 1133 1134 symval = (h->root.u.def.value 1135 + h->root.u.def.section->output_section->vma 1136 + h->root.u.def.section->output_offset); 1137 } 1138 1139 /* For simplicity of coding, we are going to modify the section 1140 contents, the section relocs, and the BFD symbol table. We 1141 must tell the rest of the code not to free up this 1142 information. It would be possible to instead create a table 1143 of changes which have to be made, as is done in coff-mips.c; 1144 that would be more work, but would require less memory when 1145 the linker is run. */ 1146 1147 /* Try to turn a 24 branch/call into a 16bit relative 1148 * branch/call. */ 1149 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24) 1150 { 1151 bfd_vma value = symval; 1152 1153 /* Deal with pc-relative gunk. */ 1154 value -= (sec->output_section->vma + sec->output_offset); 1155 value -= irel->r_offset; 1156 value += irel->r_addend; 1157 1158 /* See if the value will fit in 16 bits, note the high value is 1159 0xfffe + 2 as the target will be two bytes closer if we are 1160 able to relax. */ 1161 if ((long) value < 0x10000 && (long) value > -0x10002) 1162 { 1163 unsigned int code; 1164 1165 /* Get the opcode. */ 1166 code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset); 1167 1168 /* Verify it's a 'bcond' and fix the opcode. */ 1169 if ((code & 0xffff) == 0x0010) 1170 { 1171 bfd_put_16 (abfd, 0x1800 | ((0xf & (code >>20))<<4), contents + irel->r_offset); 1172 bfd_put_16 (abfd, value, contents + irel->r_offset+2); 1173 } 1174 else 1175 continue; 1176 1177 /* Note that we've changed the relocs, section contents, etc. */ 1178 elf_section_data (sec)->relocs = internal_relocs; 1179 elf_section_data (sec)->this_hdr.contents = contents; 1180 symtab_hdr->contents = (unsigned char *) isymbuf; 1181 1182 /* Fix the relocation's type. */ 1183 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1184 R_CR16_DISP16); 1185 1186 /* Delete two bytes of data. */ 1187 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec, 1188 irel->r_offset + 2, 2)) 1189 goto error_return; 1190 1191 /* That will change things, so, we should relax again. 1192 Note that this is not required, and it may be slow. */ 1193 *again = TRUE; 1194 } 1195 } 1196 1197 /* Try to turn a 16bit pc-relative branch into an 1198 8bit pc-relative branch. */ 1199 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16) 1200 { 1201 bfd_vma value = symval; 1202 1203 /* Deal with pc-relative gunk. */ 1204 value -= (sec->output_section->vma + sec->output_offset); 1205 value -= irel->r_offset; 1206 value += irel->r_addend; 1207 1208 /* See if the value will fit in 8 bits, note the high value is 1209 0xfc + 2 as the target will be two bytes closer if we are 1210 able to relax. */ 1211 if ((long) value < 0xfe && (long) value > -0x100) 1212 { 1213 unsigned short code; 1214 1215 /* Get the opcode. */ 1216 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset); 1217 1218 /* Verify it's a 'bcond' opcode. */ 1219 if ((code & 0xff00) == 0x1800) 1220 { 1221 bfd_put_8 (abfd, 0x1 | ((0xf & (code>>4))<<4), contents + irel->r_offset); 1222 bfd_put_8 (abfd, value, contents + irel->r_offset+2); 1223 } 1224 else 1225 continue; 1226 1227 /* Note that we've changed the relocs, section contents, etc. */ 1228 elf_section_data (sec)->relocs = internal_relocs; 1229 elf_section_data (sec)->this_hdr.contents = contents; 1230 symtab_hdr->contents = (unsigned char *) isymbuf; 1231 1232 /* Fix the relocation's type. */ 1233 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1234 R_CR16_DISP8); 1235 1236 /* Delete two bytes of data. */ 1237 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec, 1238 irel->r_offset + 2, 2)) 1239 goto error_return; 1240 1241 /* That will change things, so, we should relax again. 1242 Note that this is not required, and it may be slow. */ 1243 *again = TRUE; 1244 } 1245 } 1246 1247#if 0 // REVISIT: To support IMM relaxation in CR16 target 1248 /* Try to turn a 32bit immediate address into 1249 a 20bit immediate address. */ 1250 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32) 1251 { 1252 bfd_vma value = symval; 1253 1254 /* See if the value will fit in 20 bits. */ 1255 if ((long) value < 0x7ffff && (long) value > -0x80000) 1256 { 1257 unsigned short code; 1258 1259 /* Get the opcode. */ 1260 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset); 1261 1262 /* Verify it's a 'arithmetic double'. */ 1263 if ((code & 0xfff0) != 0x0070) 1264 continue; 1265 1266 /* Note that we've changed the relocs, section contents, etc. */ 1267 elf_section_data (sec)->relocs = internal_relocs; 1268 elf_section_data (sec)->this_hdr.contents = contents; 1269 symtab_hdr->contents = (unsigned char *) isymbuf; 1270 1271 /* Fix the opcode. */ 1272 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset); 1273 1274 /* Fix the relocation's type. */ 1275 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1276 R_CR16_IMM20); 1277 1278 /* Delete two bytes of data. */ 1279 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec, 1280 irel->r_offset + 2, 2)) 1281 goto error_return; 1282 1283 /* That will change things, so, we should relax again. 1284 Note that this is not required, and it may be slow. */ 1285 *again = TRUE; 1286 } 1287 } 1288 /* Try to turn a 20bit/16bit immediate address into 1289 a 4bit immediate address. */ 1290 if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20) 1291 || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16)) 1292 { 1293 bfd_vma value = symval; 1294 1295 /* See if the value will fit in 4 bits. */ 1296 if ((long) value < 0x7 && (long) value > -0x8) 1297 { 1298 unsigned short code; 1299 1300 /* Get the opcode. */ 1301 code = (unsigned short) bfd_get_8 (abfd, contents + irel->r_offset); 1302 1303 /* Verify it's a 'arithmetic double'. */ 1304 if (((code & 0xff) != 0x50) || ((code & 0xff) != 0x45)) 1305 continue; 1306 1307 /* Note that we've changed the relocs, section contents, etc. */ 1308 elf_section_data (sec)->relocs = internal_relocs; 1309 elf_section_data (sec)->this_hdr.contents = contents; 1310 symtab_hdr->contents = (unsigned char *) isymbuf; 1311 1312 /* Fix the opcode. */ 1313 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset); 1314 1315 /* Fix the relocation's type. */ 1316 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1317 R_CR16_IMM4); 1318 1319 /* Delete two bytes of data. */ 1320 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec, 1321 irel->r_offset + 2, 2)) 1322 goto error_return; 1323 1324 /* That will change things, so, we should relax again. 1325 Note that this is not required, and it may be slow. */ 1326 *again = TRUE; 1327 } 1328 } 1329#endif 1330 } 1331 1332 if (isymbuf != NULL 1333 && symtab_hdr->contents != (unsigned char *) isymbuf) 1334 { 1335 if (! link_info->keep_memory) 1336 free (isymbuf); 1337 else 1338 { 1339 /* Cache the symbols for elf_link_input_bfd. */ 1340 symtab_hdr->contents = (unsigned char *) isymbuf; 1341 } 1342 } 1343 1344 if (contents != NULL 1345 && elf_section_data (sec)->this_hdr.contents != contents) 1346 { 1347 if (! link_info->keep_memory) 1348 free (contents); 1349 else 1350 { 1351 /* Cache the section contents for elf_link_input_bfd. */ 1352 elf_section_data (sec)->this_hdr.contents = contents; 1353 } 1354 } 1355 1356 if (internal_relocs != NULL 1357 && elf_section_data (sec)->relocs != internal_relocs) 1358 free (internal_relocs); 1359 1360 return TRUE; 1361 1362 error_return: 1363 if (isymbuf != NULL 1364 && symtab_hdr->contents != (unsigned char *) isymbuf) 1365 free (isymbuf); 1366 if (contents != NULL 1367 && elf_section_data (sec)->this_hdr.contents != contents) 1368 free (contents); 1369 if (internal_relocs != NULL 1370 && elf_section_data (sec)->relocs != internal_relocs) 1371 free (internal_relocs); 1372 1373 return FALSE; 1374} 1375 1376static asection * 1377elf32_cr16_gc_mark_hook (asection *sec, 1378 struct bfd_link_info *info ATTRIBUTE_UNUSED, 1379 Elf_Internal_Rela *rel ATTRIBUTE_UNUSED, 1380 struct elf_link_hash_entry *h, 1381 Elf_Internal_Sym *sym) 1382{ 1383 if (h == NULL) 1384 return bfd_section_from_elf_index (sec->owner, sym->st_shndx); 1385 1386 switch (h->root.type) 1387 { 1388 case bfd_link_hash_defined: 1389 case bfd_link_hash_defweak: 1390 return h->root.u.def.section; 1391 1392 case bfd_link_hash_common: 1393 return h->root.u.c.p->section; 1394 1395 default: 1396 return NULL; 1397 } 1398} 1399 1400/* Update the got entry reference counts for the section being removed. */ 1401 1402static bfd_boolean 1403elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, 1404 struct bfd_link_info *info ATTRIBUTE_UNUSED, 1405 asection *sec ATTRIBUTE_UNUSED, 1406 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED) 1407{ 1408 /* We don't support garbage collection of GOT and PLT relocs yet. */ 1409 return TRUE; 1410} 1411 1412/* Definitions for setting CR16 target vector. */ 1413#define TARGET_LITTLE_SYM bfd_elf32_cr16_vec 1414#define TARGET_LITTLE_NAME "elf32-cr16" 1415#define ELF_ARCH bfd_arch_cr16 1416#define ELF_MACHINE_CODE EM_CR16 1417#define ELF_MAXPAGESIZE 0x1 1418#define elf_symbol_leading_char '_' 1419 1420#define bfd_elf32_bfd_reloc_type_lookup elf_cr16_reloc_type_lookup 1421#define bfd_elf32_bfd_reloc_name_lookup elf_cr16_reloc_name_lookup 1422#define elf_info_to_howto elf_cr16_info_to_howto 1423#define elf_info_to_howto_rel 0 1424#define elf_backend_relocate_section elf32_cr16_relocate_section 1425#define bfd_elf32_bfd_relax_section elf32_cr16_relax_section 1426#define bfd_elf32_bfd_get_relocated_section_contents \ 1427 elf32_cr16_get_relocated_section_contents 1428#define elf_backend_gc_mark_hook elf32_cr16_gc_mark_hook 1429#define elf_backend_gc_sweep_hook elf32_cr16_gc_sweep_hook 1430#define elf_backend_can_gc_sections 1 1431#define elf_backend_rela_normal 1 1432 1433#include "elf32-target.h" 1434