1 1.1 christos /* Xstormy16-specific support for 32-bit ELF. 2 1.10 christos Copyright (C) 2000-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of BFD, the Binary File Descriptor library. 5 1.1 christos 6 1.1 christos This program is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3 of the License, or 9 1.1 christos (at your option) any later version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program; if not, write to the Free Software 18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 1.1 christos MA 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos #include "sysdep.h" 22 1.1 christos #include "bfd.h" 23 1.1 christos #include "libbfd.h" 24 1.1 christos #include "elf-bfd.h" 25 1.1 christos #include "elf/xstormy16.h" 26 1.1 christos #include "libiberty.h" 27 1.1 christos 28 1.1 christos /* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */ 29 1.1 christos 30 1.1 christos static bfd_reloc_status_type 31 1.1 christos xstormy16_elf_24_reloc (bfd *abfd, 32 1.1 christos arelent *reloc_entry, 33 1.1 christos asymbol *symbol, 34 1.1 christos void * data, 35 1.1 christos asection *input_section, 36 1.1 christos bfd *output_bfd, 37 1.1 christos char **error_message ATTRIBUTE_UNUSED) 38 1.1 christos { 39 1.1 christos bfd_vma relocation, x; 40 1.1 christos 41 1.1 christos if (output_bfd != NULL) 42 1.1 christos { 43 1.1 christos reloc_entry->address += input_section->output_offset; 44 1.1 christos return bfd_reloc_ok; 45 1.1 christos } 46 1.1 christos 47 1.1 christos if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 48 1.1 christos return bfd_reloc_outofrange; 49 1.1 christos 50 1.1 christos if (bfd_is_com_section (symbol->section)) 51 1.1 christos relocation = 0; 52 1.1 christos else 53 1.1 christos relocation = symbol->value; 54 1.1 christos 55 1.1 christos relocation += symbol->section->output_section->vma; 56 1.1 christos relocation += symbol->section->output_offset; 57 1.1 christos relocation += reloc_entry->addend; 58 1.1 christos 59 1.1 christos x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 60 1.1 christos x &= 0x0000ff00; 61 1.1 christos x |= relocation & 0xff; 62 1.1 christos x |= (relocation << 8) & 0xffff0000; 63 1.1 christos bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address); 64 1.1 christos 65 1.1 christos if (relocation & ~ (bfd_vma) 0xffffff) 66 1.1 christos return bfd_reloc_overflow; 67 1.1 christos 68 1.1 christos return bfd_reloc_ok; 69 1.1 christos } 70 1.1 christos 71 1.1 christos static reloc_howto_type xstormy16_elf_howto_table [] = 72 1.1 christos { 73 1.1 christos /* This reloc does nothing. */ 74 1.1 christos HOWTO (R_XSTORMY16_NONE, /* type */ 75 1.1 christos 0, /* rightshift */ 76 1.8 christos 0, /* size */ 77 1.3 christos 0, /* bitsize */ 78 1.8 christos false, /* pc_relative */ 79 1.1 christos 0, /* bitpos */ 80 1.3 christos complain_overflow_dont, /* complain_on_overflow */ 81 1.1 christos bfd_elf_generic_reloc, /* special_function */ 82 1.1 christos "R_XSTORMY16_NONE", /* name */ 83 1.8 christos false, /* partial_inplace */ 84 1.1 christos 0, /* src_mask */ 85 1.1 christos 0, /* dst_mask */ 86 1.8 christos false), /* pcrel_offset */ 87 1.1 christos 88 1.1 christos /* A 32 bit absolute relocation. */ 89 1.1 christos HOWTO (R_XSTORMY16_32, /* type */ 90 1.1 christos 0, /* rightshift */ 91 1.8 christos 4, /* size */ 92 1.1 christos 32, /* bitsize */ 93 1.8 christos false, /* pc_relative */ 94 1.1 christos 0, /* bitpos */ 95 1.1 christos complain_overflow_dont, /* complain_on_overflow */ 96 1.1 christos bfd_elf_generic_reloc, /* special_function */ 97 1.1 christos "R_XSTORMY16_32", /* name */ 98 1.8 christos false, /* partial_inplace */ 99 1.1 christos 0, /* src_mask */ 100 1.1 christos 0xffffffff, /* dst_mask */ 101 1.8 christos false), /* pcrel_offset */ 102 1.1 christos 103 1.1 christos /* A 16 bit absolute relocation. */ 104 1.1 christos HOWTO (R_XSTORMY16_16, /* type */ 105 1.1 christos 0, /* rightshift */ 106 1.8 christos 2, /* size */ 107 1.1 christos 16, /* bitsize */ 108 1.8 christos false, /* pc_relative */ 109 1.1 christos 0, /* bitpos */ 110 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */ 111 1.1 christos bfd_elf_generic_reloc, /* special_function */ 112 1.1 christos "R_XSTORMY16_16", /* name */ 113 1.8 christos false, /* partial_inplace */ 114 1.1 christos 0, /* src_mask */ 115 1.1 christos 0xffff, /* dst_mask */ 116 1.8 christos false), /* pcrel_offset */ 117 1.1 christos 118 1.1 christos /* An 8 bit absolute relocation. */ 119 1.1 christos HOWTO (R_XSTORMY16_8, /* type */ 120 1.1 christos 0, /* rightshift */ 121 1.8 christos 1, /* size */ 122 1.1 christos 8, /* bitsize */ 123 1.8 christos false, /* pc_relative */ 124 1.1 christos 0, /* bitpos */ 125 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */ 126 1.1 christos bfd_elf_generic_reloc, /* special_function */ 127 1.1 christos "R_XSTORMY16_8", /* name */ 128 1.8 christos false, /* partial_inplace */ 129 1.1 christos 0, /* src_mask */ 130 1.1 christos 0xff, /* dst_mask */ 131 1.8 christos false), /* pcrel_offset */ 132 1.1 christos 133 1.1 christos /* A 32 bit pc-relative relocation. */ 134 1.1 christos HOWTO (R_XSTORMY16_PC32, /* type */ 135 1.1 christos 0, /* rightshift */ 136 1.8 christos 4, /* size */ 137 1.1 christos 32, /* bitsize */ 138 1.8 christos true, /* pc_relative */ 139 1.1 christos 0, /* bitpos */ 140 1.1 christos complain_overflow_dont, /* complain_on_overflow */ 141 1.1 christos bfd_elf_generic_reloc, /* special_function */ 142 1.1 christos "R_XSTORMY16_PC32", /* name */ 143 1.8 christos false, /* partial_inplace */ 144 1.1 christos 0, /* src_mask */ 145 1.1 christos 0xffffffff, /* dst_mask */ 146 1.8 christos true), /* pcrel_offset */ 147 1.1 christos 148 1.1 christos /* A 16 bit pc-relative relocation. */ 149 1.1 christos HOWTO (R_XSTORMY16_PC16, /* type */ 150 1.1 christos 0, /* rightshift */ 151 1.8 christos 2, /* size */ 152 1.1 christos 16, /* bitsize */ 153 1.8 christos true, /* pc_relative */ 154 1.1 christos 0, /* bitpos */ 155 1.1 christos complain_overflow_signed, /* complain_on_overflow */ 156 1.1 christos bfd_elf_generic_reloc, /* special_function */ 157 1.1 christos "R_XSTORMY16_PC16", /* name */ 158 1.8 christos false, /* partial_inplace */ 159 1.1 christos 0, /* src_mask */ 160 1.1 christos 0xffffffff, /* dst_mask */ 161 1.8 christos true), /* pcrel_offset */ 162 1.1 christos 163 1.1 christos /* An 8 bit pc-relative relocation. */ 164 1.1 christos HOWTO (R_XSTORMY16_PC8, /* type */ 165 1.1 christos 0, /* rightshift */ 166 1.8 christos 1, /* size */ 167 1.1 christos 8, /* bitsize */ 168 1.8 christos true, /* pc_relative */ 169 1.1 christos 0, /* bitpos */ 170 1.1 christos complain_overflow_signed, /* complain_on_overflow */ 171 1.1 christos bfd_elf_generic_reloc, /* special_function */ 172 1.1 christos "R_XSTORMY16_PC8", /* name */ 173 1.8 christos false, /* partial_inplace */ 174 1.1 christos 0, /* src_mask */ 175 1.1 christos 0xffffffff, /* dst_mask */ 176 1.8 christos true), /* pcrel_offset */ 177 1.1 christos 178 1.1 christos /* A 12-bit pc-relative relocation suitable for the branch instructions. */ 179 1.1 christos HOWTO (R_XSTORMY16_REL_12, /* type */ 180 1.1 christos 1, /* rightshift */ 181 1.8 christos 2, /* size */ 182 1.1 christos 11, /* bitsize */ 183 1.8 christos true, /* pc_relative */ 184 1.1 christos 1, /* bitpos */ 185 1.1 christos complain_overflow_signed, /* complain_on_overflow */ 186 1.1 christos bfd_elf_generic_reloc, /* special_function */ 187 1.1 christos "R_XSTORMY16_REL_12", /* name */ 188 1.8 christos false, /* partial_inplace */ 189 1.1 christos 0, /* src_mask */ 190 1.1 christos 0x0ffe, /* dst_mask */ 191 1.8 christos true), /* pcrel_offset */ 192 1.1 christos 193 1.1 christos /* A 24-bit absolute relocation suitable for the jump instructions. */ 194 1.1 christos HOWTO (R_XSTORMY16_24, /* type */ 195 1.1 christos 0, /* rightshift */ 196 1.8 christos 4, /* size */ 197 1.1 christos 24, /* bitsize */ 198 1.8 christos false, /* pc_relative */ 199 1.1 christos 0, /* bitpos */ 200 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */ 201 1.1 christos xstormy16_elf_24_reloc, /* special_function */ 202 1.1 christos "R_XSTORMY16_24", /* name */ 203 1.8 christos true, /* partial_inplace */ 204 1.1 christos 0, /* src_mask */ 205 1.1 christos 0xffff00ff, /* dst_mask */ 206 1.8 christos true), /* pcrel_offset */ 207 1.1 christos 208 1.1 christos /* A 16 bit absolute relocation to a function pointer. */ 209 1.1 christos HOWTO (R_XSTORMY16_FPTR16, /* type */ 210 1.1 christos 0, /* rightshift */ 211 1.8 christos 2, /* size */ 212 1.1 christos 16, /* bitsize */ 213 1.8 christos false, /* pc_relative */ 214 1.1 christos 0, /* bitpos */ 215 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */ 216 1.1 christos bfd_elf_generic_reloc, /* special_function */ 217 1.1 christos "R_XSTORMY16_FPTR16", /* name */ 218 1.8 christos false, /* partial_inplace */ 219 1.1 christos 0, /* src_mask */ 220 1.1 christos 0xffffffff, /* dst_mask */ 221 1.8 christos false), /* pcrel_offset */ 222 1.1 christos 223 1.1 christos /* Low order 16 bit value of a high memory address. */ 224 1.1 christos HOWTO (R_XSTORMY16_LO16, /* type */ 225 1.1 christos 0, /* rightshift */ 226 1.8 christos 2, /* size */ 227 1.1 christos 16, /* bitsize */ 228 1.8 christos false, /* pc_relative */ 229 1.1 christos 0, /* bitpos */ 230 1.1 christos complain_overflow_dont, /* complain_on_overflow */ 231 1.1 christos bfd_elf_generic_reloc, /* special_function */ 232 1.1 christos "R_XSTORMY16_LO16", /* name */ 233 1.8 christos false, /* partial_inplace */ 234 1.1 christos 0, /* src_mask */ 235 1.1 christos 0xffff, /* dst_mask */ 236 1.8 christos false), /* pcrel_offset */ 237 1.1 christos 238 1.1 christos /* High order 16 bit value of a high memory address. */ 239 1.1 christos HOWTO (R_XSTORMY16_HI16, /* type */ 240 1.1 christos 16, /* rightshift */ 241 1.8 christos 2, /* size */ 242 1.1 christos 16, /* bitsize */ 243 1.8 christos false, /* pc_relative */ 244 1.1 christos 0, /* bitpos */ 245 1.1 christos complain_overflow_dont, /* complain_on_overflow */ 246 1.1 christos bfd_elf_generic_reloc, /* special_function */ 247 1.1 christos "R_XSTORMY16_HI16", /* name */ 248 1.8 christos false, /* partial_inplace */ 249 1.1 christos 0, /* src_mask */ 250 1.1 christos 0xffff, /* dst_mask */ 251 1.8 christos false), /* pcrel_offset */ 252 1.1 christos 253 1.1 christos /* A 12 bit absolute relocation. */ 254 1.1 christos HOWTO (R_XSTORMY16_12, /* type */ 255 1.1 christos 0, /* rightshift */ 256 1.8 christos 2, /* size */ 257 1.1 christos 12, /* bitsize */ 258 1.8 christos false, /* pc_relative */ 259 1.1 christos 0, /* bitpos */ 260 1.1 christos complain_overflow_signed, /* complain_on_overflow */ 261 1.1 christos bfd_elf_generic_reloc, /* special_function */ 262 1.1 christos "R_XSTORMY16_12", /* name */ 263 1.8 christos false, /* partial_inplace */ 264 1.1 christos 0x0000, /* src_mask */ 265 1.1 christos 0x0fff, /* dst_mask */ 266 1.8 christos false), /* pcrel_offset */ 267 1.1 christos }; 268 1.1 christos 269 1.1 christos static reloc_howto_type xstormy16_elf_howto_table2 [] = 270 1.1 christos { 271 1.1 christos /* GNU extension to record C++ vtable hierarchy */ 272 1.1 christos HOWTO (R_XSTORMY16_GNU_VTINHERIT, /* type */ 273 1.6 christos 0, /* rightshift */ 274 1.8 christos 4, /* size */ 275 1.6 christos 0, /* bitsize */ 276 1.8 christos false, /* pc_relative */ 277 1.6 christos 0, /* bitpos */ 278 1.6 christos complain_overflow_dont, /* complain_on_overflow */ 279 1.6 christos NULL, /* special_function */ 280 1.6 christos "R_XSTORMY16_GNU_VTINHERIT", /* name */ 281 1.8 christos false, /* partial_inplace */ 282 1.6 christos 0, /* src_mask */ 283 1.6 christos 0, /* dst_mask */ 284 1.8 christos false), /* pcrel_offset */ 285 1.1 christos 286 1.1 christos /* GNU extension to record C++ vtable member usage */ 287 1.1 christos HOWTO (R_XSTORMY16_GNU_VTENTRY, /* type */ 288 1.6 christos 0, /* rightshift */ 289 1.8 christos 4, /* size */ 290 1.6 christos 0, /* bitsize */ 291 1.8 christos false, /* pc_relative */ 292 1.6 christos 0, /* bitpos */ 293 1.6 christos complain_overflow_dont, /* complain_on_overflow */ 294 1.6 christos _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 295 1.6 christos "R_XSTORMY16_GNU_VTENTRY", /* name */ 296 1.8 christos false, /* partial_inplace */ 297 1.6 christos 0, /* src_mask */ 298 1.6 christos 0, /* dst_mask */ 299 1.8 christos false), /* pcrel_offset */ 300 1.1 christos 301 1.1 christos }; 302 1.1 christos 303 1.1 christos /* Map BFD reloc types to XSTORMY16 ELF reloc types. */ 305 1.1 christos 306 1.1 christos typedef struct xstormy16_reloc_map 307 1.1 christos { 308 1.6 christos bfd_reloc_code_real_type bfd_reloc_val; 309 1.6 christos unsigned int xstormy16_reloc_val; 310 1.1 christos reloc_howto_type * table; 311 1.1 christos } reloc_map; 312 1.1 christos 313 1.1 christos static const reloc_map xstormy16_reloc_map [] = 314 1.6 christos { 315 1.6 christos { BFD_RELOC_NONE, R_XSTORMY16_NONE, xstormy16_elf_howto_table }, 316 1.6 christos { BFD_RELOC_32, R_XSTORMY16_32, xstormy16_elf_howto_table }, 317 1.6 christos { BFD_RELOC_16, R_XSTORMY16_16, xstormy16_elf_howto_table }, 318 1.6 christos { BFD_RELOC_8, R_XSTORMY16_8, xstormy16_elf_howto_table }, 319 1.6 christos { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32, xstormy16_elf_howto_table }, 320 1.6 christos { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16, xstormy16_elf_howto_table }, 321 1.6 christos { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8, xstormy16_elf_howto_table }, 322 1.6 christos { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12, xstormy16_elf_howto_table }, 323 1.6 christos { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24, xstormy16_elf_howto_table }, 324 1.6 christos { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16, xstormy16_elf_howto_table }, 325 1.6 christos { BFD_RELOC_LO16, R_XSTORMY16_LO16, xstormy16_elf_howto_table }, 326 1.6 christos { BFD_RELOC_HI16, R_XSTORMY16_HI16, xstormy16_elf_howto_table }, 327 1.6 christos { BFD_RELOC_XSTORMY16_12, R_XSTORMY16_12, xstormy16_elf_howto_table }, 328 1.6 christos { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 }, 329 1.1 christos { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY, xstormy16_elf_howto_table2 }, 330 1.1 christos }; 331 1.1 christos 332 1.1 christos static reloc_howto_type * 333 1.1 christos xstormy16_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, 334 1.1 christos bfd_reloc_code_real_type code) 335 1.1 christos { 336 1.1 christos unsigned int i; 337 1.3 christos 338 1.1 christos for (i = ARRAY_SIZE (xstormy16_reloc_map); i--;) 339 1.1 christos { 340 1.1 christos const reloc_map * entry; 341 1.1 christos 342 1.1 christos entry = xstormy16_reloc_map + i; 343 1.1 christos 344 1.1 christos if (entry->bfd_reloc_val == code) 345 1.1 christos return entry->table + (entry->xstormy16_reloc_val 346 1.1 christos - entry->table[0].type); 347 1.1 christos } 348 1.1 christos 349 1.1 christos return NULL; 350 1.1 christos } 351 1.1 christos 352 1.1 christos static reloc_howto_type * 353 1.1 christos xstormy16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 354 1.1 christos const char *r_name) 355 1.1 christos { 356 1.1 christos unsigned int i; 357 1.1 christos 358 1.1 christos for (i = 0; 359 1.1 christos i < (sizeof (xstormy16_elf_howto_table) 360 1.1 christos / sizeof (xstormy16_elf_howto_table[0])); 361 1.1 christos i++) 362 1.1 christos if (xstormy16_elf_howto_table[i].name != NULL 363 1.1 christos && strcasecmp (xstormy16_elf_howto_table[i].name, r_name) == 0) 364 1.1 christos return &xstormy16_elf_howto_table[i]; 365 1.1 christos 366 1.1 christos for (i = 0; 367 1.1 christos i < (sizeof (xstormy16_elf_howto_table2) 368 1.1 christos / sizeof (xstormy16_elf_howto_table2[0])); 369 1.1 christos i++) 370 1.1 christos if (xstormy16_elf_howto_table2[i].name != NULL 371 1.1 christos && strcasecmp (xstormy16_elf_howto_table2[i].name, r_name) == 0) 372 1.1 christos return &xstormy16_elf_howto_table2[i]; 373 1.1 christos 374 1.1 christos return NULL; 375 1.1 christos } 376 1.1 christos 377 1.1 christos /* Set the howto pointer for an XSTORMY16 ELF reloc. */ 378 1.8 christos 379 1.6 christos static bool 380 1.1 christos xstormy16_info_to_howto_rela (bfd * abfd, 381 1.1 christos arelent * cache_ptr, 382 1.1 christos Elf_Internal_Rela * dst) 383 1.1 christos { 384 1.1 christos unsigned int r_type = ELF32_R_TYPE (dst->r_info); 385 1.1 christos 386 1.1 christos if (r_type <= (unsigned int) R_XSTORMY16_12) 387 1.1 christos cache_ptr->howto = &xstormy16_elf_howto_table [r_type]; 388 1.6 christos else if (r_type - R_XSTORMY16_GNU_VTINHERIT 389 1.6 christos <= ((unsigned int) R_XSTORMY16_GNU_VTENTRY 390 1.1 christos - (unsigned int) R_XSTORMY16_GNU_VTINHERIT)) 391 1.1 christos cache_ptr->howto 392 1.1 christos = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT]; 393 1.6 christos else 394 1.6 christos { 395 1.6 christos /* xgettext:c-format */ 396 1.6 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 397 1.6 christos abfd, r_type); 398 1.8 christos bfd_set_error (bfd_error_bad_value); 399 1.6 christos return false; 400 1.8 christos } 401 1.1 christos return true; 402 1.1 christos } 403 1.1 christos 404 1.1 christos /* We support 16-bit pointers to code above 64k by generating a thunk 406 1.1 christos below 64k containing a JMPF instruction to the final address. We 407 1.1 christos cannot, unfortunately, minimize the number of thunks unless the 408 1.1 christos -relax switch is given, as otherwise we have no idea where the 409 1.8 christos sections will fall in the address space. */ 410 1.1 christos 411 1.1 christos static bool 412 1.1 christos xstormy16_elf_check_relocs (bfd *abfd, 413 1.1 christos struct bfd_link_info *info, 414 1.1 christos asection *sec, 415 1.1 christos const Elf_Internal_Rela *relocs) 416 1.1 christos { 417 1.1 christos const Elf_Internal_Rela *rel, *relend; 418 1.1 christos struct elf_link_hash_entry **sym_hashes; 419 1.1 christos Elf_Internal_Shdr *symtab_hdr; 420 1.1 christos bfd_vma *local_plt_offsets; 421 1.1 christos asection *splt; 422 1.3 christos bfd *dynobj; 423 1.8 christos 424 1.1 christos if (bfd_link_relocatable (info)) 425 1.1 christos return true; 426 1.1 christos 427 1.1 christos symtab_hdr = &elf_tdata(abfd)->symtab_hdr; 428 1.1 christos sym_hashes = elf_sym_hashes (abfd); 429 1.1 christos local_plt_offsets = elf_local_got_offsets (abfd); 430 1.1 christos dynobj = elf_hash_table(info)->dynobj; 431 1.1 christos 432 1.1 christos relend = relocs + sec->reloc_count; 433 1.1 christos for (rel = relocs; rel < relend; ++rel) 434 1.1 christos { 435 1.1 christos unsigned long r_symndx; 436 1.1 christos struct elf_link_hash_entry *h; 437 1.1 christos bfd_vma *offset; 438 1.1 christos 439 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 440 1.1 christos if (r_symndx < symtab_hdr->sh_info) 441 1.1 christos h = NULL; 442 1.1 christos else 443 1.1 christos { 444 1.1 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 445 1.1 christos while (h->root.type == bfd_link_hash_indirect 446 1.1 christos || h->root.type == bfd_link_hash_warning) 447 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link; 448 1.1 christos } 449 1.6 christos 450 1.1 christos switch (ELF32_R_TYPE (rel->r_info)) 451 1.1 christos { 452 1.1 christos /* This relocation describes a 16-bit pointer to a function. 453 1.1 christos We may need to allocate a thunk in low memory; reserve memory 454 1.1 christos for it now. */ 455 1.1 christos case R_XSTORMY16_FPTR16: 456 1.1 christos if (rel->r_addend != 0) 457 1.1 christos { 458 1.1 christos (*info->callbacks->warning) 459 1.1 christos (info, _("non-zero addend in @fptr reloc"), 0, 460 1.1 christos abfd, 0, 0); 461 1.1 christos } 462 1.1 christos 463 1.6 christos if (dynobj == NULL) 464 1.1 christos elf_hash_table (info)->dynobj = dynobj = abfd; 465 1.1 christos splt = elf_hash_table (info)->splt; 466 1.6 christos if (splt == NULL) 467 1.6 christos { 468 1.6 christos flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS 469 1.6 christos | SEC_IN_MEMORY | SEC_LINKER_CREATED 470 1.6 christos | SEC_READONLY | SEC_CODE); 471 1.6 christos 472 1.6 christos splt = bfd_make_section_anyway_with_flags (dynobj, ".plt", 473 1.6 christos flags); 474 1.7 christos elf_hash_table (info)->splt = splt; 475 1.8 christos if (splt == NULL 476 1.1 christos || !bfd_set_section_alignment (splt, 1)) 477 1.1 christos return false; 478 1.1 christos } 479 1.1 christos 480 1.1 christos if (h != NULL) 481 1.1 christos offset = &h->plt.offset; 482 1.1 christos else 483 1.1 christos { 484 1.1 christos if (local_plt_offsets == NULL) 485 1.1 christos { 486 1.1 christos size_t size; 487 1.1 christos unsigned int i; 488 1.1 christos 489 1.1 christos size = symtab_hdr->sh_info * sizeof (bfd_vma); 490 1.8 christos local_plt_offsets = bfd_alloc (abfd, size); 491 1.1 christos if (local_plt_offsets == NULL) 492 1.1 christos return false; 493 1.1 christos elf_local_got_offsets (abfd) = local_plt_offsets; 494 1.1 christos 495 1.1 christos for (i = 0; i < symtab_hdr->sh_info; i++) 496 1.1 christos local_plt_offsets[i] = (bfd_vma) -1; 497 1.1 christos } 498 1.1 christos offset = &local_plt_offsets[r_symndx]; 499 1.1 christos } 500 1.1 christos 501 1.1 christos if (*offset == (bfd_vma) -1) 502 1.1 christos { 503 1.1 christos *offset = splt->size; 504 1.1 christos splt->size += 4; 505 1.1 christos } 506 1.1 christos break; 507 1.1 christos 508 1.6 christos /* This relocation describes the C++ object vtable hierarchy. 509 1.6 christos Reconstruct it for later use during GC. */ 510 1.8 christos case R_XSTORMY16_GNU_VTINHERIT: 511 1.6 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 512 1.1 christos return false; 513 1.1 christos break; 514 1.1 christos 515 1.6 christos /* This relocation describes which C++ vtable entries are actually 516 1.7 christos used. Record for later use during GC. */ 517 1.8 christos case R_XSTORMY16_GNU_VTENTRY: 518 1.6 christos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 519 1.1 christos return false; 520 1.1 christos break; 521 1.1 christos } 522 1.8 christos } 523 1.1 christos 524 1.1 christos return true; 525 1.1 christos } 526 1.1 christos 527 1.1 christos /* A subroutine of xstormy16_elf_relax_section. If the global symbol H 528 1.1 christos is within the low 64k, remove any entry for it in the plt. */ 529 1.1 christos 530 1.1 christos struct relax_plt_data 531 1.8 christos { 532 1.1 christos asection *splt; 533 1.1 christos bool *again; 534 1.8 christos }; 535 1.1 christos 536 1.1 christos static bool 537 1.1 christos xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata) 538 1.1 christos { 539 1.1 christos struct relax_plt_data *data = (struct relax_plt_data *) xdata; 540 1.1 christos 541 1.1 christos if (h->plt.offset != (bfd_vma) -1) 542 1.1 christos { 543 1.1 christos bfd_vma address; 544 1.1 christos 545 1.1 christos if (h->root.type == bfd_link_hash_undefined 546 1.1 christos || h->root.type == bfd_link_hash_undefweak) 547 1.1 christos address = 0; 548 1.1 christos else 549 1.1 christos address = (h->root.u.def.section->output_section->vma 550 1.1 christos + h->root.u.def.section->output_offset 551 1.1 christos + h->root.u.def.value); 552 1.1 christos 553 1.1 christos if (address <= 0xffff) 554 1.1 christos { 555 1.8 christos h->plt.offset = -1; 556 1.1 christos data->splt->size -= 4; 557 1.1 christos *data->again = true; 558 1.1 christos } 559 1.8 christos } 560 1.1 christos 561 1.1 christos return true; 562 1.1 christos } 563 1.1 christos 564 1.1 christos /* A subroutine of xstormy16_elf_relax_section. If the global symbol H 565 1.8 christos previously had a plt entry, give it a new entry offset. */ 566 1.1 christos 567 1.1 christos static bool 568 1.1 christos xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata) 569 1.1 christos { 570 1.1 christos bfd_vma *entry = (bfd_vma *) xdata; 571 1.1 christos 572 1.1 christos if (h->plt.offset != (bfd_vma) -1) 573 1.1 christos { 574 1.1 christos h->plt.offset = *entry; 575 1.1 christos *entry += 4; 576 1.8 christos } 577 1.1 christos 578 1.1 christos return true; 579 1.8 christos } 580 1.1 christos 581 1.1 christos static bool 582 1.1 christos xstormy16_elf_relax_section (bfd *dynobj, 583 1.8 christos asection *splt, 584 1.1 christos struct bfd_link_info *info, 585 1.1 christos bool *again) 586 1.1 christos { 587 1.1 christos struct relax_plt_data relax_plt_data; 588 1.1 christos bfd *ibfd; 589 1.8 christos 590 1.1 christos /* Assume nothing changes. */ 591 1.8 christos *again = false; 592 1.8 christos 593 1.8 christos if (bfd_link_relocatable (info) 594 1.1 christos || !is_elf_hash_table (info->hash)) 595 1.1 christos return true; 596 1.1 christos 597 1.1 christos /* We only relax the .plt section at the moment. */ 598 1.8 christos if (dynobj != elf_hash_table (info)->dynobj 599 1.1 christos || strcmp (splt->name, ".plt") != 0) 600 1.1 christos return true; 601 1.1 christos 602 1.8 christos /* Quick check for an empty plt. */ 603 1.1 christos if (splt->size == 0) 604 1.1 christos return true; 605 1.1 christos 606 1.1 christos /* Map across all global symbols; see which ones happen to 607 1.1 christos fall in the low 64k. */ 608 1.1 christos relax_plt_data.splt = splt; 609 1.1 christos relax_plt_data.again = again; 610 1.1 christos elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check, 611 1.1 christos &relax_plt_data); 612 1.1 christos 613 1.3 christos /* Likewise for local symbols, though that's somewhat less convenient 614 1.1 christos as we have to walk the list of input bfds and swap in symbol data. */ 615 1.1 christos for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next) 616 1.1 christos { 617 1.1 christos bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd); 618 1.1 christos Elf_Internal_Shdr *symtab_hdr; 619 1.1 christos Elf_Internal_Sym *isymbuf = NULL; 620 1.1 christos unsigned int idx; 621 1.1 christos 622 1.1 christos if (! local_plt_offsets) 623 1.1 christos continue; 624 1.1 christos 625 1.1 christos symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 626 1.1 christos if (symtab_hdr->sh_info != 0) 627 1.1 christos { 628 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 629 1.1 christos if (isymbuf == NULL) 630 1.1 christos isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr, 631 1.1 christos symtab_hdr->sh_info, 0, 632 1.8 christos NULL, NULL, NULL); 633 1.1 christos if (isymbuf == NULL) 634 1.1 christos return false; 635 1.1 christos } 636 1.1 christos 637 1.1 christos for (idx = 0; idx < symtab_hdr->sh_info; ++idx) 638 1.1 christos { 639 1.1 christos Elf_Internal_Sym *isym; 640 1.1 christos asection *tsec; 641 1.1 christos bfd_vma address; 642 1.1 christos 643 1.1 christos if (local_plt_offsets[idx] == (bfd_vma) -1) 644 1.1 christos continue; 645 1.1 christos 646 1.1 christos isym = &isymbuf[idx]; 647 1.1 christos if (isym->st_shndx == SHN_UNDEF) 648 1.1 christos continue; 649 1.1 christos else if (isym->st_shndx == SHN_ABS) 650 1.1 christos tsec = bfd_abs_section_ptr; 651 1.1 christos else if (isym->st_shndx == SHN_COMMON) 652 1.1 christos tsec = bfd_com_section_ptr; 653 1.1 christos else 654 1.1 christos tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx); 655 1.1 christos 656 1.1 christos address = (tsec->output_section->vma 657 1.1 christos + tsec->output_offset 658 1.1 christos + isym->st_value); 659 1.1 christos if (address <= 0xffff) 660 1.1 christos { 661 1.8 christos local_plt_offsets[idx] = -1; 662 1.1 christos splt->size -= 4; 663 1.1 christos *again = true; 664 1.1 christos } 665 1.1 christos } 666 1.1 christos 667 1.1 christos if (isymbuf != NULL 668 1.1 christos && symtab_hdr->contents != (unsigned char *) isymbuf) 669 1.1 christos { 670 1.1 christos if (! info->keep_memory) 671 1.1 christos free (isymbuf); 672 1.1 christos else 673 1.1 christos { 674 1.1 christos /* Cache the symbols for elf_link_input_bfd. */ 675 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf; 676 1.1 christos } 677 1.1 christos } 678 1.1 christos } 679 1.1 christos 680 1.1 christos /* If we changed anything, walk the symbols again to reallocate 681 1.1 christos .plt entry addresses. */ 682 1.1 christos if (*again && splt->size > 0) 683 1.1 christos { 684 1.1 christos bfd_vma entry = 0; 685 1.1 christos 686 1.1 christos elf_link_hash_traverse (elf_hash_table (info), 687 1.3 christos xstormy16_relax_plt_realloc, &entry); 688 1.1 christos 689 1.1 christos for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next) 690 1.1 christos { 691 1.1 christos bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd); 692 1.1 christos unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info; 693 1.1 christos unsigned int idx; 694 1.1 christos 695 1.1 christos if (! local_plt_offsets) 696 1.1 christos continue; 697 1.1 christos 698 1.1 christos for (idx = 0; idx < nlocals; ++idx) 699 1.6 christos if (local_plt_offsets[idx] != (bfd_vma) -1) 700 1.1 christos { 701 1.1 christos local_plt_offsets[idx] = entry; 702 1.1 christos entry += 4; 703 1.1 christos } 704 1.1 christos } 705 1.8 christos } 706 1.1 christos 707 1.1 christos return true; 708 1.8 christos } 709 1.10 christos 710 1.10 christos static bool 711 1.1 christos xstormy16_elf_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, 712 1.1 christos struct bfd_link_info *info) 713 1.1 christos { 714 1.1 christos bfd *dynobj; 715 1.3 christos asection *splt; 716 1.8 christos 717 1.1 christos if (bfd_link_relocatable (info)) 718 1.1 christos return true; 719 1.1 christos 720 1.8 christos dynobj = elf_hash_table (info)->dynobj; 721 1.1 christos if (dynobj == NULL) 722 1.6 christos return true; 723 1.1 christos 724 1.1 christos splt = elf_hash_table (info)->splt; 725 1.1 christos BFD_ASSERT (splt != NULL); 726 1.1 christos 727 1.8 christos splt->contents = bfd_zalloc (dynobj, splt->size); 728 1.10 christos if (splt->contents == NULL) 729 1.1 christos return false; 730 1.8 christos splt->alloced = 1; 731 1.1 christos 732 1.1 christos return true; 733 1.1 christos } 734 1.1 christos 735 1.1 christos /* Relocate an XSTORMY16 ELF section. 737 1.1 christos 738 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker 739 1.1 christos to handle the relocations for a section. 740 1.1 christos 741 1.1 christos The relocs are always passed as Rela structures; if the section 742 1.1 christos actually uses Rel structures, the r_addend field will always be 743 1.1 christos zero. 744 1.1 christos 745 1.1 christos This function is responsible for adjusting the section contents as 746 1.1 christos necessary, and (if using Rela relocs and generating a relocatable 747 1.1 christos output file) adjusting the reloc addend as necessary. 748 1.1 christos 749 1.1 christos This function does not have to worry about setting the reloc 750 1.1 christos address or the reloc symbol index. 751 1.1 christos 752 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols. 753 1.1 christos 754 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file 755 1.1 christos corresponding to the st_shndx field of each local symbol. 756 1.1 christos 757 1.1 christos The global hash table entry for the global symbols can be found 758 1.1 christos via elf_sym_hashes (input_bfd). 759 1.1 christos 760 1.1 christos When generating relocatable output, this function must handle 761 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is 762 1.1 christos going to be the section symbol corresponding to the output 763 1.8 christos section, which means that the addend must be adjusted 764 1.6 christos accordingly. */ 765 1.6 christos 766 1.6 christos static int 767 1.6 christos xstormy16_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, 768 1.6 christos struct bfd_link_info * info, 769 1.6 christos bfd * input_bfd, 770 1.6 christos asection * input_section, 771 1.6 christos bfd_byte * contents, 772 1.1 christos Elf_Internal_Rela * relocs, 773 1.6 christos Elf_Internal_Sym * local_syms, 774 1.1 christos asection ** local_sections) 775 1.6 christos { 776 1.6 christos Elf_Internal_Shdr * symtab_hdr; 777 1.1 christos struct elf_link_hash_entry ** sym_hashes; 778 1.1 christos Elf_Internal_Rela * rel; 779 1.1 christos Elf_Internal_Rela * relend; 780 1.1 christos asection *splt; 781 1.1 christos 782 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 783 1.6 christos sym_hashes = elf_sym_hashes (input_bfd); 784 1.1 christos relend = relocs + input_section->reloc_count; 785 1.1 christos 786 1.1 christos splt = elf_hash_table (info)->splt; 787 1.6 christos 788 1.6 christos for (rel = relocs; rel < relend; rel ++) 789 1.6 christos { 790 1.6 christos reloc_howto_type * howto; 791 1.1 christos unsigned long r_symndx; 792 1.6 christos Elf_Internal_Sym * sym; 793 1.6 christos asection * sec; 794 1.6 christos struct elf_link_hash_entry * h; 795 1.6 christos bfd_vma relocation; 796 1.1 christos bfd_reloc_status_type r; 797 1.1 christos const char * name = NULL; 798 1.1 christos int r_type; 799 1.1 christos 800 1.1 christos r_type = ELF32_R_TYPE (rel->r_info); 801 1.1 christos 802 1.1 christos if ( r_type == R_XSTORMY16_GNU_VTINHERIT 803 1.1 christos || r_type == R_XSTORMY16_GNU_VTENTRY) 804 1.1 christos continue; 805 1.1 christos 806 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 807 1.1 christos howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info); 808 1.1 christos h = NULL; 809 1.1 christos sym = NULL; 810 1.1 christos sec = NULL; 811 1.1 christos 812 1.1 christos if (r_symndx < symtab_hdr->sh_info) 813 1.1 christos { 814 1.1 christos sym = local_syms + r_symndx; 815 1.1 christos sec = local_sections [r_symndx]; 816 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 817 1.8 christos } 818 1.1 christos else 819 1.1 christos { 820 1.1 christos bool unresolved_reloc, warned, ignored; 821 1.1 christos 822 1.3 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 823 1.1 christos r_symndx, symtab_hdr, sym_hashes, 824 1.1 christos h, sec, relocation, 825 1.1 christos unresolved_reloc, warned, ignored); 826 1.1 christos } 827 1.1 christos 828 1.1 christos if (sec != NULL && discarded_section (sec)) 829 1.3 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 830 1.1 christos rel, 1, relend, howto, 0, contents); 831 1.1 christos 832 1.1 christos if (bfd_link_relocatable (info)) 833 1.1 christos continue; 834 1.1 christos 835 1.1 christos if (h != NULL) 836 1.1 christos name = h->root.root.string; 837 1.1 christos else 838 1.1 christos { 839 1.7 christos name = (bfd_elf_string_from_elf_section 840 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name)); 841 1.1 christos if (name == NULL || *name == '\0') 842 1.1 christos name = bfd_section_name (sec); 843 1.1 christos } 844 1.1 christos 845 1.1 christos switch (ELF32_R_TYPE (rel->r_info)) 846 1.1 christos { 847 1.1 christos case R_XSTORMY16_24: 848 1.1 christos { 849 1.1 christos bfd_vma reloc = relocation + rel->r_addend; 850 1.1 christos unsigned int x; 851 1.1 christos 852 1.1 christos x = bfd_get_32 (input_bfd, contents + rel->r_offset); 853 1.1 christos x &= 0x0000ff00; 854 1.1 christos x |= reloc & 0xff; 855 1.1 christos x |= (reloc << 8) & 0xffff0000; 856 1.1 christos bfd_put_32 (input_bfd, x, contents + rel->r_offset); 857 1.1 christos 858 1.1 christos if (reloc & ~0xffffff) 859 1.1 christos r = bfd_reloc_overflow; 860 1.1 christos else 861 1.1 christos r = bfd_reloc_ok; 862 1.1 christos break; 863 1.1 christos } 864 1.1 christos 865 1.1 christos case R_XSTORMY16_FPTR16: 866 1.1 christos { 867 1.1 christos bfd_vma *plt_offset; 868 1.1 christos 869 1.1 christos if (h != NULL) 870 1.1 christos plt_offset = &h->plt.offset; 871 1.1 christos else 872 1.1 christos plt_offset = elf_local_got_offsets (input_bfd) + r_symndx; 873 1.6 christos 874 1.1 christos if (relocation <= 0xffff) 875 1.6 christos { 876 1.1 christos /* If the symbol is in range for a 16-bit address, we should 877 1.1 christos have deallocated the plt entry in relax_section. */ 878 1.1 christos BFD_ASSERT (*plt_offset == (bfd_vma) -1); 879 1.1 christos } 880 1.1 christos else 881 1.1 christos { 882 1.1 christos /* If the symbol is out of range for a 16-bit address, 883 1.1 christos we must have allocated a plt entry. */ 884 1.1 christos BFD_ASSERT (*plt_offset != (bfd_vma) -1); 885 1.1 christos 886 1.1 christos /* If this is the first time we've processed this symbol, 887 1.1 christos fill in the plt entry with the correct symbol address. */ 888 1.1 christos if ((*plt_offset & 1) == 0) 889 1.1 christos { 890 1.1 christos unsigned int x; 891 1.1 christos 892 1.1 christos x = 0x00000200; /* jmpf */ 893 1.1 christos x |= relocation & 0xff; 894 1.1 christos x |= (relocation << 8) & 0xffff0000; 895 1.1 christos bfd_put_32 (input_bfd, x, splt->contents + *plt_offset); 896 1.1 christos *plt_offset |= 1; 897 1.1 christos } 898 1.1 christos 899 1.1 christos relocation = (splt->output_section->vma 900 1.1 christos + splt->output_offset 901 1.1 christos + (*plt_offset & -2)); 902 1.1 christos } 903 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section, 904 1.1 christos contents, rel->r_offset, 905 1.1 christos relocation, 0); 906 1.1 christos break; 907 1.1 christos } 908 1.1 christos 909 1.1 christos default: 910 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section, 911 1.1 christos contents, rel->r_offset, 912 1.1 christos relocation, rel->r_addend); 913 1.1 christos break; 914 1.1 christos } 915 1.1 christos 916 1.1 christos if (r != bfd_reloc_ok) 917 1.1 christos { 918 1.1 christos const char * msg = NULL; 919 1.1 christos 920 1.5 christos switch (r) 921 1.1 christos { 922 1.1 christos case bfd_reloc_overflow: 923 1.1 christos (*info->callbacks->reloc_overflow) 924 1.1 christos (info, (h ? &h->root : NULL), name, howto->name, 925 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset); 926 1.5 christos break; 927 1.8 christos 928 1.1 christos case bfd_reloc_undefined: 929 1.1 christos (*info->callbacks->undefined_symbol) 930 1.1 christos (info, name, input_bfd, input_section, rel->r_offset, true); 931 1.1 christos break; 932 1.1 christos 933 1.1 christos case bfd_reloc_outofrange: 934 1.1 christos msg = _("internal error: out of range error"); 935 1.1 christos break; 936 1.1 christos 937 1.1 christos case bfd_reloc_notsupported: 938 1.1 christos msg = _("internal error: unsupported relocation error"); 939 1.1 christos break; 940 1.1 christos 941 1.1 christos case bfd_reloc_dangerous: 942 1.1 christos msg = _("internal error: dangerous relocation"); 943 1.1 christos break; 944 1.1 christos 945 1.1 christos default: 946 1.1 christos msg = _("internal error: unknown error"); 947 1.1 christos break; 948 1.5 christos } 949 1.5 christos 950 1.1 christos if (msg) 951 1.1 christos (*info->callbacks->warning) (info, msg, name, input_bfd, 952 1.1 christos input_section, rel->r_offset); 953 1.8 christos } 954 1.1 christos } 955 1.1 christos 956 1.1 christos return true; 957 1.1 christos } 958 1.8 christos 959 1.1 christos /* This must exist if dynobj is ever set. */ 960 1.1 christos 961 1.1 christos static bool 962 1.6 christos xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED, 963 1.6 christos struct bfd_link_info *info) 964 1.1 christos { 965 1.1 christos bfd *dynobj = elf_hash_table (info)->dynobj; 966 1.1 christos asection *splt = elf_hash_table (info)->splt; 967 1.1 christos 968 1.6 christos /* As an extra sanity check, verify that all plt entries have 969 1.1 christos been filled in. */ 970 1.1 christos 971 1.1 christos if (dynobj != NULL && splt != NULL) 972 1.1 christos { 973 1.1 christos bfd_byte *contents = splt->contents; 974 1.1 christos unsigned int i, size = splt->size; 975 1.1 christos 976 1.1 christos for (i = 0; i < size; i += 4) 977 1.1 christos { 978 1.1 christos unsigned int x = bfd_get_32 (dynobj, contents + i); 979 1.1 christos 980 1.1 christos BFD_ASSERT (x != 0); 981 1.8 christos } 982 1.1 christos } 983 1.1 christos 984 1.1 christos return true; 985 1.1 christos } 986 1.1 christos 987 1.1 christos /* Return the section that should be marked against GC for a given 989 1.1 christos relocation. */ 990 1.1 christos 991 1.1 christos static asection * 992 1.1 christos xstormy16_elf_gc_mark_hook (asection *sec, 993 1.1 christos struct bfd_link_info *info, 994 1.1 christos Elf_Internal_Rela *rel, 995 1.1 christos struct elf_link_hash_entry *h, 996 1.1 christos Elf_Internal_Sym *sym) 997 1.1 christos { 998 1.1 christos if (h != NULL) 999 1.1 christos switch (ELF32_R_TYPE (rel->r_info)) 1000 1.1 christos { 1001 1.1 christos case R_XSTORMY16_GNU_VTINHERIT: 1002 1.1 christos case R_XSTORMY16_GNU_VTENTRY: 1003 1.1 christos return NULL; 1004 1.1 christos } 1005 1.1 christos 1006 1.1 christos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 1007 1.1 christos } 1008 1.1 christos 1009 1.3 christos #define ELF_ARCH bfd_arch_xstormy16 1011 1.1 christos #define ELF_MACHINE_CODE EM_XSTORMY16 1012 1.1 christos #define ELF_MAXPAGESIZE 0x100 1013 1.1 christos 1014 1.1 christos #define TARGET_LITTLE_SYM xstormy16_elf32_vec 1015 1.1 christos #define TARGET_LITTLE_NAME "elf32-xstormy16" 1016 1.6 christos 1017 1.10 christos #define elf_info_to_howto_rel NULL 1018 1.10 christos #define elf_info_to_howto xstormy16_info_to_howto_rela 1019 1.1 christos #define elf_backend_relocate_section xstormy16_elf_relocate_section 1020 1.6 christos #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook 1021 1.1 christos #define elf_backend_check_relocs xstormy16_elf_check_relocs 1022 1.1 christos #define elf_backend_early_size_sections \ 1023 1.1 christos xstormy16_elf_early_size_sections 1024 1.1 christos #define elf_backend_omit_section_dynsym \ 1025 1.1 christos _bfd_elf_omit_section_dynsym_all 1026 1.1 christos #define elf_backend_finish_dynamic_sections \ 1027 1.1 christos xstormy16_elf_finish_dynamic_sections 1028 1.1 christos 1029 1.1 christos #define elf_backend_can_gc_sections 1 1030 1.1 christos #define elf_backend_rela_normal 1 1031 1.1 christos 1032 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup 1033 #define bfd_elf32_bfd_reloc_name_lookup \ 1034 xstormy16_reloc_name_lookup 1035 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section 1036 1037 #include "elf32-target.h" 1038