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