1 /* Freescale XGATE-specific support for 32-bit ELF 2 Copyright (C) 2010-2022 Free Software Foundation, Inc. 3 Contributed by Sean Keys(skeys@ipdatasys.com) 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 "bfdlink.h" 25 #include "libbfd.h" 26 #include "elf-bfd.h" 27 #include "elf/xgate.h" 28 #include "opcode/xgate.h" 29 #include "libiberty.h" 30 31 /* Forward declarations. */ 32 static bfd_reloc_status_type xgate_elf_ignore_reloc 33 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 34 static bfd_reloc_status_type xgate_elf_special_reloc 35 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 36 37 /* Use REL instead of RELA to save space */ 38 #define USE_REL 1 39 40 static reloc_howto_type elf_xgate_howto_table[] = 41 { 42 /* This reloc does nothing. */ 43 HOWTO (R_XGATE_NONE, /* type */ 44 0, /* rightshift */ 45 0, /* size */ 46 0, /* bitsize */ 47 false, /* pc_relative */ 48 0, /* bitpos */ 49 complain_overflow_dont,/* complain_on_overflow */ 50 bfd_elf_generic_reloc, /* special_function */ 51 "R_XGATE_NONE", /* name */ 52 false, /* partial_inplace */ 53 0, /* src_mask */ 54 0, /* dst_mask */ 55 false), /* pcrel_offset */ 56 57 /* A 8 bit absolute relocation. */ 58 HOWTO (R_XGATE_8, /* type */ 59 0, /* rightshift */ 60 1, /* size */ 61 8, /* bitsize */ 62 false, /* pc_relative */ 63 0, /* bitpos */ 64 complain_overflow_bitfield, /* complain_on_overflow */ 65 bfd_elf_generic_reloc, /* special_function */ 66 "R_XGATE_8", /* name */ 67 false, /* partial_inplace */ 68 0x00ff, /* src_mask */ 69 0x00ff, /* dst_mask */ 70 false), /* pcrel_offset */ 71 72 /* A 8 bit PC-rel relocation. */ 73 HOWTO (R_XGATE_PCREL_8, /* type */ 74 0, /* rightshift */ 75 1, /* size */ 76 8, /* bitsize */ 77 true, /* pc_relative */ 78 0, /* bitpos */ 79 complain_overflow_bitfield, /* complain_on_overflow */ 80 bfd_elf_generic_reloc, /* special_function */ 81 "R_XGATE_PCREL_8", /* name */ 82 false, /* partial_inplace */ 83 0x00ff, /* src_mask */ 84 0x00ff, /* dst_mask */ 85 true), /* pcrel_offset */ 86 87 /* A 16 bit absolute relocation. */ 88 HOWTO (R_XGATE_16, /* type */ 89 0, /* rightshift */ 90 2, /* size */ 91 16, /* bitsize */ 92 false, /* pc_relative */ 93 0, /* bitpos */ 94 complain_overflow_dont /*bitfield */, /* complain_on_overflow */ 95 bfd_elf_generic_reloc, /* special_function */ 96 "R_XGATE_16", /* name */ 97 false, /* partial_inplace */ 98 0xffff, /* src_mask */ 99 0xffff, /* dst_mask */ 100 false), /* pcrel_offset */ 101 102 /* A 32 bit absolute relocation. This one is never used for the 103 code relocation. It's used by gas for -gstabs generation. */ 104 HOWTO (R_XGATE_32, /* type */ 105 0, /* rightshift */ 106 4, /* size */ 107 32, /* bitsize */ 108 false, /* pc_relative */ 109 0, /* bitpos */ 110 complain_overflow_bitfield, /* complain_on_overflow */ 111 bfd_elf_generic_reloc, /* special_function */ 112 "R_XGATE_32", /* name */ 113 false, /* partial_inplace */ 114 0xffffffff, /* src_mask */ 115 0xffffffff, /* dst_mask */ 116 false), /* pcrel_offset */ 117 118 /* A 16 bit PC-rel relocation. */ 119 HOWTO (R_XGATE_PCREL_16, /* type */ 120 0, /* rightshift */ 121 2, /* size */ 122 16, /* bitsize */ 123 true, /* pc_relative */ 124 0, /* bitpos */ 125 complain_overflow_dont, /* complain_on_overflow */ 126 bfd_elf_generic_reloc, /* special_function */ 127 "R_XGATE_PCREL_16", /* name */ 128 false, /* partial_inplace */ 129 0xffff, /* src_mask */ 130 0xffff, /* dst_mask */ 131 true), /* pcrel_offset */ 132 133 /* GNU extension to record C++ vtable hierarchy. */ 134 HOWTO (R_XGATE_GNU_VTINHERIT, /* type */ 135 0, /* rightshift */ 136 2, /* size */ 137 0, /* bitsize */ 138 false, /* pc_relative */ 139 0, /* bitpos */ 140 complain_overflow_dont, /* complain_on_overflow */ 141 NULL, /* special_function */ 142 "R_XGATE_GNU_VTINHERIT", /* name */ 143 false, /* partial_inplace */ 144 0, /* src_mask */ 145 0, /* dst_mask */ 146 false), /* pcrel_offset */ 147 148 /* GNU extension to record C++ vtable member usage. */ 149 HOWTO (R_XGATE_GNU_VTENTRY, /* type */ 150 0, /* rightshift */ 151 2, /* size */ 152 0, /* bitsize */ 153 false, /* pc_relative */ 154 0, /* bitpos */ 155 complain_overflow_dont, /* complain_on_overflow */ 156 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 157 "R_XGATE_GNU_VTENTRY", /* name */ 158 false, /* partial_inplace */ 159 0, /* src_mask */ 160 0, /* dst_mask */ 161 false), /* pcrel_offset */ 162 163 /* A 24 bit relocation. */ 164 HOWTO (R_XGATE_24, /* type */ 165 0, /* rightshift */ 166 2, /* size */ 167 16, /* bitsize */ 168 false, /* pc_relative */ 169 0, /* bitpos */ 170 complain_overflow_dont, /* complain_on_overflow */ 171 bfd_elf_generic_reloc, /* special_function */ 172 "R_XGATE_IMM8_LO", /* name */ 173 false, /* partial_inplace */ 174 0x00ff, /* src_mask */ 175 0x00ff, /* dst_mask */ 176 false), /* pcrel_offset */ 177 178 /* A 16-bit low relocation. */ 179 HOWTO (R_XGATE_LO16, /* type */ 180 8, /* rightshift */ 181 2, /* size */ 182 16, /* bitsize */ 183 false, /* pc_relative */ 184 0, /* bitpos */ 185 complain_overflow_dont, /* complain_on_overflow */ 186 bfd_elf_generic_reloc, /* special_function */ 187 "R_XGATE_IMM8_HI", /* name */ 188 false, /* partial_inplace */ 189 0x00ff, /* src_mask */ 190 0x00ff, /* dst_mask */ 191 false), /* pcrel_offset */ 192 193 /* A page relocation. */ 194 HOWTO (R_XGATE_GPAGE, /* type */ 195 0, /* rightshift */ 196 1, /* size */ 197 8, /* bitsize */ 198 false, /* pc_relative */ 199 0, /* bitpos */ 200 complain_overflow_dont, /* complain_on_overflow */ 201 xgate_elf_special_reloc,/* special_function */ 202 "R_XGATE_GPAGE", /* name */ 203 false, /* partial_inplace */ 204 0x00ff, /* src_mask */ 205 0x00ff, /* dst_mask */ 206 false), /* pcrel_offset */ 207 208 /* A 9 bit absolute relocation. */ 209 HOWTO (R_XGATE_PCREL_9, /* type */ 210 0, /* rightshift */ 211 2, /* size */ 212 9, /* bitsize */ 213 true, /* pc_relative */ 214 0, /* bitpos */ 215 complain_overflow_bitfield, /* complain_on_overflow */ 216 bfd_elf_generic_reloc, /* special_function */ 217 "R_XGATE_PCREL_9", /* name */ 218 false, /* partial_inplace */ 219 0xffff, /* src_mask */ 220 0xffff, /* dst_mask */ 221 true), /* pcrel_offset */ 222 223 /* A 8 bit absolute relocation (upper address). */ 224 HOWTO (R_XGATE_PCREL_10, /* type */ 225 8, /* rightshift */ 226 1, /* size */ 227 10, /* bitsize */ 228 true, /* pc_relative */ 229 0, /* bitpos */ 230 complain_overflow_dont, /* complain_on_overflow */ 231 bfd_elf_generic_reloc, /* special_function */ 232 "R_XGATE_PCREL_10", /* name */ 233 false, /* partial_inplace */ 234 0x00ff, /* src_mask */ 235 0x00ff, /* dst_mask */ 236 true), /* pcrel_offset */ 237 238 /* A 8 bit absolute relocation. */ 239 HOWTO (R_XGATE_IMM8_LO, /* type */ 240 0, /* rightshift */ 241 2, /* size */ 242 16, /* bitsize */ 243 false, /* pc_relative */ 244 0, /* bitpos */ 245 complain_overflow_dont, /* complain_on_overflow */ 246 bfd_elf_generic_reloc, /* special_function */ 247 "R_XGATE_IMM8_LO", /* name */ 248 false, /* partial_inplace */ 249 0xffff, /* src_mask */ 250 0xffff, /* dst_mask */ 251 false), /* pcrel_offset */ 252 253 /* A 16 bit absolute relocation (upper address). */ 254 HOWTO (R_XGATE_IMM8_HI, /* type */ 255 8, /* rightshift */ 256 2, /* size */ 257 16, /* bitsize */ 258 false, /* pc_relative */ 259 0, /* bitpos */ 260 complain_overflow_dont, /* complain_on_overflow */ 261 bfd_elf_generic_reloc, /* special_function */ 262 "R_XGATE_IMM8_HI", /* name */ 263 false, /* partial_inplace */ 264 0x00ff, /* src_mask */ 265 0x00ff, /* dst_mask */ 266 false), /* pcrel_offset */ 267 268 /* A 3 bit absolute relocation. */ 269 HOWTO (R_XGATE_IMM3, /* type */ 270 8, /* rightshift */ 271 2, /* size */ 272 16, /* bitsize */ 273 false, /* pc_relative */ 274 0, /* bitpos */ 275 complain_overflow_dont, /* complain_on_overflow */ 276 bfd_elf_generic_reloc, /* special_function */ 277 "R_XGATE_IMM3", /* name */ 278 false, /* partial_inplace */ 279 0x00ff, /* src_mask */ 280 0x00ff, /* dst_mask */ 281 false), /* pcrel_offset */ 282 283 /* A 4 bit absolute relocation. */ 284 HOWTO (R_XGATE_IMM4, /* type */ 285 8, /* rightshift */ 286 2, /* size */ 287 16, /* bitsize */ 288 false, /* pc_relative */ 289 0, /* bitpos */ 290 complain_overflow_dont, /* complain_on_overflow */ 291 bfd_elf_generic_reloc, /* special_function */ 292 "R_XGATE_IMM4", /* name */ 293 false, /* partial_inplace */ 294 0x00ff, /* src_mask */ 295 0x00ff, /* dst_mask */ 296 false), /* pcrel_offset */ 297 298 /* A 5 bit absolute relocation. */ 299 HOWTO (R_XGATE_IMM5, /* type */ 300 8, /* rightshift */ 301 2, /* size */ 302 16, /* bitsize */ 303 false, /* pc_relative */ 304 0, /* bitpos */ 305 complain_overflow_dont, /* complain_on_overflow */ 306 bfd_elf_generic_reloc, /* special_function */ 307 "R_XGATE_IMM5", /* name */ 308 false, /* partial_inplace */ 309 0x00ff, /* src_mask */ 310 0x00ff, /* dst_mask */ 311 false), /* pcrel_offset */ 312 313 /* Mark beginning of a jump instruction (any form). */ 314 HOWTO (R_XGATE_RL_JUMP, /* type */ 315 0, /* rightshift */ 316 2, /* size */ 317 0, /* bitsize */ 318 false, /* pc_relative */ 319 0, /* bitpos */ 320 complain_overflow_dont, /* complain_on_overflow */ 321 xgate_elf_ignore_reloc, /* special_function */ 322 "R_XGATE_RL_JUMP", /* name */ 323 true, /* partial_inplace */ 324 0, /* src_mask */ 325 0, /* dst_mask */ 326 true), /* pcrel_offset */ 327 328 /* Mark beginning of Gcc relaxation group instruction. */ 329 HOWTO (R_XGATE_RL_GROUP, /* type */ 330 0, /* rightshift */ 331 2, /* size */ 332 0, /* bitsize */ 333 false, /* pc_relative */ 334 0, /* bitpos */ 335 complain_overflow_dont, /* complain_on_overflow */ 336 xgate_elf_ignore_reloc, /* special_function */ 337 "R_XGATE_RL_GROUP", /* name */ 338 true, /* partial_inplace */ 339 0, /* src_mask */ 340 0, /* dst_mask */ 341 true), /* pcrel_offset */ 342 }; 343 344 /* Map BFD reloc types to XGATE ELF reloc types. */ 345 346 struct xgate_reloc_map 347 { 348 bfd_reloc_code_real_type bfd_reloc_val; 349 unsigned char elf_reloc_val; 350 }; 351 352 static const struct xgate_reloc_map xgate_reloc_map[] = 353 { 354 {BFD_RELOC_NONE, R_XGATE_NONE}, 355 {BFD_RELOC_8, R_XGATE_8}, 356 {BFD_RELOC_8_PCREL, R_XGATE_PCREL_8}, 357 {BFD_RELOC_16_PCREL, R_XGATE_PCREL_16}, 358 {BFD_RELOC_16, R_XGATE_16}, 359 {BFD_RELOC_32, R_XGATE_32}, 360 361 {BFD_RELOC_VTABLE_INHERIT, R_XGATE_GNU_VTINHERIT}, 362 {BFD_RELOC_VTABLE_ENTRY, R_XGATE_GNU_VTENTRY}, 363 364 {BFD_RELOC_XGATE_LO16, R_XGATE_LO16}, 365 {BFD_RELOC_XGATE_GPAGE, R_XGATE_GPAGE}, 366 {BFD_RELOC_XGATE_24, R_XGATE_24}, 367 {BFD_RELOC_XGATE_PCREL_9, R_XGATE_PCREL_9}, 368 {BFD_RELOC_XGATE_PCREL_10, R_XGATE_PCREL_10}, 369 {BFD_RELOC_XGATE_IMM8_LO, R_XGATE_IMM8_LO}, 370 {BFD_RELOC_XGATE_IMM8_HI, R_XGATE_IMM8_HI}, 371 {BFD_RELOC_XGATE_IMM3, R_XGATE_IMM3}, 372 {BFD_RELOC_XGATE_IMM4, R_XGATE_IMM4}, 373 {BFD_RELOC_XGATE_IMM5, R_XGATE_IMM5}, 374 375 {BFD_RELOC_XGATE_RL_JUMP, R_XGATE_RL_JUMP}, 376 {BFD_RELOC_XGATE_RL_GROUP, R_XGATE_RL_GROUP}, 377 }; 378 379 static reloc_howto_type * 380 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 381 bfd_reloc_code_real_type code) 382 { 383 unsigned int i; 384 385 for (i = 0; i < ARRAY_SIZE (xgate_reloc_map); i++) 386 if (xgate_reloc_map[i].bfd_reloc_val == code) 387 return &elf_xgate_howto_table[xgate_reloc_map[i].elf_reloc_val]; 388 389 return NULL; 390 } 391 392 static reloc_howto_type * 393 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 394 { 395 unsigned int i; 396 397 for (i = 0; i < ARRAY_SIZE (elf_xgate_howto_table); i++) 398 if (elf_xgate_howto_table[i].name != NULL 399 && strcasecmp (elf_xgate_howto_table[i].name, r_name) == 0) 400 return &elf_xgate_howto_table[i]; 401 402 return NULL; 403 } 404 405 /* Set the howto pointer for an XGATE ELF reloc. */ 406 407 static bool 408 xgate_info_to_howto_rel (bfd *abfd, 409 arelent *cache_ptr, 410 Elf_Internal_Rela *dst) 411 { 412 unsigned int r_type; 413 414 r_type = ELF32_R_TYPE (dst->r_info); 415 if (r_type >= (unsigned int) R_XGATE_max) 416 { 417 /* xgettext:c-format */ 418 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 419 abfd, r_type); 420 bfd_set_error (bfd_error_bad_value); 421 return false; 422 } 423 cache_ptr->howto = &elf_xgate_howto_table[r_type]; 424 return true; 425 } 426 427 /* Specific sections: 428 - The .page0 is a data section that is mapped in [0x0000..0x00FF]. 429 Page0 accesses are faster on the M68HC12. 430 - The .vectors is the section that represents the interrupt 431 vectors. 432 - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */ 433 static const struct bfd_elf_special_section elf32_xgate_special_sections[] = 434 { 435 { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 436 { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 437 { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, 438 { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC }, 439 /*{ STRING_COMMA_LEN (".xgate"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 440 TODO finish this implementation */ 441 { NULL, 0, 0, 0, 0 } 442 }; 443 444 /* Hook called when reading symbols. */ 445 446 static void 447 elf32_xgate_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, 448 asymbol *sym) 449 { 450 /* Mark xgate symbols. */ 451 ((elf_symbol_type *) sym)->internal_elf_sym.st_target_internal = 1; 452 } 453 454 /* This function is used for relocs which are only used for relaxing, 455 which the linker should otherwise ignore. */ 456 457 static bfd_reloc_status_type 458 xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, 459 arelent *reloc_entry, 460 asymbol *symbol ATTRIBUTE_UNUSED, 461 void *data ATTRIBUTE_UNUSED, 462 asection *input_section, 463 bfd *output_bfd, 464 char **error_message ATTRIBUTE_UNUSED) 465 { 466 if (output_bfd != NULL) 467 reloc_entry->address += input_section->output_offset; 468 return bfd_reloc_ok; 469 } 470 471 static bfd_reloc_status_type 472 xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED, 473 arelent *reloc_entry ATTRIBUTE_UNUSED, 474 asymbol *symbol ATTRIBUTE_UNUSED, 475 void *data ATTRIBUTE_UNUSED, 476 asection *input_section ATTRIBUTE_UNUSED, 477 bfd *output_bfd ATTRIBUTE_UNUSED, 478 char **error_message ATTRIBUTE_UNUSED) 479 { 480 abort (); 481 } 482 483 static bool 484 _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr) 485 { 486 FILE *file = (FILE *) ptr; 487 488 BFD_ASSERT (abfd != NULL && ptr != NULL); 489 490 /* Print normal ELF private data. */ 491 _bfd_elf_print_private_bfd_data (abfd, ptr); 492 493 /* xgettext:c-format */ 494 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags); 495 496 if (elf_elfheader (abfd)->e_flags & E_XGATE_I32) 497 fprintf (file, _("[abi=32-bit int, ")); 498 else 499 fprintf (file, _("[abi=16-bit int, ")); 500 501 if (elf_elfheader (abfd)->e_flags & E_XGATE_F64) 502 fprintf (file, _("64-bit double, ")); 503 else 504 fprintf (file, _("32-bit double, ")); 505 if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH) 506 fprintf (file, _("cpu=XGATE]")); 507 else 508 fprintf (file, _("error reading cpu type from elf private data")); 509 fputc ('\n', file); 510 511 return true; 512 } 513 514 #define ELF_ARCH bfd_arch_xgate 515 #define ELF_MACHINE_CODE EM_XGATE 516 517 #define ELF_MAXPAGESIZE 0x1000 518 519 #define TARGET_BIG_SYM xgate_elf32_vec 520 #define TARGET_BIG_NAME "elf32-xgate" 521 522 #define elf_info_to_howto_rel xgate_info_to_howto_rel 523 #define elf_backend_special_sections elf32_xgate_special_sections 524 #define elf_backend_symbol_processing elf32_xgate_backend_symbol_processing 525 #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data 526 527 #include "elf32-target.h" 528