1 1.1 christos /* 32-bit ELF support for TI PRU. 2 1.1.1.5 christos Copyright (C) 2014-2024 Free Software Foundation, Inc. 3 1.1 christos Contributed by Dimitar Dimitrov <dimitar (at) dinux.eu> 4 1.1 christos Based on elf32-nios2.c 5 1.1 christos 6 1.1 christos This file is part of BFD, the Binary File Descriptor library. 7 1.1 christos 8 1.1 christos This program is free software; you can redistribute it and/or modify 9 1.1 christos it under the terms of the GNU General Public License as published by 10 1.1 christos the Free Software Foundation; either version 3 of the License, or 11 1.1 christos (at your option) any later version. 12 1.1 christos 13 1.1 christos This program is distributed in the hope that it will be useful, 14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 christos GNU General Public License for more details. 17 1.1 christos 18 1.1 christos You should have received a copy of the GNU General Public License 19 1.1 christos along with this program; if not, write to the Free Software 20 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 1.1 christos MA 02110-1301, USA. */ 22 1.1 christos 23 1.1 christos /* This file handles TI PRU ELF targets. */ 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 "bfdlink.h" 29 1.1 christos #include "genlink.h" 30 1.1 christos #include "elf-bfd.h" 31 1.1 christos #include "elf/pru.h" 32 1.1 christos #include "opcode/pru.h" 33 1.1.1.2 christos #include "libiberty.h" 34 1.1 christos 35 1.1.1.3 christos /* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ 36 1.1.1.3 christos #define OCTETS_PER_BYTE(ABFD, SEC) 1 37 1.1.1.3 christos 38 1.1 christos #define SWAP_VALS(A,B) \ 39 1.1 christos do { \ 40 1.1 christos (A) ^= (B); \ 41 1.1 christos (B) ^= (A); \ 42 1.1 christos (A) ^= (B); \ 43 1.1 christos } while (0) 44 1.1 christos 45 1.1 christos /* Enable debugging printout at stdout with this variable. */ 46 1.1.1.4 christos static bool debug_relax = false; 47 1.1 christos 48 1.1 christos /* Forward declarations. */ 49 1.1 christos static bfd_reloc_status_type pru_elf32_pmem_relocate 50 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 51 1.1 christos static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate 52 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 53 1.1 christos static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate 54 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 55 1.1 christos static bfd_reloc_status_type pru_elf32_ldi32_relocate 56 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 57 1.1 christos static bfd_reloc_status_type bfd_elf_pru_diff_relocate 58 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 59 1.1 christos 60 1.1 christos /* Target vector. */ 61 1.1 christos extern const bfd_target pru_elf32_vec; 62 1.1 christos 63 1.1 christos /* The relocation table used for SHT_REL sections. */ 64 1.1 christos static reloc_howto_type elf_pru_howto_table_rel[] = { 65 1.1 christos /* No relocation. */ 66 1.1 christos HOWTO (R_PRU_NONE, /* type */ 67 1.1 christos 0, /* rightshift */ 68 1.1.1.4 christos 0, /* size */ 69 1.1.1.4 christos 0, /* bitsize */ 70 1.1.1.4 christos false, /* pc_relative */ 71 1.1 christos 0, /* bitpos */ 72 1.1 christos complain_overflow_dont,/* complain_on_overflow */ 73 1.1 christos bfd_elf_generic_reloc, /* special_function */ 74 1.1 christos "R_PRU_NONE", /* name */ 75 1.1.1.4 christos false, /* partial_inplace */ 76 1.1 christos 0, /* src_mask */ 77 1.1 christos 0, /* dst_mask */ 78 1.1.1.4 christos false), /* pcrel_offset */ 79 1.1 christos 80 1.1 christos HOWTO (R_PRU_16_PMEM, 81 1.1 christos 2, 82 1.1.1.4 christos 2, /* short */ 83 1.1 christos 32, 84 1.1.1.4 christos false, 85 1.1 christos 0, 86 1.1 christos complain_overflow_dont, 87 1.1 christos bfd_elf_generic_reloc, 88 1.1 christos "R_PRU_16_PMEM", 89 1.1.1.4 christos false, 90 1.1 christos 0, /* src_mask */ 91 1.1 christos 0xffff, 92 1.1.1.4 christos false), 93 1.1 christos 94 1.1 christos HOWTO (R_PRU_U16_PMEMIMM, 95 1.1 christos 2, 96 1.1.1.4 christos 4, 97 1.1 christos 32, 98 1.1.1.4 christos false, 99 1.1 christos 8, 100 1.1 christos complain_overflow_unsigned, 101 1.1 christos pru_elf32_pmem_relocate, 102 1.1 christos "R_PRU_U16_PMEMIMM", 103 1.1.1.4 christos false, 104 1.1 christos 0, /* src_mask */ 105 1.1 christos 0x00ffff00, 106 1.1.1.4 christos false), 107 1.1 christos 108 1.1 christos HOWTO (R_PRU_BFD_RELOC_16, 109 1.1 christos 0, 110 1.1.1.4 christos 2, /* short */ 111 1.1 christos 16, 112 1.1.1.4 christos false, 113 1.1 christos 0, 114 1.1 christos complain_overflow_bitfield, 115 1.1 christos bfd_elf_generic_reloc, 116 1.1 christos "R_PRU_BFD_RELOC16", 117 1.1.1.4 christos false, 118 1.1 christos 0, /* src_mask */ 119 1.1 christos 0x0000ffff, 120 1.1.1.4 christos false), 121 1.1 christos 122 1.1 christos /* 16-bit unsigned immediate relocation. */ 123 1.1 christos HOWTO (R_PRU_U16, /* type */ 124 1.1 christos 0, /* rightshift */ 125 1.1.1.4 christos 4, /* size */ 126 1.1 christos 16, /* bitsize */ 127 1.1.1.4 christos false, /* pc_relative */ 128 1.1 christos 8, /* bitpos */ 129 1.1 christos complain_overflow_unsigned, /* complain on overflow */ 130 1.1 christos bfd_elf_generic_reloc, /* special function */ 131 1.1 christos "R_PRU_U16", /* name */ 132 1.1.1.4 christos false, /* partial_inplace */ 133 1.1 christos 0, /* src_mask */ 134 1.1 christos 0x00ffff00, /* dest_mask */ 135 1.1.1.4 christos false), /* pcrel_offset */ 136 1.1 christos 137 1.1 christos HOWTO (R_PRU_32_PMEM, 138 1.1 christos 2, 139 1.1.1.4 christos 4, /* long */ 140 1.1 christos 32, 141 1.1.1.4 christos false, 142 1.1 christos 0, 143 1.1 christos complain_overflow_dont, 144 1.1 christos pru_elf32_pmem_relocate, 145 1.1 christos "R_PRU_32_PMEM", 146 1.1.1.4 christos false, 147 1.1 christos 0, /* src_mask */ 148 1.1 christos 0xffffffff, 149 1.1.1.4 christos false), 150 1.1 christos 151 1.1 christos HOWTO (R_PRU_BFD_RELOC_32, 152 1.1 christos 0, 153 1.1.1.4 christos 4, /* long */ 154 1.1 christos 32, 155 1.1.1.4 christos false, 156 1.1 christos 0, 157 1.1 christos complain_overflow_dont, 158 1.1 christos bfd_elf_generic_reloc, 159 1.1 christos "R_PRU_BFD_RELOC32", 160 1.1.1.4 christos false, 161 1.1 christos 0, /* src_mask */ 162 1.1 christos 0xffffffff, 163 1.1.1.4 christos false), 164 1.1 christos 165 1.1 christos HOWTO (R_PRU_S10_PCREL, 166 1.1 christos 2, 167 1.1.1.4 christos 4, 168 1.1 christos 10, 169 1.1.1.4 christos true, 170 1.1 christos 0, 171 1.1 christos complain_overflow_bitfield, 172 1.1 christos pru_elf32_s10_pcrel_relocate, 173 1.1 christos "R_PRU_S10_PCREL", 174 1.1.1.4 christos false, 175 1.1 christos 0, /* src_mask */ 176 1.1 christos 0x060000ff, 177 1.1.1.4 christos true), 178 1.1 christos 179 1.1 christos HOWTO (R_PRU_U8_PCREL, 180 1.1 christos 2, 181 1.1.1.4 christos 4, 182 1.1 christos 8, 183 1.1.1.4 christos true, 184 1.1 christos 0, 185 1.1 christos complain_overflow_unsigned, 186 1.1 christos pru_elf32_u8_pcrel_relocate, 187 1.1 christos "R_PRU_U8_PCREL", 188 1.1.1.4 christos false, 189 1.1 christos 0, /* src_mask */ 190 1.1 christos 0x000000ff, 191 1.1.1.4 christos true), 192 1.1 christos 193 1.1 christos HOWTO (R_PRU_LDI32, 194 1.1 christos 0, /* rightshift */ 195 1.1.1.4 christos 8, /* size */ 196 1.1 christos 32, /* bitsize */ 197 1.1.1.4 christos false, /* pc_relative */ 198 1.1 christos 0, /* bitpos */ 199 1.1 christos complain_overflow_unsigned, /* complain on overflow */ 200 1.1 christos pru_elf32_ldi32_relocate, /* special function */ 201 1.1 christos "R_PRU_LDI32", /* name */ 202 1.1.1.4 christos false, /* partial_inplace */ 203 1.1 christos 0, /* src_mask */ 204 1.1 christos 0xffffffff, /* dest_mask */ 205 1.1.1.4 christos false), /* pcrel_offset */ 206 1.1 christos 207 1.1 christos /* GNU-specific relocations. */ 208 1.1 christos HOWTO (R_PRU_GNU_BFD_RELOC_8, 209 1.1 christos 0, 210 1.1.1.4 christos 1, /* byte */ 211 1.1 christos 8, 212 1.1.1.4 christos false, 213 1.1 christos 0, 214 1.1 christos complain_overflow_bitfield, 215 1.1 christos bfd_elf_generic_reloc, 216 1.1 christos "R_PRU_BFD_RELOC8", 217 1.1.1.4 christos false, 218 1.1 christos 0, /* src_mask */ 219 1.1 christos 0x000000ff, 220 1.1.1.4 christos false), 221 1.1 christos 222 1.1 christos HOWTO (R_PRU_GNU_DIFF8, /* type */ 223 1.1 christos 0, /* rightshift */ 224 1.1.1.4 christos 1, /* size */ 225 1.1.1.2 christos 8, /* bitsize */ 226 1.1.1.4 christos false, /* pc_relative */ 227 1.1 christos 0, /* bitpos */ 228 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */ 229 1.1 christos bfd_elf_pru_diff_relocate, /* special_function */ 230 1.1.1.2 christos "R_PRU_DIFF8", /* name */ 231 1.1.1.4 christos false, /* partial_inplace */ 232 1.1 christos 0, /* src_mask */ 233 1.1 christos 0xff, /* dst_mask */ 234 1.1.1.4 christos false), /* pcrel_offset */ 235 1.1 christos 236 1.1.1.2 christos HOWTO (R_PRU_GNU_DIFF16, /* type */ 237 1.1 christos 0, /* rightshift */ 238 1.1.1.4 christos 2, /* size */ 239 1.1 christos 16, /* bitsize */ 240 1.1.1.4 christos false, /* pc_relative */ 241 1.1 christos 0, /* bitpos */ 242 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */ 243 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */ 244 1.1.1.2 christos "R_PRU_DIFF16", /* name */ 245 1.1.1.4 christos false, /* partial_inplace */ 246 1.1 christos 0, /* src_mask */ 247 1.1 christos 0xffff, /* dst_mask */ 248 1.1.1.4 christos false), /* pcrel_offset */ 249 1.1 christos 250 1.1.1.2 christos HOWTO (R_PRU_GNU_DIFF32, /* type */ 251 1.1 christos 0, /* rightshift */ 252 1.1.1.4 christos 4, /* size */ 253 1.1 christos 32, /* bitsize */ 254 1.1.1.4 christos false, /* pc_relative */ 255 1.1 christos 0, /* bitpos */ 256 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */ 257 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */ 258 1.1.1.2 christos "R_PRU_DIFF32", /* name */ 259 1.1.1.4 christos false, /* partial_inplace */ 260 1.1 christos 0, /* src_mask */ 261 1.1.1.2 christos 0xffffffff, /* dst_mask */ 262 1.1.1.4 christos false), /* pcrel_offset */ 263 1.1 christos 264 1.1 christos HOWTO (R_PRU_GNU_DIFF16_PMEM, /* type */ 265 1.1 christos 0, /* rightshift */ 266 1.1.1.4 christos 2, /* size */ 267 1.1 christos 16, /* bitsize */ 268 1.1.1.4 christos false, /* pc_relative */ 269 1.1 christos 0, /* bitpos */ 270 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */ 271 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */ 272 1.1.1.2 christos "R_PRU_DIFF16_PMEM", /* name */ 273 1.1.1.4 christos false, /* partial_inplace */ 274 1.1 christos 0, /* src_mask */ 275 1.1 christos 0xffff, /* dst_mask */ 276 1.1.1.4 christos false), /* pcrel_offset */ 277 1.1 christos 278 1.1 christos HOWTO (R_PRU_GNU_DIFF32_PMEM, /* type */ 279 1.1 christos 0, /* rightshift */ 280 1.1.1.4 christos 4, /* size */ 281 1.1 christos 32, /* bitsize */ 282 1.1.1.4 christos false, /* pc_relative */ 283 1.1 christos 0, /* bitpos */ 284 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */ 285 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */ 286 1.1.1.2 christos "R_PRU_DIFF32_PMEM", /* name */ 287 1.1.1.4 christos false, /* partial_inplace */ 288 1.1 christos 0, /* src_mask */ 289 1.1 christos 0xffffffff, /* dst_mask */ 290 1.1.1.4 christos false), /* pcrel_offset */ 291 1.1 christos 292 1.1 christos /* Add other relocations here. */ 293 1.1 christos }; 294 1.1 christos 295 1.1 christos static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1]; 296 1.1 christos 297 1.1 christos /* Return the howto for relocation RTYPE. */ 298 1.1.1.2 christos 299 1.1 christos static reloc_howto_type * 300 1.1 christos lookup_howto (unsigned int rtype) 301 1.1 christos { 302 1.1.1.4 christos static bool initialized = false; 303 1.1 christos int i; 304 1.1 christos int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel) 305 1.1 christos / sizeof (elf_pru_howto_table_rel[0])); 306 1.1 christos 307 1.1.1.2 christos if (! initialized) 308 1.1 christos { 309 1.1.1.4 christos initialized = true; 310 1.1 christos memset (elf_code_to_howto_index, 0xff, 311 1.1 christos sizeof (elf_code_to_howto_index)); 312 1.1 christos for (i = 0; i < howto_tbl_size; i++) 313 1.1 christos elf_code_to_howto_index[elf_pru_howto_table_rel[i].type] = i; 314 1.1 christos } 315 1.1 christos 316 1.1.1.2 christos if (rtype > R_PRU_ILLEGAL) 317 1.1.1.2 christos return NULL; 318 1.1 christos i = elf_code_to_howto_index[rtype]; 319 1.1 christos if (i >= howto_tbl_size) 320 1.1.1.2 christos return NULL; 321 1.1 christos return elf_pru_howto_table_rel + i; 322 1.1 christos } 323 1.1 christos 324 1.1 christos /* Map for converting BFD reloc types to PRU reloc types. */ 325 1.1.1.2 christos 326 1.1 christos struct elf_reloc_map 327 1.1 christos { 328 1.1 christos bfd_reloc_code_real_type bfd_val; 329 1.1 christos enum elf_pru_reloc_type elf_val; 330 1.1 christos }; 331 1.1 christos 332 1.1.1.2 christos static const struct elf_reloc_map pru_reloc_map[] = 333 1.1.1.2 christos { 334 1.1 christos {BFD_RELOC_NONE, R_PRU_NONE}, 335 1.1 christos {BFD_RELOC_PRU_16_PMEM, R_PRU_16_PMEM}, 336 1.1 christos {BFD_RELOC_PRU_U16_PMEMIMM, R_PRU_U16_PMEMIMM}, 337 1.1 christos {BFD_RELOC_16, R_PRU_BFD_RELOC_16}, 338 1.1 christos {BFD_RELOC_PRU_U16, R_PRU_U16}, 339 1.1 christos {BFD_RELOC_PRU_32_PMEM, R_PRU_32_PMEM}, 340 1.1 christos {BFD_RELOC_32, R_PRU_BFD_RELOC_32}, 341 1.1 christos {BFD_RELOC_PRU_S10_PCREL, R_PRU_S10_PCREL}, 342 1.1 christos {BFD_RELOC_PRU_U8_PCREL, R_PRU_U8_PCREL}, 343 1.1 christos {BFD_RELOC_PRU_LDI32, R_PRU_LDI32}, 344 1.1 christos 345 1.1 christos {BFD_RELOC_8, R_PRU_GNU_BFD_RELOC_8}, 346 1.1 christos {BFD_RELOC_PRU_GNU_DIFF8, R_PRU_GNU_DIFF8}, 347 1.1 christos {BFD_RELOC_PRU_GNU_DIFF16, R_PRU_GNU_DIFF16}, 348 1.1 christos {BFD_RELOC_PRU_GNU_DIFF32, R_PRU_GNU_DIFF32}, 349 1.1 christos {BFD_RELOC_PRU_GNU_DIFF16_PMEM, R_PRU_GNU_DIFF16_PMEM}, 350 1.1 christos {BFD_RELOC_PRU_GNU_DIFF32_PMEM, R_PRU_GNU_DIFF32_PMEM}, 351 1.1 christos }; 352 1.1 christos 353 1.1 christos 354 1.1 christos /* Assorted hash table functions. */ 355 1.1 christos 356 1.1 christos /* Create an entry in a PRU ELF linker hash table. */ 357 1.1.1.2 christos 358 1.1 christos static struct bfd_hash_entry * 359 1.1 christos link_hash_newfunc (struct bfd_hash_entry *entry, 360 1.1 christos struct bfd_hash_table *table, const char *string) 361 1.1 christos { 362 1.1 christos /* Allocate the structure if it has not already been allocated by a 363 1.1 christos subclass. */ 364 1.1 christos if (entry == NULL) 365 1.1 christos { 366 1.1 christos entry = bfd_hash_allocate (table, 367 1.1 christos sizeof (struct elf_link_hash_entry)); 368 1.1 christos if (entry == NULL) 369 1.1 christos return entry; 370 1.1 christos } 371 1.1 christos 372 1.1 christos /* Call the allocation method of the superclass. */ 373 1.1 christos entry = _bfd_elf_link_hash_newfunc (entry, table, string); 374 1.1 christos 375 1.1 christos return entry; 376 1.1 christos } 377 1.1 christos 378 1.1 christos /* Implement bfd_elf32_bfd_reloc_type_lookup: 379 1.1 christos Given a BFD reloc type, return a howto structure. */ 380 1.1.1.2 christos 381 1.1 christos static reloc_howto_type * 382 1.1 christos pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 383 1.1 christos bfd_reloc_code_real_type code) 384 1.1 christos { 385 1.1.1.2 christos unsigned int i; 386 1.1.1.2 christos 387 1.1.1.2 christos for (i = 0; i < ARRAY_SIZE (pru_reloc_map); ++i) 388 1.1 christos if (pru_reloc_map[i].bfd_val == code) 389 1.1 christos return lookup_howto ((unsigned int) pru_reloc_map[i].elf_val); 390 1.1 christos return NULL; 391 1.1 christos } 392 1.1 christos 393 1.1 christos /* Implement bfd_elf32_bfd_reloc_name_lookup: 394 1.1 christos Given a reloc name, return a howto structure. */ 395 1.1.1.2 christos 396 1.1 christos static reloc_howto_type * 397 1.1 christos pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 398 1.1 christos const char *r_name) 399 1.1 christos { 400 1.1 christos unsigned int i; 401 1.1.1.2 christos 402 1.1.1.2 christos for (i = 0; i < ARRAY_SIZE (elf_pru_howto_table_rel); i++) 403 1.1 christos if (elf_pru_howto_table_rel[i].name 404 1.1 christos && strcasecmp (elf_pru_howto_table_rel[i].name, r_name) == 0) 405 1.1 christos return &elf_pru_howto_table_rel[i]; 406 1.1 christos 407 1.1 christos return NULL; 408 1.1 christos } 409 1.1 christos 410 1.1 christos /* Implement elf_info_to_howto: 411 1.1 christos Given a ELF32 relocation, fill in a arelent structure. */ 412 1.1.1.2 christos 413 1.1.1.4 christos static bool 414 1.1.1.2 christos pru_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr, 415 1.1 christos Elf_Internal_Rela *dst) 416 1.1 christos { 417 1.1 christos unsigned int r_type; 418 1.1 christos 419 1.1 christos r_type = ELF32_R_TYPE (dst->r_info); 420 1.1.1.2 christos if (r_type >= R_PRU_ILLEGAL) 421 1.1.1.2 christos { 422 1.1.1.2 christos /* xgettext:c-format */ 423 1.1.1.2 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type); 424 1.1.1.2 christos bfd_set_error (bfd_error_bad_value); 425 1.1.1.4 christos return false; 426 1.1.1.2 christos } 427 1.1.1.3 christos 428 1.1 christos cache_ptr->howto = lookup_howto (r_type); 429 1.1.1.2 christos return cache_ptr->howto != NULL; 430 1.1 christos } 431 1.1 christos 432 1.1 christos /* Do the relocations that require special handling. */ 433 1.1 christos /* Produce a word address for program memory. Linker scripts will put .text 434 1.1 christos at a high offset in order to differentiate it from .data. So here we also 435 1.1 christos mask the high bits of PMEM address. 436 1.1 christos 437 1.1 christos But why 1MB when internal Program Memory much smaller? We want to catch 438 1.1 christos unintended overflows. 439 1.1 christos 440 1.1 christos Why not use (1<<31) as an offset and a mask? Sitara DDRAM usually resides 441 1.1 christos there, and users might want to put some shared carveout memory region in 442 1.1 christos their linker scripts. So 0x80000000 might be a valid .data address. 443 1.1 christos 444 1.1 christos Note that we still keep and pass down the original howto. This way we 445 1.1 christos can reuse this function for several different relocations. */ 446 1.1 christos static bfd_reloc_status_type 447 1.1 christos pru_elf32_do_pmem_relocate (bfd *abfd, reloc_howto_type *howto, 448 1.1 christos asection *input_section, 449 1.1 christos bfd_byte *data, bfd_vma offset, 450 1.1 christos bfd_vma symbol_value, bfd_vma addend) 451 1.1 christos { 452 1.1 christos symbol_value = symbol_value + addend; 453 1.1 christos addend = 0; 454 1.1 christos symbol_value &= 0x3fffff; 455 1.1 christos return _bfd_final_link_relocate (howto, abfd, input_section, 456 1.1 christos data, offset, symbol_value, addend); 457 1.1 christos } 458 1.1 christos 459 1.1 christos /* Direct copy of _bfd_final_link_relocate, but with special 460 1.1 christos "fill-in". This copy-paste mumbo jumbo is only needed because BFD 461 1.1 christos cannot deal correctly with non-contiguous bit fields. */ 462 1.1 christos static bfd_reloc_status_type 463 1.1 christos pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto, 464 1.1 christos asection *input_section, 465 1.1 christos bfd_byte *contents, bfd_vma address, 466 1.1 christos bfd_vma relocation, bfd_vma addend) 467 1.1 christos { 468 1.1 christos bfd_byte *location; 469 1.1 christos bfd_vma x = 0; 470 1.1 christos bfd_vma qboff; 471 1.1 christos bfd_reloc_status_type flag = bfd_reloc_ok; 472 1.1 christos 473 1.1 christos /* Sanity check the address. */ 474 1.1 christos if (address > bfd_get_section_limit (input_bfd, input_section)) 475 1.1 christos return bfd_reloc_outofrange; 476 1.1 christos 477 1.1 christos BFD_ASSERT (howto->pc_relative); 478 1.1 christos BFD_ASSERT (howto->pcrel_offset); 479 1.1 christos 480 1.1 christos relocation = relocation + addend - (input_section->output_section->vma 481 1.1 christos + input_section->output_offset) - address; 482 1.1 christos 483 1.1 christos location = contents + address; 484 1.1 christos 485 1.1 christos /* Get the value we are going to relocate. */ 486 1.1 christos BFD_ASSERT (bfd_get_reloc_size (howto) == 4); 487 1.1 christos x = bfd_get_32 (input_bfd, location); 488 1.1 christos 489 1.1 christos qboff = GET_BROFF_SIGNED (x) << howto->rightshift; 490 1.1 christos relocation += qboff; 491 1.1 christos 492 1.1 christos BFD_ASSERT (howto->complain_on_overflow == complain_overflow_bitfield); 493 1.1 christos 494 1.1 christos if (relocation > 2047 && relocation < (bfd_vma)-2048l) 495 1.1 christos flag = bfd_reloc_overflow; 496 1.1 christos 497 1.1 christos /* Check that target address is word-aligned. */ 498 1.1 christos if (relocation & ((1 << howto->rightshift) - 1)) 499 1.1 christos flag = bfd_reloc_outofrange; 500 1.1 christos 501 1.1 christos relocation >>= (bfd_vma) howto->rightshift; 502 1.1 christos 503 1.1 christos /* Fill-in the RELOCATION to the right bits of X. */ 504 1.1 christos SET_BROFF_URAW (x, relocation); 505 1.1 christos 506 1.1 christos bfd_put_32 (input_bfd, x, location); 507 1.1 christos 508 1.1 christos return flag; 509 1.1 christos } 510 1.1 christos 511 1.1 christos static bfd_reloc_status_type 512 1.1 christos pru_elf32_do_u8_pcrel_relocate (bfd *abfd, reloc_howto_type *howto, 513 1.1 christos asection *input_section, 514 1.1 christos bfd_byte *data, bfd_vma offset, 515 1.1 christos bfd_vma symbol_value, bfd_vma addend) 516 1.1 christos { 517 1.1 christos bfd_vma relocation; 518 1.1 christos 519 1.1 christos BFD_ASSERT (howto->pc_relative); 520 1.1 christos BFD_ASSERT (howto->pcrel_offset); 521 1.1 christos 522 1.1 christos relocation = symbol_value + addend - (input_section->output_section->vma 523 1.1 christos + input_section->output_offset) - offset; 524 1.1 christos relocation >>= howto->rightshift; 525 1.1 christos 526 1.1 christos /* 0 and 1 are invalid target labels for LOOP. We cannot 527 1.1 christos encode this info in HOWTO, so catch such cases here. */ 528 1.1 christos if (relocation < 2) 529 1.1 christos return bfd_reloc_outofrange; 530 1.1 christos 531 1.1 christos return _bfd_final_link_relocate (howto, abfd, input_section, 532 1.1 christos data, offset, symbol_value, addend); 533 1.1 christos } 534 1.1 christos 535 1.1 christos /* Idea and code taken from elf32-d30v. */ 536 1.1 christos static bfd_reloc_status_type 537 1.1 christos pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto, 538 1.1 christos asection *input_section, 539 1.1 christos bfd_byte *data, bfd_vma offset, 540 1.1 christos bfd_vma symbol_value, bfd_vma addend) 541 1.1 christos { 542 1.1.1.3 christos bfd_vma relocation; 543 1.1.1.3 christos bfd_size_type octets = offset * OCTETS_PER_BYTE (abfd, input_section); 544 1.1 christos bfd_byte *location; 545 1.1.1.2 christos unsigned long in1, in2; 546 1.1 christos 547 1.1 christos /* A hacked-up version of _bfd_final_link_relocate() follows. */ 548 1.1 christos 549 1.1 christos /* Sanity check the address. */ 550 1.1 christos if (octets + bfd_get_reloc_size (howto) 551 1.1 christos > bfd_get_section_limit_octets (abfd, input_section)) 552 1.1 christos return bfd_reloc_outofrange; 553 1.1 christos 554 1.1 christos /* This function assumes that we are dealing with a basic relocation 555 1.1 christos against a symbol. We want to compute the value of the symbol to 556 1.1 christos relocate to. This is just VALUE, the value of the symbol, plus 557 1.1 christos ADDEND, any addend associated with the reloc. */ 558 1.1 christos relocation = symbol_value + addend; 559 1.1 christos 560 1.1 christos BFD_ASSERT (!howto->pc_relative); 561 1.1 christos 562 1.1 christos /* A hacked-up version of _bfd_relocate_contents() follows. */ 563 1.1.1.3 christos location = data + octets; 564 1.1 christos 565 1.1 christos BFD_ASSERT (!howto->pc_relative); 566 1.1 christos 567 1.1 christos in1 = bfd_get_32 (abfd, location); 568 1.1 christos in2 = bfd_get_32 (abfd, location + 4); 569 1.1 christos 570 1.1.1.2 christos SET_INSN_FIELD (IMM16, in1, relocation >> 16); 571 1.1.1.2 christos SET_INSN_FIELD (IMM16, in2, relocation & 0xffff); 572 1.1 christos 573 1.1 christos bfd_put_32 (abfd, in1, location); 574 1.1 christos bfd_put_32 (abfd, in2, location + 4); 575 1.1 christos 576 1.1.1.2 christos /* Old GAS and LD versions have a bug, where the two 577 1.1.1.2 christos LDI instructions are swapped. Detect such object 578 1.1.1.2 christos files and bail. */ 579 1.1.1.2 christos if (GET_INSN_FIELD (RDSEL, in1) != RSEL_31_16) 580 1.1.1.2 christos { 581 1.1.1.2 christos /* xgettext:c-format */ 582 1.1.1.2 christos _bfd_error_handler (_("error: %pB: old incompatible object file detected"), 583 1.1.1.2 christos abfd); 584 1.1.1.2 christos return bfd_reloc_notsupported; 585 1.1.1.2 christos } 586 1.1.1.2 christos 587 1.1 christos return bfd_reloc_ok; 588 1.1 christos } 589 1.1 christos 590 1.1 christos /* HOWTO handlers for relocations that require special handling. */ 591 1.1 christos 592 1.1 christos static bfd_reloc_status_type 593 1.1 christos pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry, 594 1.1 christos asymbol *symbol, void *data, 595 1.1 christos asection *input_section, bfd *output_bfd, 596 1.1 christos char **error_message) 597 1.1 christos { 598 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just 599 1.1 christos call the generic function. Any adjustment will be done at final 600 1.1 christos link time. */ 601 1.1 christos if (output_bfd != NULL) 602 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 603 1.1 christos input_section, output_bfd, error_message); 604 1.1 christos 605 1.1.1.2 christos BFD_ASSERT (0); 606 1.1 christos return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto, 607 1.1 christos input_section, 608 1.1 christos data, reloc_entry->address, 609 1.1 christos (symbol->value 610 1.1 christos + symbol->section->output_section->vma 611 1.1 christos + symbol->section->output_offset), 612 1.1 christos reloc_entry->addend); 613 1.1 christos } 614 1.1 christos 615 1.1 christos static bfd_reloc_status_type 616 1.1 christos pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry, 617 1.1 christos asymbol *symbol, void *data, 618 1.1 christos asection *input_section, bfd *output_bfd, 619 1.1 christos char **error_message) 620 1.1 christos { 621 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just 622 1.1 christos call the generic function. Any adjustment will be done at final 623 1.1 christos link time. */ 624 1.1 christos if (output_bfd != NULL) 625 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 626 1.1 christos input_section, output_bfd, error_message); 627 1.1 christos 628 1.1 christos return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto, 629 1.1 christos input_section, data, 630 1.1 christos reloc_entry->address, 631 1.1 christos (symbol->value 632 1.1 christos + symbol->section->output_section->vma 633 1.1 christos + symbol->section->output_offset), 634 1.1 christos reloc_entry->addend); 635 1.1 christos } 636 1.1 christos 637 1.1 christos static bfd_reloc_status_type 638 1.1 christos pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 639 1.1 christos void *data, asection *input_section, 640 1.1 christos bfd *output_bfd, 641 1.1 christos char **error_message) 642 1.1 christos { 643 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just 644 1.1 christos call the generic function. Any adjustment will be done at final 645 1.1 christos link time. */ 646 1.1 christos if (output_bfd != NULL) 647 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 648 1.1 christos input_section, output_bfd, error_message); 649 1.1 christos 650 1.1 christos return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto, 651 1.1 christos input_section, 652 1.1 christos data, reloc_entry->address, 653 1.1 christos (symbol->value 654 1.1 christos + symbol->section->output_section->vma 655 1.1 christos + symbol->section->output_offset), 656 1.1 christos reloc_entry->addend); 657 1.1 christos } 658 1.1 christos 659 1.1 christos static bfd_reloc_status_type 660 1.1 christos pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 661 1.1 christos void *data, asection *input_section, 662 1.1 christos bfd *output_bfd, 663 1.1 christos char **error_message) 664 1.1 christos { 665 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just 666 1.1 christos call the generic function. Any adjustment will be done at final 667 1.1 christos link time. */ 668 1.1 christos if (output_bfd != NULL) 669 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 670 1.1 christos input_section, output_bfd, error_message); 671 1.1 christos 672 1.1 christos return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto, 673 1.1 christos input_section, 674 1.1 christos data, reloc_entry->address, 675 1.1 christos (symbol->value 676 1.1 christos + symbol->section->output_section->vma 677 1.1 christos + symbol->section->output_offset), 678 1.1 christos reloc_entry->addend); 679 1.1 christos } 680 1.1 christos 681 1.1 christos 682 1.1 christos /* Implement elf_backend_relocate_section. */ 683 1.1.1.4 christos static int 684 1.1 christos pru_elf32_relocate_section (bfd *output_bfd, 685 1.1 christos struct bfd_link_info *info, 686 1.1 christos bfd *input_bfd, 687 1.1 christos asection *input_section, 688 1.1 christos bfd_byte *contents, 689 1.1 christos Elf_Internal_Rela *relocs, 690 1.1 christos Elf_Internal_Sym *local_syms, 691 1.1 christos asection **local_sections) 692 1.1 christos { 693 1.1.1.2 christos struct bfd_elf_section_data * esd = elf_section_data (input_section); 694 1.1 christos Elf_Internal_Shdr *symtab_hdr; 695 1.1 christos struct elf_link_hash_entry **sym_hashes; 696 1.1 christos Elf_Internal_Rela *rel; 697 1.1 christos Elf_Internal_Rela *relend; 698 1.1.1.4 christos bool is_rel_reloc; 699 1.1 christos 700 1.1 christos symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 701 1.1 christos sym_hashes = elf_sym_hashes (input_bfd); 702 1.1 christos relend = relocs + input_section->reloc_count; 703 1.1 christos 704 1.1.1.2 christos /* See if we have a REL type relocation. */ 705 1.1.1.2 christos is_rel_reloc = (esd->rel.hdr != NULL); 706 1.1.1.2 christos /* Sanity check - only one type of relocation per section. 707 1.1.1.2 christos FIXME: Theoretically it is possible to have both types, 708 1.1.1.2 christos but if that happens how can we distinguish between the two ? */ 709 1.1.1.2 christos BFD_ASSERT (! is_rel_reloc || ! esd->rela.hdr); 710 1.1.1.2 christos 711 1.1 christos for (rel = relocs; rel < relend; rel++) 712 1.1 christos { 713 1.1 christos reloc_howto_type *howto; 714 1.1 christos unsigned long r_symndx; 715 1.1 christos Elf_Internal_Sym *sym; 716 1.1 christos asection *sec; 717 1.1 christos struct elf_link_hash_entry *h; 718 1.1 christos bfd_vma relocation; 719 1.1 christos bfd_reloc_status_type r = bfd_reloc_ok; 720 1.1 christos const char *name = NULL; 721 1.1 christos const char* msg = (const char*) NULL; 722 1.1.1.4 christos bool unresolved_reloc; 723 1.1.1.2 christos bfd_vma addend; 724 1.1.1.2 christos 725 1.1.1.2 christos /* If we are using a REL relocation then the addend should be empty. */ 726 1.1.1.2 christos BFD_ASSERT (! is_rel_reloc || rel->r_addend == 0); 727 1.1 christos 728 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 729 1.1 christos 730 1.1 christos howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info)); 731 1.1 christos h = NULL; 732 1.1 christos sym = NULL; 733 1.1 christos sec = NULL; 734 1.1 christos 735 1.1 christos if (r_symndx < symtab_hdr->sh_info) 736 1.1 christos { 737 1.1 christos sym = local_syms + r_symndx; 738 1.1 christos sec = local_sections[r_symndx]; 739 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 740 1.1 christos } 741 1.1 christos else 742 1.1 christos { 743 1.1.1.4 christos bool warned, ignored; 744 1.1 christos 745 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 746 1.1 christos r_symndx, symtab_hdr, sym_hashes, 747 1.1 christos h, sec, relocation, 748 1.1 christos unresolved_reloc, warned, ignored); 749 1.1 christos } 750 1.1 christos 751 1.1 christos if (sec && discarded_section (sec)) 752 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 753 1.1 christos rel, 1, relend, howto, 0, contents); 754 1.1 christos 755 1.1 christos /* Nothing more to do unless this is a final link. */ 756 1.1 christos if (bfd_link_relocatable (info)) 757 1.1 christos continue; 758 1.1 christos 759 1.1 christos if (howto) 760 1.1 christos { 761 1.1 christos switch (howto->type) 762 1.1 christos { 763 1.1 christos case R_PRU_NONE: 764 1.1 christos /* We don't need to find a value for this symbol. It's just a 765 1.1 christos marker. */ 766 1.1 christos r = bfd_reloc_ok; 767 1.1 christos break; 768 1.1 christos 769 1.1.1.2 christos case R_PRU_U16: 770 1.1.1.2 christos if (is_rel_reloc) 771 1.1.1.2 christos { 772 1.1.1.2 christos unsigned long insn; 773 1.1.1.2 christos insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 774 1.1.1.2 christos addend = GET_INSN_FIELD (IMM16, insn); 775 1.1.1.2 christos } 776 1.1.1.2 christos else 777 1.1.1.2 christos addend = rel->r_addend; 778 1.1.1.2 christos r = _bfd_final_link_relocate (howto, input_bfd, 779 1.1.1.2 christos input_section, contents, 780 1.1.1.2 christos rel->r_offset, relocation, 781 1.1.1.2 christos addend); 782 1.1.1.2 christos break; 783 1.1.1.2 christos 784 1.1 christos case R_PRU_U16_PMEMIMM: 785 1.1 christos case R_PRU_32_PMEM: 786 1.1 christos case R_PRU_16_PMEM: 787 1.1.1.2 christos if (is_rel_reloc && howto->type == R_PRU_U16_PMEMIMM) 788 1.1.1.2 christos { 789 1.1.1.2 christos unsigned long insn; 790 1.1.1.2 christos insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 791 1.1.1.2 christos addend = GET_INSN_FIELD (IMM16, insn) << 2; 792 1.1.1.2 christos } 793 1.1.1.2 christos else if (is_rel_reloc && howto->type == R_PRU_32_PMEM) 794 1.1.1.2 christos { 795 1.1.1.2 christos addend = bfd_get_32 (input_bfd, contents + rel->r_offset); 796 1.1.1.2 christos addend <<= 2; 797 1.1.1.2 christos } 798 1.1.1.2 christos else if (is_rel_reloc && howto->type == R_PRU_16_PMEM) 799 1.1.1.2 christos { 800 1.1.1.2 christos addend = bfd_get_16 (input_bfd, contents + rel->r_offset); 801 1.1.1.2 christos addend <<= 2; 802 1.1.1.2 christos } 803 1.1.1.2 christos else 804 1.1.1.2 christos { 805 1.1.1.2 christos BFD_ASSERT (!is_rel_reloc); 806 1.1.1.2 christos addend = rel->r_addend; 807 1.1.1.2 christos } 808 1.1 christos r = pru_elf32_do_pmem_relocate (input_bfd, howto, 809 1.1 christos input_section, 810 1.1 christos contents, rel->r_offset, 811 1.1.1.2 christos relocation, addend); 812 1.1 christos break; 813 1.1 christos case R_PRU_S10_PCREL: 814 1.1.1.2 christos BFD_ASSERT (! is_rel_reloc); 815 1.1 christos r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto, 816 1.1 christos input_section, 817 1.1 christos contents, 818 1.1 christos rel->r_offset, 819 1.1 christos relocation, 820 1.1 christos rel->r_addend); 821 1.1 christos break; 822 1.1 christos case R_PRU_U8_PCREL: 823 1.1.1.2 christos BFD_ASSERT (! is_rel_reloc); 824 1.1 christos r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto, 825 1.1 christos input_section, 826 1.1 christos contents, 827 1.1 christos rel->r_offset, 828 1.1 christos relocation, 829 1.1 christos rel->r_addend); 830 1.1 christos break; 831 1.1 christos case R_PRU_LDI32: 832 1.1.1.2 christos if (is_rel_reloc) 833 1.1.1.2 christos { 834 1.1.1.2 christos unsigned long in1, in2; 835 1.1.1.2 christos in1 = bfd_get_32 (input_bfd, contents + rel->r_offset); 836 1.1.1.2 christos in2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); 837 1.1.1.2 christos addend = (GET_INSN_FIELD (IMM16, in1) << 16) 838 1.1.1.2 christos | GET_INSN_FIELD (IMM16, in2); 839 1.1.1.2 christos } 840 1.1.1.2 christos else 841 1.1.1.2 christos { 842 1.1.1.2 christos addend = rel->r_addend; 843 1.1.1.2 christos } 844 1.1 christos r = pru_elf32_do_ldi32_relocate (input_bfd, howto, 845 1.1 christos input_section, 846 1.1 christos contents, 847 1.1 christos rel->r_offset, 848 1.1 christos relocation, 849 1.1.1.2 christos addend); 850 1.1 christos break; 851 1.1 christos case R_PRU_GNU_DIFF8: 852 1.1 christos case R_PRU_GNU_DIFF16: 853 1.1 christos case R_PRU_GNU_DIFF32: 854 1.1 christos case R_PRU_GNU_DIFF16_PMEM: 855 1.1 christos case R_PRU_GNU_DIFF32_PMEM: 856 1.1.1.2 christos /* GNU extensions support only rela. */ 857 1.1.1.2 christos BFD_ASSERT (! is_rel_reloc); 858 1.1 christos /* Nothing to do here, as contents already contain the 859 1.1 christos diff value. */ 860 1.1 christos r = bfd_reloc_ok; 861 1.1 christos break; 862 1.1 christos 863 1.1.1.2 christos case R_PRU_BFD_RELOC_16: 864 1.1.1.2 christos if (is_rel_reloc) 865 1.1.1.2 christos addend = bfd_get_16 (input_bfd, contents + rel->r_offset); 866 1.1.1.2 christos else 867 1.1.1.2 christos addend = rel->r_addend; 868 1.1.1.2 christos r = _bfd_final_link_relocate (howto, input_bfd, 869 1.1.1.2 christos input_section, contents, 870 1.1.1.2 christos rel->r_offset, relocation, 871 1.1.1.2 christos addend); 872 1.1.1.2 christos break; 873 1.1.1.2 christos 874 1.1.1.2 christos case R_PRU_BFD_RELOC_32: 875 1.1.1.2 christos if (is_rel_reloc) 876 1.1.1.2 christos addend = bfd_get_32 (input_bfd, contents + rel->r_offset); 877 1.1.1.2 christos else 878 1.1.1.2 christos addend = rel->r_addend; 879 1.1.1.2 christos r = _bfd_final_link_relocate (howto, input_bfd, 880 1.1.1.2 christos input_section, contents, 881 1.1.1.2 christos rel->r_offset, relocation, 882 1.1.1.2 christos addend); 883 1.1.1.2 christos break; 884 1.1.1.2 christos 885 1.1.1.2 christos case R_PRU_GNU_BFD_RELOC_8: 886 1.1.1.2 christos BFD_ASSERT (! is_rel_reloc); 887 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, 888 1.1 christos input_section, contents, 889 1.1 christos rel->r_offset, relocation, 890 1.1 christos rel->r_addend); 891 1.1 christos break; 892 1.1.1.2 christos 893 1.1.1.2 christos default: 894 1.1.1.2 christos BFD_ASSERT (0); 895 1.1.1.2 christos break; 896 1.1 christos } 897 1.1 christos } 898 1.1 christos else 899 1.1 christos r = bfd_reloc_notsupported; 900 1.1 christos 901 1.1 christos if (r != bfd_reloc_ok) 902 1.1 christos { 903 1.1 christos if (h != NULL) 904 1.1 christos name = h->root.root.string; 905 1.1 christos else 906 1.1 christos { 907 1.1 christos name = bfd_elf_string_from_elf_section (input_bfd, 908 1.1 christos symtab_hdr->sh_link, 909 1.1 christos sym->st_name); 910 1.1 christos if (name == NULL || *name == '\0') 911 1.1.1.3 christos name = bfd_section_name (sec); 912 1.1 christos } 913 1.1 christos 914 1.1 christos switch (r) 915 1.1 christos { 916 1.1 christos case bfd_reloc_overflow: 917 1.1 christos (*info->callbacks->reloc_overflow) (info, NULL, name, 918 1.1 christos howto->name, (bfd_vma) 0, 919 1.1 christos input_bfd, input_section, 920 1.1 christos rel->r_offset); 921 1.1 christos break; 922 1.1 christos 923 1.1 christos case bfd_reloc_undefined: 924 1.1 christos (*info->callbacks->undefined_symbol) (info, name, input_bfd, 925 1.1 christos input_section, 926 1.1.1.4 christos rel->r_offset, true); 927 1.1 christos break; 928 1.1 christos 929 1.1 christos case bfd_reloc_outofrange: 930 1.1 christos if (msg == NULL) 931 1.1 christos msg = _("relocation out of range"); 932 1.1 christos break; 933 1.1 christos 934 1.1 christos case bfd_reloc_notsupported: 935 1.1 christos if (msg == NULL) 936 1.1 christos msg = _("unsupported relocation"); 937 1.1 christos break; 938 1.1 christos 939 1.1 christos case bfd_reloc_dangerous: 940 1.1 christos if (msg == NULL) 941 1.1 christos msg = _("dangerous relocation"); 942 1.1 christos break; 943 1.1 christos 944 1.1 christos default: 945 1.1 christos if (msg == NULL) 946 1.1 christos msg = _("unknown error"); 947 1.1 christos break; 948 1.1 christos } 949 1.1 christos 950 1.1 christos if (msg) 951 1.1 christos { 952 1.1 christos (*info->callbacks->warning) (info, msg, name, input_bfd, 953 1.1 christos input_section, rel->r_offset); 954 1.1.1.4 christos return false; 955 1.1 christos } 956 1.1 christos } 957 1.1 christos } 958 1.1.1.4 christos return true; 959 1.1 christos } 960 1.1 christos 961 1.1 christos 962 1.1 christos /* Perform a diff relocation. Nothing to do, as the difference value is 964 1.1 christos already written into the section's contents. */ 965 1.1 christos 966 1.1 christos static bfd_reloc_status_type 967 1.1 christos bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED, 968 1.1 christos arelent *reloc_entry ATTRIBUTE_UNUSED, 969 1.1 christos asymbol *symbol ATTRIBUTE_UNUSED, 970 1.1 christos void *data ATTRIBUTE_UNUSED, 971 1.1 christos asection *input_section ATTRIBUTE_UNUSED, 972 1.1 christos bfd *output_bfd ATTRIBUTE_UNUSED, 973 1.1 christos char **error_message ATTRIBUTE_UNUSED) 974 1.1 christos { 975 1.1 christos return bfd_reloc_ok; 976 1.1 christos } 977 1.1 christos 978 1.1 christos 979 1.1 christos /* Returns whether the relocation type passed is a diff reloc. */ 980 1.1.1.4 christos 981 1.1 christos static bool 982 1.1 christos elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel) 983 1.1 christos { 984 1.1 christos return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8 985 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16 986 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32 987 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM 988 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM); 989 1.1 christos } 990 1.1 christos 991 1.1 christos /* Reduce the diff value written in the section by count if the shrinked 992 1.1 christos insn address happens to fall between the two symbols for which this 993 1.1 christos diff reloc was emitted. */ 994 1.1 christos 995 1.1 christos static void 996 1.1 christos elf32_pru_adjust_diff_reloc_value (bfd *abfd, 997 1.1 christos struct bfd_section *isec, 998 1.1 christos Elf_Internal_Rela *irel, 999 1.1 christos bfd_vma symval, 1000 1.1 christos bfd_vma shrinked_insn_address, 1001 1.1 christos int count) 1002 1.1 christos { 1003 1.1 christos unsigned char *reloc_contents = NULL; 1004 1.1 christos unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents; 1005 1.1 christos if (isec_contents == NULL) 1006 1.1 christos { 1007 1.1 christos if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents)) 1008 1.1 christos return; 1009 1.1 christos 1010 1.1 christos elf_section_data (isec)->this_hdr.contents = isec_contents; 1011 1.1 christos } 1012 1.1 christos 1013 1.1 christos reloc_contents = isec_contents + irel->r_offset; 1014 1.1 christos 1015 1.1 christos /* Read value written in object file. */ 1016 1.1 christos bfd_signed_vma x = 0; 1017 1.1 christos switch (ELF32_R_TYPE (irel->r_info)) 1018 1.1 christos { 1019 1.1 christos case R_PRU_GNU_DIFF8: 1020 1.1 christos { 1021 1.1 christos x = bfd_get_signed_8 (abfd, reloc_contents); 1022 1.1 christos break; 1023 1.1 christos } 1024 1.1 christos case R_PRU_GNU_DIFF16: 1025 1.1 christos { 1026 1.1 christos x = bfd_get_signed_16 (abfd, reloc_contents); 1027 1.1 christos break; 1028 1.1 christos } 1029 1.1 christos case R_PRU_GNU_DIFF32: 1030 1.1 christos { 1031 1.1 christos x = bfd_get_signed_32 (abfd, reloc_contents); 1032 1.1 christos break; 1033 1.1 christos } 1034 1.1 christos case R_PRU_GNU_DIFF16_PMEM: 1035 1.1 christos { 1036 1.1 christos x = bfd_get_signed_16 (abfd, reloc_contents) * 4; 1037 1.1 christos break; 1038 1.1 christos } 1039 1.1 christos case R_PRU_GNU_DIFF32_PMEM: 1040 1.1 christos { 1041 1.1 christos x = bfd_get_signed_32 (abfd, reloc_contents) * 4; 1042 1.1 christos break; 1043 1.1 christos } 1044 1.1 christos default: 1045 1.1 christos { 1046 1.1 christos BFD_FAIL (); 1047 1.1 christos } 1048 1.1 christos } 1049 1.1 christos 1050 1.1 christos /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written 1051 1.1 christos into the object file at the reloc offset. sym2's logical value is 1052 1.1 christos symval (<start_of_section>) + reloc addend. Compute the start and end 1053 1.1 christos addresses and check if the shrinked insn falls between sym1 and sym2. */ 1054 1.1 christos 1055 1.1 christos bfd_vma end_address = symval + irel->r_addend; 1056 1.1 christos bfd_vma start_address = end_address - x; 1057 1.1 christos 1058 1.1 christos /* Shrink the absolute DIFF value (get the to labels "closer" 1059 1.1 christos together), because we have removed data between labels. */ 1060 1.1 christos if (x < 0) 1061 1.1 christos { 1062 1.1 christos x += count; 1063 1.1 christos /* In case the signed x is negative, restore order. */ 1064 1.1 christos SWAP_VALS (end_address, start_address); 1065 1.1 christos } 1066 1.1 christos else 1067 1.1 christos { 1068 1.1 christos x -= count; 1069 1.1 christos } 1070 1.1 christos 1071 1.1 christos /* Reduce the diff value by count bytes and write it back into section 1072 1.1 christos contents. */ 1073 1.1 christos 1074 1.1 christos if (shrinked_insn_address >= start_address 1075 1.1 christos && shrinked_insn_address <= end_address) 1076 1.1 christos { 1077 1.1 christos switch (ELF32_R_TYPE (irel->r_info)) 1078 1.1 christos { 1079 1.1 christos case R_PRU_GNU_DIFF8: 1080 1.1 christos { 1081 1.1 christos bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents); 1082 1.1 christos break; 1083 1.1 christos } 1084 1.1 christos case R_PRU_GNU_DIFF16: 1085 1.1 christos { 1086 1.1 christos bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents); 1087 1.1 christos break; 1088 1.1 christos } 1089 1.1 christos case R_PRU_GNU_DIFF32: 1090 1.1 christos { 1091 1.1 christos bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents); 1092 1.1 christos break; 1093 1.1 christos } 1094 1.1 christos case R_PRU_GNU_DIFF16_PMEM: 1095 1.1 christos { 1096 1.1 christos bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents); 1097 1.1 christos break; 1098 1.1 christos } 1099 1.1 christos case R_PRU_GNU_DIFF32_PMEM: 1100 1.1 christos { 1101 1.1 christos bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents); 1102 1.1 christos break; 1103 1.1 christos } 1104 1.1 christos default: 1105 1.1 christos { 1106 1.1 christos BFD_FAIL (); 1107 1.1 christos } 1108 1.1 christos } 1109 1.1 christos 1110 1.1 christos } 1111 1.1 christos } 1112 1.1 christos 1113 1.1 christos /* Delete some bytes from a section while changing the size of an instruction. 1114 1.1 christos The parameter "addr" denotes the section-relative offset pointing just 1115 1.1 christos behind the shrinked instruction. "addr+count" point at the first 1116 1.1 christos byte just behind the original unshrinked instruction. 1117 1.1 christos 1118 1.1 christos Idea copied from the AVR port. */ 1119 1.1.1.4 christos 1120 1.1 christos static bool 1121 1.1 christos pru_elf_relax_delete_bytes (bfd *abfd, 1122 1.1 christos asection *sec, 1123 1.1 christos bfd_vma addr, 1124 1.1 christos int count) 1125 1.1 christos { 1126 1.1 christos Elf_Internal_Shdr *symtab_hdr; 1127 1.1 christos unsigned int sec_shndx; 1128 1.1 christos bfd_byte *contents; 1129 1.1 christos Elf_Internal_Rela *irel, *irelend; 1130 1.1 christos Elf_Internal_Sym *isym; 1131 1.1 christos Elf_Internal_Sym *isymbuf = NULL; 1132 1.1 christos bfd_vma toaddr; 1133 1.1 christos struct elf_link_hash_entry **sym_hashes; 1134 1.1 christos struct elf_link_hash_entry **end_hashes; 1135 1.1 christos unsigned int symcount; 1136 1.1 christos 1137 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 1138 1.1 christos sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); 1139 1.1 christos contents = elf_section_data (sec)->this_hdr.contents; 1140 1.1 christos 1141 1.1 christos toaddr = sec->size; 1142 1.1 christos 1143 1.1 christos irel = elf_section_data (sec)->relocs; 1144 1.1 christos irelend = irel + sec->reloc_count; 1145 1.1 christos 1146 1.1 christos /* Actually delete the bytes. */ 1147 1.1 christos if (toaddr - addr - count > 0) 1148 1.1 christos memmove (contents + addr, contents + addr + count, 1149 1.1 christos (size_t) (toaddr - addr - count)); 1150 1.1 christos sec->size -= count; 1151 1.1 christos 1152 1.1 christos /* Adjust all the reloc addresses. */ 1153 1.1 christos for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) 1154 1.1 christos { 1155 1.1 christos bfd_vma old_reloc_address; 1156 1.1 christos 1157 1.1 christos old_reloc_address = (sec->output_section->vma 1158 1.1 christos + sec->output_offset + irel->r_offset); 1159 1.1 christos 1160 1.1 christos /* Get the new reloc address. */ 1161 1.1 christos if ((irel->r_offset > addr 1162 1.1 christos && irel->r_offset < toaddr)) 1163 1.1 christos { 1164 1.1 christos if (debug_relax) 1165 1.1 christos printf ("Relocation at address 0x%x needs to be moved.\n" 1166 1.1 christos "Old section offset: 0x%x, New section offset: 0x%x \n", 1167 1.1 christos (unsigned int) old_reloc_address, 1168 1.1 christos (unsigned int) irel->r_offset, 1169 1.1 christos (unsigned int) ((irel->r_offset) - count)); 1170 1.1 christos 1171 1.1 christos irel->r_offset -= count; 1172 1.1 christos } 1173 1.1 christos 1174 1.1 christos } 1175 1.1 christos 1176 1.1 christos /* The reloc's own addresses are now ok. However, we need to readjust 1177 1.1 christos the reloc's addend, i.e. the reloc's value if two conditions are met: 1178 1.1 christos 1.) the reloc is relative to a symbol in this section that 1179 1.1 christos is located in front of the shrinked instruction 1180 1.1 christos 2.) symbol plus addend end up behind the shrinked instruction. 1181 1.1 christos 1182 1.1 christos The most common case where this happens are relocs relative to 1183 1.1 christos the section-start symbol. 1184 1.1 christos 1185 1.1 christos This step needs to be done for all of the sections of the bfd. */ 1186 1.1 christos 1187 1.1 christos { 1188 1.1 christos struct bfd_section *isec; 1189 1.1 christos 1190 1.1 christos for (isec = abfd->sections; isec; isec = isec->next) 1191 1.1 christos { 1192 1.1 christos bfd_vma symval; 1193 1.1 christos bfd_vma shrinked_insn_address; 1194 1.1 christos 1195 1.1 christos if (isec->reloc_count == 0) 1196 1.1 christos continue; 1197 1.1 christos 1198 1.1.1.2 christos shrinked_insn_address = (sec->output_section->vma 1199 1.1 christos + sec->output_offset + addr); 1200 1.1 christos 1201 1.1 christos irel = elf_section_data (isec)->relocs; 1202 1.1 christos /* PR 12161: Read in the relocs for this section if necessary. */ 1203 1.1.1.4 christos if (irel == NULL) 1204 1.1 christos irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true); 1205 1.1 christos 1206 1.1 christos for (irelend = irel + isec->reloc_count; 1207 1.1 christos irel < irelend; 1208 1.1 christos irel++) 1209 1.1 christos { 1210 1.1 christos /* Read this BFD's local symbols if we haven't done 1211 1.1 christos so already. */ 1212 1.1 christos if (isymbuf == NULL && symtab_hdr->sh_info != 0) 1213 1.1 christos { 1214 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 1215 1.1 christos if (isymbuf == NULL) 1216 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 1217 1.1 christos symtab_hdr->sh_info, 0, 1218 1.1 christos NULL, NULL, NULL); 1219 1.1.1.4 christos if (isymbuf == NULL) 1220 1.1 christos return false; 1221 1.1 christos } 1222 1.1 christos 1223 1.1 christos /* Get the value of the symbol referred to by the reloc. */ 1224 1.1 christos if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 1225 1.1 christos { 1226 1.1 christos /* A local symbol. */ 1227 1.1 christos asection *sym_sec; 1228 1.1 christos 1229 1.1 christos isym = isymbuf + ELF32_R_SYM (irel->r_info); 1230 1.1 christos sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 1231 1.1 christos symval = isym->st_value; 1232 1.1 christos /* If the reloc is absolute, it will not have 1233 1.1 christos a symbol or section associated with it. */ 1234 1.1 christos if (sym_sec == sec) 1235 1.1 christos { 1236 1.1 christos symval += sym_sec->output_section->vma 1237 1.1 christos + sym_sec->output_offset; 1238 1.1 christos 1239 1.1 christos if (debug_relax) 1240 1.1 christos printf ("Checking if the relocation's " 1241 1.1 christos "addend needs corrections.\n" 1242 1.1 christos "Address of anchor symbol: 0x%x \n" 1243 1.1 christos "Address of relocation target: 0x%x \n" 1244 1.1 christos "Address of relaxed insn: 0x%x \n", 1245 1.1 christos (unsigned int) symval, 1246 1.1 christos (unsigned int) (symval + irel->r_addend), 1247 1.1 christos (unsigned int) shrinked_insn_address); 1248 1.1 christos 1249 1.1 christos /* Shrink the special DIFF relocations. */ 1250 1.1 christos if (elf32_pru_is_diff_reloc (irel)) 1251 1.1 christos { 1252 1.1 christos elf32_pru_adjust_diff_reloc_value (abfd, isec, irel, 1253 1.1 christos symval, 1254 1.1 christos shrinked_insn_address, 1255 1.1 christos count); 1256 1.1 christos } 1257 1.1 christos 1258 1.1 christos /* Fix the addend, if it is affected. */ 1259 1.1 christos if (symval <= shrinked_insn_address 1260 1.1 christos && (symval + irel->r_addend) > shrinked_insn_address) 1261 1.1 christos { 1262 1.1 christos 1263 1.1 christos irel->r_addend -= count; 1264 1.1 christos 1265 1.1 christos if (debug_relax) 1266 1.1 christos printf ("Relocation's addend needed to be fixed \n"); 1267 1.1 christos } 1268 1.1 christos } 1269 1.1 christos /* else...Reference symbol is absolute. 1270 1.1 christos No adjustment needed. */ 1271 1.1 christos } 1272 1.1 christos /* else...Reference symbol is extern. No need for adjusting 1273 1.1 christos the addend. */ 1274 1.1 christos } 1275 1.1 christos } 1276 1.1 christos } 1277 1.1 christos 1278 1.1 christos /* Adjust the local symbols defined in this section. */ 1279 1.1 christos isym = (Elf_Internal_Sym *) symtab_hdr->contents; 1280 1.1 christos /* Fix PR 9841, there may be no local symbols. */ 1281 1.1 christos if (isym != NULL) 1282 1.1 christos { 1283 1.1 christos Elf_Internal_Sym *isymend; 1284 1.1 christos 1285 1.1 christos isymend = isym + symtab_hdr->sh_info; 1286 1.1 christos for (; isym < isymend; isym++) 1287 1.1 christos { 1288 1.1 christos if (isym->st_shndx == sec_shndx) 1289 1.1 christos { 1290 1.1 christos if (isym->st_value > addr 1291 1.1 christos && isym->st_value <= toaddr) 1292 1.1 christos isym->st_value -= count; 1293 1.1 christos 1294 1.1 christos if (isym->st_value <= addr 1295 1.1 christos && isym->st_value + isym->st_size > addr) 1296 1.1 christos { 1297 1.1 christos /* If this assert fires then we have a symbol that ends 1298 1.1 christos part way through an instruction. Does that make 1299 1.1 christos sense? */ 1300 1.1 christos BFD_ASSERT (isym->st_value + isym->st_size >= addr + count); 1301 1.1 christos isym->st_size -= count; 1302 1.1 christos } 1303 1.1 christos } 1304 1.1 christos } 1305 1.1 christos } 1306 1.1 christos 1307 1.1 christos /* Now adjust the global symbols defined in this section. */ 1308 1.1 christos symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) 1309 1.1 christos - symtab_hdr->sh_info); 1310 1.1 christos sym_hashes = elf_sym_hashes (abfd); 1311 1.1 christos end_hashes = sym_hashes + symcount; 1312 1.1 christos for (; sym_hashes < end_hashes; sym_hashes++) 1313 1.1 christos { 1314 1.1 christos struct elf_link_hash_entry *sym_hash = *sym_hashes; 1315 1.1 christos if ((sym_hash->root.type == bfd_link_hash_defined 1316 1.1 christos || sym_hash->root.type == bfd_link_hash_defweak) 1317 1.1 christos && sym_hash->root.u.def.section == sec) 1318 1.1 christos { 1319 1.1 christos if (sym_hash->root.u.def.value > addr 1320 1.1 christos && sym_hash->root.u.def.value <= toaddr) 1321 1.1 christos sym_hash->root.u.def.value -= count; 1322 1.1 christos 1323 1.1 christos if (sym_hash->root.u.def.value <= addr 1324 1.1 christos && (sym_hash->root.u.def.value + sym_hash->size > addr)) 1325 1.1 christos { 1326 1.1 christos /* If this assert fires then we have a symbol that ends 1327 1.1 christos part way through an instruction. Does that make 1328 1.1 christos sense? */ 1329 1.1 christos BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size 1330 1.1 christos >= addr + count); 1331 1.1 christos sym_hash->size -= count; 1332 1.1 christos } 1333 1.1 christos } 1334 1.1 christos } 1335 1.1.1.4 christos 1336 1.1 christos return true; 1337 1.1 christos } 1338 1.1.1.4 christos 1339 1.1.1.4 christos static bool 1340 1.1.1.4 christos pru_elf32_relax_section (bfd *abfd, asection *sec, 1341 1.1.1.4 christos struct bfd_link_info *link_info, 1342 1.1 christos bool *again) 1343 1.1 christos { 1344 1.1 christos Elf_Internal_Shdr * symtab_hdr; 1345 1.1 christos Elf_Internal_Rela * internal_relocs; 1346 1.1 christos Elf_Internal_Rela * irel; 1347 1.1 christos Elf_Internal_Rela * irelend; 1348 1.1 christos bfd_byte * contents = NULL; 1349 1.1 christos Elf_Internal_Sym * isymbuf = NULL; 1350 1.1 christos 1351 1.1.1.4 christos /* Assume nothing changes. */ 1352 1.1 christos *again = false; 1353 1.1 christos 1354 1.1 christos /* We don't have to do anything for a relocatable link, if 1355 1.1 christos this section does not have relocs, or if this is not a 1356 1.1 christos code section. */ 1357 1.1.1.5 christos if (bfd_link_relocatable (link_info) 1358 1.1.1.5 christos || sec->reloc_count == 0 1359 1.1.1.5 christos || (sec->flags & SEC_RELOC) == 0 1360 1.1.1.5 christos || (sec->flags & SEC_HAS_CONTENTS) == 0 1361 1.1.1.4 christos || (sec->flags & SEC_CODE) == 0) 1362 1.1 christos return true; 1363 1.1 christos 1364 1.1 christos symtab_hdr = & elf_tdata (abfd)->symtab_hdr; 1365 1.1 christos 1366 1.1 christos /* Get a copy of the native relocations. */ 1367 1.1 christos internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, 1368 1.1 christos link_info->keep_memory); 1369 1.1 christos if (internal_relocs == NULL) 1370 1.1 christos goto error_return; 1371 1.1 christos 1372 1.1 christos /* Walk through them looking for relaxing opportunities. */ 1373 1.1 christos irelend = internal_relocs + sec->reloc_count; 1374 1.1 christos 1375 1.1 christos for (irel = internal_relocs; irel < irelend; irel++) 1376 1.1 christos { 1377 1.1 christos bfd_vma symval; 1378 1.1 christos 1379 1.1 christos /* Get the section contents if we haven't done so already. */ 1380 1.1 christos if (contents == NULL) 1381 1.1 christos { 1382 1.1 christos /* Get cached copy if it exists. */ 1383 1.1 christos if (elf_section_data (sec)->this_hdr.contents != NULL) 1384 1.1 christos contents = elf_section_data (sec)->this_hdr.contents; 1385 1.1 christos else if (! bfd_malloc_and_get_section (abfd, sec, &contents)) 1386 1.1 christos goto error_return; 1387 1.1 christos } 1388 1.1 christos 1389 1.1 christos /* Read this BFD's local symbols if we haven't done so already. */ 1390 1.1 christos if (isymbuf == NULL && symtab_hdr->sh_info != 0) 1391 1.1 christos { 1392 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 1393 1.1 christos if (isymbuf == NULL) 1394 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 1395 1.1 christos symtab_hdr->sh_info, 0, 1396 1.1 christos NULL, NULL, NULL); 1397 1.1 christos if (isymbuf == NULL) 1398 1.1 christos goto error_return; 1399 1.1 christos } 1400 1.1 christos 1401 1.1 christos /* Get the value of the symbol referred to by the reloc. */ 1402 1.1 christos if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 1403 1.1 christos { 1404 1.1 christos /* A local symbol. */ 1405 1.1 christos Elf_Internal_Sym *isym; 1406 1.1 christos asection *sym_sec; 1407 1.1 christos 1408 1.1 christos isym = isymbuf + ELF32_R_SYM (irel->r_info); 1409 1.1 christos if (isym->st_shndx == SHN_UNDEF) 1410 1.1 christos sym_sec = bfd_und_section_ptr; 1411 1.1 christos else if (isym->st_shndx == SHN_ABS) 1412 1.1 christos sym_sec = bfd_abs_section_ptr; 1413 1.1 christos else if (isym->st_shndx == SHN_COMMON) 1414 1.1 christos sym_sec = bfd_com_section_ptr; 1415 1.1 christos else 1416 1.1 christos sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 1417 1.1 christos symval = (isym->st_value 1418 1.1 christos + sym_sec->output_section->vma + sym_sec->output_offset); 1419 1.1 christos } 1420 1.1 christos else 1421 1.1 christos { 1422 1.1 christos unsigned long indx; 1423 1.1 christos struct elf_link_hash_entry *h; 1424 1.1 christos 1425 1.1 christos /* An external symbol. */ 1426 1.1 christos indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; 1427 1.1 christos h = elf_sym_hashes (abfd)[indx]; 1428 1.1 christos BFD_ASSERT (h != NULL); 1429 1.1 christos 1430 1.1 christos if (h->root.type != bfd_link_hash_defined 1431 1.1 christos && h->root.type != bfd_link_hash_defweak) 1432 1.1 christos /* This appears to be a reference to an undefined 1433 1.1 christos symbol. Just ignore it--it will be caught by the 1434 1.1 christos regular reloc processing. */ 1435 1.1 christos continue; 1436 1.1 christos 1437 1.1 christos symval = (h->root.u.def.value 1438 1.1 christos + h->root.u.def.section->output_section->vma 1439 1.1 christos + h->root.u.def.section->output_offset); 1440 1.1 christos } 1441 1.1 christos 1442 1.1 christos /* For simplicity of coding, we are going to modify the section 1443 1.1 christos contents, the section relocs, and the BFD symbol table. We 1444 1.1 christos must tell the rest of the code not to free up this 1445 1.1 christos information. It would be possible to instead create a table 1446 1.1 christos of changes which have to be made, as is done in coff-mips.c; 1447 1.1 christos that would be more work, but would require less memory when 1448 1.1 christos the linker is run. */ 1449 1.1 christos 1450 1.1 christos /* Check if we can remove an LDI instruction from the LDI32 1451 1.1 christos pseudo instruction if the upper 16 operand bits are zero. */ 1452 1.1 christos if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32) 1453 1.1 christos { 1454 1.1 christos bfd_vma value = symval + irel->r_addend; 1455 1.1 christos 1456 1.1 christos if (debug_relax) 1457 1.1 christos printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value); 1458 1.1 christos 1459 1.1 christos if ((long) value >> 16 == 0) 1460 1.1.1.2 christos { 1461 1.1.1.2 christos unsigned long insn; 1462 1.1 christos 1463 1.1 christos /* Note that we've changed the relocs, section contents. */ 1464 1.1 christos elf_section_data (sec)->relocs = internal_relocs; 1465 1.1 christos elf_section_data (sec)->this_hdr.contents = contents; 1466 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf; 1467 1.1.1.2 christos 1468 1.1.1.2 christos /* Make the second instruction load the 16-bit constant 1469 1.1.1.2 christos into the full 32-bit register. */ 1470 1.1.1.2 christos insn = bfd_get_32 (abfd, contents + irel->r_offset + 4); 1471 1.1.1.2 christos 1472 1.1.1.2 christos /* Old GAS and LD versions have a bug, where the two 1473 1.1.1.2 christos LDI instructions are swapped. Detect such object 1474 1.1.1.2 christos files and bail. */ 1475 1.1.1.2 christos if (GET_INSN_FIELD (RDSEL, insn) != RSEL_15_0) 1476 1.1.1.2 christos { 1477 1.1.1.2 christos /* xgettext:c-format */ 1478 1.1.1.2 christos _bfd_error_handler (_("error: %pB: old incompatible object file detected"), 1479 1.1.1.2 christos abfd); 1480 1.1.1.2 christos goto error_return; 1481 1.1.1.2 christos } 1482 1.1.1.2 christos 1483 1.1.1.2 christos SET_INSN_FIELD (RDSEL, insn, RSEL_31_0); 1484 1.1.1.2 christos bfd_put_32 (abfd, insn, contents + irel->r_offset + 4); 1485 1.1.1.2 christos 1486 1.1.1.2 christos /* Delete the first LDI instruction. Note that there should 1487 1.1.1.2 christos be no relocations or symbols pointing to the second LDI 1488 1.1.1.2 christos instruction. */ 1489 1.1 christos if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 4)) 1490 1.1 christos goto error_return; 1491 1.1.1.2 christos 1492 1.1.1.2 christos /* We're done with deletion of the first instruction. 1493 1.1 christos Set a regular LDI relocation for the second instruction 1494 1.1 christos we left to load the 16-bit value into the 32-bit 1495 1.1 christos register. */ 1496 1.1 christos irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1497 1.1 christos R_PRU_U16); 1498 1.1 christos 1499 1.1 christos /* That will change things, so, we should relax again. 1500 1.1.1.4 christos Note that this is not required, and it may be slow. */ 1501 1.1 christos *again = true; 1502 1.1 christos } 1503 1.1 christos } 1504 1.1 christos } 1505 1.1 christos 1506 1.1 christos if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) 1507 1.1 christos { 1508 1.1 christos if (!link_info->keep_memory) 1509 1.1 christos free (isymbuf); 1510 1.1 christos else 1511 1.1 christos { 1512 1.1 christos /* Cache the symbols for elf_link_input_bfd. */ 1513 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf; 1514 1.1 christos } 1515 1.1 christos } 1516 1.1 christos 1517 1.1 christos if (contents != NULL 1518 1.1 christos && elf_section_data (sec)->this_hdr.contents != contents) 1519 1.1 christos { 1520 1.1 christos if (!link_info->keep_memory) 1521 1.1 christos free (contents); 1522 1.1 christos else 1523 1.1 christos { 1524 1.1 christos /* Cache the section contents for elf_link_input_bfd. */ 1525 1.1 christos elf_section_data (sec)->this_hdr.contents = contents; 1526 1.1 christos } 1527 1.1 christos } 1528 1.1.1.3 christos 1529 1.1 christos if (elf_section_data (sec)->relocs != internal_relocs) 1530 1.1 christos free (internal_relocs); 1531 1.1.1.4 christos 1532 1.1 christos return true; 1533 1.1.1.3 christos 1534 1.1.1.3 christos error_return: 1535 1.1 christos if (symtab_hdr->contents != (unsigned char *) isymbuf) 1536 1.1.1.3 christos free (isymbuf); 1537 1.1 christos if (elf_section_data (sec)->this_hdr.contents != contents) 1538 1.1.1.3 christos free (contents); 1539 1.1 christos if (elf_section_data (sec)->relocs != internal_relocs) 1540 1.1 christos free (internal_relocs); 1541 1.1.1.4 christos 1542 1.1 christos return false; 1543 1.1 christos } 1544 1.1 christos 1545 1.1 christos /* Free the derived linker hash table. */ 1546 1.1 christos static void 1547 1.1 christos pru_elf32_link_hash_table_free (bfd *obfd) 1548 1.1 christos { 1549 1.1 christos _bfd_elf_link_hash_table_free (obfd); 1550 1.1 christos } 1551 1.1 christos 1552 1.1 christos /* Implement bfd_elf32_bfd_link_hash_table_create. */ 1553 1.1 christos static struct bfd_link_hash_table * 1554 1.1 christos pru_elf32_link_hash_table_create (bfd *abfd) 1555 1.1 christos { 1556 1.1.1.3 christos struct elf_link_hash_table *ret; 1557 1.1 christos size_t amt = sizeof (struct elf_link_hash_table); 1558 1.1 christos 1559 1.1 christos ret = bfd_zmalloc (amt); 1560 1.1 christos if (ret == NULL) 1561 1.1 christos return NULL; 1562 1.1.1.6 christos 1563 1.1.1.6 christos if (!_bfd_elf_link_hash_table_init (ret, abfd, link_hash_newfunc, 1564 1.1 christos sizeof (struct elf_link_hash_entry))) 1565 1.1 christos { 1566 1.1 christos free (ret); 1567 1.1 christos return NULL; 1568 1.1 christos } 1569 1.1 christos 1570 1.1 christos ret->root.hash_table_free = pru_elf32_link_hash_table_free; 1571 1.1 christos 1572 1.1 christos return &ret->root; 1573 1.1 christos } 1574 1.1 christos 1575 1.1 christos #define ELF_ARCH bfd_arch_pru 1576 1.1 christos #define ELF_TARGET_ID PRU_ELF_DATA 1577 1.1 christos #define ELF_MACHINE_CODE EM_TI_PRU 1578 1.1 christos 1579 1.1 christos #define ELF_MAXPAGESIZE 1 1580 1.1 christos 1581 1.1 christos #define bfd_elf32_bfd_link_hash_table_create \ 1582 1.1 christos pru_elf32_link_hash_table_create 1583 1.1 christos 1584 1.1 christos /* Relocation table lookup macros. */ 1585 1.1 christos 1586 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup 1587 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup 1588 1.1 christos 1589 1.1.1.2 christos #define elf_info_to_howto pru_elf32_info_to_howto 1590 1.1 christos #define elf_info_to_howto_rel NULL 1591 1.1 christos 1592 1.1 christos /* elf backend functions. */ 1593 1.1.1.2 christos 1594 1.1.1.2 christos /* TI folks like to use a mix of REL and RELA relocations. See also 1595 1.1.1.2 christos the MSP430 and TI C6X backends. */ 1596 1.1.1.2 christos #define elf_backend_may_use_rel_p 1 1597 1.1.1.2 christos #define elf_backend_may_use_rela_p 1 1598 1.1.1.2 christos #define elf_backend_default_use_rela_p 1 1599 1.1 christos 1600 1.1 christos #define elf_backend_rela_normal 1 1601 1.1 christos 1602 1.1 christos #define elf_backend_relocate_section pru_elf32_relocate_section 1603 1.1.1.4 christos #define bfd_elf32_bfd_relax_section pru_elf32_relax_section 1604 1.1.1.4 christos #define elf_backend_can_gc_sections 1 1605 1.1.1.4 christos 1606 1.1 christos #define elf_backend_default_execstack 0 1607 1.1 christos 1608 1.1 christos #define TARGET_LITTLE_SYM pru_elf32_vec 1609 1.1 christos #define TARGET_LITTLE_NAME "elf32-pru" 1610 1.1 christos 1611 #include "elf32-target.h" 1612