1 1.1 christos /* Adapteva epiphany specific support for 32-bit ELF 2 1.10 christos Copyright (C) 2000-2025 Free Software Foundation, Inc. 3 1.1 christos Contributed by Embecosm on behalf of Adapteva, Inc. 4 1.1 christos 5 1.1 christos This file is part of BFD, the Binary File Descriptor library. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program; if not, write to the Free Software 19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 1.1 christos MA 02110-1301, USA. */ 21 1.1 christos 22 1.1 christos #include "sysdep.h" 23 1.1 christos #include "bfd.h" 24 1.1 christos #include "libbfd.h" 25 1.1 christos #include "elf-bfd.h" 26 1.1 christos #include "elf/epiphany.h" 27 1.1 christos #include "libiberty.h" 28 1.1 christos 29 1.1 christos /* Struct used to pass miscellaneous paramaters which 30 1.1 christos helps to avoid overly long parameter lists. */ 31 1.1 christos struct misc 32 1.1 christos { 33 1.1 christos Elf_Internal_Shdr * symtab_hdr; 34 1.1 christos Elf_Internal_Rela * irelbase; 35 1.6 christos bfd_byte * contents; 36 1.1 christos Elf_Internal_Sym * isymbuf; 37 1.1 christos }; 38 1.1 christos 39 1.1 christos struct epiphany_opcode 40 1.1 christos { 41 1.1 christos unsigned short opcode; 42 1.1 christos unsigned short mask; 43 1.1 christos }; 44 1.1 christos 45 1.8 christos static bool epiphany_relaxed = false; 46 1.1 christos 47 1.1 christos /* Relocation tables. */ 48 1.1 christos static reloc_howto_type epiphany_elf_howto_table [] = 49 1.1 christos { 50 1.1 christos #define AHOW(t,rs,s,bs,pr,bp,co,name,sm,dm) \ 51 1.6 christos HOWTO(t, /* type */ \ 52 1.6 christos rs, /* rightshift */ \ 53 1.8 christos s, /* size */ \ 54 1.6 christos bs, /* bitsize */ \ 55 1.6 christos pr, /* pc_relative */ \ 56 1.6 christos bp, /* bitpos */ \ 57 1.1 christos co, /* complain_on_overflow */ \ 58 1.1 christos bfd_elf_generic_reloc,/* special_function */ \ 59 1.6 christos name, /* name */ \ 60 1.8 christos false, /* partial_inplace */ \ 61 1.6 christos sm, /* src_mask */ \ 62 1.6 christos dm, /* dst_mask */ \ 63 1.6 christos pr) /* pcrel_offset */ 64 1.1 christos 65 1.1 christos /* This reloc does nothing. */ 66 1.8 christos AHOW (R_EPIPHANY_NONE, 0, 0,0, false, 0, complain_overflow_dont, "R_EPIPHANY_NONE", 0, 0), 67 1.1 christos 68 1.1 christos /* 8 bit absolute (not likely) */ 69 1.8 christos AHOW (R_EPIPHANY_8, 0, 1, 8, false, 0, complain_overflow_bitfield, "R_EPIPHANY_8", 0x000000ff, 0x000000ff), 70 1.1 christos /* 16 bit absolute */ 71 1.8 christos AHOW (R_EPIPHANY_16, 0, 2,16, false, 0, complain_overflow_bitfield, "R_EPIPHANY_16", 0x0000ffff, 0x00ff1fe0), 72 1.1 christos /* A 32 bit absolute relocation. */ 73 1.8 christos AHOW (R_EPIPHANY_32, 0, 4,32, false, 0, complain_overflow_dont, "R_EPIPHANY_32", 0xffffffff, 0xffffffff), 74 1.1 christos 75 1.1 christos /* 8 bit relative relocation */ 76 1.8 christos HOWTO ( R_EPIPHANY_8_PCREL, 0, 1, 8, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", false, 0x000000ff, 0x000000ff, false), 77 1.1 christos /* 16 bit relative relocation */ 78 1.8 christos HOWTO ( R_EPIPHANY_16_PCREL, 0, 2, 16, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", false, 0x000000ff, 0x000000ff, false), 79 1.1 christos /* 32 bit relative relocation */ 80 1.8 christos HOWTO ( R_EPIPHANY_32_PCREL, 0, 4, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", false, 0x000000ff, 0x000000ff, false), 81 1.1 christos 82 1.1 christos /* 8 bit pc-relative relocation */ 83 1.8 christos AHOW (R_EPIPHANY_SIMM8, 1, 1, 8, true, 8, complain_overflow_signed, "R_EPIPHANY_SIMM8", 0x000000ff, 0x0000ff00), 84 1.1 christos /* 24 bit pc-relative relocation */ 85 1.8 christos AHOW (R_EPIPHANY_SIMM24, 1, 4,24, true, 8, complain_overflow_signed, "R_EPIPHANY_SIMM24", 0x00ffffff, 0xffffff00), 86 1.1 christos 87 1.1 christos /* %HIGH(EA) */ 88 1.8 christos AHOW (R_EPIPHANY_HIGH, 0, 4,16, false, 0, complain_overflow_dont, "R_EPIPHANY_HIGH", 0x0ff01fe0, 0x0ff01fe0), 89 1.1 christos 90 1.1 christos /* %LOW(EA) */ 91 1.8 christos AHOW (R_EPIPHANY_LOW, 0, 4,16, false, 0, complain_overflow_dont, "R_EPIPHANY_LOW", 0x0ff01fe0, 0x0ff01fe0), 92 1.1 christos 93 1.1 christos /* simm11 */ 94 1.8 christos AHOW (R_EPIPHANY_SIMM11, 0, 4,11, false, 0, complain_overflow_bitfield, "R_EPIPHANY_SIMM11", 0x00ff0380, 0x00ff0380), 95 1.1 christos /* imm12 - sign-magnitude */ 96 1.8 christos AHOW (R_EPIPHANY_IMM11, 0, 4,11, false, 0, complain_overflow_bitfield, "R_EPIPHANY_IMM12", 0x00ff0380, 0x00ff0380), 97 1.1 christos /* imm8 */ 98 1.8 christos AHOW (R_EPIPHANY_IMM8, 0, 2, 8, false, 8, complain_overflow_signed, "R_EPIPHANY_IMM8", 0x0000ff00, 0x0000ff00) 99 1.1 christos 100 1.1 christos 101 1.1 christos }; 102 1.1 christos #undef AHOW 103 1.1 christos 104 1.1 christos /* Map BFD reloc types to EPIPHANY ELF reloc types. */ 105 1.1 christos 106 1.1 christos static reloc_howto_type * 107 1.1 christos epiphany_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, 108 1.1 christos bfd_reloc_code_real_type code) 109 1.1 christos { 110 1.1 christos /* Note that the epiphany_elf_howto_table is indxed by the R_ 111 1.1 christos constants. Thus, the order that the howto records appear in the 112 1.1 christos table *must* match the order of the relocation types defined in 113 1.1 christos include/elf/epiphany.h. */ 114 1.1 christos 115 1.1 christos switch (code) 116 1.1 christos { 117 1.1 christos case BFD_RELOC_NONE: 118 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_NONE]; 119 1.1 christos 120 1.1 christos case BFD_RELOC_EPIPHANY_SIMM8: 121 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM8]; 122 1.1 christos case BFD_RELOC_EPIPHANY_SIMM24: 123 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM24]; 124 1.1 christos 125 1.1 christos case BFD_RELOC_8_PCREL: 126 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8_PCREL]; 127 1.1 christos case BFD_RELOC_16_PCREL: 128 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16_PCREL]; 129 1.1 christos case BFD_RELOC_32_PCREL: 130 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32_PCREL]; 131 1.1 christos 132 1.1 christos case BFD_RELOC_8: 133 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8]; 134 1.1 christos case BFD_RELOC_16: 135 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16]; 136 1.1 christos case BFD_RELOC_32: 137 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32]; 138 1.1 christos 139 1.1 christos case BFD_RELOC_EPIPHANY_HIGH: 140 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_HIGH]; 141 1.1 christos case BFD_RELOC_EPIPHANY_LOW: 142 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_LOW]; 143 1.1 christos 144 1.1 christos case BFD_RELOC_EPIPHANY_SIMM11: 145 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM11]; 146 1.1 christos case BFD_RELOC_EPIPHANY_IMM11: 147 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM11]; 148 1.1 christos 149 1.1 christos case BFD_RELOC_EPIPHANY_IMM8: 150 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM8]; 151 1.1 christos 152 1.1 christos default: 153 1.1 christos /* Pacify gcc -Wall. */ 154 1.1 christos return NULL; 155 1.1 christos } 156 1.1 christos return NULL; 157 1.1 christos } 158 1.1 christos 159 1.1 christos static reloc_howto_type * 160 1.1 christos epiphany_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 161 1.1 christos { 162 1.1 christos unsigned int i; 163 1.1 christos 164 1.1 christos for (i = 0; i < ARRAY_SIZE (epiphany_elf_howto_table); i++) 165 1.1 christos if (epiphany_elf_howto_table[i].name != NULL 166 1.1 christos && strcasecmp (epiphany_elf_howto_table[i].name, r_name) == 0) 167 1.1 christos return &epiphany_elf_howto_table[i]; 168 1.1 christos 169 1.1 christos return NULL; 170 1.1 christos } 171 1.1 christos 172 1.1 christos #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000) 173 1.1 christos #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset) 174 1.1 christos 175 1.1 christos /* This function handles relaxing for the epiphany. 176 1.1 christos Dummy placeholder for future optimizations. */ 177 1.1 christos 178 1.8 christos static bool 179 1.1 christos epiphany_elf_relax_section (bfd *abfd, asection *sec, 180 1.1 christos struct bfd_link_info *link_info, 181 1.8 christos bool *again) 182 1.1 christos { 183 1.1 christos Elf_Internal_Shdr *symtab_hdr; 184 1.1 christos Elf_Internal_Rela *internal_relocs; 185 1.1 christos bfd_byte *contents = NULL; 186 1.1 christos Elf_Internal_Sym *isymbuf = NULL; 187 1.1 christos static asection * first_section = NULL; 188 1.1 christos static unsigned long search_addr; 189 1.1 christos static unsigned long page_start = 0; 190 1.1 christos static unsigned long page_end = 0; 191 1.1 christos static unsigned int pass = 0; 192 1.8 christos static bool new_pass = false; 193 1.8 christos static bool changed = false; 194 1.1 christos struct misc misc ATTRIBUTE_UNUSED; 195 1.1 christos asection *stab; 196 1.1 christos 197 1.1 christos /* Assume nothing changes. */ 198 1.8 christos *again = false; 199 1.1 christos 200 1.1 christos if (first_section == NULL) 201 1.1 christos { 202 1.8 christos epiphany_relaxed = true; 203 1.1 christos first_section = sec; 204 1.1 christos } 205 1.1 christos 206 1.1 christos if (first_section == sec) 207 1.1 christos { 208 1.1 christos pass++; 209 1.8 christos new_pass = true; 210 1.1 christos } 211 1.1 christos 212 1.1 christos /* We don't have to do anything for a relocatable link, 213 1.1 christos if this section does not have relocs, or if this is 214 1.1 christos not a code section. */ 215 1.3 christos if (bfd_link_relocatable (link_info) 216 1.9 christos || sec->reloc_count == 0 217 1.1 christos || (sec->flags & SEC_RELOC) == 0 218 1.9 christos || (sec->flags & SEC_HAS_CONTENTS) == 0 219 1.1 christos || (sec->flags & SEC_CODE) == 0) 220 1.8 christos return true; 221 1.1 christos 222 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 223 1.1 christos 224 1.1 christos internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, 225 1.1 christos link_info->keep_memory); 226 1.1 christos if (internal_relocs == NULL) 227 1.1 christos goto error_return; 228 1.1 christos 229 1.1 christos /* Make sure the stac.rela stuff gets read in. */ 230 1.1 christos stab = bfd_get_section_by_name (abfd, ".stab"); 231 1.1 christos 232 1.1 christos if (stab) 233 1.1 christos { 234 1.1 christos /* So stab does exits. */ 235 1.1 christos Elf_Internal_Rela * irelbase ATTRIBUTE_UNUSED; 236 1.1 christos 237 1.1 christos irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL, 238 1.1 christos link_info->keep_memory); 239 1.1 christos } 240 1.1 christos 241 1.1 christos /* Get section contents cached copy if it exists. */ 242 1.1 christos if (contents == NULL) 243 1.1 christos { 244 1.1 christos /* Get cached copy if it exists. */ 245 1.1 christos if (elf_section_data (sec)->this_hdr.contents != NULL) 246 1.1 christos contents = elf_section_data (sec)->this_hdr.contents; 247 1.1 christos else 248 1.1 christos { 249 1.1 christos /* Go get them off disk. */ 250 1.1 christos if (!bfd_malloc_and_get_section (abfd, sec, &contents)) 251 1.1 christos goto error_return; 252 1.1 christos } 253 1.1 christos } 254 1.1 christos 255 1.1 christos /* Read this BFD's symbols cached copy if it exists. */ 256 1.1 christos if (isymbuf == NULL && symtab_hdr->sh_info != 0) 257 1.1 christos { 258 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 259 1.1 christos if (isymbuf == NULL) 260 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 261 1.1 christos symtab_hdr->sh_info, 0, 262 1.1 christos NULL, NULL, NULL); 263 1.1 christos if (isymbuf == NULL) 264 1.1 christos goto error_return; 265 1.1 christos } 266 1.1 christos 267 1.1 christos misc.symtab_hdr = symtab_hdr; 268 1.1 christos misc.isymbuf = isymbuf; 269 1.1 christos misc.irelbase = internal_relocs; 270 1.1 christos misc.contents = contents; 271 1.1 christos 272 1.1 christos /* This is where all the relaxation actually get done. */ 273 1.1 christos if ((pass == 1) || (new_pass && !changed)) 274 1.1 christos { 275 1.1 christos /* On the first pass we simply search for the lowest page that 276 1.1 christos we havn't relaxed yet. Note that the pass count is reset 277 1.1 christos each time a page is complete in order to move on to the next page. 278 1.1 christos If we can't find any more pages then we are finished. */ 279 1.1 christos if (new_pass) 280 1.1 christos { 281 1.1 christos pass = 1; 282 1.8 christos new_pass = false; 283 1.8 christos changed = true; /* Pre-initialize to break out of pass 1. */ 284 1.1 christos search_addr = 0xFFFFFFFF; 285 1.1 christos } 286 1.1 christos 287 1.1 christos if ((BASEADDR (sec) + sec->size < search_addr) 288 1.1 christos && (BASEADDR (sec) + sec->size > page_end)) 289 1.1 christos { 290 1.1 christos if (BASEADDR (sec) <= page_end) 291 1.1 christos search_addr = page_end + 1; 292 1.1 christos else 293 1.1 christos search_addr = BASEADDR (sec); 294 1.1 christos 295 1.1 christos /* Found a page => more work to do. */ 296 1.8 christos *again = true; 297 1.1 christos } 298 1.1 christos } 299 1.1 christos else 300 1.1 christos { 301 1.1 christos if (new_pass) 302 1.1 christos { 303 1.8 christos new_pass = false; 304 1.8 christos changed = false; 305 1.1 christos page_start = PAGENO (search_addr); 306 1.1 christos page_end = page_start | 0x00003FFF; 307 1.1 christos } 308 1.1 christos 309 1.1 christos /* Only process sections in range. */ 310 1.1 christos if ((BASEADDR (sec) + sec->size >= page_start) 311 1.1 christos && (BASEADDR (sec) <= page_end)) 312 1.1 christos { 313 1.1 christos #if 0 314 1.1 christos if (!epiphany_elf_relax_section_page (abfd, sec, &changed, &misc, 315 1.1 christos page_start, page_end)) 316 1.1 christos #endif 317 1.8 christos return false; 318 1.1 christos } 319 1.8 christos *again = true; 320 1.1 christos } 321 1.1 christos 322 1.1 christos /* Perform some house keeping after relaxing the section. */ 323 1.1 christos 324 1.1 christos if (isymbuf != NULL 325 1.1 christos && symtab_hdr->contents != (unsigned char *) isymbuf) 326 1.1 christos { 327 1.1 christos if (! link_info->keep_memory) 328 1.1 christos free (isymbuf); 329 1.1 christos else 330 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf; 331 1.1 christos } 332 1.1 christos 333 1.1 christos if (contents != NULL 334 1.1 christos && elf_section_data (sec)->this_hdr.contents != contents) 335 1.1 christos { 336 1.1 christos if (! link_info->keep_memory) 337 1.1 christos free (contents); 338 1.1 christos else 339 1.1 christos { 340 1.1 christos /* Cache the section contents for elf_link_input_bfd. */ 341 1.1 christos elf_section_data (sec)->this_hdr.contents = contents; 342 1.1 christos } 343 1.1 christos } 344 1.1 christos 345 1.8 christos if (elf_section_data (sec)->relocs != internal_relocs) 346 1.1 christos free (internal_relocs); 347 1.1 christos 348 1.8 christos return true; 349 1.1 christos 350 1.1 christos error_return: 351 1.8 christos if (symtab_hdr->contents != (unsigned char *) isymbuf) 352 1.1 christos free (isymbuf); 353 1.8 christos if (elf_section_data (sec)->this_hdr.contents != contents) 354 1.1 christos free (contents); 355 1.8 christos if (elf_section_data (sec)->relocs != internal_relocs) 356 1.1 christos free (internal_relocs); 357 1.8 christos return false; 358 1.1 christos } 359 1.1 christos 360 1.1 christos /* Set the howto pointer for a EPIPHANY ELF reloc. */ 361 1.1 christos 362 1.8 christos static bool 363 1.6 christos epiphany_info_to_howto_rela (bfd * abfd, 364 1.1 christos arelent * cache_ptr, 365 1.1 christos Elf_Internal_Rela * dst) 366 1.1 christos { 367 1.1 christos unsigned int r_type; 368 1.1 christos 369 1.1 christos r_type = ELF32_R_TYPE (dst->r_info); 370 1.3 christos if (r_type >= (unsigned int) R_EPIPHANY_max) 371 1.3 christos { 372 1.6 christos /* xgettext:c-format */ 373 1.6 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 374 1.6 christos abfd, r_type); 375 1.6 christos bfd_set_error (bfd_error_bad_value); 376 1.8 christos return false; 377 1.3 christos } 378 1.1 christos cache_ptr->howto = & epiphany_elf_howto_table [r_type]; 379 1.8 christos return true; 380 1.1 christos } 381 1.1 christos 382 1.1 christos /* Perform a single relocation. 383 1.1 christos By default we use the standard BFD routines. */ 384 1.1 christos 385 1.1 christos static bfd_reloc_status_type 386 1.1 christos epiphany_final_link_relocate (reloc_howto_type * howto, 387 1.6 christos bfd * input_bfd, 388 1.6 christos asection * input_section, 389 1.6 christos bfd_byte * contents, 390 1.1 christos Elf_Internal_Rela * rel, 391 1.6 christos bfd_vma relocation) 392 1.1 christos { 393 1.1 christos switch (howto->type) 394 1.1 christos { 395 1.1 christos /* Handle 16 bit immediates. */ 396 1.1 christos case R_EPIPHANY_HIGH: 397 1.1 christos relocation += rel->r_addend; 398 1.1 christos relocation >>= 16; 399 1.1 christos goto common; 400 1.1 christos 401 1.1 christos case R_EPIPHANY_LOW: 402 1.1 christos relocation += rel->r_addend; 403 1.1 christos common: 404 1.1 christos relocation = ((relocation & 0xff00L) << 12) 405 1.1 christos | ((relocation & 0x00ffL) << 5); 406 1.1 christos /* Sanity check the address. */ 407 1.1 christos if (rel->r_offset > bfd_get_section_limit (input_bfd, input_section)) 408 1.1 christos return bfd_reloc_outofrange; 409 1.1 christos 410 1.1 christos return _bfd_relocate_contents (howto, input_bfd, relocation, 411 1.1 christos contents + rel->r_offset); 412 1.1 christos 413 1.1 christos case R_EPIPHANY_SIMM11: 414 1.1 christos relocation += rel->r_addend; 415 1.1 christos /* Check signed overflow. */ 416 1.1 christos if ((int)relocation > 1023 || (int)relocation < -1024) 417 1.1 christos return bfd_reloc_outofrange; 418 1.1 christos goto disp11; 419 1.1 christos 420 1.1 christos case R_EPIPHANY_IMM11: 421 1.1 christos relocation += rel->r_addend; 422 1.1 christos if ((unsigned int) relocation > 0x7ff) 423 1.1 christos return bfd_reloc_outofrange; 424 1.6 christos /* Fall through. */ 425 1.1 christos disp11: 426 1.6 christos relocation = (((relocation & 7) << 5) 427 1.6 christos | ((relocation & 0x7f8 ) << 13)); 428 1.1 christos return _bfd_relocate_contents (howto, input_bfd, relocation, 429 1.1 christos contents + rel->r_offset); 430 1.1 christos 431 1.1 christos /* Pass others through. */ 432 1.1 christos default: 433 1.1 christos break; 434 1.1 christos } 435 1.1 christos 436 1.1 christos /* Only install relocation if above tests did not disqualify it. */ 437 1.1 christos return _bfd_final_link_relocate (howto, input_bfd, input_section, 438 1.1 christos contents, rel->r_offset, 439 1.1 christos relocation, rel->r_addend); 440 1.1 christos } 441 1.1 christos 442 1.1 christos /* Relocate an EPIPHANY ELF section. 443 1.1 christos 444 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker 445 1.1 christos to handle the relocations for a section. 446 1.1 christos 447 1.1 christos The relocs are always passed as Rela structures; if the section 448 1.1 christos actually uses Rel structures, the r_addend field will always be 449 1.1 christos zero. 450 1.1 christos 451 1.1 christos This function is responsible for adjusting the section contents as 452 1.1 christos necessary, and (if using Rela relocs and generating a relocatable 453 1.1 christos output file) adjusting the reloc addend as necessary. 454 1.1 christos 455 1.1 christos This function does not have to worry about setting the reloc 456 1.1 christos address or the reloc symbol index. 457 1.1 christos 458 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols. 459 1.1 christos 460 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file 461 1.1 christos corresponding to the st_shndx field of each local symbol. 462 1.1 christos 463 1.1 christos The global hash table entry for the global symbols can be found 464 1.1 christos via elf_sym_hashes (input_bfd). 465 1.1 christos 466 1.1 christos When generating relocatable output, this function must handle 467 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is 468 1.1 christos going to be the section symbol corresponding to the output 469 1.1 christos section, which means that the addend must be adjusted 470 1.1 christos accordingly. */ 471 1.1 christos 472 1.8 christos static int 473 1.1 christos epiphany_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, 474 1.1 christos struct bfd_link_info *info, 475 1.1 christos bfd *input_bfd, 476 1.1 christos asection *input_section, 477 1.1 christos bfd_byte *contents, 478 1.1 christos Elf_Internal_Rela *relocs, 479 1.1 christos Elf_Internal_Sym *local_syms, 480 1.1 christos asection **local_sections) 481 1.1 christos { 482 1.1 christos Elf_Internal_Shdr *symtab_hdr; 483 1.1 christos struct elf_link_hash_entry **sym_hashes; 484 1.1 christos Elf_Internal_Rela *rel; 485 1.1 christos Elf_Internal_Rela *relend; 486 1.1 christos 487 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 488 1.1 christos sym_hashes = elf_sym_hashes (input_bfd); 489 1.1 christos relend = relocs + input_section->reloc_count; 490 1.1 christos 491 1.1 christos for (rel = relocs; rel < relend; rel ++) 492 1.1 christos { 493 1.6 christos reloc_howto_type * howto; 494 1.6 christos unsigned long r_symndx; 495 1.6 christos Elf_Internal_Sym * sym; 496 1.6 christos asection * sec; 497 1.1 christos struct elf_link_hash_entry * h; 498 1.6 christos bfd_vma relocation; 499 1.6 christos bfd_reloc_status_type r; 500 1.6 christos const char * name = NULL; 501 1.6 christos int r_type ATTRIBUTE_UNUSED; 502 1.1 christos 503 1.1 christos r_type = ELF32_R_TYPE (rel->r_info); 504 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 505 1.1 christos howto = epiphany_elf_howto_table + ELF32_R_TYPE (rel->r_info); 506 1.1 christos h = NULL; 507 1.1 christos sym = NULL; 508 1.1 christos sec = NULL; 509 1.1 christos 510 1.1 christos if (r_symndx < symtab_hdr->sh_info) 511 1.1 christos { 512 1.1 christos sym = local_syms + r_symndx; 513 1.1 christos sec = local_sections [r_symndx]; 514 1.1 christos relocation = BASEADDR (sec) + sym->st_value; 515 1.1 christos 516 1.1 christos name = bfd_elf_string_from_elf_section 517 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name); 518 1.7 christos name = name == NULL ? bfd_section_name (sec) : name; 519 1.1 christos } 520 1.1 christos else 521 1.1 christos { 522 1.8 christos bool warned ATTRIBUTE_UNUSED; 523 1.8 christos bool unresolved_reloc ATTRIBUTE_UNUSED; 524 1.8 christos bool ignored ATTRIBUTE_UNUSED; 525 1.1 christos 526 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 527 1.1 christos r_symndx, symtab_hdr, sym_hashes, 528 1.1 christos h, sec, relocation, 529 1.3 christos unresolved_reloc, warned, ignored); 530 1.1 christos 531 1.1 christos name = h->root.root.string; 532 1.1 christos } 533 1.1 christos 534 1.1 christos if (sec != NULL && discarded_section (sec)) 535 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 536 1.1 christos rel, 1, relend, howto, 0, contents); 537 1.1 christos 538 1.3 christos if (bfd_link_relocatable (info)) 539 1.1 christos continue; 540 1.1 christos 541 1.1 christos /* Finally, the sole EPIPHANY-specific part. */ 542 1.1 christos r = epiphany_final_link_relocate (howto, input_bfd, input_section, 543 1.1 christos contents, rel, relocation); 544 1.1 christos 545 1.1 christos if (r != bfd_reloc_ok) 546 1.1 christos { 547 1.1 christos const char * msg = NULL; 548 1.1 christos 549 1.1 christos switch (r) 550 1.1 christos { 551 1.1 christos case bfd_reloc_overflow: 552 1.5 christos (*info->callbacks->reloc_overflow) 553 1.1 christos (info, (h ? &h->root : NULL), name, howto->name, 554 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset); 555 1.1 christos break; 556 1.1 christos 557 1.1 christos case bfd_reloc_undefined: 558 1.5 christos (*info->callbacks->undefined_symbol) 559 1.8 christos (info, name, input_bfd, input_section, rel->r_offset, true); 560 1.1 christos break; 561 1.1 christos 562 1.1 christos case bfd_reloc_outofrange: 563 1.1 christos msg = _("internal error: out of range error"); 564 1.1 christos break; 565 1.1 christos 566 1.1 christos /* This is how epiphany_final_link_relocate tells us of a 567 1.1 christos non-kosher reference between insn & data address spaces. */ 568 1.1 christos case bfd_reloc_notsupported: 569 1.1 christos if (sym != NULL) /* Only if it's not an unresolved symbol. */ 570 1.1 christos msg = _("unsupported relocation between data/insn address spaces"); 571 1.1 christos break; 572 1.1 christos 573 1.1 christos case bfd_reloc_dangerous: 574 1.1 christos msg = _("internal error: dangerous relocation"); 575 1.1 christos break; 576 1.1 christos 577 1.1 christos default: 578 1.1 christos msg = _("internal error: unknown error"); 579 1.1 christos break; 580 1.1 christos } 581 1.1 christos 582 1.1 christos if (msg) 583 1.5 christos (*info->callbacks->warning) (info, msg, name, input_bfd, 584 1.5 christos input_section, rel->r_offset); 585 1.1 christos } 586 1.1 christos } 587 1.1 christos 588 1.8 christos return true; 589 1.1 christos } 590 1.1 christos 591 1.1 christos /* We only have a little-endian target. */ 592 1.3 christos #define TARGET_LITTLE_SYM epiphany_elf32_vec 593 1.1 christos #define TARGET_LITTLE_NAME "elf32-epiphany" 594 1.1 christos 595 1.1 christos #define ELF_ARCH bfd_arch_epiphany 596 1.1 christos #define ELF_MACHINE_CODE EM_ADAPTEVA_EPIPHANY 597 1.1 christos 598 1.1 christos #define ELF_MAXPAGESIZE 0x8000 /* No pages on the EPIPHANY. */ 599 1.1 christos 600 1.1 christos #define elf_info_to_howto_rel NULL 601 1.1 christos #define elf_info_to_howto epiphany_info_to_howto_rela 602 1.1 christos 603 1.6 christos #define elf_backend_can_gc_sections 1 604 1.1 christos #define elf_backend_rela_normal 1 605 1.1 christos #define elf_backend_relocate_section epiphany_elf_relocate_section 606 1.1 christos 607 1.1 christos #define elf_symbol_leading_char '_' 608 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup epiphany_reloc_type_lookup 609 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup epiphany_reloc_name_lookup 610 1.1 christos #define bfd_elf32_bfd_relax_section epiphany_elf_relax_section 611 1.1 christos 612 1.1 christos #include "elf32-target.h" 613