1 1.1 christos /* 32-bit ELF support for S+core. 2 1.11 christos Copyright (C) 2006-2024 Free Software Foundation, Inc. 3 1.1 christos Contributed by 4 1.1 christos Brain.lin (brain.lin (at) sunplusct.com) 5 1.1 christos Mei Ligang (ligang (at) sunnorth.com.cn) 6 1.1 christos Pei-Lin Tsai (pltsai (at) sunplus.com) 7 1.1 christos 8 1.1 christos This file is part of BFD, the Binary File Descriptor library. 9 1.1 christos 10 1.1 christos This program is free software; you can redistribute it and/or modify 11 1.1 christos it under the terms of the GNU General Public License as published by 12 1.1 christos the Free Software Foundation; either version 3 of the License, or 13 1.1 christos (at your option) any later version. 14 1.1 christos 15 1.1 christos This program is distributed in the hope that it will be useful, 16 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 17 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 1.1 christos GNU General Public License for more details. 19 1.1 christos 20 1.1 christos You should have received a copy of the GNU General Public License 21 1.1 christos along with this program; if not, write to the Free Software 22 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 23 1.1 christos MA 02110-1301, USA. */ 24 1.1 christos 25 1.1 christos #include "sysdep.h" 26 1.1 christos #include "bfd.h" 27 1.1 christos #include "libbfd.h" 28 1.1 christos #include "libiberty.h" 29 1.1 christos #include "elf-bfd.h" 30 1.1 christos #include "elf/score.h" 31 1.1 christos #include "elf/common.h" 32 1.1 christos #include "elf/internal.h" 33 1.1 christos #include "hashtab.h" 34 1.1 christos #include "elf32-score.h" 35 1.1 christos 36 1.1 christos 37 1.1 christos int score3 = 0; 38 1.1 christos int score7 = 1; 39 1.1 christos 40 1.1 christos /* The SCORE ELF linker needs additional information for each symbol in 41 1.1 christos the global hash table. */ 42 1.1 christos struct score_elf_link_hash_entry 43 1.1 christos { 44 1.1 christos struct elf_link_hash_entry root; 45 1.1 christos 46 1.1 christos /* Number of R_SCORE_ABS32, R_SCORE_REL32 relocs against this symbol. */ 47 1.1 christos unsigned int possibly_dynamic_relocs; 48 1.1 christos 49 1.1 christos /* If the R_SCORE_ABS32, R_SCORE_REL32 reloc is against a readonly section. */ 50 1.10 christos bool readonly_reloc; 51 1.1 christos 52 1.1 christos /* We must not create a stub for a symbol that has relocations related to 53 1.1 christos taking the function's address, i.e. any but R_SCORE_CALL15 ones. */ 54 1.10 christos bool no_fn_stub; 55 1.1 christos 56 1.1 christos /* Are we forced local? This will only be set if we have converted 57 1.1 christos the initial global GOT entry to a local GOT entry. */ 58 1.10 christos bool forced_local; 59 1.1 christos }; 60 1.1 christos 61 1.1 christos /* Traverse a score ELF linker hash table. */ 62 1.1 christos #define score_elf_link_hash_traverse(table, func, info) \ 63 1.10 christos (elf_link_hash_traverse \ 64 1.10 christos ((table), \ 65 1.10 christos (bool (*) (struct elf_link_hash_entry *, void *)) (func), \ 66 1.1 christos (info))) 67 1.1 christos 68 1.1 christos /* This structure is used to hold .got entries while estimating got sizes. */ 69 1.1 christos struct score_got_entry 70 1.1 christos { 71 1.1 christos /* The input bfd in which the symbol is defined. */ 72 1.1 christos bfd *abfd; 73 1.1 christos /* The index of the symbol, as stored in the relocation r_info, if 74 1.1 christos we have a local symbol; -1 otherwise. */ 75 1.1 christos long symndx; 76 1.1 christos union 77 1.1 christos { 78 1.1 christos /* If abfd == NULL, an address that must be stored in the got. */ 79 1.1 christos bfd_vma address; 80 1.1 christos /* If abfd != NULL && symndx != -1, the addend of the relocation 81 1.1 christos that should be added to the symbol value. */ 82 1.1 christos bfd_vma addend; 83 1.1 christos /* If abfd != NULL && symndx == -1, the hash table entry 84 1.1 christos corresponding to a global symbol in the got (or, local, if 85 1.1 christos h->forced_local). */ 86 1.1 christos struct score_elf_link_hash_entry *h; 87 1.1 christos } d; 88 1.1 christos 89 1.1 christos /* The offset from the beginning of the .got section to the entry 90 1.1 christos corresponding to this symbol+addend. If it's a global symbol 91 1.1 christos whose offset is yet to be decided, it's going to be -1. */ 92 1.1 christos long gotidx; 93 1.1 christos }; 94 1.1 christos 95 1.1 christos /* This structure is passed to score_elf_sort_hash_table_f when sorting 96 1.1 christos the dynamic symbols. */ 97 1.1 christos 98 1.1 christos struct score_elf_hash_sort_data 99 1.1 christos { 100 1.1 christos /* The symbol in the global GOT with the lowest dynamic symbol table index. */ 101 1.1 christos struct elf_link_hash_entry *low; 102 1.1 christos /* The least dynamic symbol table index corresponding to a symbol with a GOT entry. */ 103 1.1 christos long min_got_dynindx; 104 1.1 christos /* The greatest dynamic symbol table index corresponding to a symbol 105 1.1 christos with a GOT entry that is not referenced (e.g., a dynamic symbol 106 1.1 christos with dynamic relocations pointing to it from non-primary GOTs). */ 107 1.1 christos long max_unref_got_dynindx; 108 1.1 christos /* The greatest dynamic symbol table index not corresponding to a 109 1.1 christos symbol without a GOT entry. */ 110 1.1 christos long max_non_got_dynindx; 111 1.1 christos }; 112 1.1 christos 113 1.1 christos struct score_got_info 114 1.1 christos { 115 1.1 christos /* The global symbol in the GOT with the lowest index in the dynamic 116 1.1 christos symbol table. */ 117 1.1 christos struct elf_link_hash_entry *global_gotsym; 118 1.1 christos /* The number of global .got entries. */ 119 1.1 christos unsigned int global_gotno; 120 1.1 christos /* The number of local .got entries. */ 121 1.1 christos unsigned int local_gotno; 122 1.1 christos /* The number of local .got entries we have used. */ 123 1.1 christos unsigned int assigned_gotno; 124 1.1 christos /* A hash table holding members of the got. */ 125 1.1 christos struct htab *got_entries; 126 1.1 christos /* In multi-got links, a pointer to the next got (err, rather, most 127 1.1 christos of the time, it points to the previous got). */ 128 1.1 christos struct score_got_info *next; 129 1.1 christos }; 130 1.1 christos 131 1.1 christos /* A structure used to count GOT entries, for GOT entry or ELF symbol table traversal. */ 132 1.1 christos struct _score_elf_section_data 133 1.1 christos { 134 1.1 christos struct bfd_elf_section_data elf; 135 1.1 christos union 136 1.1 christos { 137 1.1 christos struct score_got_info *got_info; 138 1.1 christos bfd_byte *tdata; 139 1.1 christos } 140 1.1 christos u; 141 1.1 christos }; 142 1.1 christos 143 1.1 christos #define score_elf_section_data(sec) \ 144 1.1 christos ((struct _score_elf_section_data *) elf_section_data (sec)) 145 1.1 christos 146 1.1 christos /* The size of a symbol-table entry. */ 147 1.1 christos #define SCORE_ELF_SYM_SIZE(abfd) \ 148 1.1 christos (get_elf_backend_data (abfd)->s->sizeof_sym) 149 1.1 christos 150 1.1 christos /* In case we're on a 32-bit machine, construct a 64-bit "-1" value 151 1.1 christos from smaller values. Start with zero, widen, *then* decrement. */ 152 1.1 christos #define MINUS_ONE (((bfd_vma)0) - 1) 153 1.1 christos #define MINUS_TWO (((bfd_vma)0) - 2) 154 1.1 christos 155 1.1 christos #define PDR_SIZE 32 156 1.1 christos 157 1.1 christos 158 1.1 christos /* The number of local .got entries we reserve. */ 159 1.1 christos #define SCORE_RESERVED_GOTNO (2) 160 1.1 christos #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 161 1.1 christos 162 1.1 christos /* The offset of $gp from the beginning of the .got section. */ 163 1.1 christos #define ELF_SCORE_GP_OFFSET(abfd) (0x3ff0) 164 1.1 christos /* The maximum size of the GOT for it to be addressable using 15-bit offsets from $gp. */ 165 1.1 christos #define SCORE_ELF_GOT_MAX_SIZE(abfd) (ELF_SCORE_GP_OFFSET(abfd) + 0x3fff) 166 1.1 christos 167 1.1 christos #define SCORE_ELF_STUB_SECTION_NAME (".SCORE.stub") 168 1.1 christos #define SCORE_FUNCTION_STUB_SIZE (16) 169 1.1 christos 170 1.1 christos #define STUB_LW 0xc3bcc010 /* lw r29, [r28, -0x3ff0] */ 171 1.1 christos #define STUB_MOVE 0x8363bc56 /* mv r27, r3 */ 172 1.1 christos #define STUB_LI16 0x87548000 /* ori r26, .dynsym_index */ 173 1.1 christos #define STUB_BRL 0x801dbc09 /* brl r29 */ 174 1.1 christos 175 1.1 christos #define SCORE_ELF_GOT_SIZE(abfd) \ 176 1.1 christos (get_elf_backend_data (abfd)->s->arch_size / 8) 177 1.1 christos 178 1.1 christos #define SCORE_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \ 179 1.8 christos (_bfd_elf_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val)) 180 1.1 christos 181 1.1 christos /* The size of an external dynamic table entry. */ 182 1.1 christos #define SCORE_ELF_DYN_SIZE(abfd) \ 183 1.1 christos (get_elf_backend_data (abfd)->s->sizeof_dyn) 184 1.1 christos 185 1.1 christos /* The size of an external REL relocation. */ 186 1.1 christos #define SCORE_ELF_REL_SIZE(abfd) \ 187 1.1 christos (get_elf_backend_data (abfd)->s->sizeof_rel) 188 1.1 christos 189 1.1 christos /* The default alignment for sections, as a power of two. */ 190 1.1 christos #define SCORE_ELF_LOG_FILE_ALIGN(abfd)\ 191 1.1 christos (get_elf_backend_data (abfd)->s->log_file_align) 192 1.1 christos 193 1.1 christos static bfd_byte *hi16_rel_addr; 194 1.1 christos 195 1.1 christos /* This will be used when we sort the dynamic relocation records. */ 196 1.1 christos static bfd *reldyn_sorting_bfd; 197 1.1 christos 198 1.1 christos /* SCORE ELF uses two common sections. One is the usual one, and the 199 1.1 christos other is for small objects. All the small objects are kept 200 1.1 christos together, and then referenced via the gp pointer, which yields 201 1.1 christos faster assembler code. This is what we use for the small common 202 1.1 christos section. This approach is copied from ecoff.c. */ 203 1.1 christos static asection score_elf_scom_section; 204 1.10 christos static const asymbol score_elf_scom_symbol = 205 1.10 christos GLOBAL_SYM_INIT (".scommon", &score_elf_scom_section); 206 1.10 christos static asection score_elf_scom_section = 207 1.10 christos BFD_FAKE_SECTION (score_elf_scom_section, &score_elf_scom_symbol, 208 1.10 christos ".scommon", 0, SEC_IS_COMMON | SEC_SMALL_DATA); 209 1.1 christos 210 1.1 christos static bfd_vma 211 1.1 christos score_bfd_get_16 (bfd *abfd, const void *data) 212 1.1 christos { 213 1.1 christos return bfd_get_16 (abfd, data); 214 1.1 christos } 215 1.1 christos 216 1.1 christos static bfd_vma 217 1.1 christos score3_bfd_getl32 (const void *p) 218 1.1 christos { 219 1.1 christos const bfd_byte *addr = p; 220 1.1 christos unsigned long v; 221 1.1 christos 222 1.1 christos v = (unsigned long) addr[2]; 223 1.1 christos v |= (unsigned long) addr[3] << 8; 224 1.1 christos v |= (unsigned long) addr[0] << 16; 225 1.1 christos v |= (unsigned long) addr[1] << 24; 226 1.1 christos return v; 227 1.1 christos } 228 1.1 christos 229 1.1 christos static bfd_vma 230 1.1 christos score3_bfd_getl48 (const void *p) 231 1.1 christos { 232 1.1 christos const bfd_byte *addr = p; 233 1.10 christos uint64_t v; 234 1.1 christos 235 1.10 christos v = (uint64_t) addr[4]; 236 1.10 christos v |= (uint64_t) addr[5] << 8; 237 1.10 christos v |= (uint64_t) addr[2] << 16; 238 1.10 christos v |= (uint64_t) addr[3] << 24; 239 1.10 christos v |= (uint64_t) addr[0] << 32; 240 1.10 christos v |= (uint64_t) addr[1] << 40; 241 1.1 christos return v; 242 1.1 christos } 243 1.1 christos 244 1.1 christos static bfd_vma 245 1.1 christos score_bfd_get_32 (bfd *abfd, const void *data) 246 1.1 christos { 247 1.1 christos if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) 248 1.1 christos return score3_bfd_getl32 (data); 249 1.1 christos else 250 1.1 christos return bfd_get_32 (abfd, data); 251 1.1 christos } 252 1.1 christos 253 1.1 christos static bfd_vma 254 1.1 christos score_bfd_get_48 (bfd *abfd, const void *p) 255 1.1 christos { 256 1.1 christos if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) 257 1.1 christos return score3_bfd_getl48 (p); 258 1.1 christos else 259 1.1 christos return bfd_get_bits (p, 48, 1); 260 1.1 christos } 261 1.1 christos 262 1.1 christos static void 263 1.1 christos score_bfd_put_16 (bfd *abfd, bfd_vma addr, void *data) 264 1.1 christos { 265 1.1 christos return bfd_put_16 (abfd, addr, data); 266 1.1 christos } 267 1.1 christos 268 1.1 christos static void 269 1.1 christos score3_bfd_putl32 (bfd_vma data, void *p) 270 1.1 christos { 271 1.1 christos bfd_byte *addr = p; 272 1.1 christos addr[0] = (data >> 16) & 0xff; 273 1.1 christos addr[1] = (data >> 24) & 0xff; 274 1.1 christos addr[2] = data & 0xff; 275 1.1 christos addr[3] = (data >> 8) & 0xff; 276 1.1 christos } 277 1.1 christos 278 1.1 christos static void 279 1.1 christos score3_bfd_putl48 (bfd_vma data, void *p) 280 1.1 christos { 281 1.1 christos bfd_byte *addr = p; 282 1.1 christos addr[0] = (data >> 32) & 0xff; 283 1.1 christos addr[1] = (data >> 40) & 0xff; 284 1.1 christos addr[2] = (data >> 16) & 0xff; 285 1.1 christos addr[3] = (data >> 24) & 0xff; 286 1.1 christos addr[4] = data & 0xff; 287 1.1 christos addr[5] = (data >> 8) & 0xff; 288 1.1 christos } 289 1.1 christos 290 1.1 christos static void 291 1.1 christos score_bfd_put_32 (bfd *abfd, bfd_vma addr, void *data) 292 1.1 christos { 293 1.1 christos if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) 294 1.1 christos return score3_bfd_putl32 (addr, data); 295 1.1 christos else 296 1.1 christos return bfd_put_32 (abfd, addr, data); 297 1.1 christos } 298 1.1 christos 299 1.1 christos static void 300 1.1 christos score_bfd_put_48 (bfd *abfd, bfd_vma val, void *p) 301 1.1 christos { 302 1.1 christos if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) 303 1.1 christos return score3_bfd_putl48 (val, p); 304 1.1 christos else 305 1.1 christos return bfd_put_bits (val, p, 48, 1); 306 1.1 christos } 307 1.1 christos 308 1.1 christos static bfd_reloc_status_type 309 1.1 christos score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, 310 1.8 christos arelent *reloc_entry, 311 1.8 christos asymbol *symbol ATTRIBUTE_UNUSED, 312 1.8 christos void * data, 313 1.8 christos asection *input_section ATTRIBUTE_UNUSED, 314 1.8 christos bfd *output_bfd ATTRIBUTE_UNUSED, 315 1.8 christos char **error_message ATTRIBUTE_UNUSED) 316 1.1 christos { 317 1.1 christos hi16_rel_addr = (bfd_byte *) data + reloc_entry->address; 318 1.1 christos return bfd_reloc_ok; 319 1.1 christos } 320 1.1 christos 321 1.1 christos static bfd_reloc_status_type 322 1.1 christos score_elf_lo16_reloc (bfd *abfd, 323 1.8 christos arelent *reloc_entry, 324 1.8 christos asymbol *symbol ATTRIBUTE_UNUSED, 325 1.8 christos void * data, 326 1.8 christos asection *input_section, 327 1.8 christos bfd *output_bfd ATTRIBUTE_UNUSED, 328 1.8 christos char **error_message ATTRIBUTE_UNUSED) 329 1.1 christos { 330 1.1 christos bfd_vma addend = 0, offset = 0; 331 1.1 christos unsigned long val; 332 1.1 christos unsigned long hi16_offset, hi16_value, uvalue; 333 1.1 christos 334 1.1 christos hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr); 335 1.1 christos hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1; 336 1.1 christos addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 337 1.1 christos offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; 338 1.1 christos val = reloc_entry->addend; 339 1.1 christos if (reloc_entry->address > input_section->size) 340 1.1 christos return bfd_reloc_outofrange; 341 1.1 christos uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val; 342 1.1 christos hi16_offset = (uvalue >> 16) << 1; 343 1.1 christos hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); 344 1.1 christos score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr); 345 1.1 christos offset = (uvalue & 0xffff) << 1; 346 1.1 christos addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000); 347 1.1 christos score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); 348 1.1 christos return bfd_reloc_ok; 349 1.1 christos } 350 1.1 christos 351 1.1 christos /* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a 352 1.1 christos dangerous relocation. */ 353 1.1 christos 354 1.10 christos static bool 355 1.1 christos score_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp) 356 1.1 christos { 357 1.1 christos unsigned int count; 358 1.1 christos asymbol **sym; 359 1.1 christos unsigned int i; 360 1.1 christos 361 1.1 christos /* If we've already figured out what GP will be, just return it. */ 362 1.1 christos *pgp = _bfd_get_gp_value (output_bfd); 363 1.1 christos if (*pgp) 364 1.10 christos return true; 365 1.1 christos 366 1.1 christos count = bfd_get_symcount (output_bfd); 367 1.1 christos sym = bfd_get_outsymbols (output_bfd); 368 1.1 christos 369 1.1 christos /* The linker script will have created a symbol named `_gp' with the 370 1.1 christos appropriate value. */ 371 1.1 christos if (sym == NULL) 372 1.1 christos i = count; 373 1.1 christos else 374 1.1 christos { 375 1.1 christos for (i = 0; i < count; i++, sym++) 376 1.8 christos { 377 1.8 christos const char *name; 378 1.1 christos 379 1.8 christos name = bfd_asymbol_name (*sym); 380 1.8 christos if (*name == '_' && strcmp (name, "_gp") == 0) 381 1.8 christos { 382 1.8 christos *pgp = bfd_asymbol_value (*sym); 383 1.8 christos _bfd_set_gp_value (output_bfd, *pgp); 384 1.8 christos break; 385 1.8 christos } 386 1.8 christos } 387 1.1 christos } 388 1.1 christos 389 1.1 christos if (i >= count) 390 1.1 christos { 391 1.1 christos /* Only get the error once. */ 392 1.1 christos *pgp = 4; 393 1.1 christos _bfd_set_gp_value (output_bfd, *pgp); 394 1.10 christos return false; 395 1.1 christos } 396 1.1 christos 397 1.10 christos return true; 398 1.1 christos } 399 1.1 christos 400 1.1 christos /* We have to figure out the gp value, so that we can adjust the 401 1.1 christos symbol value correctly. We look up the symbol _gp in the output 402 1.1 christos BFD. If we can't find it, we're stuck. We cache it in the ELF 403 1.1 christos target data. We don't need to adjust the symbol value for an 404 1.1 christos external symbol if we are producing relocatable output. */ 405 1.1 christos static bfd_reloc_status_type 406 1.1 christos score_elf_final_gp (bfd *output_bfd, 407 1.8 christos asymbol *symbol, 408 1.10 christos bool relocatable, 409 1.8 christos char **error_message, 410 1.8 christos bfd_vma *pgp) 411 1.1 christos { 412 1.1 christos if (bfd_is_und_section (symbol->section) 413 1.1 christos && ! relocatable) 414 1.1 christos { 415 1.1 christos *pgp = 0; 416 1.1 christos return bfd_reloc_undefined; 417 1.1 christos } 418 1.1 christos 419 1.1 christos *pgp = _bfd_get_gp_value (output_bfd); 420 1.1 christos if (*pgp == 0 421 1.1 christos && (! relocatable 422 1.8 christos || (symbol->flags & BSF_SECTION_SYM) != 0)) 423 1.1 christos { 424 1.1 christos if (relocatable) 425 1.8 christos { 426 1.8 christos /* Make up a value. */ 427 1.8 christos *pgp = symbol->section->output_section->vma + 0x4000; 428 1.8 christos _bfd_set_gp_value (output_bfd, *pgp); 429 1.8 christos } 430 1.1 christos else if (!score_elf_assign_gp (output_bfd, pgp)) 431 1.8 christos { 432 1.8 christos *error_message = 433 1.8 christos (char *) _("GP relative relocation when _gp not defined"); 434 1.8 christos return bfd_reloc_dangerous; 435 1.8 christos } 436 1.1 christos } 437 1.1 christos 438 1.1 christos return bfd_reloc_ok; 439 1.1 christos } 440 1.1 christos 441 1.1 christos static bfd_reloc_status_type 442 1.1 christos score_elf_gprel15_with_gp (bfd *abfd, 443 1.8 christos arelent *reloc_entry, 444 1.8 christos asection *input_section, 445 1.10 christos bool relocateable, 446 1.8 christos void * data, 447 1.8 christos bfd_vma gp ATTRIBUTE_UNUSED) 448 1.1 christos { 449 1.1 christos unsigned long insn; 450 1.1 christos 451 1.1 christos if (reloc_entry->address > input_section->size) 452 1.1 christos return bfd_reloc_outofrange; 453 1.1 christos 454 1.1 christos insn = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 455 1.1 christos if (((reloc_entry->addend & 0xffffc000) != 0) 456 1.1 christos && ((reloc_entry->addend & 0xffffc000) != 0xffffc000)) 457 1.1 christos return bfd_reloc_overflow; 458 1.1 christos 459 1.1 christos insn = (insn & ~0x7fff) | (reloc_entry->addend & 0x7fff); 460 1.1 christos score_bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); 461 1.1 christos if (relocateable) 462 1.1 christos reloc_entry->address += input_section->output_offset; 463 1.1 christos 464 1.1 christos return bfd_reloc_ok; 465 1.1 christos } 466 1.1 christos 467 1.1 christos static bfd_reloc_status_type 468 1.1 christos gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, 469 1.10 christos asection *input_section, bool relocatable, 470 1.8 christos void *data, bfd_vma gp) 471 1.1 christos { 472 1.1 christos bfd_vma relocation; 473 1.1 christos bfd_vma val; 474 1.1 christos 475 1.1 christos if (bfd_is_com_section (symbol->section)) 476 1.1 christos relocation = 0; 477 1.1 christos else 478 1.1 christos relocation = symbol->value; 479 1.1 christos 480 1.1 christos relocation += symbol->section->output_section->vma; 481 1.1 christos relocation += symbol->section->output_offset; 482 1.1 christos 483 1.1 christos if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 484 1.1 christos return bfd_reloc_outofrange; 485 1.1 christos 486 1.1 christos /* Set val to the offset into the section or symbol. */ 487 1.1 christos val = reloc_entry->addend; 488 1.1 christos 489 1.1 christos if (reloc_entry->howto->partial_inplace) 490 1.1 christos val += score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 491 1.1 christos 492 1.1 christos /* Adjust val for the final section location and GP value. If we 493 1.1 christos are producing relocatable output, we don't want to do this for 494 1.1 christos an external symbol. */ 495 1.1 christos if (! relocatable 496 1.1 christos || (symbol->flags & BSF_SECTION_SYM) != 0) 497 1.1 christos val += relocation - gp; 498 1.1 christos 499 1.1 christos if (reloc_entry->howto->partial_inplace) 500 1.1 christos score_bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address); 501 1.1 christos else 502 1.1 christos reloc_entry->addend = val; 503 1.1 christos 504 1.1 christos if (relocatable) 505 1.1 christos reloc_entry->address += input_section->output_offset; 506 1.1 christos 507 1.1 christos return bfd_reloc_ok; 508 1.1 christos } 509 1.1 christos 510 1.1 christos static bfd_reloc_status_type 511 1.1 christos score_elf_gprel15_reloc (bfd *abfd, 512 1.8 christos arelent *reloc_entry, 513 1.8 christos asymbol *symbol, 514 1.8 christos void * data, 515 1.8 christos asection *input_section, 516 1.8 christos bfd *output_bfd, 517 1.8 christos char **error_message) 518 1.1 christos { 519 1.10 christos bool relocateable; 520 1.1 christos bfd_reloc_status_type ret; 521 1.1 christos bfd_vma gp; 522 1.1 christos 523 1.1 christos if (output_bfd != NULL 524 1.1 christos && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0) 525 1.1 christos { 526 1.1 christos reloc_entry->address += input_section->output_offset; 527 1.1 christos return bfd_reloc_ok; 528 1.1 christos } 529 1.1 christos if (output_bfd != NULL) 530 1.10 christos relocateable = true; 531 1.1 christos else 532 1.1 christos { 533 1.10 christos relocateable = false; 534 1.1 christos output_bfd = symbol->section->output_section->owner; 535 1.1 christos } 536 1.1 christos 537 1.1 christos ret = score_elf_final_gp (output_bfd, symbol, relocateable, error_message, &gp); 538 1.1 christos if (ret != bfd_reloc_ok) 539 1.1 christos return ret; 540 1.1 christos 541 1.10 christos return score_elf_gprel15_with_gp (abfd, reloc_entry, 542 1.10 christos input_section, relocateable, data, gp); 543 1.1 christos } 544 1.1 christos 545 1.1 christos /* Do a R_SCORE_GPREL32 relocation. This is a 32 bit value which must 546 1.1 christos become the offset from the gp register. */ 547 1.1 christos 548 1.1 christos static bfd_reloc_status_type 549 1.1 christos score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 550 1.8 christos void *data, asection *input_section, bfd *output_bfd, 551 1.8 christos char **error_message) 552 1.1 christos { 553 1.10 christos bool relocatable; 554 1.1 christos bfd_reloc_status_type ret; 555 1.1 christos bfd_vma gp; 556 1.1 christos 557 1.1 christos /* R_SCORE_GPREL32 relocations are defined for local symbols only. */ 558 1.1 christos if (output_bfd != NULL 559 1.1 christos && (symbol->flags & BSF_SECTION_SYM) == 0 560 1.1 christos && (symbol->flags & BSF_LOCAL) != 0) 561 1.1 christos { 562 1.1 christos *error_message = (char *) 563 1.8 christos _("32bits gp relative relocation occurs for an external symbol"); 564 1.1 christos return bfd_reloc_outofrange; 565 1.1 christos } 566 1.1 christos 567 1.1 christos if (output_bfd != NULL) 568 1.10 christos relocatable = true; 569 1.1 christos else 570 1.1 christos { 571 1.10 christos relocatable = false; 572 1.1 christos output_bfd = symbol->section->output_section->owner; 573 1.1 christos } 574 1.1 christos 575 1.1 christos ret = score_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp); 576 1.1 christos if (ret != bfd_reloc_ok) 577 1.1 christos return ret; 578 1.1 christos 579 1.1 christos gp = 0; 580 1.1 christos return gprel32_with_gp (abfd, symbol, reloc_entry, input_section, 581 1.8 christos relocatable, data, gp); 582 1.1 christos } 583 1.1 christos 584 1.1 christos /* A howto special_function for R_SCORE_GOT15 relocations. This is just 585 1.1 christos like any other 16-bit relocation when applied to global symbols, but is 586 1.1 christos treated in the same as R_SCORE_HI16 when applied to local symbols. */ 587 1.1 christos static bfd_reloc_status_type 588 1.1 christos score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 589 1.8 christos void *data, asection *input_section, 590 1.8 christos bfd *output_bfd, char **error_message) 591 1.1 christos { 592 1.1 christos if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 593 1.9 christos || bfd_is_und_section (bfd_asymbol_section (symbol)) 594 1.9 christos || bfd_is_com_section (bfd_asymbol_section (symbol))) 595 1.1 christos /* The relocation is against a global symbol. */ 596 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 597 1.8 christos input_section, output_bfd, 598 1.8 christos error_message); 599 1.1 christos 600 1.1 christos return score_elf_hi16_reloc (abfd, reloc_entry, symbol, data, 601 1.8 christos input_section, output_bfd, error_message); 602 1.1 christos } 603 1.1 christos 604 1.1 christos static bfd_reloc_status_type 605 1.1 christos score_elf_got_lo16_reloc (bfd *abfd, 606 1.8 christos arelent *reloc_entry, 607 1.8 christos asymbol *symbol ATTRIBUTE_UNUSED, 608 1.8 christos void * data, 609 1.8 christos asection *input_section, 610 1.8 christos bfd *output_bfd ATTRIBUTE_UNUSED, 611 1.8 christos char **error_message ATTRIBUTE_UNUSED) 612 1.1 christos { 613 1.1 christos bfd_vma addend = 0, offset = 0; 614 1.1 christos signed long val; 615 1.1 christos signed long hi16_offset, hi16_value, uvalue; 616 1.1 christos 617 1.1 christos hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr); 618 1.1 christos hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1; 619 1.1 christos addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 620 1.1 christos offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; 621 1.1 christos val = reloc_entry->addend; 622 1.1 christos if (reloc_entry->address > input_section->size) 623 1.1 christos return bfd_reloc_outofrange; 624 1.1 christos uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val; 625 1.1 christos if ((uvalue > -0x8000) && (uvalue < 0x7fff)) 626 1.1 christos hi16_offset = 0; 627 1.1 christos else 628 1.1 christos hi16_offset = (uvalue >> 16) & 0x7fff; 629 1.1 christos hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); 630 1.1 christos score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr); 631 1.1 christos offset = (uvalue & 0xffff) << 1; 632 1.1 christos addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000); 633 1.1 christos score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); 634 1.1 christos return bfd_reloc_ok; 635 1.1 christos } 636 1.1 christos 637 1.1 christos static reloc_howto_type elf32_score_howto_table[] = 638 1.1 christos { 639 1.1 christos /* No relocation. */ 640 1.8 christos HOWTO (R_SCORE_NONE, /* type */ 641 1.8 christos 0, /* rightshift */ 642 1.10 christos 0, /* size */ 643 1.8 christos 0, /* bitsize */ 644 1.10 christos false, /* pc_relative */ 645 1.8 christos 0, /* bitpos */ 646 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 647 1.8 christos bfd_elf_generic_reloc, /* special_function */ 648 1.8 christos "R_SCORE_NONE", /* name */ 649 1.10 christos false, /* partial_inplace */ 650 1.8 christos 0, /* src_mask */ 651 1.8 christos 0, /* dst_mask */ 652 1.10 christos false), /* pcrel_offset */ 653 1.1 christos 654 1.1 christos /* R_SCORE_HI16 */ 655 1.8 christos HOWTO (R_SCORE_HI16, /* type */ 656 1.8 christos 0, /* rightshift */ 657 1.10 christos 4, /* size */ 658 1.8 christos 16, /* bitsize */ 659 1.10 christos false, /* pc_relative */ 660 1.8 christos 1, /* bitpos */ 661 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 662 1.8 christos score_elf_hi16_reloc, /* special_function */ 663 1.8 christos "R_SCORE_HI16", /* name */ 664 1.10 christos true, /* partial_inplace */ 665 1.8 christos 0x37fff, /* src_mask */ 666 1.8 christos 0x37fff, /* dst_mask */ 667 1.10 christos false), /* pcrel_offset */ 668 1.1 christos 669 1.1 christos /* R_SCORE_LO16 */ 670 1.8 christos HOWTO (R_SCORE_LO16, /* type */ 671 1.8 christos 0, /* rightshift */ 672 1.10 christos 4, /* size */ 673 1.8 christos 16, /* bitsize */ 674 1.10 christos false, /* pc_relative */ 675 1.8 christos 1, /* bitpos */ 676 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 677 1.8 christos score_elf_lo16_reloc, /* special_function */ 678 1.8 christos "R_SCORE_LO16", /* name */ 679 1.10 christos true, /* partial_inplace */ 680 1.8 christos 0x37fff, /* src_mask */ 681 1.8 christos 0x37fff, /* dst_mask */ 682 1.10 christos false), /* pcrel_offset */ 683 1.1 christos 684 1.1 christos /* R_SCORE_BCMP */ 685 1.8 christos HOWTO (R_SCORE_BCMP, /* type */ 686 1.8 christos 1, /* rightshift */ 687 1.10 christos 4, /* size */ 688 1.8 christos 16, /* bitsize */ 689 1.10 christos true, /* pc_relative */ 690 1.8 christos 1, /* bitpos */ 691 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 692 1.8 christos bfd_elf_generic_reloc, /* special_function */ 693 1.8 christos "R_SCORE_BCMP", /* name */ 694 1.10 christos false, /* partial_inplace */ 695 1.8 christos 0x03e00381, /* src_mask */ 696 1.8 christos 0x03e00381, /* dst_mask */ 697 1.10 christos false), /* pcrel_offset */ 698 1.1 christos 699 1.1 christos /*R_SCORE_24 */ 700 1.8 christos HOWTO (R_SCORE_24, /* type */ 701 1.8 christos 1, /* rightshift */ 702 1.10 christos 4, /* size */ 703 1.8 christos 24, /* bitsize */ 704 1.10 christos false, /* pc_relative */ 705 1.8 christos 1, /* bitpos */ 706 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 707 1.8 christos bfd_elf_generic_reloc, /* special_function */ 708 1.8 christos "R_SCORE_24", /* name */ 709 1.10 christos false, /* partial_inplace */ 710 1.8 christos 0x3ff7fff, /* src_mask */ 711 1.8 christos 0x3ff7fff, /* dst_mask */ 712 1.10 christos false), /* pcrel_offset */ 713 1.1 christos 714 1.1 christos /*R_SCORE_PC19 */ 715 1.8 christos HOWTO (R_SCORE_PC19, /* type */ 716 1.8 christos 1, /* rightshift */ 717 1.10 christos 4, /* size */ 718 1.8 christos 19, /* bitsize */ 719 1.10 christos true, /* pc_relative */ 720 1.8 christos 1, /* bitpos */ 721 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 722 1.8 christos bfd_elf_generic_reloc, /* special_function */ 723 1.8 christos "R_SCORE_PC19", /* name */ 724 1.10 christos false, /* partial_inplace */ 725 1.8 christos 0x3ff03fe, /* src_mask */ 726 1.8 christos 0x3ff03fe, /* dst_mask */ 727 1.10 christos false), /* pcrel_offset */ 728 1.1 christos 729 1.1 christos /*R_SCORE16_11 */ 730 1.8 christos HOWTO (R_SCORE16_11, /* type */ 731 1.8 christos 1, /* rightshift */ 732 1.10 christos 2, /* size */ 733 1.8 christos 11, /* bitsize */ 734 1.10 christos false, /* pc_relative */ 735 1.8 christos 1, /* bitpos */ 736 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 737 1.8 christos bfd_elf_generic_reloc, /* special_function */ 738 1.8 christos "R_SCORE16_11", /* name */ 739 1.10 christos false, /* partial_inplace */ 740 1.8 christos 0x000000ffe, /* src_mask */ 741 1.8 christos 0x000000ffe, /* dst_mask */ 742 1.10 christos false), /* pcrel_offset */ 743 1.1 christos 744 1.1 christos /* R_SCORE16_PC8 */ 745 1.8 christos HOWTO (R_SCORE16_PC8, /* type */ 746 1.8 christos 1, /* rightshift */ 747 1.10 christos 2, /* size */ 748 1.8 christos 9, /* bitsize */ 749 1.10 christos true, /* pc_relative */ 750 1.8 christos 0, /* bitpos */ 751 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 752 1.8 christos bfd_elf_generic_reloc, /* special_function */ 753 1.8 christos "R_SCORE16_PC8", /* name */ 754 1.10 christos false, /* partial_inplace */ 755 1.8 christos 0x000001ff, /* src_mask */ 756 1.8 christos 0x000001ff, /* dst_mask */ 757 1.10 christos false), /* pcrel_offset */ 758 1.1 christos 759 1.1 christos /* 32 bit absolute */ 760 1.8 christos HOWTO (R_SCORE_ABS32, /* type 8 */ 761 1.8 christos 0, /* rightshift */ 762 1.10 christos 4, /* size */ 763 1.8 christos 32, /* bitsize */ 764 1.10 christos false, /* pc_relative */ 765 1.8 christos 0, /* bitpos */ 766 1.8 christos complain_overflow_bitfield, /* complain_on_overflow */ 767 1.8 christos bfd_elf_generic_reloc, /* special_function */ 768 1.8 christos "R_SCORE_ABS32", /* name */ 769 1.10 christos false, /* partial_inplace */ 770 1.8 christos 0xffffffff, /* src_mask */ 771 1.8 christos 0xffffffff, /* dst_mask */ 772 1.10 christos false), /* pcrel_offset */ 773 1.1 christos 774 1.1 christos /* 16 bit absolute */ 775 1.8 christos HOWTO (R_SCORE_ABS16, /* type 11 */ 776 1.8 christos 0, /* rightshift */ 777 1.10 christos 2, /* size */ 778 1.8 christos 16, /* bitsize */ 779 1.10 christos false, /* pc_relative */ 780 1.8 christos 0, /* bitpos */ 781 1.8 christos complain_overflow_bitfield, /* complain_on_overflow */ 782 1.8 christos bfd_elf_generic_reloc, /* special_function */ 783 1.8 christos "R_SCORE_ABS16", /* name */ 784 1.10 christos false, /* partial_inplace */ 785 1.8 christos 0x0000ffff, /* src_mask */ 786 1.8 christos 0x0000ffff, /* dst_mask */ 787 1.10 christos false), /* pcrel_offset */ 788 1.1 christos 789 1.1 christos /* R_SCORE_DUMMY2 */ 790 1.8 christos HOWTO (R_SCORE_DUMMY2, /* type */ 791 1.8 christos 0, /* rightshift */ 792 1.10 christos 4, /* size */ 793 1.8 christos 16, /* bitsize */ 794 1.10 christos false, /* pc_relative */ 795 1.8 christos 0, /* bitpos */ 796 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 797 1.8 christos bfd_elf_generic_reloc, /* special_function */ 798 1.8 christos "R_SCORE_DUMMY2", /* name */ 799 1.10 christos true, /* partial_inplace */ 800 1.8 christos 0x00007fff, /* src_mask */ 801 1.8 christos 0x00007fff, /* dst_mask */ 802 1.10 christos false), /* pcrel_offset */ 803 1.1 christos 804 1.1 christos /* R_SCORE_GP15 */ 805 1.8 christos HOWTO (R_SCORE_GP15, /* type */ 806 1.8 christos 0, /* rightshift */ 807 1.10 christos 4, /* size */ 808 1.8 christos 16, /* bitsize */ 809 1.10 christos false, /* pc_relative */ 810 1.8 christos 0, /* bitpos */ 811 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 812 1.8 christos score_elf_gprel15_reloc,/* special_function */ 813 1.8 christos "R_SCORE_GP15", /* name */ 814 1.10 christos true, /* partial_inplace */ 815 1.8 christos 0x00007fff, /* src_mask */ 816 1.8 christos 0x00007fff, /* dst_mask */ 817 1.10 christos false), /* pcrel_offset */ 818 1.1 christos 819 1.1 christos /* GNU extension to record C++ vtable hierarchy. */ 820 1.1 christos HOWTO (R_SCORE_GNU_VTINHERIT, /* type */ 821 1.8 christos 0, /* rightshift */ 822 1.10 christos 4, /* size */ 823 1.8 christos 0, /* bitsize */ 824 1.10 christos false, /* pc_relative */ 825 1.8 christos 0, /* bitpos */ 826 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 827 1.8 christos NULL, /* special_function */ 828 1.8 christos "R_SCORE_GNU_VTINHERIT", /* name */ 829 1.10 christos false, /* partial_inplace */ 830 1.8 christos 0, /* src_mask */ 831 1.8 christos 0, /* dst_mask */ 832 1.10 christos false), /* pcrel_offset */ 833 1.1 christos 834 1.1 christos /* GNU extension to record C++ vtable member usage */ 835 1.8 christos HOWTO (R_SCORE_GNU_VTENTRY, /* type */ 836 1.8 christos 0, /* rightshift */ 837 1.10 christos 4, /* size */ 838 1.8 christos 0, /* bitsize */ 839 1.10 christos false, /* pc_relative */ 840 1.8 christos 0, /* bitpos */ 841 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 842 1.8 christos _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 843 1.8 christos "R_SCORE_GNU_VTENTRY", /* name */ 844 1.10 christos false, /* partial_inplace */ 845 1.8 christos 0, /* src_mask */ 846 1.8 christos 0, /* dst_mask */ 847 1.10 christos false), /* pcrel_offset */ 848 1.1 christos 849 1.1 christos /* Reference to global offset table. */ 850 1.8 christos HOWTO (R_SCORE_GOT15, /* type */ 851 1.8 christos 0, /* rightshift */ 852 1.10 christos 4, /* size */ 853 1.8 christos 16, /* bitsize */ 854 1.10 christos false, /* pc_relative */ 855 1.8 christos 0, /* bitpos */ 856 1.8 christos complain_overflow_signed, /* complain_on_overflow */ 857 1.8 christos score_elf_got15_reloc, /* special_function */ 858 1.8 christos "R_SCORE_GOT15", /* name */ 859 1.10 christos true, /* partial_inplace */ 860 1.8 christos 0x00007fff, /* src_mask */ 861 1.8 christos 0x00007fff, /* dst_mask */ 862 1.10 christos false), /* pcrel_offset */ 863 1.1 christos 864 1.1 christos /* Low 16 bits of displacement in global offset table. */ 865 1.8 christos HOWTO (R_SCORE_GOT_LO16, /* type */ 866 1.8 christos 0, /* rightshift */ 867 1.10 christos 4, /* size */ 868 1.8 christos 16, /* bitsize */ 869 1.10 christos false, /* pc_relative */ 870 1.8 christos 1, /* bitpos */ 871 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 872 1.8 christos score_elf_got_lo16_reloc, /* special_function */ 873 1.8 christos "R_SCORE_GOT_LO16", /* name */ 874 1.10 christos true, /* partial_inplace */ 875 1.8 christos 0x37ffe, /* src_mask */ 876 1.8 christos 0x37ffe, /* dst_mask */ 877 1.10 christos false), /* pcrel_offset */ 878 1.1 christos 879 1.1 christos /* 15 bit call through global offset table. */ 880 1.8 christos HOWTO (R_SCORE_CALL15, /* type */ 881 1.8 christos 0, /* rightshift */ 882 1.10 christos 4, /* size */ 883 1.8 christos 16, /* bitsize */ 884 1.10 christos false, /* pc_relative */ 885 1.8 christos 0, /* bitpos */ 886 1.8 christos complain_overflow_signed, /* complain_on_overflow */ 887 1.8 christos bfd_elf_generic_reloc, /* special_function */ 888 1.8 christos "R_SCORE_CALL15", /* name */ 889 1.10 christos true, /* partial_inplace */ 890 1.8 christos 0x0000ffff, /* src_mask */ 891 1.8 christos 0x0000ffff, /* dst_mask */ 892 1.10 christos false), /* pcrel_offset */ 893 1.1 christos 894 1.1 christos /* 32 bit GP relative reference. */ 895 1.8 christos HOWTO (R_SCORE_GPREL32, /* type */ 896 1.8 christos 0, /* rightshift */ 897 1.10 christos 4, /* size */ 898 1.8 christos 32, /* bitsize */ 899 1.10 christos false, /* pc_relative */ 900 1.8 christos 0, /* bitpos */ 901 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 902 1.8 christos score_elf_gprel32_reloc, /* special_function */ 903 1.8 christos "R_SCORE_GPREL32", /* name */ 904 1.10 christos true, /* partial_inplace */ 905 1.8 christos 0xffffffff, /* src_mask */ 906 1.8 christos 0xffffffff, /* dst_mask */ 907 1.10 christos false), /* pcrel_offset */ 908 1.1 christos 909 1.1 christos /* 32 bit symbol relative relocation. */ 910 1.8 christos HOWTO (R_SCORE_REL32, /* type */ 911 1.8 christos 0, /* rightshift */ 912 1.10 christos 4, /* size */ 913 1.8 christos 32, /* bitsize */ 914 1.10 christos false, /* pc_relative */ 915 1.8 christos 0, /* bitpos */ 916 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 917 1.8 christos bfd_elf_generic_reloc, /* special_function */ 918 1.8 christos "R_SCORE_REL32", /* name */ 919 1.10 christos true, /* partial_inplace */ 920 1.8 christos 0xffffffff, /* src_mask */ 921 1.8 christos 0xffffffff, /* dst_mask */ 922 1.10 christos false), /* pcrel_offset */ 923 1.1 christos 924 1.1 christos /* R_SCORE_DUMMY_HI16 */ 925 1.8 christos HOWTO (R_SCORE_DUMMY_HI16, /* type */ 926 1.8 christos 0, /* rightshift */ 927 1.10 christos 4, /* size */ 928 1.8 christos 16, /* bitsize */ 929 1.10 christos false, /* pc_relative */ 930 1.8 christos 1, /* bitpos */ 931 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 932 1.8 christos score_elf_hi16_reloc, /* special_function */ 933 1.8 christos "R_SCORE_DUMMY_HI16", /* name */ 934 1.10 christos true, /* partial_inplace */ 935 1.8 christos 0x37fff, /* src_mask */ 936 1.8 christos 0x37fff, /* dst_mask */ 937 1.10 christos false), /* pcrel_offset */ 938 1.1 christos 939 1.1 christos /* R_SCORE_IMM30 */ 940 1.8 christos HOWTO (R_SCORE_IMM30, /* type */ 941 1.8 christos 2, /* rightshift */ 942 1.10 christos 4, /* size */ 943 1.8 christos 30, /* bitsize */ 944 1.10 christos false, /* pc_relative */ 945 1.8 christos 7, /* bitpos */ 946 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 947 1.8 christos bfd_elf_generic_reloc, /* special_function */ 948 1.8 christos "R_SCORE_IMM30", /* name */ 949 1.10 christos false, /* partial_inplace */ 950 1.8 christos 0x7f7fff7f80LL, /* src_mask */ 951 1.8 christos 0x7f7fff7f80LL, /* dst_mask */ 952 1.10 christos false), /* pcrel_offset */ 953 1.1 christos 954 1.1 christos /* R_SCORE_IMM32 */ 955 1.8 christos HOWTO (R_SCORE_IMM32, /* type */ 956 1.8 christos 0, /* rightshift */ 957 1.10 christos 4, /* size */ 958 1.8 christos 32, /* bitsize */ 959 1.10 christos false, /* pc_relative */ 960 1.8 christos 5, /* bitpos */ 961 1.8 christos complain_overflow_dont,/* complain_on_overflow */ 962 1.8 christos bfd_elf_generic_reloc, /* special_function */ 963 1.8 christos "R_SCORE_IMM32", /* name */ 964 1.10 christos false, /* partial_inplace */ 965 1.8 christos 0x7f7fff7fe0LL, /* src_mask */ 966 1.8 christos 0x7f7fff7fe0LL, /* dst_mask */ 967 1.10 christos false), /* pcrel_offset */ 968 1.1 christos }; 969 1.1 christos 970 1.1 christos struct score_reloc_map 971 1.1 christos { 972 1.1 christos bfd_reloc_code_real_type bfd_reloc_val; 973 1.1 christos unsigned char elf_reloc_val; 974 1.1 christos }; 975 1.1 christos 976 1.1 christos static const struct score_reloc_map elf32_score_reloc_map[] = 977 1.1 christos { 978 1.8 christos {BFD_RELOC_NONE, R_SCORE_NONE}, 979 1.8 christos {BFD_RELOC_HI16_S, R_SCORE_HI16}, 980 1.8 christos {BFD_RELOC_LO16, R_SCORE_LO16}, 981 1.8 christos {BFD_RELOC_SCORE_BCMP, R_SCORE_BCMP}, 982 1.8 christos {BFD_RELOC_SCORE_JMP, R_SCORE_24}, 983 1.8 christos {BFD_RELOC_SCORE_BRANCH, R_SCORE_PC19}, 984 1.8 christos {BFD_RELOC_SCORE16_JMP, R_SCORE16_11}, 985 1.8 christos {BFD_RELOC_SCORE16_BRANCH, R_SCORE16_PC8}, 986 1.8 christos {BFD_RELOC_32, R_SCORE_ABS32}, 987 1.8 christos {BFD_RELOC_16, R_SCORE_ABS16}, 988 1.8 christos {BFD_RELOC_SCORE_DUMMY2, R_SCORE_DUMMY2}, 989 1.8 christos {BFD_RELOC_SCORE_GPREL15, R_SCORE_GP15}, 990 1.8 christos {BFD_RELOC_VTABLE_INHERIT, R_SCORE_GNU_VTINHERIT}, 991 1.8 christos {BFD_RELOC_VTABLE_ENTRY, R_SCORE_GNU_VTENTRY}, 992 1.8 christos {BFD_RELOC_SCORE_GOT15, R_SCORE_GOT15}, 993 1.8 christos {BFD_RELOC_SCORE_GOT_LO16, R_SCORE_GOT_LO16}, 994 1.8 christos {BFD_RELOC_SCORE_CALL15, R_SCORE_CALL15}, 995 1.8 christos {BFD_RELOC_GPREL32, R_SCORE_GPREL32}, 996 1.8 christos {BFD_RELOC_32_PCREL, R_SCORE_REL32}, 997 1.8 christos {BFD_RELOC_SCORE_DUMMY_HI16, R_SCORE_DUMMY_HI16}, 998 1.8 christos {BFD_RELOC_SCORE_IMM30, R_SCORE_IMM30}, 999 1.8 christos {BFD_RELOC_SCORE_IMM32, R_SCORE_IMM32}, 1000 1.1 christos }; 1001 1.1 christos 1002 1.1 christos /* got_entries only match if they're identical, except for gotidx, so 1003 1.1 christos use all fields to compute the hash, and compare the appropriate 1004 1.1 christos union members. */ 1005 1.1 christos static hashval_t 1006 1.1 christos score_elf_got_entry_hash (const void *entry_) 1007 1.1 christos { 1008 1.1 christos const struct score_got_entry *entry = (struct score_got_entry *)entry_; 1009 1.1 christos 1010 1.1 christos return entry->symndx 1011 1.1 christos + (!entry->abfd ? entry->d.address : entry->abfd->id); 1012 1.1 christos } 1013 1.1 christos 1014 1.1 christos static int 1015 1.1 christos score_elf_got_entry_eq (const void *entry1, const void *entry2) 1016 1.1 christos { 1017 1.1 christos const struct score_got_entry *e1 = (struct score_got_entry *)entry1; 1018 1.1 christos const struct score_got_entry *e2 = (struct score_got_entry *)entry2; 1019 1.1 christos 1020 1.1 christos return e1->abfd == e2->abfd && e1->symndx == e2->symndx 1021 1.1 christos && (! e1->abfd ? e1->d.address == e2->d.address 1022 1.8 christos : e1->symndx >= 0 ? e1->d.addend == e2->d.addend 1023 1.8 christos : e1->d.h == e2->d.h); 1024 1.1 christos } 1025 1.1 christos 1026 1.1 christos /* If H needs a GOT entry, assign it the highest available dynamic 1027 1.1 christos index. Otherwise, assign it the lowest available dynamic 1028 1.1 christos index. */ 1029 1.10 christos static bool 1030 1.1 christos score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data) 1031 1.1 christos { 1032 1.1 christos struct score_elf_hash_sort_data *hsd = data; 1033 1.1 christos 1034 1.1 christos /* Symbols without dynamic symbol table entries aren't interesting at all. */ 1035 1.1 christos if (h->root.dynindx == -1) 1036 1.10 christos return true; 1037 1.1 christos 1038 1.1 christos /* Global symbols that need GOT entries that are not explicitly 1039 1.1 christos referenced are marked with got offset 2. Those that are 1040 1.1 christos referenced get a 1, and those that don't need GOT entries get 1041 1.1 christos -1. */ 1042 1.1 christos if (h->root.got.offset == 2) 1043 1.1 christos { 1044 1.1 christos if (hsd->max_unref_got_dynindx == hsd->min_got_dynindx) 1045 1.8 christos hsd->low = (struct elf_link_hash_entry *) h; 1046 1.1 christos h->root.dynindx = hsd->max_unref_got_dynindx++; 1047 1.1 christos } 1048 1.1 christos else if (h->root.got.offset != 1) 1049 1.1 christos h->root.dynindx = hsd->max_non_got_dynindx++; 1050 1.1 christos else 1051 1.1 christos { 1052 1.1 christos h->root.dynindx = --hsd->min_got_dynindx; 1053 1.1 christos hsd->low = (struct elf_link_hash_entry *) h; 1054 1.1 christos } 1055 1.1 christos 1056 1.10 christos return true; 1057 1.1 christos } 1058 1.1 christos 1059 1.1 christos static asection * 1060 1.10 christos score_elf_got_section (bfd *abfd, bool maybe_excluded) 1061 1.1 christos { 1062 1.1 christos asection *sgot = bfd_get_linker_section (abfd, ".got"); 1063 1.1 christos 1064 1.1 christos if (sgot == NULL || (! maybe_excluded && (sgot->flags & SEC_EXCLUDE) != 0)) 1065 1.1 christos return NULL; 1066 1.1 christos return sgot; 1067 1.1 christos } 1068 1.1 christos 1069 1.1 christos /* Returns the GOT information associated with the link indicated by 1070 1.1 christos INFO. If SGOTP is non-NULL, it is filled in with the GOT section. */ 1071 1.1 christos static struct score_got_info * 1072 1.1 christos score_elf_got_info (bfd *abfd, asection **sgotp) 1073 1.1 christos { 1074 1.1 christos asection *sgot; 1075 1.1 christos struct score_got_info *g; 1076 1.1 christos 1077 1.10 christos sgot = score_elf_got_section (abfd, true); 1078 1.1 christos BFD_ASSERT (sgot != NULL); 1079 1.1 christos BFD_ASSERT (elf_section_data (sgot) != NULL); 1080 1.1 christos g = score_elf_section_data (sgot)->u.got_info; 1081 1.1 christos BFD_ASSERT (g != NULL); 1082 1.1 christos 1083 1.1 christos if (sgotp) 1084 1.1 christos *sgotp = sgot; 1085 1.1 christos return g; 1086 1.1 christos } 1087 1.1 christos 1088 1.1 christos /* Sort the dynamic symbol table so that symbols that need GOT entries 1089 1.1 christos appear towards the end. This reduces the amount of GOT space 1090 1.1 christos required. MAX_LOCAL is used to set the number of local symbols 1091 1.1 christos known to be in the dynamic symbol table. During 1092 1.11 christos s3_bfd_score_elf_late_size_sections, this value is 1. Afterward, the 1093 1.1 christos section symbols are added and the count is higher. */ 1094 1.10 christos static bool 1095 1.1 christos score_elf_sort_hash_table (struct bfd_link_info *info, 1096 1.8 christos unsigned long max_local) 1097 1.1 christos { 1098 1.1 christos struct score_elf_hash_sort_data hsd; 1099 1.1 christos struct score_got_info *g; 1100 1.1 christos bfd *dynobj; 1101 1.1 christos 1102 1.1 christos dynobj = elf_hash_table (info)->dynobj; 1103 1.1 christos 1104 1.1 christos g = score_elf_got_info (dynobj, NULL); 1105 1.1 christos 1106 1.1 christos hsd.low = NULL; 1107 1.1 christos hsd.max_unref_got_dynindx = 1108 1.1 christos hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount 1109 1.1 christos /* In the multi-got case, assigned_gotno of the master got_info 1110 1.1 christos indicate the number of entries that aren't referenced in the 1111 1.1 christos primary GOT, but that must have entries because there are 1112 1.1 christos dynamic relocations that reference it. Since they aren't 1113 1.1 christos referenced, we move them to the end of the GOT, so that they 1114 1.1 christos don't prevent other entries that are referenced from getting 1115 1.1 christos too large offsets. */ 1116 1.1 christos - (g->next ? g->assigned_gotno : 0); 1117 1.1 christos hsd.max_non_got_dynindx = max_local; 1118 1.1 christos score_elf_link_hash_traverse (elf_hash_table (info), 1119 1.1 christos score_elf_sort_hash_table_f, 1120 1.1 christos &hsd); 1121 1.1 christos 1122 1.1 christos /* There should have been enough room in the symbol table to 1123 1.1 christos accommodate both the GOT and non-GOT symbols. */ 1124 1.1 christos BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx); 1125 1.1 christos BFD_ASSERT ((unsigned long)hsd.max_unref_got_dynindx 1126 1.8 christos <= elf_hash_table (info)->dynsymcount); 1127 1.1 christos 1128 1.1 christos /* Now we know which dynamic symbol has the lowest dynamic symbol 1129 1.1 christos table index in the GOT. */ 1130 1.1 christos g->global_gotsym = hsd.low; 1131 1.1 christos 1132 1.10 christos return true; 1133 1.1 christos } 1134 1.1 christos 1135 1.1 christos /* Create an entry in an score ELF linker hash table. */ 1136 1.1 christos 1137 1.1 christos static struct bfd_hash_entry * 1138 1.1 christos score_elf_link_hash_newfunc (struct bfd_hash_entry *entry, 1139 1.8 christos struct bfd_hash_table *table, 1140 1.8 christos const char *string) 1141 1.1 christos { 1142 1.1 christos struct score_elf_link_hash_entry *ret = (struct score_elf_link_hash_entry *) entry; 1143 1.1 christos 1144 1.1 christos /* Allocate the structure if it has not already been allocated by a subclass. */ 1145 1.1 christos if (ret == NULL) 1146 1.1 christos ret = bfd_hash_allocate (table, sizeof (struct score_elf_link_hash_entry)); 1147 1.1 christos if (ret == NULL) 1148 1.1 christos return (struct bfd_hash_entry *) ret; 1149 1.1 christos 1150 1.1 christos /* Call the allocation method of the superclass. */ 1151 1.1 christos ret = ((struct score_elf_link_hash_entry *) 1152 1.8 christos _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); 1153 1.1 christos 1154 1.1 christos if (ret != NULL) 1155 1.1 christos { 1156 1.1 christos ret->possibly_dynamic_relocs = 0; 1157 1.10 christos ret->readonly_reloc = false; 1158 1.10 christos ret->no_fn_stub = false; 1159 1.10 christos ret->forced_local = false; 1160 1.1 christos } 1161 1.1 christos 1162 1.1 christos return (struct bfd_hash_entry *) ret; 1163 1.1 christos } 1164 1.1 christos 1165 1.1 christos /* Returns the first relocation of type r_type found, beginning with 1166 1.1 christos RELOCATION. RELEND is one-past-the-end of the relocation table. */ 1167 1.1 christos static const Elf_Internal_Rela * 1168 1.1 christos score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type, 1169 1.8 christos const Elf_Internal_Rela *relocation, 1170 1.8 christos const Elf_Internal_Rela *relend) 1171 1.1 christos { 1172 1.1 christos while (relocation < relend) 1173 1.1 christos { 1174 1.1 christos if (ELF32_R_TYPE (relocation->r_info) == r_type) 1175 1.8 christos return relocation; 1176 1.1 christos 1177 1.1 christos ++relocation; 1178 1.1 christos } 1179 1.1 christos 1180 1.1 christos /* We didn't find it. */ 1181 1.1 christos bfd_set_error (bfd_error_bad_value); 1182 1.1 christos return NULL; 1183 1.1 christos } 1184 1.1 christos 1185 1.1 christos /* This function is called via qsort() to sort the dynamic relocation 1186 1.1 christos entries by increasing r_symndx value. */ 1187 1.1 christos static int 1188 1.1 christos score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2) 1189 1.1 christos { 1190 1.1 christos Elf_Internal_Rela int_reloc1; 1191 1.1 christos Elf_Internal_Rela int_reloc2; 1192 1.1 christos 1193 1.1 christos bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg1, &int_reloc1); 1194 1.1 christos bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg2, &int_reloc2); 1195 1.1 christos 1196 1.1 christos return (ELF32_R_SYM (int_reloc1.r_info) - ELF32_R_SYM (int_reloc2.r_info)); 1197 1.1 christos } 1198 1.1 christos 1199 1.1 christos /* Return whether a relocation is against a local symbol. */ 1200 1.10 christos static bool 1201 1.1 christos score_elf_local_relocation_p (bfd *input_bfd, 1202 1.8 christos const Elf_Internal_Rela *relocation, 1203 1.8 christos asection **local_sections, 1204 1.10 christos bool check_forced) 1205 1.1 christos { 1206 1.1 christos unsigned long r_symndx; 1207 1.1 christos Elf_Internal_Shdr *symtab_hdr; 1208 1.1 christos struct score_elf_link_hash_entry *h; 1209 1.1 christos size_t extsymoff; 1210 1.1 christos 1211 1.1 christos r_symndx = ELF32_R_SYM (relocation->r_info); 1212 1.1 christos symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 1213 1.1 christos extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info; 1214 1.1 christos 1215 1.1 christos if (r_symndx < extsymoff) 1216 1.10 christos return true; 1217 1.1 christos if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL) 1218 1.10 christos return true; 1219 1.1 christos 1220 1.1 christos if (check_forced) 1221 1.1 christos { 1222 1.1 christos /* Look up the hash table to check whether the symbol was forced local. */ 1223 1.1 christos h = (struct score_elf_link_hash_entry *) 1224 1.8 christos elf_sym_hashes (input_bfd) [r_symndx - extsymoff]; 1225 1.1 christos /* Find the real hash-table entry for this symbol. */ 1226 1.1 christos while (h->root.root.type == bfd_link_hash_indirect 1227 1.8 christos || h->root.root.type == bfd_link_hash_warning) 1228 1.8 christos h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; 1229 1.1 christos if (h->root.forced_local) 1230 1.10 christos return true; 1231 1.1 christos } 1232 1.1 christos 1233 1.10 christos return false; 1234 1.1 christos } 1235 1.1 christos 1236 1.1 christos /* Returns the dynamic relocation section for DYNOBJ. */ 1237 1.1 christos static asection * 1238 1.10 christos score_elf_rel_dyn_section (bfd *dynobj, bool create_p) 1239 1.1 christos { 1240 1.1 christos static const char dname[] = ".rel.dyn"; 1241 1.1 christos asection *sreloc; 1242 1.1 christos 1243 1.1 christos sreloc = bfd_get_linker_section (dynobj, dname); 1244 1.1 christos if (sreloc == NULL && create_p) 1245 1.1 christos { 1246 1.1 christos sreloc = bfd_make_section_anyway_with_flags (dynobj, dname, 1247 1.1 christos (SEC_ALLOC 1248 1.1 christos | SEC_LOAD 1249 1.1 christos | SEC_HAS_CONTENTS 1250 1.1 christos | SEC_IN_MEMORY 1251 1.1 christos | SEC_LINKER_CREATED 1252 1.1 christos | SEC_READONLY)); 1253 1.1 christos if (sreloc == NULL 1254 1.9 christos || !bfd_set_section_alignment (sreloc, 1255 1.9 christos SCORE_ELF_LOG_FILE_ALIGN (dynobj))) 1256 1.8 christos return NULL; 1257 1.1 christos } 1258 1.1 christos return sreloc; 1259 1.1 christos } 1260 1.1 christos 1261 1.1 christos static void 1262 1.1 christos score_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n) 1263 1.1 christos { 1264 1.1 christos asection *s; 1265 1.1 christos 1266 1.10 christos s = score_elf_rel_dyn_section (abfd, false); 1267 1.1 christos BFD_ASSERT (s != NULL); 1268 1.1 christos 1269 1.1 christos if (s->size == 0) 1270 1.1 christos { 1271 1.1 christos /* Make room for a null element. */ 1272 1.1 christos s->size += SCORE_ELF_REL_SIZE (abfd); 1273 1.1 christos ++s->reloc_count; 1274 1.1 christos } 1275 1.1 christos s->size += n * SCORE_ELF_REL_SIZE (abfd); 1276 1.1 christos } 1277 1.1 christos 1278 1.1 christos /* Create a rel.dyn relocation for the dynamic linker to resolve. REL 1279 1.1 christos is the original relocation, which is now being transformed into a 1280 1.1 christos dynamic relocation. The ADDENDP is adjusted if necessary; the 1281 1.1 christos caller should store the result in place of the original addend. */ 1282 1.10 christos static bool 1283 1.1 christos score_elf_create_dynamic_relocation (bfd *output_bfd, 1284 1.8 christos struct bfd_link_info *info, 1285 1.8 christos const Elf_Internal_Rela *rel, 1286 1.8 christos struct score_elf_link_hash_entry *h, 1287 1.8 christos bfd_vma symbol, 1288 1.8 christos bfd_vma *addendp, asection *input_section) 1289 1.1 christos { 1290 1.1 christos Elf_Internal_Rela outrel[3]; 1291 1.1 christos asection *sreloc; 1292 1.1 christos bfd *dynobj; 1293 1.1 christos int r_type; 1294 1.1 christos long indx; 1295 1.10 christos bool defined_p; 1296 1.1 christos 1297 1.1 christos r_type = ELF32_R_TYPE (rel->r_info); 1298 1.1 christos dynobj = elf_hash_table (info)->dynobj; 1299 1.10 christos sreloc = score_elf_rel_dyn_section (dynobj, false); 1300 1.1 christos BFD_ASSERT (sreloc != NULL); 1301 1.1 christos BFD_ASSERT (sreloc->contents != NULL); 1302 1.1 christos BFD_ASSERT (sreloc->reloc_count * SCORE_ELF_REL_SIZE (output_bfd) < sreloc->size); 1303 1.1 christos 1304 1.1 christos outrel[0].r_offset = 1305 1.1 christos _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset); 1306 1.1 christos outrel[1].r_offset = 1307 1.1 christos _bfd_elf_section_offset (output_bfd, info, input_section, rel[1].r_offset); 1308 1.1 christos outrel[2].r_offset = 1309 1.1 christos _bfd_elf_section_offset (output_bfd, info, input_section, rel[2].r_offset); 1310 1.1 christos 1311 1.1 christos if (outrel[0].r_offset == MINUS_ONE) 1312 1.1 christos /* The relocation field has been deleted. */ 1313 1.10 christos return true; 1314 1.1 christos 1315 1.1 christos if (outrel[0].r_offset == MINUS_TWO) 1316 1.1 christos { 1317 1.1 christos /* The relocation field has been converted into a relative value of 1318 1.8 christos some sort. Functions like _bfd_elf_write_section_eh_frame expect 1319 1.8 christos the field to be fully relocated, so add in the symbol's value. */ 1320 1.1 christos *addendp += symbol; 1321 1.10 christos return true; 1322 1.1 christos } 1323 1.1 christos 1324 1.1 christos /* We must now calculate the dynamic symbol table index to use 1325 1.1 christos in the relocation. */ 1326 1.1 christos if (h != NULL 1327 1.1 christos && (! info->symbolic || !h->root.def_regular) 1328 1.1 christos /* h->root.dynindx may be -1 if this symbol was marked to 1329 1.8 christos become local. */ 1330 1.1 christos && h->root.dynindx != -1) 1331 1.1 christos { 1332 1.1 christos indx = h->root.dynindx; 1333 1.8 christos /* ??? glibc's ld.so just adds the final GOT entry to the 1334 1.8 christos relocation field. It therefore treats relocs against 1335 1.8 christos defined symbols in the same way as relocs against 1336 1.8 christos undefined symbols. */ 1337 1.10 christos defined_p = false; 1338 1.1 christos } 1339 1.1 christos else 1340 1.1 christos { 1341 1.1 christos indx = 0; 1342 1.10 christos defined_p = true; 1343 1.1 christos } 1344 1.1 christos 1345 1.1 christos /* If the relocation was previously an absolute relocation and 1346 1.1 christos this symbol will not be referred to by the relocation, we must 1347 1.1 christos adjust it by the value we give it in the dynamic symbol table. 1348 1.1 christos Otherwise leave the job up to the dynamic linker. */ 1349 1.1 christos if (defined_p && r_type != R_SCORE_REL32) 1350 1.1 christos *addendp += symbol; 1351 1.1 christos 1352 1.1 christos /* The relocation is always an REL32 relocation because we don't 1353 1.1 christos know where the shared library will wind up at load-time. */ 1354 1.1 christos outrel[0].r_info = ELF32_R_INFO ((unsigned long) indx, R_SCORE_REL32); 1355 1.1 christos 1356 1.1 christos /* For strict adherence to the ABI specification, we should 1357 1.1 christos generate a R_SCORE_64 relocation record by itself before the 1358 1.1 christos _REL32/_64 record as well, such that the addend is read in as 1359 1.1 christos a 64-bit value (REL32 is a 32-bit relocation, after all). 1360 1.1 christos However, since none of the existing ELF64 SCORE dynamic 1361 1.1 christos loaders seems to care, we don't waste space with these 1362 1.1 christos artificial relocations. If this turns out to not be true, 1363 1.1 christos score_elf_allocate_dynamic_relocations() should be tweaked so 1364 1.1 christos as to make room for a pair of dynamic relocations per 1365 1.1 christos invocation if ABI_64_P, and here we should generate an 1366 1.1 christos additional relocation record with R_SCORE_64 by itself for a 1367 1.1 christos NULL symbol before this relocation record. */ 1368 1.1 christos outrel[1].r_info = ELF32_R_INFO (0, R_SCORE_NONE); 1369 1.1 christos outrel[2].r_info = ELF32_R_INFO (0, R_SCORE_NONE); 1370 1.1 christos 1371 1.1 christos /* Adjust the output offset of the relocation to reference the 1372 1.1 christos correct location in the output file. */ 1373 1.1 christos outrel[0].r_offset += (input_section->output_section->vma 1374 1.8 christos + input_section->output_offset); 1375 1.1 christos outrel[1].r_offset += (input_section->output_section->vma 1376 1.8 christos + input_section->output_offset); 1377 1.1 christos outrel[2].r_offset += (input_section->output_section->vma 1378 1.8 christos + input_section->output_offset); 1379 1.1 christos 1380 1.1 christos /* Put the relocation back out. We have to use the special 1381 1.1 christos relocation outputter in the 64-bit case since the 64-bit 1382 1.1 christos relocation format is non-standard. */ 1383 1.1 christos bfd_elf32_swap_reloc_out 1384 1.1 christos (output_bfd, &outrel[0], 1385 1.1 christos (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel))); 1386 1.1 christos 1387 1.1 christos /* We've now added another relocation. */ 1388 1.1 christos ++sreloc->reloc_count; 1389 1.1 christos 1390 1.1 christos /* Make sure the output section is writable. The dynamic linker 1391 1.1 christos will be writing to it. */ 1392 1.1 christos elf_section_data (input_section->output_section)->this_hdr.sh_flags |= SHF_WRITE; 1393 1.1 christos 1394 1.10 christos return true; 1395 1.1 christos } 1396 1.1 christos 1397 1.10 christos static bool 1398 1.1 christos score_elf_create_got_section (bfd *abfd, 1399 1.8 christos struct bfd_link_info *info, 1400 1.10 christos bool maybe_exclude) 1401 1.1 christos { 1402 1.1 christos flagword flags; 1403 1.1 christos asection *s; 1404 1.1 christos struct elf_link_hash_entry *h; 1405 1.1 christos struct bfd_link_hash_entry *bh; 1406 1.1 christos struct score_got_info *g; 1407 1.9 christos size_t amt; 1408 1.1 christos 1409 1.1 christos /* This function may be called more than once. */ 1410 1.10 christos s = score_elf_got_section (abfd, true); 1411 1.1 christos if (s) 1412 1.1 christos { 1413 1.1 christos if (! maybe_exclude) 1414 1.8 christos s->flags &= ~SEC_EXCLUDE; 1415 1.10 christos return true; 1416 1.1 christos } 1417 1.1 christos 1418 1.1 christos flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 1419 1.1 christos 1420 1.1 christos if (maybe_exclude) 1421 1.1 christos flags |= SEC_EXCLUDE; 1422 1.1 christos 1423 1.1 christos /* We have to use an alignment of 2**4 here because this is hardcoded 1424 1.1 christos in the function stub generation and in the linker script. */ 1425 1.1 christos s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); 1426 1.7 christos elf_hash_table (info)->sgot = s; 1427 1.7 christos if (s == NULL 1428 1.9 christos || !bfd_set_section_alignment (s, 4)) 1429 1.10 christos return false; 1430 1.1 christos 1431 1.1 christos /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the 1432 1.1 christos linker script because we don't want to define the symbol if we 1433 1.1 christos are not creating a global offset table. */ 1434 1.1 christos bh = NULL; 1435 1.1 christos if (! (_bfd_generic_link_add_one_symbol 1436 1.8 christos (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, 1437 1.10 christos 0, NULL, false, get_elf_backend_data (abfd)->collect, &bh))) 1438 1.10 christos return false; 1439 1.1 christos 1440 1.1 christos h = (struct elf_link_hash_entry *) bh; 1441 1.1 christos h->non_elf = 0; 1442 1.1 christos h->def_regular = 1; 1443 1.1 christos h->type = STT_OBJECT; 1444 1.7 christos elf_hash_table (info)->hgot = h; 1445 1.1 christos 1446 1.6 christos if (bfd_link_pic (info) && ! bfd_elf_link_record_dynamic_symbol (info, h)) 1447 1.10 christos return false; 1448 1.1 christos 1449 1.1 christos amt = sizeof (struct score_got_info); 1450 1.1 christos g = bfd_alloc (abfd, amt); 1451 1.1 christos if (g == NULL) 1452 1.10 christos return false; 1453 1.1 christos 1454 1.1 christos g->global_gotsym = NULL; 1455 1.1 christos g->global_gotno = 0; 1456 1.1 christos 1457 1.1 christos g->local_gotno = SCORE_RESERVED_GOTNO; 1458 1.1 christos g->assigned_gotno = SCORE_RESERVED_GOTNO; 1459 1.1 christos g->next = NULL; 1460 1.1 christos 1461 1.1 christos g->got_entries = htab_try_create (1, score_elf_got_entry_hash, 1462 1.8 christos score_elf_got_entry_eq, NULL); 1463 1.1 christos if (g->got_entries == NULL) 1464 1.10 christos return false; 1465 1.1 christos score_elf_section_data (s)->u.got_info = g; 1466 1.1 christos score_elf_section_data (s)->elf.this_hdr.sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; 1467 1.1 christos 1468 1.10 christos return true; 1469 1.1 christos } 1470 1.1 christos 1471 1.1 christos /* Calculate the %high function. */ 1472 1.1 christos static bfd_vma 1473 1.1 christos score_elf_high (bfd_vma value) 1474 1.1 christos { 1475 1.1 christos return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff; 1476 1.1 christos } 1477 1.1 christos 1478 1.1 christos /* Create a local GOT entry for VALUE. Return the index of the entry, 1479 1.1 christos or -1 if it could not be created. */ 1480 1.1 christos static struct score_got_entry * 1481 1.1 christos score_elf_create_local_got_entry (bfd *abfd, 1482 1.8 christos bfd *ibfd ATTRIBUTE_UNUSED, 1483 1.8 christos struct score_got_info *gg, 1484 1.8 christos asection *sgot, bfd_vma value, 1485 1.8 christos unsigned long r_symndx ATTRIBUTE_UNUSED, 1486 1.8 christos struct score_elf_link_hash_entry *h ATTRIBUTE_UNUSED, 1487 1.8 christos int r_type ATTRIBUTE_UNUSED) 1488 1.1 christos { 1489 1.1 christos struct score_got_entry entry, **loc; 1490 1.1 christos struct score_got_info *g; 1491 1.1 christos 1492 1.1 christos entry.abfd = NULL; 1493 1.1 christos entry.symndx = -1; 1494 1.1 christos entry.d.address = value; 1495 1.1 christos 1496 1.1 christos g = gg; 1497 1.1 christos loc = (struct score_got_entry **) htab_find_slot (g->got_entries, &entry, INSERT); 1498 1.1 christos if (*loc) 1499 1.1 christos return *loc; 1500 1.1 christos 1501 1.1 christos entry.gotidx = SCORE_ELF_GOT_SIZE (abfd) * g->assigned_gotno++; 1502 1.1 christos 1503 1.1 christos *loc = bfd_alloc (abfd, sizeof entry); 1504 1.1 christos 1505 1.1 christos if (! *loc) 1506 1.1 christos return NULL; 1507 1.1 christos 1508 1.1 christos memcpy (*loc, &entry, sizeof entry); 1509 1.1 christos 1510 1.1 christos if (g->assigned_gotno >= g->local_gotno) 1511 1.1 christos { 1512 1.1 christos (*loc)->gotidx = -1; 1513 1.1 christos /* We didn't allocate enough space in the GOT. */ 1514 1.7 christos _bfd_error_handler 1515 1.8 christos (_("not enough GOT space for local GOT entries")); 1516 1.1 christos bfd_set_error (bfd_error_bad_value); 1517 1.1 christos return NULL; 1518 1.1 christos } 1519 1.1 christos 1520 1.1 christos score_bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx)); 1521 1.1 christos 1522 1.1 christos return *loc; 1523 1.1 christos } 1524 1.1 christos 1525 1.1 christos /* Find a GOT entry whose higher-order 16 bits are the same as those 1526 1.1 christos for value. Return the index into the GOT for this entry. */ 1527 1.1 christos static bfd_vma 1528 1.1 christos score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, 1529 1.10 christos bfd_vma value, bool external) 1530 1.1 christos { 1531 1.1 christos asection *sgot; 1532 1.1 christos struct score_got_info *g; 1533 1.1 christos struct score_got_entry *entry; 1534 1.1 christos 1535 1.1 christos if (!external) 1536 1.1 christos { 1537 1.1 christos /* Although the ABI says that it is "the high-order 16 bits" that we 1538 1.8 christos want, it is really the %high value. The complete value is 1539 1.8 christos calculated with a `addiu' of a LO16 relocation, just as with a 1540 1.8 christos HI16/LO16 pair. */ 1541 1.1 christos value = score_elf_high (value) << 16; 1542 1.1 christos } 1543 1.1 christos 1544 1.1 christos g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot); 1545 1.1 christos 1546 1.1 christos entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, 0, NULL, 1547 1.8 christos R_SCORE_GOT15); 1548 1.1 christos if (entry) 1549 1.1 christos return entry->gotidx; 1550 1.1 christos else 1551 1.1 christos return MINUS_ONE; 1552 1.1 christos } 1553 1.1 christos 1554 1.1 christos static void 1555 1.1 christos s3_bfd_score_elf_hide_symbol (struct bfd_link_info *info, 1556 1.8 christos struct elf_link_hash_entry *entry, 1557 1.10 christos bool force_local) 1558 1.1 christos { 1559 1.1 christos bfd *dynobj; 1560 1.1 christos asection *got; 1561 1.1 christos struct score_got_info *g; 1562 1.1 christos struct score_elf_link_hash_entry *h; 1563 1.1 christos 1564 1.1 christos h = (struct score_elf_link_hash_entry *) entry; 1565 1.1 christos if (h->forced_local) 1566 1.1 christos return; 1567 1.10 christos h->forced_local = true; 1568 1.1 christos 1569 1.1 christos dynobj = elf_hash_table (info)->dynobj; 1570 1.1 christos if (dynobj != NULL && force_local) 1571 1.1 christos { 1572 1.10 christos got = score_elf_got_section (dynobj, false); 1573 1.1 christos if (got == NULL) 1574 1.8 christos return; 1575 1.1 christos g = score_elf_section_data (got)->u.got_info; 1576 1.1 christos 1577 1.1 christos if (g->next) 1578 1.8 christos { 1579 1.8 christos struct score_got_entry e; 1580 1.8 christos struct score_got_info *gg = g; 1581 1.8 christos 1582 1.8 christos /* Since we're turning what used to be a global symbol into a 1583 1.8 christos local one, bump up the number of local entries of each GOT 1584 1.8 christos that had an entry for it. This will automatically decrease 1585 1.8 christos the number of global entries, since global_gotno is actually 1586 1.8 christos the upper limit of global entries. */ 1587 1.8 christos e.abfd = dynobj; 1588 1.8 christos e.symndx = -1; 1589 1.8 christos e.d.h = h; 1590 1.8 christos 1591 1.8 christos for (g = g->next; g != gg; g = g->next) 1592 1.8 christos if (htab_find (g->got_entries, &e)) 1593 1.8 christos { 1594 1.8 christos BFD_ASSERT (g->global_gotno > 0); 1595 1.8 christos g->local_gotno++; 1596 1.8 christos g->global_gotno--; 1597 1.8 christos } 1598 1.8 christos 1599 1.8 christos /* If this was a global symbol forced into the primary GOT, we 1600 1.8 christos no longer need an entry for it. We can't release the entry 1601 1.8 christos at this point, but we must at least stop counting it as one 1602 1.8 christos of the symbols that required a forced got entry. */ 1603 1.8 christos if (h->root.got.offset == 2) 1604 1.8 christos { 1605 1.8 christos BFD_ASSERT (gg->assigned_gotno > 0); 1606 1.8 christos gg->assigned_gotno--; 1607 1.8 christos } 1608 1.8 christos } 1609 1.1 christos else if (g->global_gotno == 0 && g->global_gotsym == NULL) 1610 1.8 christos /* If we haven't got through GOT allocation yet, just bump up the 1611 1.8 christos number of local entries, as this symbol won't be counted as 1612 1.8 christos global. */ 1613 1.8 christos g->local_gotno++; 1614 1.1 christos else if (h->root.got.offset == 1) 1615 1.8 christos { 1616 1.8 christos /* If we're past non-multi-GOT allocation and this symbol had 1617 1.8 christos been marked for a global got entry, give it a local entry 1618 1.8 christos instead. */ 1619 1.8 christos BFD_ASSERT (g->global_gotno > 0); 1620 1.8 christos g->local_gotno++; 1621 1.8 christos g->global_gotno--; 1622 1.8 christos } 1623 1.1 christos } 1624 1.1 christos 1625 1.1 christos _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local); 1626 1.1 christos } 1627 1.1 christos 1628 1.1 christos /* If H is a symbol that needs a global GOT entry, but has a dynamic 1629 1.1 christos symbol table index lower than any we've seen to date, record it for 1630 1.1 christos posterity. */ 1631 1.10 christos static bool 1632 1.1 christos score_elf_record_global_got_symbol (struct elf_link_hash_entry *h, 1633 1.8 christos bfd *abfd, 1634 1.8 christos struct bfd_link_info *info, 1635 1.8 christos struct score_got_info *g) 1636 1.1 christos { 1637 1.1 christos struct score_got_entry entry, **loc; 1638 1.1 christos 1639 1.1 christos /* A global symbol in the GOT must also be in the dynamic symbol table. */ 1640 1.1 christos if (h->dynindx == -1) 1641 1.1 christos { 1642 1.1 christos switch (ELF_ST_VISIBILITY (h->other)) 1643 1.8 christos { 1644 1.8 christos case STV_INTERNAL: 1645 1.8 christos case STV_HIDDEN: 1646 1.10 christos s3_bfd_score_elf_hide_symbol (info, h, true); 1647 1.8 christos break; 1648 1.8 christos } 1649 1.1 christos if (!bfd_elf_link_record_dynamic_symbol (info, h)) 1650 1.10 christos return false; 1651 1.1 christos } 1652 1.1 christos 1653 1.1 christos entry.abfd = abfd; 1654 1.1 christos entry.symndx = -1; 1655 1.1 christos entry.d.h = (struct score_elf_link_hash_entry *)h; 1656 1.1 christos 1657 1.1 christos loc = (struct score_got_entry **)htab_find_slot (g->got_entries, &entry, INSERT); 1658 1.1 christos 1659 1.1 christos /* If we've already marked this entry as needing GOT space, we don't 1660 1.1 christos need to do it again. */ 1661 1.1 christos if (*loc) 1662 1.10 christos return true; 1663 1.1 christos 1664 1.1 christos *loc = bfd_alloc (abfd, sizeof entry); 1665 1.1 christos if (! *loc) 1666 1.10 christos return false; 1667 1.1 christos 1668 1.1 christos entry.gotidx = -1; 1669 1.1 christos 1670 1.1 christos memcpy (*loc, &entry, sizeof (entry)); 1671 1.1 christos 1672 1.1 christos if (h->got.offset != MINUS_ONE) 1673 1.10 christos return true; 1674 1.1 christos 1675 1.1 christos /* By setting this to a value other than -1, we are indicating that 1676 1.1 christos there needs to be a GOT entry for H. Avoid using zero, as the 1677 1.1 christos generic ELF copy_indirect_symbol tests for <= 0. */ 1678 1.1 christos h->got.offset = 1; 1679 1.1 christos 1680 1.10 christos return true; 1681 1.1 christos } 1682 1.1 christos 1683 1.1 christos /* Reserve space in G for a GOT entry containing the value of symbol 1684 1.1 christos SYMNDX in input bfd ABDF, plus ADDEND. */ 1685 1.10 christos static bool 1686 1.1 christos score_elf_record_local_got_symbol (bfd *abfd, 1687 1.8 christos long symndx, 1688 1.8 christos bfd_vma addend, 1689 1.8 christos struct score_got_info *g) 1690 1.1 christos { 1691 1.1 christos struct score_got_entry entry, **loc; 1692 1.1 christos 1693 1.1 christos entry.abfd = abfd; 1694 1.1 christos entry.symndx = symndx; 1695 1.1 christos entry.d.addend = addend; 1696 1.1 christos loc = (struct score_got_entry **)htab_find_slot (g->got_entries, &entry, INSERT); 1697 1.1 christos 1698 1.1 christos if (*loc) 1699 1.10 christos return true; 1700 1.1 christos 1701 1.1 christos entry.gotidx = g->local_gotno++; 1702 1.1 christos 1703 1.1 christos *loc = bfd_alloc (abfd, sizeof(entry)); 1704 1.1 christos if (! *loc) 1705 1.10 christos return false; 1706 1.1 christos 1707 1.1 christos memcpy (*loc, &entry, sizeof (entry)); 1708 1.1 christos 1709 1.10 christos return true; 1710 1.1 christos } 1711 1.1 christos 1712 1.1 christos /* Returns the GOT offset at which the indicated address can be found. 1713 1.1 christos If there is not yet a GOT entry for this value, create one. 1714 1.1 christos Returns -1 if no satisfactory GOT offset can be found. */ 1715 1.1 christos static bfd_vma 1716 1.1 christos score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, 1717 1.8 christos bfd_vma value, unsigned long r_symndx, 1718 1.8 christos struct score_elf_link_hash_entry *h, int r_type) 1719 1.1 christos { 1720 1.1 christos asection *sgot; 1721 1.1 christos struct score_got_info *g; 1722 1.1 christos struct score_got_entry *entry; 1723 1.1 christos 1724 1.1 christos g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot); 1725 1.1 christos 1726 1.1 christos entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, 1727 1.8 christos r_symndx, h, r_type); 1728 1.1 christos if (!entry) 1729 1.1 christos return MINUS_ONE; 1730 1.1 christos 1731 1.1 christos else 1732 1.1 christos return entry->gotidx; 1733 1.1 christos } 1734 1.1 christos 1735 1.1 christos /* Returns the GOT index for the global symbol indicated by H. */ 1736 1.1 christos 1737 1.1 christos static bfd_vma 1738 1.1 christos score_elf_global_got_index (bfd *abfd, struct elf_link_hash_entry *h) 1739 1.1 christos { 1740 1.1 christos bfd_vma got_index; 1741 1.1 christos asection *sgot; 1742 1.1 christos struct score_got_info *g; 1743 1.1 christos long global_got_dynindx = 0; 1744 1.1 christos 1745 1.1 christos g = score_elf_got_info (abfd, &sgot); 1746 1.1 christos if (g->global_gotsym != NULL) 1747 1.1 christos global_got_dynindx = g->global_gotsym->dynindx; 1748 1.1 christos 1749 1.1 christos /* Once we determine the global GOT entry with the lowest dynamic 1750 1.1 christos symbol table index, we must put all dynamic symbols with greater 1751 1.1 christos indices into the GOT. That makes it easy to calculate the GOT 1752 1.1 christos offset. */ 1753 1.1 christos BFD_ASSERT (h->dynindx >= global_got_dynindx); 1754 1.1 christos got_index = ((h->dynindx - global_got_dynindx + g->local_gotno) * SCORE_ELF_GOT_SIZE (abfd)); 1755 1.1 christos BFD_ASSERT (got_index < sgot->size); 1756 1.1 christos 1757 1.1 christos return got_index; 1758 1.1 christos } 1759 1.1 christos 1760 1.1 christos /* Returns the offset for the entry at the INDEXth position in the GOT. */ 1761 1.1 christos 1762 1.1 christos static bfd_vma 1763 1.1 christos score_elf_got_offset_from_index (bfd *dynobj, 1764 1.1 christos bfd *output_bfd, 1765 1.8 christos bfd *input_bfd ATTRIBUTE_UNUSED, 1766 1.1 christos bfd_vma got_index) 1767 1.1 christos { 1768 1.1 christos asection *sgot; 1769 1.1 christos bfd_vma gp; 1770 1.1 christos 1771 1.1 christos score_elf_got_info (dynobj, &sgot); 1772 1.1 christos gp = _bfd_get_gp_value (output_bfd); 1773 1.1 christos 1774 1.1 christos return sgot->output_section->vma + sgot->output_offset + got_index - gp; 1775 1.1 christos } 1776 1.1 christos 1777 1.1 christos /* Follow indirect and warning hash entries so that each got entry 1778 1.1 christos points to the final symbol definition. P must point to a pointer 1779 1.1 christos to the hash table we're traversing. Since this traversal may 1780 1.1 christos modify the hash table, we set this pointer to NULL to indicate 1781 1.1 christos we've made a potentially-destructive change to the hash table, so 1782 1.1 christos the traversal must be restarted. */ 1783 1.1 christos static int 1784 1.1 christos score_elf_resolve_final_got_entry (void **entryp, void *p) 1785 1.1 christos { 1786 1.1 christos struct score_got_entry *entry = (struct score_got_entry *)*entryp; 1787 1.1 christos htab_t got_entries = *(htab_t *)p; 1788 1.1 christos 1789 1.1 christos if (entry->abfd != NULL && entry->symndx == -1) 1790 1.1 christos { 1791 1.1 christos struct score_elf_link_hash_entry *h = entry->d.h; 1792 1.1 christos 1793 1.1 christos while (h->root.root.type == bfd_link_hash_indirect 1794 1.8 christos || h->root.root.type == bfd_link_hash_warning) 1795 1.8 christos h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; 1796 1.1 christos 1797 1.1 christos if (entry->d.h == h) 1798 1.8 christos return 1; 1799 1.1 christos 1800 1.1 christos entry->d.h = h; 1801 1.1 christos 1802 1.1 christos /* If we can't find this entry with the new bfd hash, re-insert 1803 1.8 christos it, and get the traversal restarted. */ 1804 1.1 christos if (! htab_find (got_entries, entry)) 1805 1.8 christos { 1806 1.8 christos htab_clear_slot (got_entries, entryp); 1807 1.8 christos entryp = htab_find_slot (got_entries, entry, INSERT); 1808 1.8 christos if (! *entryp) 1809 1.8 christos *entryp = entry; 1810 1.8 christos /* Abort the traversal, since the whole table may have 1811 1.8 christos moved, and leave it up to the parent to restart the 1812 1.8 christos process. */ 1813 1.8 christos *(htab_t *)p = NULL; 1814 1.8 christos return 0; 1815 1.8 christos } 1816 1.1 christos /* We might want to decrement the global_gotno count, but it's 1817 1.8 christos either too early or too late for that at this point. */ 1818 1.1 christos } 1819 1.1 christos 1820 1.1 christos return 1; 1821 1.1 christos } 1822 1.1 christos 1823 1.1 christos /* Turn indirect got entries in a got_entries table into their final locations. */ 1824 1.1 christos static void 1825 1.1 christos score_elf_resolve_final_got_entries (struct score_got_info *g) 1826 1.1 christos { 1827 1.1 christos htab_t got_entries; 1828 1.1 christos 1829 1.1 christos do 1830 1.1 christos { 1831 1.1 christos got_entries = g->got_entries; 1832 1.1 christos 1833 1.1 christos htab_traverse (got_entries, 1834 1.8 christos score_elf_resolve_final_got_entry, 1835 1.8 christos &got_entries); 1836 1.1 christos } 1837 1.1 christos while (got_entries == NULL); 1838 1.1 christos } 1839 1.1 christos 1840 1.1 christos /* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. for -r */ 1841 1.1 christos static void 1842 1.1 christos score_elf_add_to_rel (bfd *abfd, 1843 1.8 christos bfd_byte *address, 1844 1.8 christos reloc_howto_type *howto, 1845 1.8 christos bfd_signed_vma increment) 1846 1.1 christos { 1847 1.1 christos bfd_signed_vma addend; 1848 1.1 christos bfd_vma contents; 1849 1.1 christos unsigned long offset; 1850 1.1 christos unsigned long r_type = howto->type; 1851 1.1 christos unsigned long hi16_addend, hi16_offset, hi16_value, uvalue; 1852 1.1 christos 1853 1.1 christos contents = score_bfd_get_32 (abfd, address); 1854 1.1 christos /* Get the (signed) value from the instruction. */ 1855 1.1 christos addend = contents & howto->src_mask; 1856 1.1 christos if (addend & ((howto->src_mask + 1) >> 1)) 1857 1.1 christos { 1858 1.1 christos bfd_signed_vma mask; 1859 1.1 christos 1860 1.1 christos mask = -1; 1861 1.1 christos mask &= ~howto->src_mask; 1862 1.1 christos addend |= mask; 1863 1.1 christos } 1864 1.1 christos /* Add in the increment, (which is a byte value). */ 1865 1.1 christos switch (r_type) 1866 1.1 christos { 1867 1.1 christos case R_SCORE_PC19: 1868 1.1 christos offset = 1869 1.8 christos (((contents & howto->src_mask) & 0x3ff0000) >> 6) | ((contents & howto->src_mask) & 0x3ff); 1870 1.1 christos offset += increment; 1871 1.1 christos contents = 1872 1.8 christos (contents & ~howto-> 1873 1.8 christos src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff); 1874 1.1 christos score_bfd_put_32 (abfd, contents, address); 1875 1.1 christos break; 1876 1.1 christos case R_SCORE_HI16: 1877 1.1 christos break; 1878 1.1 christos case R_SCORE_LO16: 1879 1.1 christos hi16_addend = score_bfd_get_32 (abfd, address - 4); 1880 1.1 christos hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; 1881 1.1 christos offset = ((((contents >> 16) & 0x3) << 15) | (contents & 0x7fff)) >> 1; 1882 1.1 christos offset = (hi16_offset << 16) | (offset & 0xffff); 1883 1.1 christos uvalue = increment + offset; 1884 1.1 christos hi16_offset = (uvalue >> 16) << 1; 1885 1.1 christos hi16_value = (hi16_addend & (~(howto->dst_mask))) 1886 1.8 christos | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); 1887 1.1 christos score_bfd_put_32 (abfd, hi16_value, address - 4); 1888 1.1 christos offset = (uvalue & 0xffff) << 1; 1889 1.1 christos contents = (contents & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000); 1890 1.1 christos score_bfd_put_32 (abfd, contents, address); 1891 1.1 christos break; 1892 1.1 christos case R_SCORE_24: 1893 1.1 christos offset = 1894 1.8 christos (((contents & howto->src_mask) >> 1) & 0x1ff8000) | ((contents & howto->src_mask) & 0x7fff); 1895 1.1 christos offset += increment; 1896 1.1 christos contents = 1897 1.8 christos (contents & ~howto-> 1898 1.8 christos src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff); 1899 1.1 christos score_bfd_put_32 (abfd, contents, address); 1900 1.1 christos break; 1901 1.1 christos 1902 1.1 christos case R_SCORE16_11: 1903 1.1 christos 1904 1.1 christos contents = score_bfd_get_16 (abfd, address); 1905 1.1 christos offset = contents & howto->src_mask; 1906 1.1 christos offset += increment; 1907 1.1 christos contents = (contents & ~howto->src_mask) | (offset & howto->src_mask); 1908 1.1 christos score_bfd_put_16 (abfd, contents, address); 1909 1.1 christos 1910 1.1 christos break; 1911 1.1 christos case R_SCORE16_PC8: 1912 1.1 christos 1913 1.1 christos contents = score_bfd_get_16 (abfd, address); 1914 1.1 christos offset = (contents & howto->src_mask) + ((increment >> 1) & 0x1ff); 1915 1.1 christos contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); 1916 1.1 christos score_bfd_put_16 (abfd, contents, address); 1917 1.1 christos 1918 1.1 christos break; 1919 1.1 christos 1920 1.1 christos case R_SCORE_BCMP: 1921 1.1 christos contents = score_bfd_get_32 (abfd, address); 1922 1.1 christos offset = (contents & howto->src_mask); 1923 1.1 christos offset <<= howto->rightshift; 1924 1.1 christos offset += increment; 1925 1.1 christos offset >>= howto->rightshift; 1926 1.1 christos contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); 1927 1.1 christos score_bfd_put_32 (abfd, contents, address); 1928 1.1 christos break; 1929 1.1 christos 1930 1.1 christos case R_SCORE_IMM30: 1931 1.1 christos contents = score_bfd_get_48 (abfd, address); 1932 1.1 christos offset = (contents & howto->src_mask); 1933 1.1 christos offset <<= howto->rightshift; 1934 1.1 christos offset += increment; 1935 1.1 christos offset >>= howto->rightshift; 1936 1.1 christos contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); 1937 1.1 christos score_bfd_put_48 (abfd, contents, address); 1938 1.1 christos break; 1939 1.1 christos 1940 1.1 christos case R_SCORE_IMM32: 1941 1.1 christos contents = score_bfd_get_48 (abfd, address); 1942 1.1 christos offset = (contents & howto->src_mask); 1943 1.1 christos offset += increment; 1944 1.1 christos contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); 1945 1.1 christos score_bfd_put_48 (abfd, contents, address); 1946 1.1 christos break; 1947 1.1 christos 1948 1.1 christos default: 1949 1.1 christos addend += increment; 1950 1.1 christos contents = (contents & ~howto->dst_mask) | (addend & howto->dst_mask); 1951 1.1 christos score_bfd_put_32 (abfd, contents, address); 1952 1.1 christos break; 1953 1.1 christos } 1954 1.1 christos } 1955 1.1 christos 1956 1.1 christos /* Perform a relocation as part of a final link. */ 1957 1.1 christos static bfd_reloc_status_type 1958 1.1 christos score_elf_final_link_relocate (reloc_howto_type *howto, 1959 1.8 christos bfd *input_bfd, 1960 1.8 christos bfd *output_bfd, 1961 1.8 christos asection *input_section, 1962 1.8 christos bfd_byte *contents, 1963 1.8 christos Elf_Internal_Rela *rel, 1964 1.8 christos Elf_Internal_Rela *relocs, 1965 1.8 christos bfd_vma symbol, 1966 1.8 christos struct bfd_link_info *info, 1967 1.8 christos const char *sym_name ATTRIBUTE_UNUSED, 1968 1.8 christos int sym_flags ATTRIBUTE_UNUSED, 1969 1.8 christos struct score_elf_link_hash_entry *h, 1970 1.8 christos asection **local_sections, 1971 1.10 christos bool gp_disp_p) 1972 1.1 christos { 1973 1.1 christos unsigned long r_type; 1974 1.1 christos unsigned long r_symndx; 1975 1.1 christos bfd_byte *hit_data = contents + rel->r_offset; 1976 1.1 christos bfd_vma addend; 1977 1.1 christos /* The final GP value to be used for the relocatable, executable, or 1978 1.1 christos shared object file being produced. */ 1979 1.1 christos bfd_vma gp = MINUS_ONE; 1980 1.1 christos /* The place (section offset or address) of the storage unit being relocated. */ 1981 1.1 christos bfd_vma rel_addr; 1982 1.1 christos /* The offset into the global offset table at which the address of the relocation entry 1983 1.1 christos symbol, adjusted by the addend, resides during execution. */ 1984 1.1 christos bfd_vma g = MINUS_ONE; 1985 1.1 christos /* TRUE if the symbol referred to by this relocation is a local symbol. */ 1986 1.10 christos bool local_p; 1987 1.1 christos /* The eventual value we will relocate. */ 1988 1.1 christos bfd_vma value = symbol; 1989 1.1 christos unsigned long hi16_addend, hi16_offset, hi16_value, uvalue, offset, abs_value = 0; 1990 1.1 christos 1991 1.1 christos 1992 1.1 christos if (elf_gp (output_bfd) == 0) 1993 1.1 christos { 1994 1.1 christos struct bfd_link_hash_entry *bh; 1995 1.1 christos asection *o; 1996 1.1 christos 1997 1.1 christos bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1); 1998 1.1 christos if (bh != NULL && bh->type == bfd_link_hash_defined) 1999 1.8 christos elf_gp (output_bfd) = (bh->u.def.value 2000 1.8 christos + bh->u.def.section->output_section->vma 2001 1.8 christos + bh->u.def.section->output_offset); 2002 1.6 christos else if (bfd_link_relocatable (info)) 2003 1.8 christos { 2004 1.8 christos bfd_vma lo = -1; 2005 1.1 christos 2006 1.8 christos /* Find the GP-relative section with the lowest offset. */ 2007 1.8 christos for (o = output_bfd->sections; o != NULL; o = o->next) 2008 1.8 christos if (o->vma < lo) 2009 1.8 christos lo = o->vma; 2010 1.8 christos /* And calculate GP relative to that. */ 2011 1.8 christos elf_gp (output_bfd) = lo + ELF_SCORE_GP_OFFSET (input_bfd); 2012 1.8 christos } 2013 1.1 christos else 2014 1.8 christos { 2015 1.8 christos /* If the relocate_section function needs to do a reloc 2016 1.8 christos involving the GP value, it should make a reloc_dangerous 2017 1.8 christos callback to warn that GP is not defined. */ 2018 1.8 christos } 2019 1.1 christos } 2020 1.1 christos 2021 1.1 christos /* Parse the relocation. */ 2022 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 2023 1.1 christos r_type = ELF32_R_TYPE (rel->r_info); 2024 1.1 christos rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset); 2025 1.10 christos local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, true); 2026 1.1 christos 2027 1.1 christos if (r_type == R_SCORE_GOT15) 2028 1.1 christos { 2029 1.1 christos const Elf_Internal_Rela *relend; 2030 1.1 christos const Elf_Internal_Rela *lo16_rel; 2031 1.1 christos bfd_vma lo_value = 0; 2032 1.1 christos 2033 1.8 christos relend = relocs + input_section->reloc_count; 2034 1.1 christos lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend); 2035 1.1 christos if ((local_p) && (lo16_rel != NULL)) 2036 1.8 christos { 2037 1.8 christos bfd_vma tmp = 0; 2038 1.8 christos tmp = score_bfd_get_32 (input_bfd, contents + lo16_rel->r_offset); 2039 1.8 christos lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1); 2040 1.8 christos } 2041 1.1 christos addend = lo_value; 2042 1.1 christos } 2043 1.1 christos /* For score3 R_SCORE_ABS32. */ 2044 1.1 christos else if (r_type == R_SCORE_ABS32 || r_type == R_SCORE_REL32) 2045 1.1 christos { 2046 1.1 christos addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask; 2047 1.1 christos } 2048 1.1 christos else 2049 1.1 christos { 2050 1.1 christos addend = (score_bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask; 2051 1.1 christos } 2052 1.1 christos 2053 1.1 christos /* If we haven't already determined the GOT offset, or the GP value, 2054 1.1 christos and we're going to need it, get it now. */ 2055 1.1 christos switch (r_type) 2056 1.1 christos { 2057 1.1 christos case R_SCORE_CALL15: 2058 1.1 christos case R_SCORE_GOT15: 2059 1.1 christos if (!local_p) 2060 1.8 christos { 2061 1.8 christos g = score_elf_global_got_index (elf_hash_table (info)->dynobj, 2062 1.8 christos (struct elf_link_hash_entry *) h); 2063 1.8 christos if ((! elf_hash_table (info)->dynamic_sections_created 2064 1.8 christos || (bfd_link_pic (info) 2065 1.8 christos && (info->symbolic || h->root.dynindx == -1) 2066 1.8 christos && h->root.def_regular))) 2067 1.8 christos { 2068 1.8 christos /* This is a static link or a -Bsymbolic link. The 2069 1.8 christos symbol is defined locally, or was forced to be local. 2070 1.8 christos We must initialize this entry in the GOT. */ 2071 1.8 christos bfd *tmpbfd = elf_hash_table (info)->dynobj; 2072 1.10 christos asection *sgot = score_elf_got_section (tmpbfd, false); 2073 1.8 christos score_bfd_put_32 (tmpbfd, value, sgot->contents + g); 2074 1.8 christos } 2075 1.8 christos } 2076 1.1 christos else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15) 2077 1.8 christos { 2078 1.8 christos /* There's no need to create a local GOT entry here; the 2079 1.8 christos calculation for a local GOT15 entry does not involve G. */ 2080 1.8 christos ; 2081 1.8 christos } 2082 1.1 christos else 2083 1.8 christos { 2084 1.8 christos g = score_elf_local_got_index (output_bfd, input_bfd, info, 2085 1.8 christos symbol + addend, r_symndx, h, r_type); 2086 1.8 christos if (g == MINUS_ONE) 2087 1.8 christos return bfd_reloc_outofrange; 2088 1.8 christos } 2089 1.1 christos 2090 1.1 christos /* Convert GOT indices to actual offsets. */ 2091 1.1 christos g = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj, 2092 1.8 christos output_bfd, input_bfd, g); 2093 1.1 christos break; 2094 1.1 christos 2095 1.1 christos case R_SCORE_HI16: 2096 1.1 christos case R_SCORE_LO16: 2097 1.1 christos case R_SCORE_GPREL32: 2098 1.1 christos gp = _bfd_get_gp_value (output_bfd); 2099 1.1 christos break; 2100 1.1 christos 2101 1.1 christos case R_SCORE_GP15: 2102 1.1 christos gp = _bfd_get_gp_value (output_bfd); 2103 1.1 christos 2104 1.1 christos default: 2105 1.1 christos break; 2106 1.1 christos } 2107 1.1 christos 2108 1.1 christos switch (r_type) 2109 1.1 christos { 2110 1.1 christos case R_SCORE_NONE: 2111 1.1 christos return bfd_reloc_ok; 2112 1.1 christos 2113 1.1 christos case R_SCORE_ABS32: 2114 1.1 christos case R_SCORE_REL32: 2115 1.6 christos if ((bfd_link_pic (info) 2116 1.8 christos || (elf_hash_table (info)->dynamic_sections_created 2117 1.8 christos && h != NULL 2118 1.8 christos && h->root.def_dynamic 2119 1.8 christos && !h->root.def_regular)) 2120 1.8 christos && r_symndx != STN_UNDEF 2121 1.8 christos && (input_section->flags & SEC_ALLOC) != 0) 2122 1.8 christos { 2123 1.8 christos /* If we're creating a shared library, or this relocation is against a symbol 2124 1.8 christos in a shared library, then we can't know where the symbol will end up. 2125 1.8 christos So, we create a relocation record in the output, and leave the job up 2126 1.8 christos to the dynamic linker. */ 2127 1.8 christos value = addend; 2128 1.8 christos if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h, 2129 1.8 christos symbol, &value, 2130 1.8 christos input_section)) 2131 1.8 christos return bfd_reloc_undefined; 2132 1.8 christos } 2133 1.1 christos else if (r_symndx == STN_UNDEF) 2134 1.8 christos /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols 2135 1.8 christos from removed linkonce sections, or sections discarded by 2136 1.8 christos a linker script. */ 2137 1.8 christos value = 0; 2138 1.1 christos else 2139 1.8 christos { 2140 1.8 christos if (r_type != R_SCORE_REL32) 2141 1.8 christos value = symbol + addend; 2142 1.8 christos else 2143 1.8 christos value = addend; 2144 1.8 christos } 2145 1.1 christos value &= howto->dst_mask; 2146 1.1 christos bfd_put_32 (input_bfd, value, hit_data); 2147 1.1 christos return bfd_reloc_ok; 2148 1.1 christos 2149 1.1 christos case R_SCORE_ABS16: 2150 1.1 christos value += addend; 2151 1.1 christos if ((long)value > 0x7fff || (long)value < -0x8000) 2152 1.8 christos return bfd_reloc_overflow; 2153 1.1 christos score_bfd_put_16 (input_bfd, value, hit_data); 2154 1.1 christos return bfd_reloc_ok; 2155 1.1 christos 2156 1.1 christos case R_SCORE_24: 2157 1.1 christos addend = score_bfd_get_32 (input_bfd, hit_data); 2158 1.1 christos offset = (((addend & howto->src_mask) >> 1) & 0x1ff8000) | ((addend & howto->src_mask) & 0x7fff); 2159 1.1 christos if ((offset & 0x1000000) != 0) 2160 1.8 christos offset |= 0xfe000000; 2161 1.1 christos value += offset; 2162 1.6 christos abs_value = value - rel_addr; 2163 1.1 christos if ((abs_value & 0xfe000000) != 0) 2164 1.8 christos return bfd_reloc_overflow; 2165 1.1 christos addend = (addend & ~howto->src_mask) 2166 1.8 christos | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff); 2167 1.1 christos score_bfd_put_32 (input_bfd, addend, hit_data); 2168 1.1 christos return bfd_reloc_ok; 2169 1.1 christos 2170 1.1 christos /* signed imm32. */ 2171 1.1 christos case R_SCORE_IMM30: 2172 1.1 christos { 2173 1.8 christos int not_word_align_p = 0; 2174 1.8 christos bfd_vma imm_offset = 0; 2175 1.8 christos addend = score_bfd_get_48 (input_bfd, hit_data); 2176 1.8 christos imm_offset = ((addend >> 7) & 0xff) 2177 1.8 christos | (((addend >> 16) & 0x7fff) << 8) 2178 1.8 christos | (((addend >> 32) & 0x7f) << 23); 2179 1.8 christos imm_offset <<= howto->rightshift; 2180 1.8 christos value += imm_offset; 2181 1.8 christos value &= 0xffffffff; 2182 1.8 christos 2183 1.8 christos /* Check lw48/sw48 rd, value/label word align. */ 2184 1.8 christos if ((value & 0x3) != 0) 2185 1.8 christos not_word_align_p = 1; 2186 1.8 christos 2187 1.8 christos value >>= howto->rightshift; 2188 1.8 christos addend = (addend & ~howto->src_mask) 2189 1.8 christos | (((value & 0xff) >> 0) << 7) 2190 1.8 christos | (((value & 0x7fff00) >> 8) << 16) 2191 1.8 christos | (((value & 0x3f800000) >> 23) << 32); 2192 1.8 christos score_bfd_put_48 (input_bfd, addend, hit_data); 2193 1.8 christos if (not_word_align_p) 2194 1.8 christos return bfd_reloc_other; 2195 1.8 christos else 2196 1.8 christos return bfd_reloc_ok; 2197 1.1 christos } 2198 1.1 christos 2199 1.1 christos case R_SCORE_IMM32: 2200 1.1 christos { 2201 1.8 christos bfd_vma imm_offset = 0; 2202 1.8 christos addend = score_bfd_get_48 (input_bfd, hit_data); 2203 1.8 christos imm_offset = ((addend >> 5) & 0x3ff) 2204 1.8 christos | (((addend >> 16) & 0x7fff) << 10) 2205 1.8 christos | (((addend >> 32) & 0x7f) << 25); 2206 1.8 christos value += imm_offset; 2207 1.8 christos value &= 0xffffffff; 2208 1.8 christos addend = (addend & ~howto->src_mask) 2209 1.8 christos | ((value & 0x3ff) << 5) 2210 1.8 christos | (((value >> 10) & 0x7fff) << 16) 2211 1.8 christos | (((value >> 25) & 0x7f) << 32); 2212 1.8 christos score_bfd_put_48 (input_bfd, addend, hit_data); 2213 1.8 christos return bfd_reloc_ok; 2214 1.1 christos } 2215 1.1 christos 2216 1.1 christos case R_SCORE_PC19: 2217 1.1 christos addend = score_bfd_get_32 (input_bfd, hit_data); 2218 1.1 christos offset = (((addend & howto->src_mask) & 0x3ff0000) >> 6) | ((addend & howto->src_mask) & 0x3ff); 2219 1.1 christos if ((offset & 0x80000) != 0) 2220 1.8 christos offset |= 0xfff00000; 2221 1.1 christos abs_value = value = value - rel_addr + offset; 2222 1.1 christos /* exceed 20 bit : overflow. */ 2223 1.1 christos if ((abs_value & 0x80000000) == 0x80000000) 2224 1.8 christos abs_value = 0xffffffff - value + 1; 2225 1.1 christos if ((abs_value & 0xfff80000) != 0) 2226 1.8 christos return bfd_reloc_overflow; 2227 1.1 christos addend = (addend & ~howto->src_mask) 2228 1.8 christos | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff); 2229 1.1 christos score_bfd_put_32 (input_bfd, addend, hit_data); 2230 1.1 christos return bfd_reloc_ok; 2231 1.1 christos 2232 1.1 christos case R_SCORE16_11: 2233 1.1 christos addend = score_bfd_get_16 (input_bfd, hit_data); 2234 1.1 christos offset = addend & howto->src_mask; 2235 1.8 christos if ((offset & 0x800) != 0) /* Offset is negative. */ 2236 1.8 christos offset |= 0xfffff000; 2237 1.1 christos value += offset; 2238 1.6 christos abs_value = value - rel_addr; 2239 1.1 christos if ((abs_value & 0xfffff000) != 0) 2240 1.8 christos return bfd_reloc_overflow; 2241 1.1 christos addend = (addend & ~howto->src_mask) | (value & howto->src_mask); 2242 1.1 christos score_bfd_put_16 (input_bfd, addend, hit_data); 2243 1.1 christos return bfd_reloc_ok; 2244 1.1 christos 2245 1.1 christos case R_SCORE16_PC8: 2246 1.1 christos addend = score_bfd_get_16 (input_bfd, hit_data); 2247 1.1 christos offset = (addend & howto->src_mask) << 1; 2248 1.8 christos if ((offset & 0x200) != 0) /* Offset is negative. */ 2249 1.8 christos offset |= 0xfffffe00; 2250 1.1 christos abs_value = value = value - rel_addr + offset; 2251 1.1 christos /* Sign bit + exceed 9 bit. */ 2252 1.1 christos if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00)) 2253 1.8 christos return bfd_reloc_overflow; 2254 1.1 christos value >>= 1; 2255 1.1 christos addend = (addend & ~howto->src_mask) | (value & howto->src_mask); 2256 1.1 christos score_bfd_put_16 (input_bfd, addend, hit_data); 2257 1.1 christos return bfd_reloc_ok; 2258 1.1 christos 2259 1.1 christos case R_SCORE_BCMP: 2260 1.1 christos addend = score_bfd_get_32 (input_bfd, hit_data); 2261 1.1 christos offset = (addend & howto->src_mask) << howto->rightshift; 2262 1.8 christos if ((offset & 0x200) != 0) /* Offset is negative. */ 2263 1.8 christos offset |= 0xfffffe00; 2264 1.1 christos value = value - rel_addr + offset; 2265 1.1 christos /* Sign bit + exceed 9 bit. */ 2266 1.1 christos if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00)) 2267 1.8 christos return bfd_reloc_overflow; 2268 1.1 christos value >>= howto->rightshift; 2269 1.1 christos addend = (addend & ~howto->src_mask) 2270 1.8 christos | (value & 0x1) 2271 1.8 christos | (((value >> 1) & 0x7) << 7) 2272 1.8 christos | (((value >> 4) & 0x1f) << 21); 2273 1.1 christos score_bfd_put_32 (input_bfd, addend, hit_data); 2274 1.1 christos return bfd_reloc_ok; 2275 1.1 christos 2276 1.1 christos case R_SCORE_HI16: 2277 1.1 christos return bfd_reloc_ok; 2278 1.1 christos 2279 1.1 christos case R_SCORE_LO16: 2280 1.1 christos hi16_addend = score_bfd_get_32 (input_bfd, hit_data - 4); 2281 1.1 christos hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; 2282 1.1 christos addend = score_bfd_get_32 (input_bfd, hit_data); 2283 1.1 christos offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; 2284 1.1 christos offset = (hi16_offset << 16) | (offset & 0xffff); 2285 1.1 christos 2286 1.1 christos if (!gp_disp_p) 2287 1.8 christos uvalue = value + offset; 2288 1.1 christos else 2289 1.8 christos uvalue = offset + gp - rel_addr + 4; 2290 1.1 christos 2291 1.1 christos hi16_offset = (uvalue >> 16) << 1; 2292 1.1 christos hi16_value = (hi16_addend & (~(howto->dst_mask))) 2293 1.8 christos | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); 2294 1.1 christos score_bfd_put_32 (input_bfd, hi16_value, hit_data - 4); 2295 1.1 christos offset = (uvalue & 0xffff) << 1; 2296 1.1 christos value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000); 2297 1.1 christos score_bfd_put_32 (input_bfd, value, hit_data); 2298 1.1 christos return bfd_reloc_ok; 2299 1.1 christos 2300 1.1 christos case R_SCORE_GP15: 2301 1.1 christos addend = score_bfd_get_32 (input_bfd, hit_data); 2302 1.1 christos offset = addend & 0x7fff; 2303 1.1 christos if ((offset & 0x4000) == 0x4000) 2304 1.8 christos offset |= 0xffffc000; 2305 1.1 christos value = value + offset - gp; 2306 1.1 christos if (((value & 0xffffc000) != 0) && ((value & 0xffffc000) != 0xffffc000)) 2307 1.8 christos return bfd_reloc_overflow; 2308 1.1 christos value = (addend & ~howto->src_mask) | (value & howto->src_mask); 2309 1.1 christos score_bfd_put_32 (input_bfd, value, hit_data); 2310 1.1 christos return bfd_reloc_ok; 2311 1.1 christos 2312 1.1 christos case R_SCORE_GOT15: 2313 1.1 christos case R_SCORE_CALL15: 2314 1.1 christos if (local_p) 2315 1.8 christos { 2316 1.10 christos bool forced; 2317 1.1 christos 2318 1.8 christos /* The special case is when the symbol is forced to be local. We need the 2319 1.8 christos full address in the GOT since no R_SCORE_GOT_LO16 relocation follows. */ 2320 1.8 christos forced = ! score_elf_local_relocation_p (input_bfd, rel, 2321 1.10 christos local_sections, false); 2322 1.8 christos value = score_elf_got16_entry (output_bfd, input_bfd, info, 2323 1.8 christos symbol + addend, forced); 2324 1.8 christos if (value == MINUS_ONE) 2325 1.8 christos return bfd_reloc_outofrange; 2326 1.8 christos value = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj, 2327 1.8 christos output_bfd, input_bfd, value); 2328 1.8 christos } 2329 1.1 christos else 2330 1.8 christos { 2331 1.8 christos value = g; 2332 1.8 christos } 2333 1.1 christos 2334 1.1 christos if ((long) value > 0x3fff || (long) value < -0x4000) 2335 1.8 christos return bfd_reloc_overflow; 2336 1.1 christos 2337 1.1 christos addend = score_bfd_get_32 (input_bfd, hit_data); 2338 1.1 christos value = (addend & ~howto->dst_mask) | (value & howto->dst_mask); 2339 1.1 christos score_bfd_put_32 (input_bfd, value, hit_data); 2340 1.1 christos return bfd_reloc_ok; 2341 1.1 christos 2342 1.1 christos case R_SCORE_GPREL32: 2343 1.1 christos value = (addend + symbol - gp); 2344 1.1 christos value &= howto->dst_mask; 2345 1.1 christos score_bfd_put_32 (input_bfd, value, hit_data); 2346 1.1 christos return bfd_reloc_ok; 2347 1.1 christos 2348 1.1 christos case R_SCORE_GOT_LO16: 2349 1.1 christos addend = score_bfd_get_32 (input_bfd, hit_data); 2350 1.1 christos value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1); 2351 1.1 christos value += symbol; 2352 1.1 christos value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1) 2353 1.8 christos | (((value >> 14) & 0x3) << 16); 2354 1.1 christos 2355 1.1 christos score_bfd_put_32 (input_bfd, value, hit_data); 2356 1.1 christos return bfd_reloc_ok; 2357 1.1 christos 2358 1.1 christos case R_SCORE_DUMMY_HI16: 2359 1.1 christos return bfd_reloc_ok; 2360 1.1 christos 2361 1.1 christos case R_SCORE_GNU_VTINHERIT: 2362 1.1 christos case R_SCORE_GNU_VTENTRY: 2363 1.1 christos /* We don't do anything with these at present. */ 2364 1.1 christos return bfd_reloc_continue; 2365 1.1 christos 2366 1.1 christos default: 2367 1.1 christos return bfd_reloc_notsupported; 2368 1.1 christos } 2369 1.1 christos } 2370 1.1 christos 2371 1.1 christos /* Score backend functions. */ 2372 1.10 christos static bool 2373 1.10 christos s3_bfd_score_info_to_howto (bfd *abfd, 2374 1.8 christos arelent *bfd_reloc, 2375 1.8 christos Elf_Internal_Rela *elf_reloc) 2376 1.1 christos { 2377 1.1 christos unsigned int r_type; 2378 1.1 christos 2379 1.1 christos r_type = ELF32_R_TYPE (elf_reloc->r_info); 2380 1.1 christos if (r_type >= ARRAY_SIZE (elf32_score_howto_table)) 2381 1.10 christos { 2382 1.10 christos /* xgettext:c-format */ 2383 1.10 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 2384 1.10 christos abfd, r_type); 2385 1.10 christos bfd_set_error (bfd_error_bad_value); 2386 1.10 christos return false; 2387 1.10 christos } 2388 1.8 christos 2389 1.8 christos bfd_reloc->howto = &elf32_score_howto_table[r_type]; 2390 1.10 christos return true; 2391 1.1 christos } 2392 1.1 christos 2393 1.1 christos /* Relocate an score ELF section. */ 2394 1.10 christos static int 2395 1.1 christos s3_bfd_score_elf_relocate_section (bfd *output_bfd, 2396 1.8 christos struct bfd_link_info *info, 2397 1.8 christos bfd *input_bfd, 2398 1.8 christos asection *input_section, 2399 1.8 christos bfd_byte *contents, 2400 1.8 christos Elf_Internal_Rela *relocs, 2401 1.8 christos Elf_Internal_Sym *local_syms, 2402 1.8 christos asection **local_sections) 2403 1.1 christos { 2404 1.1 christos Elf_Internal_Shdr *symtab_hdr; 2405 1.1 christos Elf_Internal_Rela *rel; 2406 1.1 christos Elf_Internal_Rela *relend; 2407 1.1 christos const char *name; 2408 1.1 christos unsigned long offset; 2409 1.1 christos unsigned long hi16_addend, hi16_offset, hi16_value, uvalue; 2410 1.1 christos size_t extsymoff; 2411 1.10 christos bool gp_disp_p = false; 2412 1.1 christos 2413 1.1 christos /* Sort dynsym. */ 2414 1.1 christos if (elf_hash_table (info)->dynamic_sections_created) 2415 1.1 christos { 2416 1.1 christos bfd_size_type dynsecsymcount = 0; 2417 1.6 christos if (bfd_link_pic (info)) 2418 1.8 christos { 2419 1.8 christos asection * p; 2420 1.8 christos const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); 2421 1.8 christos 2422 1.8 christos for (p = output_bfd->sections; p ; p = p->next) 2423 1.8 christos if ((p->flags & SEC_EXCLUDE) == 0 2424 1.8 christos && (p->flags & SEC_ALLOC) != 0 2425 1.8 christos && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p)) 2426 1.8 christos ++ dynsecsymcount; 2427 1.8 christos } 2428 1.1 christos 2429 1.1 christos if (!score_elf_sort_hash_table (info, dynsecsymcount + 1)) 2430 1.10 christos return false; 2431 1.1 christos } 2432 1.1 christos 2433 1.1 christos symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 2434 1.1 christos extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info; 2435 1.1 christos rel = relocs; 2436 1.1 christos relend = relocs + input_section->reloc_count; 2437 1.1 christos for (; rel < relend; rel++) 2438 1.1 christos { 2439 1.1 christos int r_type; 2440 1.1 christos reloc_howto_type *howto; 2441 1.1 christos unsigned long r_symndx; 2442 1.1 christos Elf_Internal_Sym *sym; 2443 1.1 christos asection *sec; 2444 1.1 christos struct score_elf_link_hash_entry *h; 2445 1.1 christos bfd_vma relocation = 0; 2446 1.1 christos bfd_reloc_status_type r; 2447 1.1 christos arelent bfd_reloc; 2448 1.1 christos 2449 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 2450 1.1 christos r_type = ELF32_R_TYPE (rel->r_info); 2451 1.1 christos 2452 1.8 christos if (! s3_bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel)) 2453 1.8 christos continue; 2454 1.1 christos howto = bfd_reloc.howto; 2455 1.1 christos 2456 1.1 christos h = NULL; 2457 1.1 christos sym = NULL; 2458 1.1 christos sec = NULL; 2459 1.1 christos 2460 1.1 christos if (r_symndx < extsymoff) 2461 1.8 christos { 2462 1.8 christos sym = local_syms + r_symndx; 2463 1.8 christos sec = local_sections[r_symndx]; 2464 1.8 christos relocation = (sec->output_section->vma 2465 1.8 christos + sec->output_offset 2466 1.8 christos + sym->st_value); 2467 1.8 christos name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec); 2468 1.8 christos 2469 1.8 christos if (!bfd_link_relocatable (info) 2470 1.8 christos && (sec->flags & SEC_MERGE) 2471 1.8 christos && ELF_ST_TYPE (sym->st_info) == STT_SECTION) 2472 1.8 christos { 2473 1.8 christos asection *msec; 2474 1.8 christos bfd_vma addend, value; 2475 1.8 christos 2476 1.8 christos switch (r_type) 2477 1.8 christos { 2478 1.8 christos case R_SCORE_HI16: 2479 1.8 christos break; 2480 1.8 christos case R_SCORE_LO16: 2481 1.8 christos hi16_addend = score_bfd_get_32 (input_bfd, contents + rel->r_offset - 4); 2482 1.8 christos hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; 2483 1.8 christos value = score_bfd_get_32 (input_bfd, contents + rel->r_offset); 2484 1.8 christos offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1; 2485 1.8 christos addend = (hi16_offset << 16) | (offset & 0xffff); 2486 1.8 christos msec = sec; 2487 1.8 christos addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend); 2488 1.8 christos addend -= relocation; 2489 1.8 christos addend += msec->output_section->vma + msec->output_offset; 2490 1.8 christos uvalue = addend; 2491 1.8 christos hi16_offset = (uvalue >> 16) << 1; 2492 1.8 christos hi16_value = (hi16_addend & (~(howto->dst_mask))) 2493 1.8 christos | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); 2494 1.8 christos score_bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4); 2495 1.8 christos offset = (uvalue & 0xffff) << 1; 2496 1.8 christos value = (value & (~(howto->dst_mask))) 2497 1.8 christos | (offset & 0x7fff) | ((offset << 1) & 0x30000); 2498 1.8 christos score_bfd_put_32 (input_bfd, value, contents + rel->r_offset); 2499 1.8 christos break; 2500 1.8 christos 2501 1.8 christos case R_SCORE_IMM32: 2502 1.8 christos { 2503 1.8 christos value = score_bfd_get_48 (input_bfd, contents + rel->r_offset); 2504 1.8 christos addend = ((value >> 5) & 0x3ff) 2505 1.8 christos | (((value >> 16) & 0x7fff) << 10) 2506 1.8 christos | (((value >> 32) & 0x7f) << 25); 2507 1.8 christos msec = sec; 2508 1.8 christos addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend); 2509 1.8 christos addend -= relocation; 2510 1.8 christos addend += msec->output_section->vma + msec->output_offset; 2511 1.8 christos addend &= 0xffffffff; 2512 1.8 christos value = (value & ~howto->src_mask) 2513 1.8 christos | ((addend & 0x3ff) << 5) 2514 1.8 christos | (((addend >> 10) & 0x7fff) << 16) 2515 1.8 christos | (((addend >> 25) & 0x7f) << 32); 2516 1.8 christos score_bfd_put_48 (input_bfd, value, contents + rel->r_offset); 2517 1.8 christos break; 2518 1.8 christos } 2519 1.8 christos 2520 1.8 christos case R_SCORE_IMM30: 2521 1.8 christos { 2522 1.8 christos int not_word_align_p = 0; 2523 1.8 christos value = score_bfd_get_48 (input_bfd, contents + rel->r_offset); 2524 1.8 christos addend = ((value >> 7) & 0xff) 2525 1.8 christos | (((value >> 16) & 0x7fff) << 8) 2526 1.8 christos | (((value >> 32) & 0x7f) << 23); 2527 1.8 christos addend <<= howto->rightshift; 2528 1.8 christos msec = sec; 2529 1.8 christos addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend); 2530 1.8 christos addend -= relocation; 2531 1.8 christos addend += msec->output_section->vma + msec->output_offset; 2532 1.8 christos addend &= 0xffffffff; 2533 1.8 christos 2534 1.8 christos /* Check lw48/sw48 rd, value/label word align. */ 2535 1.8 christos if ((addend & 0x3) != 0) 2536 1.8 christos not_word_align_p = 1; 2537 1.8 christos 2538 1.8 christos addend >>= howto->rightshift; 2539 1.8 christos value = (value & ~howto->src_mask) 2540 1.8 christos | (((addend & 0xff) >> 0) << 7) 2541 1.8 christos | (((addend & 0x7fff00) >> 8) << 16) 2542 1.8 christos | (((addend & 0x3f800000) >> 23) << 32); 2543 1.8 christos score_bfd_put_48 (input_bfd, value, contents + rel->r_offset); 2544 1.8 christos 2545 1.8 christos if (not_word_align_p) 2546 1.8 christos return bfd_reloc_other; 2547 1.8 christos else 2548 1.8 christos break; 2549 1.8 christos } 2550 1.8 christos 2551 1.8 christos case R_SCORE_GOT_LO16: 2552 1.8 christos value = score_bfd_get_32 (input_bfd, contents + rel->r_offset); 2553 1.8 christos addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1); 2554 1.8 christos msec = sec; 2555 1.8 christos addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; 2556 1.8 christos addend += msec->output_section->vma + msec->output_offset; 2557 1.8 christos value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1) 2558 1.8 christos | (((addend >> 14) & 0x3) << 16); 2559 1.8 christos 2560 1.8 christos score_bfd_put_32 (input_bfd, value, contents + rel->r_offset); 2561 1.8 christos break; 2562 1.8 christos 2563 1.8 christos case R_SCORE_ABS32: 2564 1.8 christos case R_SCORE_REL32: 2565 1.8 christos value = bfd_get_32 (input_bfd, contents + rel->r_offset); 2566 1.8 christos /* Get the (signed) value from the instruction. */ 2567 1.8 christos addend = value & howto->src_mask; 2568 1.8 christos if (addend & ((howto->src_mask + 1) >> 1)) 2569 1.8 christos { 2570 1.8 christos bfd_signed_vma mask; 2571 1.8 christos 2572 1.8 christos mask = -1; 2573 1.8 christos mask &= ~howto->src_mask; 2574 1.8 christos addend |= mask; 2575 1.8 christos } 2576 1.8 christos msec = sec; 2577 1.8 christos addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; 2578 1.8 christos addend += msec->output_section->vma + msec->output_offset; 2579 1.8 christos value = (value & ~howto->dst_mask) | (addend & howto->dst_mask); 2580 1.8 christos bfd_put_32 (input_bfd, value, contents + rel->r_offset); 2581 1.8 christos break; 2582 1.8 christos 2583 1.8 christos default: 2584 1.8 christos value = score_bfd_get_32 (input_bfd, contents + rel->r_offset); 2585 1.8 christos /* Get the (signed) value from the instruction. */ 2586 1.8 christos addend = value & howto->src_mask; 2587 1.8 christos if (addend & ((howto->src_mask + 1) >> 1)) 2588 1.8 christos { 2589 1.8 christos bfd_signed_vma mask; 2590 1.8 christos 2591 1.8 christos mask = -1; 2592 1.8 christos mask &= ~howto->src_mask; 2593 1.8 christos addend |= mask; 2594 1.8 christos } 2595 1.8 christos msec = sec; 2596 1.8 christos addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; 2597 1.8 christos addend += msec->output_section->vma + msec->output_offset; 2598 1.8 christos value = (value & ~howto->dst_mask) | (addend & howto->dst_mask); 2599 1.8 christos score_bfd_put_32 (input_bfd, value, contents + rel->r_offset); 2600 1.8 christos break; 2601 1.8 christos } 2602 1.8 christos } 2603 1.8 christos } 2604 1.1 christos else 2605 1.8 christos { 2606 1.8 christos /* For global symbols we look up the symbol in the hash-table. */ 2607 1.8 christos h = ((struct score_elf_link_hash_entry *) 2608 1.8 christos elf_sym_hashes (input_bfd) [r_symndx - extsymoff]); 2609 1.3 christos 2610 1.3 christos if (info->wrap_hash != NULL 2611 1.3 christos && (input_section->flags & SEC_DEBUGGING) != 0) 2612 1.3 christos h = ((struct score_elf_link_hash_entry *) 2613 1.3 christos unwrap_hash_lookup (info, input_bfd, &h->root.root)); 2614 1.3 christos 2615 1.8 christos /* Find the real hash-table entry for this symbol. */ 2616 1.8 christos while (h->root.root.type == bfd_link_hash_indirect 2617 1.8 christos || h->root.root.type == bfd_link_hash_warning) 2618 1.8 christos h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; 2619 1.8 christos 2620 1.8 christos /* Record the name of this symbol, for our caller. */ 2621 1.8 christos name = h->root.root.root.string; 2622 1.8 christos 2623 1.8 christos /* See if this is the special GP_DISP_LABEL symbol. Note that such a 2624 1.8 christos symbol must always be a global symbol. */ 2625 1.8 christos if (strcmp (name, GP_DISP_LABEL) == 0) 2626 1.8 christos { 2627 1.8 christos /* Relocations against GP_DISP_LABEL are permitted only with 2628 1.8 christos R_SCORE_HI16 and R_SCORE_LO16 relocations. */ 2629 1.8 christos if (r_type != R_SCORE_HI16 && r_type != R_SCORE_LO16) 2630 1.8 christos return bfd_reloc_notsupported; 2631 1.8 christos 2632 1.10 christos gp_disp_p = true; 2633 1.8 christos } 2634 1.8 christos 2635 1.8 christos /* If this symbol is defined, calculate its address. Note that 2636 1.8 christos GP_DISP_LABEL is a magic symbol, always implicitly defined by the 2637 1.8 christos linker, so it's inappropriate to check to see whether or not 2638 1.8 christos its defined. */ 2639 1.8 christos else if ((h->root.root.type == bfd_link_hash_defined 2640 1.8 christos || h->root.root.type == bfd_link_hash_defweak) 2641 1.8 christos && h->root.root.u.def.section) 2642 1.8 christos { 2643 1.8 christos sec = h->root.root.u.def.section; 2644 1.8 christos if (sec->output_section) 2645 1.8 christos relocation = (h->root.root.u.def.value 2646 1.8 christos + sec->output_section->vma 2647 1.8 christos + sec->output_offset); 2648 1.8 christos else 2649 1.8 christos { 2650 1.8 christos relocation = h->root.root.u.def.value; 2651 1.8 christos } 2652 1.8 christos } 2653 1.8 christos else if (h->root.root.type == bfd_link_hash_undefweak) 2654 1.8 christos /* We allow relocations against undefined weak symbols, giving 2655 1.8 christos it the value zero, so that you can undefined weak functions 2656 1.8 christos and check to see if they exist by looking at their addresses. */ 2657 1.8 christos relocation = 0; 2658 1.8 christos else if (info->unresolved_syms_in_objects == RM_IGNORE 2659 1.8 christos && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) 2660 1.8 christos relocation = 0; 2661 1.8 christos else if (strcmp (name, "_DYNAMIC_LINK") == 0) 2662 1.8 christos { 2663 1.8 christos /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol 2664 1.8 christos in s3_bfd_score_elf_create_dynamic_sections. Otherwise, we should define 2665 1.8 christos the symbol with a value of 0. */ 2666 1.8 christos BFD_ASSERT (! bfd_link_pic (info)); 2667 1.8 christos BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL); 2668 1.8 christos relocation = 0; 2669 1.8 christos } 2670 1.8 christos else if (!bfd_link_relocatable (info)) 2671 1.8 christos { 2672 1.9 christos info->callbacks->undefined_symbol 2673 1.9 christos (info, h->root.root.root.string, input_bfd, input_section, 2674 1.9 christos rel->r_offset, 2675 1.9 christos (info->unresolved_syms_in_objects == RM_DIAGNOSE 2676 1.9 christos && !info->warn_unresolved_syms) 2677 1.6 christos || ELF_ST_VISIBILITY (h->root.other)); 2678 1.9 christos relocation = 0; 2679 1.9 christos } 2680 1.8 christos } 2681 1.1 christos 2682 1.1 christos if (sec != NULL && discarded_section (sec)) 2683 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 2684 1.1 christos rel, 1, relend, howto, 0, contents); 2685 1.1 christos 2686 1.6 christos if (bfd_link_relocatable (info)) 2687 1.8 christos { 2688 1.8 christos /* This is a relocatable link. We don't have to change 2689 1.8 christos anything, unless the reloc is against a section symbol, 2690 1.8 christos in which case we have to adjust according to where the 2691 1.8 christos section symbol winds up in the output section. */ 2692 1.8 christos if (r_symndx < symtab_hdr->sh_info) 2693 1.8 christos { 2694 1.8 christos sym = local_syms + r_symndx; 2695 1.8 christos if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) 2696 1.8 christos { 2697 1.8 christos sec = local_sections[r_symndx]; 2698 1.8 christos score_elf_add_to_rel (input_bfd, contents + rel->r_offset, 2699 1.8 christos howto, (bfd_signed_vma) (sec->output_offset + sym->st_value)); 2700 1.8 christos } 2701 1.8 christos } 2702 1.8 christos continue; 2703 1.8 christos } 2704 1.1 christos 2705 1.1 christos /* This is a final link. */ 2706 1.1 christos r = score_elf_final_link_relocate (howto, input_bfd, output_bfd, 2707 1.8 christos input_section, contents, rel, relocs, 2708 1.8 christos relocation, info, name, 2709 1.8 christos (h ? ELF_ST_TYPE ((unsigned int)h->root.root.type) : 2710 1.8 christos ELF_ST_TYPE ((unsigned int)sym->st_info)), h, local_sections, 2711 1.8 christos gp_disp_p); 2712 1.1 christos 2713 1.1 christos if (r != bfd_reloc_ok) 2714 1.8 christos { 2715 1.8 christos const char *msg = (const char *)0; 2716 1.1 christos 2717 1.8 christos switch (r) 2718 1.8 christos { 2719 1.8 christos case bfd_reloc_overflow: 2720 1.8 christos /* If the overflowing reloc was to an undefined symbol, 2721 1.8 christos we have already printed one error message and there 2722 1.8 christos is no point complaining again. */ 2723 1.6 christos if (!h || h->root.root.type != bfd_link_hash_undefined) 2724 1.6 christos (*info->callbacks->reloc_overflow) 2725 1.6 christos (info, NULL, name, howto->name, (bfd_vma) 0, 2726 1.6 christos input_bfd, input_section, rel->r_offset); 2727 1.8 christos break; 2728 1.8 christos case bfd_reloc_undefined: 2729 1.6 christos (*info->callbacks->undefined_symbol) 2730 1.10 christos (info, name, input_bfd, input_section, rel->r_offset, true); 2731 1.8 christos break; 2732 1.8 christos 2733 1.8 christos case bfd_reloc_outofrange: 2734 1.8 christos msg = _("internal error: out of range error"); 2735 1.8 christos goto common_error; 2736 1.8 christos 2737 1.8 christos case bfd_reloc_notsupported: 2738 1.8 christos msg = _("internal error: unsupported relocation error"); 2739 1.8 christos goto common_error; 2740 1.8 christos 2741 1.8 christos case bfd_reloc_dangerous: 2742 1.8 christos msg = _("internal error: dangerous error"); 2743 1.8 christos goto common_error; 2744 1.8 christos 2745 1.8 christos /* Use bfd_reloc_other to check lw48, sw48 word align. */ 2746 1.8 christos case bfd_reloc_other: 2747 1.8 christos msg = _("address not word aligned"); 2748 1.8 christos goto common_error; 2749 1.1 christos 2750 1.8 christos default: 2751 1.8 christos msg = _("internal error: unknown error"); 2752 1.8 christos /* Fall through. */ 2753 1.1 christos 2754 1.8 christos common_error: 2755 1.6 christos (*info->callbacks->warning) (info, msg, name, input_bfd, 2756 1.6 christos input_section, rel->r_offset); 2757 1.8 christos break; 2758 1.8 christos } 2759 1.8 christos } 2760 1.1 christos } 2761 1.1 christos 2762 1.10 christos return true; 2763 1.1 christos } 2764 1.1 christos 2765 1.1 christos /* Look through the relocs for a section during the first phase, and 2766 1.1 christos allocate space in the global offset table. */ 2767 1.10 christos static bool 2768 1.1 christos s3_bfd_score_elf_check_relocs (bfd *abfd, 2769 1.8 christos struct bfd_link_info *info, 2770 1.8 christos asection *sec, 2771 1.8 christos const Elf_Internal_Rela *relocs) 2772 1.1 christos { 2773 1.1 christos bfd *dynobj; 2774 1.1 christos Elf_Internal_Shdr *symtab_hdr; 2775 1.1 christos struct elf_link_hash_entry **sym_hashes; 2776 1.1 christos struct score_got_info *g; 2777 1.1 christos size_t extsymoff; 2778 1.1 christos const Elf_Internal_Rela *rel; 2779 1.1 christos const Elf_Internal_Rela *rel_end; 2780 1.1 christos asection *sgot; 2781 1.1 christos asection *sreloc; 2782 1.1 christos 2783 1.6 christos if (bfd_link_relocatable (info)) 2784 1.10 christos return true; 2785 1.1 christos 2786 1.1 christos dynobj = elf_hash_table (info)->dynobj; 2787 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 2788 1.1 christos sym_hashes = elf_sym_hashes (abfd); 2789 1.1 christos extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info; 2790 1.1 christos 2791 1.1 christos if (dynobj == NULL) 2792 1.1 christos { 2793 1.1 christos sgot = NULL; 2794 1.1 christos g = NULL; 2795 1.1 christos } 2796 1.1 christos else 2797 1.1 christos { 2798 1.10 christos sgot = score_elf_got_section (dynobj, false); 2799 1.1 christos if (sgot == NULL) 2800 1.8 christos g = NULL; 2801 1.1 christos else 2802 1.8 christos { 2803 1.8 christos BFD_ASSERT (score_elf_section_data (sgot) != NULL); 2804 1.8 christos g = score_elf_section_data (sgot)->u.got_info; 2805 1.8 christos BFD_ASSERT (g != NULL); 2806 1.8 christos } 2807 1.1 christos } 2808 1.1 christos 2809 1.1 christos sreloc = NULL; 2810 1.8 christos rel_end = relocs + sec->reloc_count; 2811 1.1 christos for (rel = relocs; rel < rel_end; ++rel) 2812 1.1 christos { 2813 1.1 christos unsigned long r_symndx; 2814 1.1 christos unsigned int r_type; 2815 1.1 christos struct elf_link_hash_entry *h; 2816 1.1 christos 2817 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 2818 1.1 christos r_type = ELF32_R_TYPE (rel->r_info); 2819 1.1 christos 2820 1.1 christos if (r_symndx < extsymoff) 2821 1.8 christos { 2822 1.8 christos h = NULL; 2823 1.8 christos } 2824 1.1 christos else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr)) 2825 1.8 christos { 2826 1.7 christos _bfd_error_handler 2827 1.7 christos /* xgettext:c-format */ 2828 1.8 christos (_("%pB: malformed reloc detected for section %pA"), abfd, sec); 2829 1.8 christos bfd_set_error (bfd_error_bad_value); 2830 1.10 christos return false; 2831 1.8 christos } 2832 1.1 christos else 2833 1.8 christos { 2834 1.8 christos h = sym_hashes[r_symndx - extsymoff]; 2835 1.1 christos 2836 1.8 christos /* This may be an indirect symbol created because of a version. */ 2837 1.8 christos if (h != NULL) 2838 1.8 christos { 2839 1.8 christos while (h->root.type == bfd_link_hash_indirect) 2840 1.8 christos h = (struct elf_link_hash_entry *)h->root.u.i.link; 2841 1.8 christos } 2842 1.8 christos } 2843 1.1 christos 2844 1.1 christos /* Some relocs require a global offset table. */ 2845 1.1 christos if (dynobj == NULL || sgot == NULL) 2846 1.8 christos { 2847 1.8 christos switch (r_type) 2848 1.8 christos { 2849 1.8 christos case R_SCORE_GOT15: 2850 1.8 christos case R_SCORE_CALL15: 2851 1.8 christos if (dynobj == NULL) 2852 1.8 christos elf_hash_table (info)->dynobj = dynobj = abfd; 2853 1.10 christos if (!score_elf_create_got_section (dynobj, info, false)) 2854 1.10 christos return false; 2855 1.8 christos g = score_elf_got_info (dynobj, &sgot); 2856 1.8 christos break; 2857 1.8 christos case R_SCORE_ABS32: 2858 1.8 christos case R_SCORE_REL32: 2859 1.8 christos if (dynobj == NULL 2860 1.6 christos && (bfd_link_pic (info) || h != NULL) 2861 1.6 christos && (sec->flags & SEC_ALLOC) != 0) 2862 1.8 christos elf_hash_table (info)->dynobj = dynobj = abfd; 2863 1.8 christos break; 2864 1.8 christos default: 2865 1.8 christos break; 2866 1.8 christos } 2867 1.8 christos } 2868 1.1 christos 2869 1.1 christos if (!h && (r_type == R_SCORE_GOT_LO16)) 2870 1.8 christos { 2871 1.8 christos if (! score_elf_record_local_got_symbol (abfd, r_symndx, rel->r_addend, g)) 2872 1.10 christos return false; 2873 1.8 christos } 2874 1.1 christos 2875 1.1 christos switch (r_type) 2876 1.8 christos { 2877 1.8 christos case R_SCORE_CALL15: 2878 1.8 christos if (h == NULL) 2879 1.8 christos { 2880 1.7 christos _bfd_error_handler 2881 1.7 christos /* xgettext:c-format */ 2882 1.8 christos (_("%pB: CALL15 reloc at %#" PRIx64 " not against global symbol"), 2883 1.8 christos abfd, (uint64_t) rel->r_offset); 2884 1.8 christos bfd_set_error (bfd_error_bad_value); 2885 1.10 christos return false; 2886 1.8 christos } 2887 1.8 christos else 2888 1.8 christos { 2889 1.8 christos /* This symbol requires a global offset table entry. */ 2890 1.8 christos if (! score_elf_record_global_got_symbol (h, abfd, info, g)) 2891 1.10 christos return false; 2892 1.8 christos 2893 1.8 christos /* We need a stub, not a plt entry for the undefined function. But we record 2894 1.8 christos it as if it needs plt. See _bfd_elf_adjust_dynamic_symbol. */ 2895 1.8 christos h->needs_plt = 1; 2896 1.8 christos h->type = STT_FUNC; 2897 1.8 christos } 2898 1.8 christos break; 2899 1.8 christos case R_SCORE_GOT15: 2900 1.8 christos if (h && ! score_elf_record_global_got_symbol (h, abfd, info, g)) 2901 1.10 christos return false; 2902 1.8 christos break; 2903 1.8 christos case R_SCORE_ABS32: 2904 1.8 christos case R_SCORE_REL32: 2905 1.8 christos if ((bfd_link_pic (info) || h != NULL) 2906 1.6 christos && (sec->flags & SEC_ALLOC) != 0) 2907 1.8 christos { 2908 1.8 christos if (sreloc == NULL) 2909 1.8 christos { 2910 1.10 christos sreloc = score_elf_rel_dyn_section (dynobj, true); 2911 1.8 christos if (sreloc == NULL) 2912 1.10 christos return false; 2913 1.8 christos } 2914 1.1 christos #define SCORE_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY) 2915 1.8 christos if (bfd_link_pic (info)) 2916 1.8 christos { 2917 1.8 christos /* When creating a shared object, we must copy these reloc types into 2918 1.8 christos the output file as R_SCORE_REL32 relocs. We make room for this reloc 2919 1.8 christos in the .rel.dyn reloc section. */ 2920 1.8 christos score_elf_allocate_dynamic_relocations (dynobj, 1); 2921 1.8 christos if ((sec->flags & SCORE_READONLY_SECTION) 2922 1.8 christos == SCORE_READONLY_SECTION) 2923 1.8 christos /* We tell the dynamic linker that there are 2924 1.8 christos relocations against the text segment. */ 2925 1.8 christos info->flags |= DF_TEXTREL; 2926 1.8 christos } 2927 1.8 christos else 2928 1.8 christos { 2929 1.8 christos struct score_elf_link_hash_entry *hscore; 2930 1.8 christos 2931 1.8 christos /* We only need to copy this reloc if the symbol is 2932 1.8 christos defined in a dynamic object. */ 2933 1.8 christos hscore = (struct score_elf_link_hash_entry *)h; 2934 1.8 christos ++hscore->possibly_dynamic_relocs; 2935 1.8 christos if ((sec->flags & SCORE_READONLY_SECTION) 2936 1.8 christos == SCORE_READONLY_SECTION) 2937 1.8 christos /* We need it to tell the dynamic linker if there 2938 1.8 christos are relocations against the text segment. */ 2939 1.10 christos hscore->readonly_reloc = true; 2940 1.8 christos } 2941 1.8 christos 2942 1.8 christos /* Even though we don't directly need a GOT entry for this symbol, 2943 1.8 christos a symbol must have a dynamic symbol table index greater that 2944 1.8 christos DT_SCORE_GOTSYM if there are dynamic relocations against it. */ 2945 1.8 christos if (h != NULL) 2946 1.8 christos { 2947 1.8 christos if (dynobj == NULL) 2948 1.8 christos elf_hash_table (info)->dynobj = dynobj = abfd; 2949 1.10 christos if (! score_elf_create_got_section (dynobj, info, true)) 2950 1.10 christos return false; 2951 1.8 christos g = score_elf_got_info (dynobj, &sgot); 2952 1.8 christos if (! score_elf_record_global_got_symbol (h, abfd, info, g)) 2953 1.10 christos return false; 2954 1.8 christos } 2955 1.8 christos } 2956 1.8 christos break; 2957 1.8 christos 2958 1.8 christos /* This relocation describes the C++ object vtable hierarchy. 2959 1.8 christos Reconstruct it for later use during GC. */ 2960 1.8 christos case R_SCORE_GNU_VTINHERIT: 2961 1.8 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 2962 1.10 christos return false; 2963 1.8 christos break; 2964 1.8 christos 2965 1.8 christos /* This relocation describes which C++ vtable entries are actually 2966 1.8 christos used. Record for later use during GC. */ 2967 1.8 christos case R_SCORE_GNU_VTENTRY: 2968 1.8 christos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) 2969 1.10 christos return false; 2970 1.8 christos break; 2971 1.8 christos default: 2972 1.8 christos break; 2973 1.8 christos } 2974 1.1 christos 2975 1.1 christos /* We must not create a stub for a symbol that has relocations 2976 1.8 christos related to taking the function's address. */ 2977 1.1 christos switch (r_type) 2978 1.8 christos { 2979 1.8 christos default: 2980 1.8 christos if (h != NULL) 2981 1.8 christos { 2982 1.8 christos struct score_elf_link_hash_entry *sh; 2983 1.8 christos 2984 1.8 christos sh = (struct score_elf_link_hash_entry *) h; 2985 1.10 christos sh->no_fn_stub = true; 2986 1.8 christos } 2987 1.8 christos break; 2988 1.8 christos case R_SCORE_CALL15: 2989 1.8 christos break; 2990 1.8 christos } 2991 1.1 christos } 2992 1.1 christos 2993 1.10 christos return true; 2994 1.1 christos } 2995 1.1 christos 2996 1.10 christos static bool 2997 1.1 christos s3_bfd_score_elf_add_symbol_hook (bfd *abfd, 2998 1.8 christos struct bfd_link_info *info ATTRIBUTE_UNUSED, 2999 1.8 christos Elf_Internal_Sym *sym, 3000 1.8 christos const char **namep ATTRIBUTE_UNUSED, 3001 1.8 christos flagword *flagsp ATTRIBUTE_UNUSED, 3002 1.8 christos asection **secp, 3003 1.8 christos bfd_vma *valp) 3004 1.1 christos { 3005 1.1 christos switch (sym->st_shndx) 3006 1.1 christos { 3007 1.1 christos case SHN_COMMON: 3008 1.1 christos if (sym->st_size > elf_gp_size (abfd)) 3009 1.8 christos break; 3010 1.1 christos /* Fall through. */ 3011 1.1 christos case SHN_SCORE_SCOMMON: 3012 1.1 christos *secp = bfd_make_section_old_way (abfd, ".scommon"); 3013 1.9 christos (*secp)->flags |= SEC_IS_COMMON | SEC_SMALL_DATA; 3014 1.1 christos *valp = sym->st_size; 3015 1.1 christos break; 3016 1.1 christos } 3017 1.1 christos 3018 1.10 christos return true; 3019 1.1 christos } 3020 1.1 christos 3021 1.1 christos static void 3022 1.1 christos s3_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym) 3023 1.1 christos { 3024 1.1 christos elf_symbol_type *elfsym; 3025 1.1 christos 3026 1.1 christos elfsym = (elf_symbol_type *) asym; 3027 1.1 christos switch (elfsym->internal_elf_sym.st_shndx) 3028 1.1 christos { 3029 1.1 christos case SHN_COMMON: 3030 1.1 christos if (asym->value > elf_gp_size (abfd)) 3031 1.8 christos break; 3032 1.1 christos /* Fall through. */ 3033 1.1 christos case SHN_SCORE_SCOMMON: 3034 1.1 christos asym->section = &score_elf_scom_section; 3035 1.1 christos asym->value = elfsym->internal_elf_sym.st_size; 3036 1.1 christos break; 3037 1.1 christos } 3038 1.1 christos } 3039 1.1 christos 3040 1.1 christos static int 3041 1.1 christos s3_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED, 3042 1.8 christos const char *name ATTRIBUTE_UNUSED, 3043 1.8 christos Elf_Internal_Sym *sym, 3044 1.8 christos asection *input_sec, 3045 1.8 christos struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) 3046 1.1 christos { 3047 1.1 christos /* If we see a common symbol, which implies a relocatable link, then 3048 1.1 christos if a symbol was small common in an input file, mark it as small 3049 1.1 christos common in the output file. */ 3050 1.1 christos if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0) 3051 1.1 christos sym->st_shndx = SHN_SCORE_SCOMMON; 3052 1.1 christos 3053 1.1 christos return 1; 3054 1.1 christos } 3055 1.1 christos 3056 1.10 christos static bool 3057 1.1 christos s3_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, 3058 1.8 christos asection *sec, 3059 1.8 christos int *retval) 3060 1.1 christos { 3061 1.9 christos if (strcmp (bfd_section_name (sec), ".scommon") == 0) 3062 1.1 christos { 3063 1.1 christos *retval = SHN_SCORE_SCOMMON; 3064 1.10 christos return true; 3065 1.1 christos } 3066 1.1 christos 3067 1.10 christos return false; 3068 1.1 christos } 3069 1.1 christos 3070 1.1 christos /* Adjust a symbol defined by a dynamic object and referenced by a 3071 1.1 christos regular object. The current definition is in some section of the 3072 1.1 christos dynamic object, but we're not including those sections. We have to 3073 1.1 christos change the definition to something the rest of the link can understand. */ 3074 1.10 christos static bool 3075 1.1 christos s3_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info, 3076 1.8 christos struct elf_link_hash_entry *h) 3077 1.1 christos { 3078 1.1 christos bfd *dynobj; 3079 1.1 christos struct score_elf_link_hash_entry *hscore; 3080 1.1 christos asection *s; 3081 1.1 christos 3082 1.1 christos dynobj = elf_hash_table (info)->dynobj; 3083 1.1 christos 3084 1.1 christos /* Make sure we know what is going on here. */ 3085 1.1 christos BFD_ASSERT (dynobj != NULL 3086 1.8 christos && (h->needs_plt 3087 1.8 christos || h->is_weakalias 3088 1.8 christos || (h->def_dynamic && h->ref_regular && !h->def_regular))); 3089 1.1 christos 3090 1.1 christos /* If this symbol is defined in a dynamic object, we need to copy 3091 1.1 christos any R_SCORE_ABS32 or R_SCORE_REL32 relocs against it into the output 3092 1.1 christos file. */ 3093 1.1 christos hscore = (struct score_elf_link_hash_entry *)h; 3094 1.6 christos if (!bfd_link_relocatable (info) 3095 1.1 christos && hscore->possibly_dynamic_relocs != 0 3096 1.1 christos && (h->root.type == bfd_link_hash_defweak || !h->def_regular)) 3097 1.1 christos { 3098 1.1 christos score_elf_allocate_dynamic_relocations (dynobj, hscore->possibly_dynamic_relocs); 3099 1.1 christos if (hscore->readonly_reloc) 3100 1.8 christos /* We tell the dynamic linker that there are relocations 3101 1.8 christos against the text segment. */ 3102 1.8 christos info->flags |= DF_TEXTREL; 3103 1.1 christos } 3104 1.1 christos 3105 1.1 christos /* For a function, create a stub, if allowed. */ 3106 1.1 christos if (!hscore->no_fn_stub && h->needs_plt) 3107 1.1 christos { 3108 1.1 christos if (!elf_hash_table (info)->dynamic_sections_created) 3109 1.10 christos return true; 3110 1.1 christos 3111 1.1 christos /* If this symbol is not defined in a regular file, then set 3112 1.8 christos the symbol to the stub location. This is required to make 3113 1.8 christos function pointers compare as equal between the normal 3114 1.8 christos executable and the shared library. */ 3115 1.1 christos if (!h->def_regular) 3116 1.8 christos { 3117 1.8 christos /* We need .stub section. */ 3118 1.8 christos s = bfd_get_linker_section (dynobj, SCORE_ELF_STUB_SECTION_NAME); 3119 1.8 christos BFD_ASSERT (s != NULL); 3120 1.8 christos 3121 1.8 christos h->root.u.def.section = s; 3122 1.8 christos h->root.u.def.value = s->size; 3123 1.8 christos 3124 1.8 christos /* XXX Write this stub address somewhere. */ 3125 1.8 christos h->plt.offset = s->size; 3126 1.8 christos 3127 1.8 christos /* Make room for this stub code. */ 3128 1.8 christos s->size += SCORE_FUNCTION_STUB_SIZE; 3129 1.8 christos 3130 1.8 christos /* The last half word of the stub will be filled with the index 3131 1.8 christos of this symbol in .dynsym section. */ 3132 1.10 christos return true; 3133 1.8 christos } 3134 1.1 christos } 3135 1.1 christos else if ((h->type == STT_FUNC) && !h->needs_plt) 3136 1.1 christos { 3137 1.1 christos /* This will set the entry for this symbol in the GOT to 0, and 3138 1.8 christos the dynamic linker will take care of this. */ 3139 1.1 christos h->root.u.def.value = 0; 3140 1.10 christos return true; 3141 1.1 christos } 3142 1.1 christos 3143 1.1 christos /* If this is a weak symbol, and there is a real definition, the 3144 1.1 christos processor independent code will have arranged for us to see the 3145 1.1 christos real definition first, and we can just use the same value. */ 3146 1.8 christos if (h->is_weakalias) 3147 1.1 christos { 3148 1.8 christos struct elf_link_hash_entry *def = weakdef (h); 3149 1.8 christos BFD_ASSERT (def->root.type == bfd_link_hash_defined); 3150 1.8 christos h->root.u.def.section = def->root.u.def.section; 3151 1.8 christos h->root.u.def.value = def->root.u.def.value; 3152 1.10 christos return true; 3153 1.1 christos } 3154 1.1 christos 3155 1.1 christos /* This is a reference to a symbol defined by a dynamic object which 3156 1.1 christos is not a function. */ 3157 1.10 christos return true; 3158 1.1 christos } 3159 1.1 christos 3160 1.1 christos /* This function is called after all the input files have been read, 3161 1.1 christos and the input sections have been assigned to output sections. */ 3162 1.10 christos static bool 3163 1.11 christos s3_bfd_score_elf_early_size_sections (bfd *output_bfd, 3164 1.11 christos struct bfd_link_info *info) 3165 1.1 christos { 3166 1.1 christos bfd *dynobj; 3167 1.1 christos asection *s; 3168 1.1 christos struct score_got_info *g; 3169 1.1 christos int i; 3170 1.1 christos bfd_size_type loadable_size = 0; 3171 1.1 christos bfd_size_type local_gotno; 3172 1.1 christos bfd *sub; 3173 1.1 christos 3174 1.1 christos dynobj = elf_hash_table (info)->dynobj; 3175 1.1 christos if (dynobj == NULL) 3176 1.1 christos /* Relocatable links don't have it. */ 3177 1.10 christos return true; 3178 1.1 christos 3179 1.1 christos g = score_elf_got_info (dynobj, &s); 3180 1.1 christos if (s == NULL) 3181 1.10 christos return true; 3182 1.1 christos 3183 1.1 christos /* Calculate the total loadable size of the output. That will give us the 3184 1.1 christos maximum number of GOT_PAGE entries required. */ 3185 1.3 christos for (sub = info->input_bfds; sub; sub = sub->link.next) 3186 1.1 christos { 3187 1.1 christos asection *subsection; 3188 1.1 christos 3189 1.1 christos for (subsection = sub->sections; 3190 1.8 christos subsection; 3191 1.8 christos subsection = subsection->next) 3192 1.8 christos { 3193 1.8 christos if ((subsection->flags & SEC_ALLOC) == 0) 3194 1.8 christos continue; 3195 1.8 christos loadable_size += ((subsection->size + 0xf) 3196 1.8 christos &~ (bfd_size_type) 0xf); 3197 1.8 christos } 3198 1.1 christos } 3199 1.1 christos 3200 1.1 christos /* There has to be a global GOT entry for every symbol with 3201 1.1 christos a dynamic symbol table index of DT_SCORE_GOTSYM or 3202 1.1 christos higher. Therefore, it make sense to put those symbols 3203 1.1 christos that need GOT entries at the end of the symbol table. We 3204 1.1 christos do that here. */ 3205 1.1 christos if (! score_elf_sort_hash_table (info, 1)) 3206 1.10 christos return false; 3207 1.1 christos 3208 1.1 christos if (g->global_gotsym != NULL) 3209 1.1 christos i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx; 3210 1.1 christos else 3211 1.1 christos /* If there are no global symbols, or none requiring 3212 1.1 christos relocations, then GLOBAL_GOTSYM will be NULL. */ 3213 1.1 christos i = 0; 3214 1.1 christos 3215 1.1 christos /* In the worst case, we'll get one stub per dynamic symbol. */ 3216 1.1 christos loadable_size += SCORE_FUNCTION_STUB_SIZE * i; 3217 1.1 christos 3218 1.1 christos /* Assume there are two loadable segments consisting of 3219 1.1 christos contiguous sections. Is 5 enough? */ 3220 1.1 christos local_gotno = (loadable_size >> 16) + 5; 3221 1.1 christos 3222 1.1 christos g->local_gotno += local_gotno; 3223 1.1 christos s->size += g->local_gotno * SCORE_ELF_GOT_SIZE (output_bfd); 3224 1.1 christos 3225 1.1 christos g->global_gotno = i; 3226 1.1 christos s->size += i * SCORE_ELF_GOT_SIZE (output_bfd); 3227 1.1 christos 3228 1.1 christos score_elf_resolve_final_got_entries (g); 3229 1.1 christos 3230 1.1 christos if (s->size > SCORE_ELF_GOT_MAX_SIZE (output_bfd)) 3231 1.1 christos { 3232 1.1 christos /* Fixme. Error message or Warning message should be issued here. */ 3233 1.1 christos } 3234 1.1 christos 3235 1.10 christos return true; 3236 1.1 christos } 3237 1.1 christos 3238 1.1 christos /* Set the sizes of the dynamic sections. */ 3239 1.10 christos static bool 3240 1.11 christos s3_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info) 3241 1.1 christos { 3242 1.1 christos bfd *dynobj; 3243 1.1 christos asection *s; 3244 1.10 christos bool reltext; 3245 1.1 christos 3246 1.1 christos dynobj = elf_hash_table (info)->dynobj; 3247 1.11 christos if (dynobj == NULL) 3248 1.11 christos return true; 3249 1.1 christos 3250 1.1 christos if (elf_hash_table (info)->dynamic_sections_created) 3251 1.1 christos { 3252 1.1 christos /* Set the contents of the .interp section to the interpreter. */ 3253 1.8 christos if (bfd_link_executable (info) && !info->nointerp) 3254 1.8 christos { 3255 1.8 christos s = bfd_get_linker_section (dynobj, ".interp"); 3256 1.8 christos BFD_ASSERT (s != NULL); 3257 1.8 christos s->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1; 3258 1.8 christos s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER; 3259 1.8 christos } 3260 1.1 christos } 3261 1.1 christos 3262 1.1 christos /* The check_relocs and adjust_dynamic_symbol entry points have 3263 1.1 christos determined the sizes of the various dynamic sections. Allocate 3264 1.1 christos memory for them. */ 3265 1.10 christos reltext = false; 3266 1.1 christos for (s = dynobj->sections; s != NULL; s = s->next) 3267 1.1 christos { 3268 1.1 christos const char *name; 3269 1.1 christos 3270 1.1 christos if ((s->flags & SEC_LINKER_CREATED) == 0) 3271 1.8 christos continue; 3272 1.1 christos 3273 1.1 christos /* It's OK to base decisions on the section name, because none 3274 1.8 christos of the dynobj section names depend upon the input files. */ 3275 1.9 christos name = bfd_section_name (s); 3276 1.1 christos 3277 1.10 christos if (startswith (name, ".rel")) 3278 1.8 christos { 3279 1.8 christos if (s->size == 0) 3280 1.8 christos { 3281 1.8 christos /* We only strip the section if the output section name 3282 1.8 christos has the same name. Otherwise, there might be several 3283 1.8 christos input sections for this output section. FIXME: This 3284 1.8 christos code is probably not needed these days anyhow, since 3285 1.8 christos the linker now does not create empty output sections. */ 3286 1.8 christos if (s->output_section != NULL 3287 1.8 christos && strcmp (name, 3288 1.9 christos bfd_section_name (s->output_section)) == 0) 3289 1.8 christos s->flags |= SEC_EXCLUDE; 3290 1.8 christos } 3291 1.8 christos else 3292 1.8 christos { 3293 1.8 christos const char *outname; 3294 1.8 christos asection *target; 3295 1.8 christos 3296 1.8 christos /* If this relocation section applies to a read only 3297 1.8 christos section, then we probably need a DT_TEXTREL entry. 3298 1.8 christos If the relocation section is .rel.dyn, we always 3299 1.8 christos assert a DT_TEXTREL entry rather than testing whether 3300 1.8 christos there exists a relocation to a read only section or 3301 1.8 christos not. */ 3302 1.9 christos outname = bfd_section_name (s->output_section); 3303 1.8 christos target = bfd_get_section_by_name (output_bfd, outname + 4); 3304 1.8 christos if ((target != NULL 3305 1.8 christos && (target->flags & SEC_READONLY) != 0 3306 1.8 christos && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0) 3307 1.10 christos reltext = true; 3308 1.8 christos 3309 1.8 christos /* We use the reloc_count field as a counter if we need 3310 1.8 christos to copy relocs into the output file. */ 3311 1.8 christos if (strcmp (name, ".rel.dyn") != 0) 3312 1.8 christos s->reloc_count = 0; 3313 1.8 christos } 3314 1.8 christos } 3315 1.10 christos else if (startswith (name, ".got")) 3316 1.8 christos { 3317 1.11 christos /* s3_bfd_score_elf_early_size_sections() has already done 3318 1.8 christos most of the work, but some symbols may have been mapped 3319 1.8 christos to versions that we must now resolve in the got_entries 3320 1.8 christos hash tables. */ 3321 1.8 christos } 3322 1.1 christos else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0) 3323 1.8 christos { 3324 1.8 christos /* IRIX rld assumes that the function stub isn't at the end 3325 1.8 christos of .text section. So put a dummy. XXX */ 3326 1.8 christos s->size += SCORE_FUNCTION_STUB_SIZE; 3327 1.8 christos } 3328 1.10 christos else if (! startswith (name, ".init")) 3329 1.8 christos { 3330 1.8 christos /* It's not one of our sections, so don't allocate space. */ 3331 1.8 christos continue; 3332 1.8 christos } 3333 1.1 christos 3334 1.1 christos /* Allocate memory for the section contents. */ 3335 1.1 christos s->contents = bfd_zalloc (dynobj, s->size); 3336 1.1 christos if (s->contents == NULL && s->size != 0) 3337 1.8 christos { 3338 1.8 christos bfd_set_error (bfd_error_no_memory); 3339 1.10 christos return false; 3340 1.8 christos } 3341 1.1 christos } 3342 1.1 christos 3343 1.1 christos if (elf_hash_table (info)->dynamic_sections_created) 3344 1.1 christos { 3345 1.1 christos /* Add some entries to the .dynamic section. We fill in the 3346 1.8 christos values later, in s3_bfd_score_elf_finish_dynamic_sections, but we 3347 1.8 christos must add the entries now so that we get the correct size for 3348 1.8 christos the .dynamic section. The DT_DEBUG entry is filled in by the 3349 1.8 christos dynamic linker and used by the debugger. */ 3350 1.1 christos 3351 1.1 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0)) 3352 1.10 christos return false; 3353 1.1 christos 3354 1.1 christos if (reltext) 3355 1.8 christos info->flags |= DF_TEXTREL; 3356 1.1 christos 3357 1.1 christos if ((info->flags & DF_TEXTREL) != 0) 3358 1.8 christos { 3359 1.8 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0)) 3360 1.10 christos return false; 3361 1.8 christos } 3362 1.1 christos 3363 1.1 christos if (! SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0)) 3364 1.10 christos return false; 3365 1.1 christos 3366 1.10 christos if (score_elf_rel_dyn_section (dynobj, false)) 3367 1.8 christos { 3368 1.8 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0)) 3369 1.10 christos return false; 3370 1.8 christos 3371 1.8 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0)) 3372 1.10 christos return false; 3373 1.8 christos 3374 1.8 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0)) 3375 1.10 christos return false; 3376 1.8 christos } 3377 1.1 christos 3378 1.1 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_BASE_ADDRESS, 0)) 3379 1.10 christos return false; 3380 1.1 christos 3381 1.1 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_LOCAL_GOTNO, 0)) 3382 1.10 christos return false; 3383 1.1 christos 3384 1.1 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_SYMTABNO, 0)) 3385 1.10 christos return false; 3386 1.1 christos 3387 1.1 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_UNREFEXTNO, 0)) 3388 1.10 christos return false; 3389 1.1 christos 3390 1.1 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_GOTSYM, 0)) 3391 1.10 christos return false; 3392 1.1 christos 3393 1.1 christos if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_HIPAGENO, 0)) 3394 1.10 christos return false; 3395 1.1 christos } 3396 1.1 christos 3397 1.10 christos return true; 3398 1.1 christos } 3399 1.1 christos 3400 1.10 christos static bool 3401 1.1 christos s3_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) 3402 1.1 christos { 3403 1.1 christos struct elf_link_hash_entry *h; 3404 1.1 christos struct bfd_link_hash_entry *bh; 3405 1.1 christos flagword flags; 3406 1.1 christos asection *s; 3407 1.1 christos 3408 1.1 christos flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 3409 1.8 christos | SEC_LINKER_CREATED | SEC_READONLY); 3410 1.1 christos 3411 1.1 christos /* ABI requests the .dynamic section to be read only. */ 3412 1.1 christos s = bfd_get_linker_section (abfd, ".dynamic"); 3413 1.1 christos if (s != NULL) 3414 1.1 christos { 3415 1.9 christos if (!bfd_set_section_flags (s, flags)) 3416 1.10 christos return false; 3417 1.1 christos } 3418 1.1 christos 3419 1.1 christos /* We need to create .got section. */ 3420 1.10 christos if (!score_elf_create_got_section (abfd, info, false)) 3421 1.10 christos return false; 3422 1.1 christos 3423 1.10 christos if (!score_elf_rel_dyn_section (elf_hash_table (info)->dynobj, true)) 3424 1.10 christos return false; 3425 1.1 christos 3426 1.1 christos /* Create .stub section. */ 3427 1.1 christos if (bfd_get_linker_section (abfd, SCORE_ELF_STUB_SECTION_NAME) == NULL) 3428 1.1 christos { 3429 1.1 christos s = bfd_make_section_anyway_with_flags (abfd, SCORE_ELF_STUB_SECTION_NAME, 3430 1.1 christos flags | SEC_CODE); 3431 1.1 christos if (s == NULL 3432 1.9 christos || !bfd_set_section_alignment (s, 2)) 3433 1.1 christos 3434 1.10 christos return false; 3435 1.1 christos } 3436 1.1 christos 3437 1.6 christos if (!bfd_link_pic (info)) 3438 1.1 christos { 3439 1.1 christos const char *name; 3440 1.1 christos 3441 1.1 christos name = "_DYNAMIC_LINK"; 3442 1.1 christos bh = NULL; 3443 1.1 christos if (!(_bfd_generic_link_add_one_symbol 3444 1.8 christos (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 3445 1.10 christos (bfd_vma) 0, NULL, false, get_elf_backend_data (abfd)->collect, &bh))) 3446 1.10 christos return false; 3447 1.1 christos 3448 1.1 christos h = (struct elf_link_hash_entry *)bh; 3449 1.1 christos h->non_elf = 0; 3450 1.1 christos h->def_regular = 1; 3451 1.1 christos h->type = STT_SECTION; 3452 1.1 christos 3453 1.1 christos if (!bfd_elf_link_record_dynamic_symbol (info, h)) 3454 1.10 christos return false; 3455 1.1 christos } 3456 1.1 christos 3457 1.10 christos return true; 3458 1.1 christos } 3459 1.1 christos 3460 1.1 christos 3461 1.1 christos /* Finish up dynamic symbol handling. We set the contents of various 3462 1.1 christos dynamic sections here. */ 3463 1.10 christos static bool 3464 1.1 christos s3_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, 3465 1.8 christos struct bfd_link_info *info, 3466 1.8 christos struct elf_link_hash_entry *h, 3467 1.8 christos Elf_Internal_Sym *sym) 3468 1.1 christos { 3469 1.1 christos bfd *dynobj; 3470 1.1 christos asection *sgot; 3471 1.1 christos struct score_got_info *g; 3472 1.1 christos const char *name; 3473 1.1 christos 3474 1.1 christos dynobj = elf_hash_table (info)->dynobj; 3475 1.1 christos 3476 1.1 christos if (h->plt.offset != MINUS_ONE) 3477 1.1 christos { 3478 1.1 christos asection *s; 3479 1.1 christos bfd_byte stub[SCORE_FUNCTION_STUB_SIZE]; 3480 1.1 christos 3481 1.1 christos /* This symbol has a stub. Set it up. */ 3482 1.1 christos BFD_ASSERT (h->dynindx != -1); 3483 1.1 christos 3484 1.1 christos s = bfd_get_linker_section (dynobj, SCORE_ELF_STUB_SECTION_NAME); 3485 1.1 christos BFD_ASSERT (s != NULL); 3486 1.1 christos 3487 1.1 christos /* FIXME: Can h->dynindex be more than 64K? */ 3488 1.1 christos if (h->dynindx & 0xffff0000) 3489 1.11 christos { 3490 1.11 christos _bfd_error_handler 3491 1.11 christos (_("%pB: cannot handle more than %d dynamic symbols"), 3492 1.11 christos output_bfd, 0xffff); 3493 1.11 christos bfd_set_error (bfd_error_bad_value); 3494 1.11 christos return false; 3495 1.11 christos } 3496 1.1 christos 3497 1.1 christos /* Fill the stub. */ 3498 1.1 christos score_bfd_put_32 (output_bfd, STUB_LW, stub); 3499 1.1 christos score_bfd_put_32 (output_bfd, STUB_MOVE, stub + 4); 3500 1.1 christos score_bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8); 3501 1.1 christos score_bfd_put_32 (output_bfd, STUB_BRL, stub + 12); 3502 1.1 christos 3503 1.1 christos BFD_ASSERT (h->plt.offset <= s->size); 3504 1.1 christos memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE); 3505 1.1 christos 3506 1.1 christos /* Mark the symbol as undefined. plt.offset != -1 occurs 3507 1.8 christos only for the referenced symbol. */ 3508 1.1 christos sym->st_shndx = SHN_UNDEF; 3509 1.1 christos 3510 1.1 christos /* The run-time linker uses the st_value field of the symbol 3511 1.8 christos to reset the global offset table entry for this external 3512 1.8 christos to its stub address when unlinking a shared object. */ 3513 1.1 christos sym->st_value = (s->output_section->vma + s->output_offset + h->plt.offset); 3514 1.1 christos } 3515 1.1 christos 3516 1.1 christos BFD_ASSERT (h->dynindx != -1 || h->forced_local); 3517 1.1 christos 3518 1.10 christos sgot = score_elf_got_section (dynobj, false); 3519 1.1 christos BFD_ASSERT (sgot != NULL); 3520 1.1 christos BFD_ASSERT (score_elf_section_data (sgot) != NULL); 3521 1.1 christos g = score_elf_section_data (sgot)->u.got_info; 3522 1.1 christos BFD_ASSERT (g != NULL); 3523 1.1 christos 3524 1.1 christos /* Run through the global symbol table, creating GOT entries for all 3525 1.1 christos the symbols that need them. */ 3526 1.1 christos if (g->global_gotsym != NULL && h->dynindx >= g->global_gotsym->dynindx) 3527 1.1 christos { 3528 1.1 christos bfd_vma offset; 3529 1.1 christos bfd_vma value; 3530 1.1 christos 3531 1.1 christos value = sym->st_value; 3532 1.1 christos offset = score_elf_global_got_index (dynobj, h); 3533 1.1 christos score_bfd_put_32 (output_bfd, value, sgot->contents + offset); 3534 1.1 christos } 3535 1.1 christos 3536 1.1 christos /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ 3537 1.1 christos name = h->root.root.string; 3538 1.1 christos if (h == elf_hash_table (info)->hdynamic 3539 1.1 christos || h == elf_hash_table (info)->hgot) 3540 1.1 christos sym->st_shndx = SHN_ABS; 3541 1.1 christos else if (strcmp (name, "_DYNAMIC_LINK") == 0) 3542 1.1 christos { 3543 1.1 christos sym->st_shndx = SHN_ABS; 3544 1.1 christos sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION); 3545 1.1 christos sym->st_value = 1; 3546 1.1 christos } 3547 1.1 christos else if (strcmp (name, GP_DISP_LABEL) == 0) 3548 1.1 christos { 3549 1.1 christos sym->st_shndx = SHN_ABS; 3550 1.1 christos sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION); 3551 1.1 christos sym->st_value = elf_gp (output_bfd); 3552 1.1 christos } 3553 1.1 christos 3554 1.10 christos return true; 3555 1.1 christos } 3556 1.1 christos 3557 1.1 christos /* Finish up the dynamic sections. */ 3558 1.10 christos static bool 3559 1.1 christos s3_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, 3560 1.8 christos struct bfd_link_info *info) 3561 1.1 christos { 3562 1.1 christos bfd *dynobj; 3563 1.1 christos asection *sdyn; 3564 1.1 christos asection *sgot; 3565 1.1 christos asection *s; 3566 1.1 christos struct score_got_info *g; 3567 1.1 christos 3568 1.1 christos dynobj = elf_hash_table (info)->dynobj; 3569 1.1 christos 3570 1.1 christos sdyn = bfd_get_linker_section (dynobj, ".dynamic"); 3571 1.1 christos 3572 1.10 christos sgot = score_elf_got_section (dynobj, false); 3573 1.1 christos if (sgot == NULL) 3574 1.1 christos g = NULL; 3575 1.1 christos else 3576 1.1 christos { 3577 1.1 christos BFD_ASSERT (score_elf_section_data (sgot) != NULL); 3578 1.1 christos g = score_elf_section_data (sgot)->u.got_info; 3579 1.1 christos BFD_ASSERT (g != NULL); 3580 1.1 christos } 3581 1.1 christos 3582 1.1 christos if (elf_hash_table (info)->dynamic_sections_created) 3583 1.1 christos { 3584 1.1 christos bfd_byte *b; 3585 1.1 christos 3586 1.1 christos BFD_ASSERT (sdyn != NULL); 3587 1.1 christos BFD_ASSERT (g != NULL); 3588 1.1 christos 3589 1.1 christos for (b = sdyn->contents; 3590 1.8 christos b < sdyn->contents + sdyn->size; 3591 1.8 christos b += SCORE_ELF_DYN_SIZE (dynobj)) 3592 1.8 christos { 3593 1.8 christos Elf_Internal_Dyn dyn; 3594 1.8 christos const char *name; 3595 1.8 christos size_t elemsize; 3596 1.10 christos bool swap_out_p; 3597 1.8 christos 3598 1.8 christos /* Read in the current dynamic entry. */ 3599 1.8 christos (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn); 3600 1.8 christos 3601 1.8 christos /* Assume that we're going to modify it and write it out. */ 3602 1.10 christos swap_out_p = true; 3603 1.8 christos 3604 1.8 christos switch (dyn.d_tag) 3605 1.8 christos { 3606 1.8 christos case DT_RELENT: 3607 1.8 christos dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj); 3608 1.8 christos break; 3609 1.8 christos 3610 1.8 christos case DT_STRSZ: 3611 1.8 christos /* Rewrite DT_STRSZ. */ 3612 1.8 christos dyn.d_un.d_val 3613 1.8 christos = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr); 3614 1.8 christos break; 3615 1.8 christos 3616 1.8 christos case DT_PLTGOT: 3617 1.8 christos s = elf_hash_table (info)->sgot; 3618 1.8 christos dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; 3619 1.8 christos break; 3620 1.8 christos 3621 1.8 christos case DT_SCORE_BASE_ADDRESS: 3622 1.8 christos s = output_bfd->sections; 3623 1.8 christos BFD_ASSERT (s != NULL); 3624 1.8 christos dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff; 3625 1.8 christos break; 3626 1.8 christos 3627 1.8 christos case DT_SCORE_LOCAL_GOTNO: 3628 1.8 christos dyn.d_un.d_val = g->local_gotno; 3629 1.8 christos break; 3630 1.8 christos 3631 1.8 christos case DT_SCORE_UNREFEXTNO: 3632 1.8 christos /* The index into the dynamic symbol table which is the 3633 1.8 christos entry of the first external symbol that is not 3634 1.8 christos referenced within the same object. */ 3635 1.8 christos dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1; 3636 1.8 christos break; 3637 1.8 christos 3638 1.8 christos case DT_SCORE_GOTSYM: 3639 1.8 christos if (g->global_gotsym) 3640 1.8 christos { 3641 1.8 christos dyn.d_un.d_val = g->global_gotsym->dynindx; 3642 1.8 christos break; 3643 1.8 christos } 3644 1.8 christos /* In case if we don't have global got symbols we default 3645 1.8 christos to setting DT_SCORE_GOTSYM to the same value as 3646 1.8 christos DT_SCORE_SYMTABNO. */ 3647 1.7 christos /* Fall through. */ 3648 1.1 christos 3649 1.8 christos case DT_SCORE_SYMTABNO: 3650 1.8 christos name = ".dynsym"; 3651 1.8 christos elemsize = SCORE_ELF_SYM_SIZE (output_bfd); 3652 1.8 christos s = bfd_get_linker_section (dynobj, name); 3653 1.8 christos dyn.d_un.d_val = s->size / elemsize; 3654 1.8 christos break; 3655 1.8 christos 3656 1.8 christos case DT_SCORE_HIPAGENO: 3657 1.8 christos dyn.d_un.d_val = g->local_gotno - SCORE_RESERVED_GOTNO; 3658 1.8 christos break; 3659 1.8 christos 3660 1.8 christos default: 3661 1.10 christos swap_out_p = false; 3662 1.8 christos break; 3663 1.8 christos } 3664 1.8 christos 3665 1.8 christos if (swap_out_p) 3666 1.8 christos (*get_elf_backend_data (dynobj)->s->swap_dyn_out) (dynobj, &dyn, b); 3667 1.8 christos } 3668 1.1 christos } 3669 1.1 christos 3670 1.1 christos /* The first entry of the global offset table will be filled at 3671 1.1 christos runtime. The second entry will be used by some runtime loaders. 3672 1.1 christos This isn't the case of IRIX rld. */ 3673 1.1 christos if (sgot != NULL && sgot->size > 0) 3674 1.1 christos { 3675 1.1 christos score_bfd_put_32 (output_bfd, 0, sgot->contents); 3676 1.1 christos score_bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd)); 3677 1.1 christos } 3678 1.1 christos 3679 1.1 christos if (sgot != NULL) 3680 1.1 christos elf_section_data (sgot->output_section)->this_hdr.sh_entsize 3681 1.1 christos = SCORE_ELF_GOT_SIZE (output_bfd); 3682 1.1 christos 3683 1.1 christos 3684 1.1 christos /* We need to sort the entries of the dynamic relocation section. */ 3685 1.10 christos s = score_elf_rel_dyn_section (dynobj, false); 3686 1.1 christos 3687 1.1 christos if (s != NULL && s->size > (bfd_vma)2 * SCORE_ELF_REL_SIZE (output_bfd)) 3688 1.1 christos { 3689 1.1 christos reldyn_sorting_bfd = output_bfd; 3690 1.1 christos qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1, 3691 1.8 christos sizeof (Elf32_External_Rel), score_elf_sort_dynamic_relocs); 3692 1.1 christos } 3693 1.1 christos 3694 1.10 christos return true; 3695 1.1 christos } 3696 1.1 christos 3697 1.1 christos /* This function set up the ELF section header for a BFD section in preparation for writing 3698 1.1 christos it out. This is where the flags and type fields are set for unusual sections. */ 3699 1.10 christos static bool 3700 1.1 christos s3_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, 3701 1.8 christos Elf_Internal_Shdr *hdr, 3702 1.8 christos asection *sec) 3703 1.1 christos { 3704 1.1 christos const char *name; 3705 1.1 christos 3706 1.9 christos name = bfd_section_name (sec); 3707 1.1 christos 3708 1.1 christos if (strcmp (name, ".got") == 0 3709 1.1 christos || strcmp (name, ".srdata") == 0 3710 1.1 christos || strcmp (name, ".sdata") == 0 3711 1.1 christos || strcmp (name, ".sbss") == 0) 3712 1.1 christos hdr->sh_flags |= SHF_SCORE_GPREL; 3713 1.1 christos 3714 1.10 christos return true; 3715 1.1 christos } 3716 1.1 christos 3717 1.1 christos /* This function do additional processing on the ELF section header before writing 3718 1.1 christos it out. This is used to set the flags and type fields for some sections. */ 3719 1.1 christos 3720 1.1 christos /* assign_file_positions_except_relocs() check section flag and if it is allocatable, 3721 1.1 christos warning message will be issued. backend_fake_section is called before 3722 1.1 christos assign_file_positions_except_relocs(); backend_section_processing after it. so, we 3723 1.1 christos modify section flag there, but not backend_fake_section. */ 3724 1.10 christos static bool 3725 1.1 christos s3_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr) 3726 1.1 christos { 3727 1.1 christos if (hdr->bfd_section != NULL) 3728 1.1 christos { 3729 1.9 christos const char *name = bfd_section_name (hdr->bfd_section); 3730 1.1 christos 3731 1.1 christos if (strcmp (name, ".sdata") == 0) 3732 1.8 christos { 3733 1.8 christos hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; 3734 1.8 christos hdr->sh_type = SHT_PROGBITS; 3735 1.8 christos } 3736 1.1 christos else if (strcmp (name, ".sbss") == 0) 3737 1.8 christos { 3738 1.8 christos hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; 3739 1.8 christos hdr->sh_type = SHT_NOBITS; 3740 1.8 christos } 3741 1.1 christos else if (strcmp (name, ".srdata") == 0) 3742 1.8 christos { 3743 1.8 christos hdr->sh_flags |= SHF_ALLOC | SHF_SCORE_GPREL; 3744 1.8 christos hdr->sh_type = SHT_PROGBITS; 3745 1.8 christos } 3746 1.1 christos } 3747 1.1 christos 3748 1.10 christos return true; 3749 1.1 christos } 3750 1.1 christos 3751 1.10 christos static bool 3752 1.1 christos s3_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents) 3753 1.1 christos { 3754 1.1 christos bfd_byte *to, *from, *end; 3755 1.1 christos int i; 3756 1.1 christos 3757 1.1 christos if (strcmp (sec->name, ".pdr") != 0) 3758 1.10 christos return false; 3759 1.1 christos 3760 1.1 christos if (score_elf_section_data (sec)->u.tdata == NULL) 3761 1.10 christos return false; 3762 1.1 christos 3763 1.1 christos to = contents; 3764 1.1 christos end = contents + sec->size; 3765 1.1 christos for (from = contents, i = 0; from < end; from += PDR_SIZE, i++) 3766 1.1 christos { 3767 1.1 christos if ((score_elf_section_data (sec)->u.tdata)[i] == 1) 3768 1.8 christos continue; 3769 1.1 christos 3770 1.1 christos if (to != from) 3771 1.8 christos memcpy (to, from, PDR_SIZE); 3772 1.1 christos 3773 1.1 christos to += PDR_SIZE; 3774 1.1 christos } 3775 1.1 christos bfd_set_section_contents (output_bfd, sec->output_section, contents, 3776 1.8 christos (file_ptr) sec->output_offset, sec->size); 3777 1.1 christos 3778 1.10 christos return true; 3779 1.1 christos } 3780 1.1 christos 3781 1.1 christos /* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old 3782 1.1 christos indirect symbol. Process additional relocation information. */ 3783 1.1 christos static void 3784 1.1 christos s3_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info, 3785 1.8 christos struct elf_link_hash_entry *dir, 3786 1.8 christos struct elf_link_hash_entry *ind) 3787 1.1 christos { 3788 1.1 christos struct score_elf_link_hash_entry *dirscore, *indscore; 3789 1.1 christos 3790 1.1 christos _bfd_elf_link_hash_copy_indirect (info, dir, ind); 3791 1.1 christos 3792 1.1 christos if (ind->root.type != bfd_link_hash_indirect) 3793 1.1 christos return; 3794 1.1 christos 3795 1.1 christos dirscore = (struct score_elf_link_hash_entry *) dir; 3796 1.1 christos indscore = (struct score_elf_link_hash_entry *) ind; 3797 1.1 christos dirscore->possibly_dynamic_relocs += indscore->possibly_dynamic_relocs; 3798 1.1 christos 3799 1.1 christos if (indscore->readonly_reloc) 3800 1.10 christos dirscore->readonly_reloc = true; 3801 1.1 christos 3802 1.1 christos if (indscore->no_fn_stub) 3803 1.10 christos dirscore->no_fn_stub = true; 3804 1.1 christos } 3805 1.1 christos 3806 1.1 christos /* Remove information about discarded functions from other sections which mention them. */ 3807 1.10 christos static bool 3808 1.1 christos s3_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie, 3809 1.8 christos struct bfd_link_info *info) 3810 1.1 christos { 3811 1.1 christos asection *o; 3812 1.10 christos bool ret = false; 3813 1.1 christos unsigned char *tdata; 3814 1.1 christos size_t i, skip; 3815 1.1 christos 3816 1.1 christos o = bfd_get_section_by_name (abfd, ".pdr"); 3817 1.1 christos if ((!o) || (o->size == 0) || (o->size % PDR_SIZE != 0) 3818 1.1 christos || (o->output_section != NULL && bfd_is_abs_section (o->output_section))) 3819 1.10 christos return false; 3820 1.1 christos 3821 1.1 christos tdata = bfd_zmalloc (o->size / PDR_SIZE); 3822 1.1 christos if (!tdata) 3823 1.10 christos return false; 3824 1.1 christos 3825 1.1 christos cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, info->keep_memory); 3826 1.1 christos if (!cookie->rels) 3827 1.1 christos { 3828 1.1 christos free (tdata); 3829 1.10 christos return false; 3830 1.1 christos } 3831 1.1 christos 3832 1.1 christos cookie->rel = cookie->rels; 3833 1.1 christos cookie->relend = cookie->rels + o->reloc_count; 3834 1.1 christos 3835 1.1 christos for (i = 0, skip = 0; i < o->size; i++) 3836 1.1 christos { 3837 1.1 christos if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie)) 3838 1.8 christos { 3839 1.8 christos tdata[i] = 1; 3840 1.8 christos skip++; 3841 1.8 christos } 3842 1.1 christos } 3843 1.1 christos 3844 1.1 christos if (skip != 0) 3845 1.1 christos { 3846 1.1 christos score_elf_section_data (o)->u.tdata = tdata; 3847 1.1 christos o->size -= skip * PDR_SIZE; 3848 1.10 christos ret = true; 3849 1.1 christos } 3850 1.1 christos else 3851 1.1 christos free (tdata); 3852 1.1 christos 3853 1.1 christos if (!info->keep_memory) 3854 1.1 christos free (cookie->rels); 3855 1.1 christos 3856 1.1 christos return ret; 3857 1.1 christos } 3858 1.1 christos 3859 1.1 christos /* Signal that discard_info() has removed the discarded relocations for this section. */ 3860 1.10 christos static bool 3861 1.1 christos s3_bfd_score_elf_ignore_discarded_relocs (asection *sec) 3862 1.1 christos { 3863 1.1 christos if (strcmp (sec->name, ".pdr") == 0) 3864 1.10 christos return true; 3865 1.10 christos return false; 3866 1.1 christos } 3867 1.1 christos 3868 1.1 christos /* Return the section that should be marked against GC for a given 3869 1.1 christos relocation. */ 3870 1.1 christos static asection * 3871 1.1 christos s3_bfd_score_elf_gc_mark_hook (asection *sec, 3872 1.8 christos struct bfd_link_info *info, 3873 1.8 christos Elf_Internal_Rela *rel, 3874 1.8 christos struct elf_link_hash_entry *h, 3875 1.8 christos Elf_Internal_Sym *sym) 3876 1.1 christos { 3877 1.1 christos if (h != NULL) 3878 1.1 christos switch (ELF32_R_TYPE (rel->r_info)) 3879 1.1 christos { 3880 1.1 christos case R_SCORE_GNU_VTINHERIT: 3881 1.1 christos case R_SCORE_GNU_VTENTRY: 3882 1.8 christos return NULL; 3883 1.1 christos } 3884 1.1 christos 3885 1.1 christos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 3886 1.1 christos } 3887 1.1 christos 3888 1.1 christos /* Support for core dump NOTE sections. */ 3889 1.1 christos 3890 1.10 christos static bool 3891 1.1 christos s3_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) 3892 1.1 christos { 3893 1.1 christos int offset; 3894 1.1 christos unsigned int raw_size; 3895 1.1 christos 3896 1.1 christos switch (note->descsz) 3897 1.1 christos { 3898 1.1 christos default: 3899 1.10 christos return false; 3900 1.1 christos 3901 1.8 christos case 148: /* Linux/Score 32-bit. */ 3902 1.1 christos /* pr_cursig */ 3903 1.1 christos elf_tdata (abfd)->core->signal 3904 1.1 christos = score_bfd_get_16 (abfd, note->descdata + 12); 3905 1.1 christos 3906 1.1 christos /* pr_pid */ 3907 1.1 christos elf_tdata (abfd)->core->lwpid 3908 1.1 christos = score_bfd_get_32 (abfd, note->descdata + 24); 3909 1.1 christos 3910 1.1 christos /* pr_reg */ 3911 1.1 christos offset = 72; 3912 1.1 christos raw_size = 72; 3913 1.1 christos 3914 1.1 christos break; 3915 1.1 christos } 3916 1.1 christos 3917 1.1 christos /* Make a ".reg/999" section. */ 3918 1.1 christos return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size, 3919 1.1 christos note->descpos + offset); 3920 1.1 christos } 3921 1.1 christos 3922 1.10 christos static bool 3923 1.1 christos s3_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) 3924 1.1 christos { 3925 1.1 christos switch (note->descsz) 3926 1.1 christos { 3927 1.1 christos default: 3928 1.10 christos return false; 3929 1.1 christos 3930 1.8 christos case 124: /* Linux/Score elf_prpsinfo. */ 3931 1.1 christos elf_tdata (abfd)->core->program 3932 1.1 christos = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); 3933 1.1 christos elf_tdata (abfd)->core->command 3934 1.1 christos = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); 3935 1.1 christos } 3936 1.1 christos 3937 1.1 christos /* Note that for some reason, a spurious space is tacked 3938 1.1 christos onto the end of the args in some (at least one anyway) 3939 1.1 christos implementations, so strip it off if it exists. */ 3940 1.1 christos 3941 1.1 christos { 3942 1.1 christos char *command = elf_tdata (abfd)->core->command; 3943 1.1 christos int n = strlen (command); 3944 1.1 christos 3945 1.1 christos if (0 < n && command[n - 1] == ' ') 3946 1.1 christos command[n - 1] = '\0'; 3947 1.1 christos } 3948 1.1 christos 3949 1.10 christos return true; 3950 1.1 christos } 3951 1.1 christos 3952 1.1 christos 3953 1.1 christos /* Score BFD functions. */ 3954 1.1 christos static reloc_howto_type * 3955 1.1 christos s3_elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) 3956 1.1 christos { 3957 1.1 christos unsigned int i; 3958 1.1 christos 3959 1.1 christos for (i = 0; i < ARRAY_SIZE (elf32_score_reloc_map); i++) 3960 1.1 christos if (elf32_score_reloc_map[i].bfd_reloc_val == code) 3961 1.1 christos return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val]; 3962 1.1 christos 3963 1.1 christos return NULL; 3964 1.1 christos } 3965 1.1 christos 3966 1.1 christos static reloc_howto_type * 3967 1.1 christos elf32_score_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 3968 1.8 christos const char *r_name) 3969 1.1 christos { 3970 1.1 christos unsigned int i; 3971 1.1 christos 3972 1.1 christos for (i = 0; 3973 1.1 christos i < (sizeof (elf32_score_howto_table) 3974 1.8 christos / sizeof (elf32_score_howto_table[0])); 3975 1.1 christos i++) 3976 1.1 christos if (elf32_score_howto_table[i].name != NULL 3977 1.8 christos && strcasecmp (elf32_score_howto_table[i].name, r_name) == 0) 3978 1.1 christos return &elf32_score_howto_table[i]; 3979 1.1 christos 3980 1.1 christos return NULL; 3981 1.1 christos } 3982 1.1 christos 3983 1.10 christos static bool 3984 1.1 christos s3_elf32_score_print_private_bfd_data (bfd *abfd, void * ptr) 3985 1.1 christos { 3986 1.1 christos FILE *file = (FILE *) ptr; 3987 1.1 christos 3988 1.1 christos BFD_ASSERT (abfd != NULL && ptr != NULL); 3989 1.1 christos 3990 1.1 christos /* Print normal ELF private data. */ 3991 1.1 christos _bfd_elf_print_private_bfd_data (abfd, ptr); 3992 1.1 christos 3993 1.1 christos /* xgettext:c-format */ 3994 1.1 christos fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags); 3995 1.1 christos if (elf_elfheader (abfd)->e_flags & EF_SCORE_PIC) 3996 1.1 christos { 3997 1.1 christos fprintf (file, _(" [pic]")); 3998 1.1 christos } 3999 1.1 christos if (elf_elfheader (abfd)->e_flags & EF_SCORE_FIXDEP) 4000 1.1 christos { 4001 1.1 christos fprintf (file, _(" [fix dep]")); 4002 1.1 christos } 4003 1.1 christos fputc ('\n', file); 4004 1.1 christos 4005 1.10 christos return true; 4006 1.1 christos } 4007 1.1 christos 4008 1.10 christos static bool 4009 1.7 christos s3_elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) 4010 1.1 christos { 4011 1.7 christos bfd *obfd = info->output_bfd; 4012 1.1 christos flagword in_flags; 4013 1.1 christos flagword out_flags; 4014 1.1 christos 4015 1.7 christos if (!_bfd_generic_verify_endian_match (ibfd, info)) 4016 1.10 christos return false; 4017 1.1 christos 4018 1.9 christos /* FIXME: What should be checked when linking shared libraries? */ 4019 1.9 christos if ((ibfd->flags & DYNAMIC) != 0) 4020 1.10 christos return true; 4021 1.9 christos 4022 1.1 christos in_flags = elf_elfheader (ibfd)->e_flags; 4023 1.1 christos out_flags = elf_elfheader (obfd)->e_flags; 4024 1.1 christos 4025 1.1 christos if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 4026 1.1 christos || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 4027 1.10 christos return true; 4028 1.1 christos 4029 1.1 christos in_flags = elf_elfheader (ibfd)->e_flags; 4030 1.1 christos out_flags = elf_elfheader (obfd)->e_flags; 4031 1.1 christos 4032 1.1 christos if (! elf_flags_init (obfd)) 4033 1.1 christos { 4034 1.10 christos elf_flags_init (obfd) = true; 4035 1.1 christos elf_elfheader (obfd)->e_flags = in_flags; 4036 1.1 christos 4037 1.1 christos if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) 4038 1.8 christos && bfd_get_arch_info (obfd)->the_default) 4039 1.8 christos { 4040 1.8 christos return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); 4041 1.8 christos } 4042 1.1 christos 4043 1.10 christos return true; 4044 1.1 christos } 4045 1.1 christos 4046 1.1 christos if (((in_flags & EF_SCORE_PIC) != 0) != ((out_flags & EF_SCORE_PIC) != 0)) 4047 1.7 christos _bfd_error_handler 4048 1.8 christos (_("%pB: warning: linking PIC files with non-PIC files"), ibfd); 4049 1.1 christos 4050 1.1 christos /* FIXME: Maybe dependency fix compatibility should be checked here. */ 4051 1.1 christos 4052 1.10 christos return true; 4053 1.1 christos } 4054 1.1 christos 4055 1.10 christos static bool 4056 1.1 christos s3_elf32_score_new_section_hook (bfd *abfd, asection *sec) 4057 1.1 christos { 4058 1.1 christos struct _score_elf_section_data *sdata; 4059 1.1 christos 4060 1.12 christos sdata = bfd_zalloc (abfd, sizeof (*sdata)); 4061 1.1 christos if (sdata == NULL) 4062 1.10 christos return false; 4063 1.1 christos sec->used_by_bfd = sdata; 4064 1.1 christos 4065 1.1 christos return _bfd_elf_new_section_hook (abfd, sec); 4066 1.1 christos } 4067 1.1 christos 4068 1.1 christos /*****************************************************************************/ 4069 1.1 christos 4070 1.1 christos /* s3_s7: backend hooks. */ 4071 1.10 christos static bool 4072 1.1 christos _bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, 4073 1.8 christos arelent *bfd_reloc, 4074 1.8 christos Elf_Internal_Rela *elf_reloc) 4075 1.1 christos { 4076 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4077 1.1 christos return s3_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc); 4078 1.1 christos else 4079 1.1 christos return s7_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc); 4080 1.1 christos } 4081 1.1 christos 4082 1.10 christos static int 4083 1.1 christos _bfd_score_elf_relocate_section (bfd *output_bfd, 4084 1.8 christos struct bfd_link_info *info, 4085 1.8 christos bfd *input_bfd, 4086 1.8 christos asection *input_section, 4087 1.8 christos bfd_byte *contents, 4088 1.8 christos Elf_Internal_Rela *relocs, 4089 1.8 christos Elf_Internal_Sym *local_syms, 4090 1.8 christos asection **local_sections) 4091 1.1 christos { 4092 1.1 christos if (bfd_get_mach (output_bfd) == bfd_mach_score3) 4093 1.1 christos return s3_bfd_score_elf_relocate_section (output_bfd, 4094 1.8 christos info, input_bfd, input_section, contents, relocs, 4095 1.8 christos local_syms, local_sections); 4096 1.1 christos else 4097 1.1 christos return s7_bfd_score_elf_relocate_section (output_bfd, 4098 1.8 christos info, input_bfd, input_section, contents, relocs, 4099 1.8 christos local_syms, local_sections); 4100 1.1 christos } 4101 1.1 christos 4102 1.10 christos static bool 4103 1.1 christos _bfd_score_elf_check_relocs (bfd *abfd, 4104 1.8 christos struct bfd_link_info *info, 4105 1.8 christos asection *sec, 4106 1.8 christos const Elf_Internal_Rela *relocs) 4107 1.1 christos { 4108 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4109 1.1 christos return s3_bfd_score_elf_check_relocs (abfd, info, sec, relocs); 4110 1.1 christos else 4111 1.1 christos return s7_bfd_score_elf_check_relocs (abfd, info, sec, relocs); 4112 1.1 christos } 4113 1.1 christos 4114 1.10 christos static bool 4115 1.1 christos _bfd_score_elf_add_symbol_hook (bfd *abfd, 4116 1.8 christos struct bfd_link_info *info ATTRIBUTE_UNUSED, 4117 1.8 christos Elf_Internal_Sym *sym, 4118 1.8 christos const char **namep ATTRIBUTE_UNUSED, 4119 1.8 christos flagword *flagsp ATTRIBUTE_UNUSED, 4120 1.8 christos asection **secp, 4121 1.8 christos bfd_vma *valp) 4122 1.1 christos { 4123 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4124 1.1 christos return s3_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, 4125 1.8 christos secp, valp); 4126 1.1 christos else 4127 1.1 christos return s7_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, 4128 1.8 christos secp, valp); 4129 1.1 christos } 4130 1.1 christos 4131 1.1 christos static void 4132 1.1 christos _bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym) 4133 1.1 christos { 4134 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4135 1.1 christos return s3_bfd_score_elf_symbol_processing (abfd, asym); 4136 1.1 christos else 4137 1.1 christos return s7_bfd_score_elf_symbol_processing (abfd, asym); 4138 1.1 christos } 4139 1.1 christos 4140 1.1 christos static int 4141 1.1 christos _bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED, 4142 1.1 christos const char *name ATTRIBUTE_UNUSED, 4143 1.1 christos Elf_Internal_Sym *sym, 4144 1.1 christos asection *input_sec, 4145 1.1 christos struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) 4146 1.1 christos { 4147 1.1 christos /* If link a empty .o, then this filed is NULL. */ 4148 1.1 christos if (info->input_bfds == NULL) 4149 1.1 christos { 4150 1.1 christos /* If we see a common symbol, which implies a relocatable link, then 4151 1.8 christos if a symbol was small common in an input file, mark it as small 4152 1.8 christos common in the output file. */ 4153 1.1 christos if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0) 4154 1.8 christos sym->st_shndx = SHN_SCORE_SCOMMON; 4155 1.1 christos return 1; 4156 1.1 christos } 4157 1.1 christos 4158 1.1 christos if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) 4159 1.1 christos return s3_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h); 4160 1.1 christos else 4161 1.1 christos return s7_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h); 4162 1.1 christos } 4163 1.1 christos 4164 1.10 christos static bool 4165 1.1 christos _bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, 4166 1.8 christos asection *sec, 4167 1.8 christos int *retval) 4168 1.1 christos { 4169 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4170 1.1 christos return s3_bfd_score_elf_section_from_bfd_section (abfd, sec, retval); 4171 1.1 christos else 4172 1.1 christos return s7_bfd_score_elf_section_from_bfd_section (abfd, sec, retval); 4173 1.1 christos } 4174 1.1 christos 4175 1.10 christos static bool 4176 1.1 christos _bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info, 4177 1.8 christos struct elf_link_hash_entry *h) 4178 1.1 christos { 4179 1.1 christos if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) 4180 1.1 christos return s3_bfd_score_elf_adjust_dynamic_symbol (info, h); 4181 1.1 christos else 4182 1.1 christos return s7_bfd_score_elf_adjust_dynamic_symbol (info, h); 4183 1.1 christos } 4184 1.1 christos 4185 1.10 christos static bool 4186 1.11 christos _bfd_score_elf_early_size_sections (bfd *output_bfd, 4187 1.11 christos struct bfd_link_info *info) 4188 1.1 christos { 4189 1.1 christos if (bfd_get_mach (output_bfd) == bfd_mach_score3) 4190 1.11 christos return s3_bfd_score_elf_early_size_sections (output_bfd, info); 4191 1.1 christos else 4192 1.11 christos return s7_bfd_score_elf_early_size_sections (output_bfd, info); 4193 1.1 christos } 4194 1.1 christos 4195 1.10 christos static bool 4196 1.11 christos _bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info) 4197 1.1 christos { 4198 1.1 christos if (bfd_get_mach (output_bfd) == bfd_mach_score3) 4199 1.11 christos return s3_bfd_score_elf_late_size_sections (output_bfd, info); 4200 1.1 christos else 4201 1.11 christos return s7_bfd_score_elf_late_size_sections (output_bfd, info); 4202 1.1 christos } 4203 1.1 christos 4204 1.10 christos static bool 4205 1.1 christos _bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) 4206 1.1 christos { 4207 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4208 1.1 christos return s3_bfd_score_elf_create_dynamic_sections (abfd, info); 4209 1.1 christos else 4210 1.1 christos return s7_bfd_score_elf_create_dynamic_sections (abfd, info); 4211 1.1 christos } 4212 1.1 christos 4213 1.10 christos static bool 4214 1.1 christos _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, 4215 1.8 christos struct bfd_link_info *info, 4216 1.8 christos struct elf_link_hash_entry *h, 4217 1.8 christos Elf_Internal_Sym *sym) 4218 1.1 christos { 4219 1.1 christos if (bfd_get_mach (output_bfd) == bfd_mach_score3) 4220 1.1 christos return s3_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym); 4221 1.1 christos else 4222 1.1 christos return s7_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym); 4223 1.1 christos } 4224 1.1 christos 4225 1.10 christos static bool 4226 1.1 christos _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, 4227 1.8 christos struct bfd_link_info *info) 4228 1.1 christos { 4229 1.1 christos if (bfd_get_mach (output_bfd) == bfd_mach_score3) 4230 1.1 christos return s3_bfd_score_elf_finish_dynamic_sections (output_bfd, info); 4231 1.1 christos else 4232 1.1 christos return s7_bfd_score_elf_finish_dynamic_sections (output_bfd, info); 4233 1.1 christos } 4234 1.1 christos 4235 1.10 christos static bool 4236 1.1 christos _bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, 4237 1.8 christos Elf_Internal_Shdr *hdr, 4238 1.8 christos asection *sec) 4239 1.1 christos { 4240 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4241 1.1 christos return s3_bfd_score_elf_fake_sections (abfd, hdr, sec); 4242 1.1 christos else 4243 1.1 christos return s7_bfd_score_elf_fake_sections (abfd, hdr, sec); 4244 1.1 christos } 4245 1.1 christos 4246 1.10 christos static bool 4247 1.1 christos _bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr) 4248 1.1 christos { 4249 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4250 1.1 christos return s3_bfd_score_elf_section_processing (abfd, hdr); 4251 1.1 christos else 4252 1.1 christos return s7_bfd_score_elf_section_processing (abfd, hdr); 4253 1.1 christos } 4254 1.1 christos 4255 1.10 christos static bool 4256 1.1 christos _bfd_score_elf_write_section (bfd *output_bfd, 4257 1.8 christos struct bfd_link_info *link_info ATTRIBUTE_UNUSED, 4258 1.8 christos asection *sec, bfd_byte *contents) 4259 1.1 christos { 4260 1.1 christos if (bfd_get_mach (output_bfd) == bfd_mach_score3) 4261 1.1 christos return s3_bfd_score_elf_write_section (output_bfd, sec, contents); 4262 1.1 christos else 4263 1.1 christos return s7_bfd_score_elf_write_section (output_bfd, sec, contents); 4264 1.1 christos } 4265 1.1 christos 4266 1.1 christos static void 4267 1.1 christos _bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info, 4268 1.8 christos struct elf_link_hash_entry *dir, 4269 1.8 christos struct elf_link_hash_entry *ind) 4270 1.1 christos { 4271 1.1 christos if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) 4272 1.1 christos return s3_bfd_score_elf_copy_indirect_symbol (info, dir, ind); 4273 1.1 christos else 4274 1.1 christos return s7_bfd_score_elf_copy_indirect_symbol (info, dir, ind); 4275 1.1 christos } 4276 1.1 christos 4277 1.1 christos static void 4278 1.1 christos _bfd_score_elf_hide_symbol (struct bfd_link_info *info, 4279 1.8 christos struct elf_link_hash_entry *entry, 4280 1.10 christos bool force_local) 4281 1.1 christos { 4282 1.1 christos if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) 4283 1.1 christos return s3_bfd_score_elf_hide_symbol (info, entry, force_local); 4284 1.1 christos else 4285 1.1 christos return s7_bfd_score_elf_hide_symbol (info, entry, force_local); 4286 1.1 christos } 4287 1.1 christos 4288 1.10 christos static bool 4289 1.1 christos _bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie, 4290 1.8 christos struct bfd_link_info *info) 4291 1.1 christos { 4292 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4293 1.1 christos return s3_bfd_score_elf_discard_info (abfd, cookie, info); 4294 1.1 christos else 4295 1.1 christos return s7_bfd_score_elf_discard_info (abfd, cookie, info); 4296 1.1 christos } 4297 1.1 christos 4298 1.10 christos static bool 4299 1.1 christos _bfd_score_elf_ignore_discarded_relocs (asection *sec) 4300 1.1 christos { 4301 1.1 christos if (bfd_get_mach (sec->owner) == bfd_mach_score3) 4302 1.1 christos return s3_bfd_score_elf_ignore_discarded_relocs (sec); 4303 1.1 christos else 4304 1.1 christos return s7_bfd_score_elf_ignore_discarded_relocs (sec); 4305 1.1 christos } 4306 1.1 christos 4307 1.1 christos static asection * 4308 1.1 christos _bfd_score_elf_gc_mark_hook (asection *sec, 4309 1.8 christos struct bfd_link_info *info, 4310 1.8 christos Elf_Internal_Rela *rel, 4311 1.8 christos struct elf_link_hash_entry *h, 4312 1.8 christos Elf_Internal_Sym *sym) 4313 1.1 christos { 4314 1.1 christos if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) 4315 1.1 christos return s3_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym); 4316 1.1 christos else 4317 1.1 christos return s7_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym); 4318 1.1 christos } 4319 1.1 christos 4320 1.10 christos static bool 4321 1.1 christos _bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) 4322 1.1 christos { 4323 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4324 1.1 christos return s3_bfd_score_elf_grok_prstatus (abfd, note); 4325 1.1 christos else 4326 1.1 christos return s7_bfd_score_elf_grok_prstatus (abfd, note); 4327 1.1 christos } 4328 1.1 christos 4329 1.10 christos static bool 4330 1.1 christos _bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) 4331 1.1 christos { 4332 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4333 1.1 christos return s3_bfd_score_elf_grok_psinfo (abfd, note); 4334 1.1 christos else 4335 1.1 christos return s7_bfd_score_elf_grok_psinfo (abfd, note); 4336 1.1 christos } 4337 1.1 christos 4338 1.1 christos static reloc_howto_type * 4339 1.1 christos elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) 4340 1.1 christos { 4341 1.1 christos /* s3: NOTE!!! 4342 1.1 christos gas will call elf32_score_reloc_type_lookup, and don't write elf file. 4343 1.1 christos So just using score3, but we don't know ld will call this or not. 4344 1.1 christos If so, this way can't work. */ 4345 1.1 christos 4346 1.1 christos if (score3) 4347 1.1 christos return s3_elf32_score_reloc_type_lookup (abfd, code); 4348 1.1 christos else 4349 1.1 christos return s7_elf32_score_reloc_type_lookup (abfd, code); 4350 1.1 christos } 4351 1.1 christos 4352 1.1 christos /* Create a score elf linker hash table. 4353 1.1 christos This is a copy of _bfd_elf_link_hash_table_create() except with a 4354 1.1 christos different hash table entry creation function. */ 4355 1.1 christos 4356 1.1 christos static struct bfd_link_hash_table * 4357 1.1 christos elf32_score_link_hash_table_create (bfd *abfd) 4358 1.1 christos { 4359 1.1 christos struct elf_link_hash_table *ret; 4360 1.9 christos size_t amt = sizeof (struct elf_link_hash_table); 4361 1.1 christos 4362 1.1 christos ret = (struct elf_link_hash_table *) bfd_zmalloc (amt); 4363 1.1 christos if (ret == NULL) 4364 1.1 christos return NULL; 4365 1.1 christos 4366 1.1 christos if (!_bfd_elf_link_hash_table_init (ret, abfd, score_elf_link_hash_newfunc, 4367 1.12 christos sizeof (struct score_elf_link_hash_entry))) 4368 1.1 christos { 4369 1.1 christos free (ret); 4370 1.1 christos return NULL; 4371 1.1 christos } 4372 1.1 christos 4373 1.1 christos return &ret->root; 4374 1.1 christos } 4375 1.1 christos 4376 1.10 christos static bool 4377 1.1 christos elf32_score_print_private_bfd_data (bfd *abfd, void * ptr) 4378 1.1 christos { 4379 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4380 1.1 christos return s3_elf32_score_print_private_bfd_data (abfd, ptr); 4381 1.1 christos else 4382 1.1 christos return s7_elf32_score_print_private_bfd_data (abfd, ptr); 4383 1.1 christos } 4384 1.1 christos 4385 1.10 christos static bool 4386 1.7 christos elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) 4387 1.1 christos { 4388 1.7 christos if (bfd_get_mach (info->output_bfd) == bfd_mach_score3) 4389 1.7 christos return s3_elf32_score_merge_private_bfd_data (ibfd, info); 4390 1.1 christos else 4391 1.7 christos return s7_elf32_score_merge_private_bfd_data (ibfd, info); 4392 1.1 christos } 4393 1.1 christos 4394 1.10 christos static bool 4395 1.1 christos elf32_score_new_section_hook (bfd *abfd, asection *sec) 4396 1.1 christos { 4397 1.1 christos if (bfd_get_mach (abfd) == bfd_mach_score3) 4398 1.1 christos return s3_elf32_score_new_section_hook (abfd, sec); 4399 1.1 christos else 4400 1.1 christos return s7_elf32_score_new_section_hook (abfd, sec); 4401 1.1 christos } 4402 1.1 christos 4403 1.1 christos 4404 1.1 christos /* s3_s7: don't need to split. */ 4405 1.1 christos 4406 1.1 christos /* Set the right machine number. */ 4407 1.10 christos static bool 4408 1.1 christos _bfd_score_elf_score_object_p (bfd * abfd) 4409 1.1 christos { 4410 1.1 christos int e_set = bfd_mach_score7; 4411 1.1 christos 4412 1.1 christos if (elf_elfheader (abfd)->e_machine == EM_SCORE) 4413 1.1 christos { 4414 1.1 christos int e_mach = elf_elfheader (abfd)->e_flags & EF_SCORE_MACH & EF_OMIT_PIC_FIXDD; 4415 1.1 christos switch (e_mach) 4416 1.8 christos { 4417 1.8 christos /* Set default target is score7. */ 4418 1.8 christos default: 4419 1.8 christos case E_SCORE_MACH_SCORE7: 4420 1.8 christos e_set = bfd_mach_score7; 4421 1.8 christos break; 4422 1.8 christos 4423 1.8 christos case E_SCORE_MACH_SCORE3: 4424 1.8 christos e_set = bfd_mach_score3; 4425 1.8 christos break; 4426 1.8 christos } 4427 1.1 christos } 4428 1.1 christos 4429 1.1 christos return bfd_default_set_arch_mach (abfd, bfd_arch_score, e_set); 4430 1.1 christos } 4431 1.1 christos 4432 1.10 christos bool 4433 1.1 christos _bfd_score_elf_common_definition (Elf_Internal_Sym *sym) 4434 1.1 christos { 4435 1.1 christos return (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_SCORE_SCOMMON); 4436 1.1 christos } 4437 1.1 christos 4438 1.1 christos /*****************************************************************************/ 4439 1.1 christos 4440 1.1 christos 4441 1.8 christos #define USE_REL 1 4442 1.8 christos #define TARGET_LITTLE_SYM score_elf32_le_vec 4443 1.8 christos #define TARGET_LITTLE_NAME "elf32-littlescore" 4444 1.8 christos #define TARGET_BIG_SYM score_elf32_be_vec 4445 1.8 christos #define TARGET_BIG_NAME "elf32-bigscore" 4446 1.8 christos #define ELF_ARCH bfd_arch_score 4447 1.8 christos #define ELF_MACHINE_CODE EM_SCORE 4448 1.8 christos #define ELF_MACHINE_ALT1 EM_SCORE_OLD 4449 1.12 christos #define ELF_TARGET_ID SCORE_ELF_DATA 4450 1.8 christos #define ELF_MAXPAGESIZE 0x8000 4451 1.8 christos 4452 1.8 christos #define elf_info_to_howto NULL 4453 1.8 christos #define elf_info_to_howto_rel _bfd_score_info_to_howto 4454 1.8 christos #define elf_backend_relocate_section _bfd_score_elf_relocate_section 4455 1.8 christos #define elf_backend_check_relocs _bfd_score_elf_check_relocs 4456 1.8 christos #define elf_backend_add_symbol_hook _bfd_score_elf_add_symbol_hook 4457 1.8 christos #define elf_backend_symbol_processing _bfd_score_elf_symbol_processing 4458 1.1 christos #define elf_backend_link_output_symbol_hook \ 4459 1.1 christos _bfd_score_elf_link_output_symbol_hook 4460 1.1 christos #define elf_backend_section_from_bfd_section \ 4461 1.1 christos _bfd_score_elf_section_from_bfd_section 4462 1.1 christos #define elf_backend_adjust_dynamic_symbol \ 4463 1.1 christos _bfd_score_elf_adjust_dynamic_symbol 4464 1.11 christos #define elf_backend_early_size_sections \ 4465 1.11 christos _bfd_score_elf_early_size_sections 4466 1.11 christos #define elf_backend_late_size_sections \ 4467 1.11 christos _bfd_score_elf_late_size_sections 4468 1.8 christos #define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all 4469 1.1 christos #define elf_backend_create_dynamic_sections \ 4470 1.1 christos _bfd_score_elf_create_dynamic_sections 4471 1.1 christos #define elf_backend_finish_dynamic_symbol \ 4472 1.1 christos _bfd_score_elf_finish_dynamic_symbol 4473 1.1 christos #define elf_backend_finish_dynamic_sections \ 4474 1.1 christos _bfd_score_elf_finish_dynamic_sections 4475 1.8 christos #define elf_backend_fake_sections _bfd_score_elf_fake_sections 4476 1.8 christos #define elf_backend_section_processing _bfd_score_elf_section_processing 4477 1.8 christos #define elf_backend_write_section _bfd_score_elf_write_section 4478 1.1 christos #define elf_backend_copy_indirect_symbol _bfd_score_elf_copy_indirect_symbol 4479 1.8 christos #define elf_backend_hide_symbol _bfd_score_elf_hide_symbol 4480 1.8 christos #define elf_backend_discard_info _bfd_score_elf_discard_info 4481 1.1 christos #define elf_backend_ignore_discarded_relocs \ 4482 1.1 christos _bfd_score_elf_ignore_discarded_relocs 4483 1.8 christos #define elf_backend_gc_mark_hook _bfd_score_elf_gc_mark_hook 4484 1.8 christos #define elf_backend_grok_prstatus _bfd_score_elf_grok_prstatus 4485 1.8 christos #define elf_backend_grok_psinfo _bfd_score_elf_grok_psinfo 4486 1.8 christos #define elf_backend_can_gc_sections 1 4487 1.8 christos #define elf_backend_want_plt_sym 0 4488 1.8 christos #define elf_backend_got_header_size (4 * SCORE_RESERVED_GOTNO) 4489 1.8 christos #define elf_backend_plt_header_size 0 4490 1.10 christos #define elf_backend_collect true 4491 1.10 christos #define elf_backend_type_change_ok true 4492 1.8 christos #define elf_backend_object_p _bfd_score_elf_score_object_p 4493 1.1 christos 4494 1.8 christos #define bfd_elf32_bfd_reloc_type_lookup elf32_score_reloc_type_lookup 4495 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup \ 4496 1.1 christos elf32_score_reloc_name_lookup 4497 1.1 christos #define bfd_elf32_bfd_link_hash_table_create elf32_score_link_hash_table_create 4498 1.1 christos #define bfd_elf32_bfd_print_private_bfd_data elf32_score_print_private_bfd_data 4499 1.1 christos #define bfd_elf32_bfd_merge_private_bfd_data elf32_score_merge_private_bfd_data 4500 1.8 christos #define bfd_elf32_new_section_hook elf32_score_new_section_hook 4501 1.1 christos 4502 1.1 christos #include "elf32-target.h" 4503