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