1/* moxie-specific support for 32-bit ELF. 2 Copyright (C) 2009-2017 Free Software Foundation, Inc. 3 4 Copied from elf32-fr30.c which is.. 5 Copyright (C) 1998-2017 Free Software Foundation, Inc. 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 22 MA 02110-1301, USA. */ 23 24#include "sysdep.h" 25#include "bfd.h" 26#include "libbfd.h" 27#include "elf-bfd.h" 28#include "elf/moxie.h" 29 30/* Forward declarations. */ 31 32static reloc_howto_type moxie_elf_howto_table [] = 33{ 34 /* This reloc does nothing. */ 35 HOWTO (R_MOXIE_NONE, /* type */ 36 0, /* rightshift */ 37 3, /* size (0 = byte, 1 = short, 2 = long) */ 38 0, /* bitsize */ 39 FALSE, /* pc_relative */ 40 0, /* bitpos */ 41 complain_overflow_dont, /* complain_on_overflow */ 42 bfd_elf_generic_reloc, /* special_function */ 43 "R_MOXIE_NONE", /* name */ 44 FALSE, /* partial_inplace */ 45 0, /* src_mask */ 46 0, /* dst_mask */ 47 FALSE), /* pcrel_offset */ 48 49 /* A 32 bit absolute relocation. */ 50 HOWTO (R_MOXIE_32, /* type */ 51 0, /* rightshift */ 52 2, /* size (0 = byte, 1 = short, 2 = long) */ 53 32, /* bitsize */ 54 FALSE, /* pc_relative */ 55 0, /* bitpos */ 56 complain_overflow_bitfield, /* complain_on_overflow */ 57 bfd_elf_generic_reloc, /* special_function */ 58 "R_MOXIE_32", /* name */ 59 FALSE, /* partial_inplace */ 60 0x00000000, /* src_mask */ 61 0xffffffff, /* dst_mask */ 62 FALSE), /* pcrel_offset */ 63 64 /* A 10 bit PC-relative relocation. */ 65 HOWTO (R_MOXIE_PCREL10, /* type. */ 66 1, /* rightshift. */ 67 1, /* size (0 = byte, 1 = short, 2 = long). */ 68 10, /* bitsize. */ 69 TRUE, /* pc_relative. */ 70 0, /* bitpos. */ 71 complain_overflow_signed, /* complain_on_overflow. */ 72 bfd_elf_generic_reloc, /* special_function. */ 73 "R_MOXIE_PCREL10", /* name. */ 74 FALSE, /* partial_inplace. */ 75 0, /* src_mask. */ 76 0x000003FF, /* dst_mask. */ 77 TRUE), /* pcrel_offset. */ 78}; 79 80/* Map BFD reloc types to MOXIE ELF reloc types. */ 81 82struct moxie_reloc_map 83{ 84 bfd_reloc_code_real_type bfd_reloc_val; 85 unsigned int moxie_reloc_val; 86}; 87 88static const struct moxie_reloc_map moxie_reloc_map [] = 89{ 90 { BFD_RELOC_NONE, R_MOXIE_NONE }, 91 { BFD_RELOC_32, R_MOXIE_32 }, 92 { BFD_RELOC_MOXIE_10_PCREL, R_MOXIE_PCREL10 }, 93}; 94 95static reloc_howto_type * 96moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 97 bfd_reloc_code_real_type code) 98{ 99 unsigned int i; 100 101 for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]); 102 i--;) 103 if (moxie_reloc_map [i].bfd_reloc_val == code) 104 return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val]; 105 106 return NULL; 107} 108 109static reloc_howto_type * 110moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 111{ 112 unsigned int i; 113 114 for (i = 0; 115 i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]); 116 i++) 117 if (moxie_elf_howto_table[i].name != NULL 118 && strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0) 119 return &moxie_elf_howto_table[i]; 120 121 return NULL; 122} 123 124/* Set the howto pointer for an MOXIE ELF reloc. */ 125 126static void 127moxie_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, 128 arelent *cache_ptr, 129 Elf_Internal_Rela *dst) 130{ 131 unsigned int r_type; 132 133 r_type = ELF32_R_TYPE (dst->r_info); 134 if (r_type >= (unsigned int) R_MOXIE_max) 135 { 136 /* xgettext:c-format */ 137 _bfd_error_handler (_("%B: invalid Moxie reloc number: %d"), abfd, r_type); 138 r_type = 0; 139 } 140 cache_ptr->howto = & moxie_elf_howto_table [r_type]; 141} 142 143/* Perform a single relocation. By default we use the standard BFD 144 routines, but a few relocs, we have to do them ourselves. */ 145 146static bfd_reloc_status_type 147moxie_final_link_relocate (reloc_howto_type *howto, 148 bfd *input_bfd, 149 asection *input_section, 150 bfd_byte *contents, 151 Elf_Internal_Rela *rel, 152 bfd_vma relocation) 153{ 154 bfd_reloc_status_type r = bfd_reloc_ok; 155 156 switch (howto->type) 157 { 158 default: 159 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 160 contents, rel->r_offset, 161 relocation, rel->r_addend); 162 } 163 164 return r; 165} 166 167/* Relocate an MOXIE ELF section. 168 169 The RELOCATE_SECTION function is called by the new ELF backend linker 170 to handle the relocations for a section. 171 172 The relocs are always passed as Rela structures; if the section 173 actually uses Rel structures, the r_addend field will always be 174 zero. 175 176 This function is responsible for adjusting the section contents as 177 necessary, and (if using Rela relocs and generating a relocatable 178 output file) adjusting the reloc addend as necessary. 179 180 This function does not have to worry about setting the reloc 181 address or the reloc symbol index. 182 183 LOCAL_SYMS is a pointer to the swapped in local symbols. 184 185 LOCAL_SECTIONS is an array giving the section in the input file 186 corresponding to the st_shndx field of each local symbol. 187 188 The global hash table entry for the global symbols can be found 189 via elf_sym_hashes (input_bfd). 190 191 When generating relocatable output, this function must handle 192 STB_LOCAL/STT_SECTION symbols specially. The output symbol is 193 going to be the section symbol corresponding to the output 194 section, which means that the addend must be adjusted 195 accordingly. */ 196 197static bfd_boolean 198moxie_elf_relocate_section (bfd *output_bfd, 199 struct bfd_link_info *info, 200 bfd *input_bfd, 201 asection *input_section, 202 bfd_byte *contents, 203 Elf_Internal_Rela *relocs, 204 Elf_Internal_Sym *local_syms, 205 asection **local_sections) 206{ 207 Elf_Internal_Shdr *symtab_hdr; 208 struct elf_link_hash_entry **sym_hashes; 209 Elf_Internal_Rela *rel; 210 Elf_Internal_Rela *relend; 211 212 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 213 sym_hashes = elf_sym_hashes (input_bfd); 214 relend = relocs + input_section->reloc_count; 215 216 for (rel = relocs; rel < relend; rel ++) 217 { 218 reloc_howto_type *howto; 219 unsigned long r_symndx; 220 Elf_Internal_Sym *sym; 221 asection *sec; 222 struct elf_link_hash_entry *h; 223 bfd_vma relocation; 224 bfd_reloc_status_type r; 225 const char *name; 226 int r_type; 227 228 r_type = ELF32_R_TYPE (rel->r_info); 229 r_symndx = ELF32_R_SYM (rel->r_info); 230 howto = moxie_elf_howto_table + r_type; 231 h = NULL; 232 sym = NULL; 233 sec = NULL; 234 235 if (r_symndx < symtab_hdr->sh_info) 236 { 237 sym = local_syms + r_symndx; 238 sec = local_sections [r_symndx]; 239 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 240 241 name = bfd_elf_string_from_elf_section 242 (input_bfd, symtab_hdr->sh_link, sym->st_name); 243 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; 244 } 245 else 246 { 247 bfd_boolean unresolved_reloc, warned, ignored; 248 249 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 250 r_symndx, symtab_hdr, sym_hashes, 251 h, sec, relocation, 252 unresolved_reloc, warned, ignored); 253 254 name = h->root.root.string; 255 } 256 257 if (sec != NULL && discarded_section (sec)) 258 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 259 rel, 1, relend, howto, 0, contents); 260 261 if (bfd_link_relocatable (info)) 262 continue; 263 264 r = moxie_final_link_relocate (howto, input_bfd, input_section, 265 contents, rel, relocation); 266 267 if (r != bfd_reloc_ok) 268 { 269 const char * msg = NULL; 270 271 switch (r) 272 { 273 case bfd_reloc_overflow: 274 (*info->callbacks->reloc_overflow) 275 (info, (h ? &h->root : NULL), name, howto->name, 276 (bfd_vma) 0, input_bfd, input_section, rel->r_offset); 277 break; 278 279 case bfd_reloc_undefined: 280 (*info->callbacks->undefined_symbol) 281 (info, name, input_bfd, input_section, rel->r_offset, TRUE); 282 break; 283 284 case bfd_reloc_outofrange: 285 msg = _("internal error: out of range error"); 286 break; 287 288 case bfd_reloc_notsupported: 289 msg = _("internal error: unsupported relocation error"); 290 break; 291 292 case bfd_reloc_dangerous: 293 msg = _("internal error: dangerous relocation"); 294 break; 295 296 default: 297 msg = _("internal error: unknown error"); 298 break; 299 } 300 301 if (msg) 302 (*info->callbacks->warning) (info, msg, name, input_bfd, 303 input_section, rel->r_offset); 304 } 305 } 306 307 return TRUE; 308} 309 310/* Return the section that should be marked against GC for a given 311 relocation. */ 312 313static asection * 314moxie_elf_gc_mark_hook (asection *sec, 315 struct bfd_link_info *info, 316 Elf_Internal_Rela *rel, 317 struct elf_link_hash_entry *h, 318 Elf_Internal_Sym *sym) 319{ 320 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 321} 322 323/* Look through the relocs for a section during the first phase. 324 Since we don't do .gots or .plts, we just need to consider the 325 virtual table relocs for gc. */ 326 327static bfd_boolean 328moxie_elf_check_relocs (bfd *abfd, 329 struct bfd_link_info *info, 330 asection *sec, 331 const Elf_Internal_Rela *relocs) 332{ 333 Elf_Internal_Shdr *symtab_hdr; 334 struct elf_link_hash_entry **sym_hashes; 335 const Elf_Internal_Rela *rel; 336 const Elf_Internal_Rela *rel_end; 337 338 if (bfd_link_relocatable (info)) 339 return TRUE; 340 341 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 342 sym_hashes = elf_sym_hashes (abfd); 343 344 rel_end = relocs + sec->reloc_count; 345 for (rel = relocs; rel < rel_end; rel++) 346 { 347 struct elf_link_hash_entry *h; 348 unsigned long r_symndx; 349 350 r_symndx = ELF32_R_SYM (rel->r_info); 351 if (r_symndx < symtab_hdr->sh_info) 352 h = NULL; 353 else 354 { 355 h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 356 while (h->root.type == bfd_link_hash_indirect 357 || h->root.type == bfd_link_hash_warning) 358 h = (struct elf_link_hash_entry *) h->root.u.i.link; 359 360 /* PR15323, ref flags aren't set for references in the same 361 object. */ 362 h->root.non_ir_ref = 1; 363 } 364 } 365 366 return TRUE; 367} 368 369#define ELF_ARCH bfd_arch_moxie 370#define ELF_MACHINE_CODE EM_MOXIE 371#define ELF_MACHINE_ALT1 EM_MOXIE_OLD 372#define ELF_MAXPAGESIZE 0x1 373 374#define TARGET_BIG_SYM moxie_elf32_be_vec 375#define TARGET_BIG_NAME "elf32-bigmoxie" 376#define TARGET_LITTLE_SYM moxie_elf32_le_vec 377#define TARGET_LITTLE_NAME "elf32-littlemoxie" 378 379#define elf_info_to_howto_rel NULL 380#define elf_info_to_howto moxie_info_to_howto_rela 381#define elf_backend_relocate_section moxie_elf_relocate_section 382#define elf_backend_gc_mark_hook moxie_elf_gc_mark_hook 383#define elf_backend_check_relocs moxie_elf_check_relocs 384 385#define elf_backend_can_gc_sections 1 386#define elf_backend_rela_normal 1 387 388#define bfd_elf32_bfd_reloc_type_lookup moxie_reloc_type_lookup 389#define bfd_elf32_bfd_reloc_name_lookup moxie_reloc_name_lookup 390 391#include "elf32-target.h" 392