1 /* picoJava specific support for 32-bit ELF 2 Copyright (C) 1999-2022 Free Software Foundation, Inc. 3 Contributed by Steve Chamberlan of Transmeta (sac@pobox.com). 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "bfd.h" 24 #include "bfdlink.h" 25 #include "libbfd.h" 26 #include "elf-bfd.h" 27 #include "elf/pj.h" 28 29 /* This function is used for normal relocs. This is like the COFF 30 function, and is almost certainly incorrect for other ELF targets. */ 31 32 static bfd_reloc_status_type 33 pj_elf_reloc (bfd *abfd, 34 arelent *reloc_entry, 35 asymbol *symbol_in, 36 void * data, 37 asection *input_section, 38 bfd *output_bfd, 39 char **error_message ATTRIBUTE_UNUSED) 40 { 41 unsigned long insn; 42 bfd_vma sym_value; 43 enum elf_pj_reloc_type r_type; 44 bfd_vma addr = reloc_entry->address; 45 bfd_byte *hit_data = addr + (bfd_byte *) data; 46 47 r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type; 48 49 if (output_bfd != NULL) 50 { 51 /* Partial linking--do nothing. */ 52 reloc_entry->address += input_section->output_offset; 53 return bfd_reloc_ok; 54 } 55 56 if (symbol_in != NULL 57 && (symbol_in->flags & BSF_WEAK) == 0 58 && bfd_is_und_section (symbol_in->section)) 59 return bfd_reloc_undefined; 60 61 if (bfd_is_com_section (symbol_in->section)) 62 sym_value = 0; 63 else 64 sym_value = (symbol_in->value + 65 symbol_in->section->output_section->vma + 66 symbol_in->section->output_offset); 67 68 switch (r_type) 69 { 70 case R_PJ_DATA_DIR32: 71 insn = bfd_get_32 (abfd, hit_data); 72 insn += sym_value + reloc_entry->addend; 73 bfd_put_32 (abfd, (bfd_vma) insn, hit_data); 74 break; 75 76 /* Relocations in code are always bigendian, no matter what the 77 data endianness is. */ 78 79 case R_PJ_CODE_DIR32: 80 insn = bfd_getb32 (hit_data); 81 insn += sym_value + reloc_entry->addend; 82 bfd_putb32 ((bfd_vma) insn, hit_data); 83 break; 84 85 case R_PJ_CODE_REL16: 86 insn = bfd_getb16 (hit_data); 87 insn += sym_value + reloc_entry->addend 88 - (input_section->output_section->vma 89 + input_section->output_offset); 90 bfd_putb16 ((bfd_vma) insn, hit_data); 91 break; 92 case R_PJ_CODE_LO16: 93 insn = bfd_getb16 (hit_data); 94 insn += sym_value + reloc_entry->addend; 95 bfd_putb16 ((bfd_vma) insn, hit_data); 96 break; 97 98 case R_PJ_CODE_HI16: 99 insn = bfd_getb16 (hit_data); 100 insn += (sym_value + reloc_entry->addend) >> 16; 101 bfd_putb16 ((bfd_vma) insn, hit_data); 102 break; 103 104 default: 105 abort (); 106 break; 107 } 108 109 return bfd_reloc_ok; 110 } 111 112 static reloc_howto_type pj_elf_howto_table[] = 113 { 114 /* No relocation. */ 115 HOWTO (R_PJ_NONE, /* type */ 116 0, /* rightshift */ 117 0, /* size */ 118 0, /* bitsize */ 119 false, /* pc_relative */ 120 0, /* bitpos */ 121 complain_overflow_dont, /* complain_on_overflow */ 122 pj_elf_reloc, /* special_function */ 123 "R_PJ_NONE", /* name */ 124 false, /* partial_inplace */ 125 0, /* src_mask */ 126 0, /* dst_mask */ 127 false), /* pcrel_offset */ 128 129 /* 32 bit absolute relocation. Setting partial_inplace to TRUE and 130 src_mask to a non-zero value is similar to the COFF toolchain. */ 131 HOWTO (R_PJ_DATA_DIR32, /* type */ 132 0, /* rightshift */ 133 4, /* size */ 134 32, /* bitsize */ 135 false, /* pc_relative */ 136 0, /* bitpos */ 137 complain_overflow_bitfield, /* complain_on_overflow */ 138 pj_elf_reloc, /* special_function */ 139 "R_PJ_DIR32", /* name */ 140 true, /* partial_inplace */ 141 0xffffffff, /* src_mask */ 142 0xffffffff, /* dst_mask */ 143 false), /* pcrel_offset */ 144 145 /* 32 bit PC relative relocation. */ 146 HOWTO (R_PJ_CODE_REL32, /* type */ 147 0, /* rightshift */ 148 4, /* size */ 149 32, /* bitsize */ 150 true, /* pc_relative */ 151 0, /* bitpos */ 152 complain_overflow_signed, /* complain_on_overflow */ 153 pj_elf_reloc, /* special_function */ 154 "R_PJ_REL32", /* name */ 155 false, /* partial_inplace */ 156 0, /* src_mask */ 157 0xffffffff, /* dst_mask */ 158 true), /* pcrel_offset */ 159 160 /* 16 bit PC relative relocation. */ 161 HOWTO (R_PJ_CODE_REL16, /* type */ 162 0, /* rightshift */ 163 2, /* size */ 164 16, /* bitsize */ 165 true, /* pc_relative */ 166 0, /* bitpos */ 167 complain_overflow_signed, /* complain_on_overf6w */ 168 pj_elf_reloc, /* special_function */ 169 "R_PJ_REL16", /* name */ 170 false, /* partial_inplace */ 171 0xffff, /* src_mask */ 172 0xffff, /* dst_mask */ 173 true), /* pcrel_offset */ 174 EMPTY_HOWTO (4), 175 EMPTY_HOWTO (5), 176 HOWTO (R_PJ_CODE_DIR32, /* type */ 177 0, /* rightshift */ 178 4, /* size */ 179 32, /* bitsize */ 180 false, /* pc_relative */ 181 0, /* bitpos */ 182 complain_overflow_bitfield, /* complain_on_overflow */ 183 pj_elf_reloc, /* special_function */ 184 "R_PJ_CODE_DIR32", /* name */ 185 true, /* partial_inplace */ 186 0xffffffff, /* src_mask */ 187 0xffffffff, /* dst_mask */ 188 false), /* pcrel_offset */ 189 190 EMPTY_HOWTO (7), 191 EMPTY_HOWTO (8), 192 EMPTY_HOWTO (9), 193 EMPTY_HOWTO (10), 194 EMPTY_HOWTO (11), 195 EMPTY_HOWTO (12), 196 197 HOWTO (R_PJ_CODE_LO16, /* type */ 198 0, /* rightshift */ 199 2, /* size */ 200 16, /* bitsize */ 201 false, /* pc_relative */ 202 0, /* bitpos */ 203 complain_overflow_unsigned, /* complain_on_overflow */ 204 pj_elf_reloc, /* special_function */ 205 "R_PJ_LO16", /* name */ 206 false, /* partial_inplace */ 207 0xffff, /* src_mask */ 208 0xffff, /* dst_mask */ 209 true), /* pcrel_offset */ 210 211 HOWTO (R_PJ_CODE_HI16, /* type */ 212 16, /* rightshift */ 213 2, /* size */ 214 16, /* bitsize */ 215 false, /* pc_relative */ 216 0, /* bitpos */ 217 complain_overflow_unsigned, /* complain_on_overflow */ 218 pj_elf_reloc, /* special_function */ 219 "R_PJ_HI16", /* name */ 220 false, /* partial_inplace */ 221 0xffff, /* src_mask */ 222 0xffff, /* dst_mask */ 223 true), /* pcrel_offset */ 224 225 /* GNU extension to record C++ vtable hierarchy. */ 226 HOWTO (R_PJ_GNU_VTINHERIT, /* type */ 227 0, /* rightshift */ 228 4, /* size */ 229 0, /* bitsize */ 230 false, /* pc_relative */ 231 0, /* bitpos */ 232 complain_overflow_dont, /* complain_on_overflow */ 233 NULL, /* special_function */ 234 "R_PJ_GNU_VTINHERIT", /* name */ 235 false, /* partial_inplace */ 236 0, /* src_mask */ 237 0, /* dst_mask */ 238 false), /* pcrel_offset */ 239 240 /* GNU extension to record C++ vtable member usage. */ 241 HOWTO (R_PJ_GNU_VTENTRY, /* type */ 242 0, /* rightshift */ 243 4, /* size */ 244 0, /* bitsize */ 245 false, /* pc_relative */ 246 0, /* bitpos */ 247 complain_overflow_dont, /* complain_on_overflow */ 248 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 249 "R_PJ_GNU_VTENTRY", /* name */ 250 false, /* partial_inplace */ 251 0, /* src_mask */ 252 0, /* dst_mask */ 253 false), /* pcrel_offset */ 254 }; 255 256 /* This structure is used to map BFD reloc codes to PJ ELF relocs. */ 257 258 struct elf_reloc_map 259 { 260 bfd_reloc_code_real_type bfd_reloc_val; 261 unsigned char elf_reloc_val; 262 }; 263 264 /* An array mapping BFD reloc codes to PJ ELF relocs. */ 265 266 static const struct elf_reloc_map pj_reloc_map[] = 267 { 268 { BFD_RELOC_NONE, R_PJ_NONE }, 269 { BFD_RELOC_32, R_PJ_DATA_DIR32 }, 270 { BFD_RELOC_PJ_CODE_DIR16, R_PJ_CODE_DIR16 }, 271 { BFD_RELOC_PJ_CODE_DIR32, R_PJ_CODE_DIR32 }, 272 { BFD_RELOC_PJ_CODE_LO16, R_PJ_CODE_LO16 }, 273 { BFD_RELOC_PJ_CODE_HI16, R_PJ_CODE_HI16 }, 274 { BFD_RELOC_PJ_CODE_REL32, R_PJ_CODE_REL32 }, 275 { BFD_RELOC_PJ_CODE_REL16, R_PJ_CODE_REL16 }, 276 { BFD_RELOC_VTABLE_INHERIT, R_PJ_GNU_VTINHERIT }, 277 { BFD_RELOC_VTABLE_ENTRY, R_PJ_GNU_VTENTRY }, 278 }; 279 280 /* Given a BFD reloc code, return the howto structure for the 281 corresponding PJ ELf reloc. */ 282 283 static reloc_howto_type * 284 pj_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 285 bfd_reloc_code_real_type code) 286 { 287 unsigned int i; 288 289 for (i = 0; i < sizeof (pj_reloc_map) / sizeof (struct elf_reloc_map); i++) 290 if (pj_reloc_map[i].bfd_reloc_val == code) 291 return & pj_elf_howto_table[(int) pj_reloc_map[i].elf_reloc_val]; 292 293 return NULL; 294 } 295 296 static reloc_howto_type * 297 pj_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 298 const char *r_name) 299 { 300 unsigned int i; 301 302 for (i = 0; 303 i < sizeof (pj_elf_howto_table) / sizeof (pj_elf_howto_table[0]); 304 i++) 305 if (pj_elf_howto_table[i].name != NULL 306 && strcasecmp (pj_elf_howto_table[i].name, r_name) == 0) 307 return &pj_elf_howto_table[i]; 308 309 return NULL; 310 } 311 312 /* Given an ELF reloc, fill in the howto field of a relent. */ 313 314 static bool 315 pj_elf_info_to_howto (bfd *abfd, 316 arelent *cache_ptr, 317 Elf_Internal_Rela *dst) 318 { 319 unsigned int r; 320 321 r = ELF32_R_TYPE (dst->r_info); 322 323 if (r >= R_PJ_max) 324 { 325 /* xgettext:c-format */ 326 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 327 abfd, r); 328 bfd_set_error (bfd_error_bad_value); 329 return false; 330 } 331 332 cache_ptr->howto = &pj_elf_howto_table[r]; 333 return true; 334 } 335 336 /* Take this moment to fill in the special picoJava bits in the 337 e_flags field. */ 338 339 static bool 340 pj_elf_final_write_processing (bfd *abfd) 341 { 342 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_ARCH; 343 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_GNUCALLS; 344 return _bfd_elf_final_write_processing (abfd); 345 } 346 347 #define TARGET_BIG_SYM pj_elf32_vec 348 #define TARGET_BIG_NAME "elf32-pj" 349 #define TARGET_LITTLE_SYM pj_elf32_le_vec 350 #define TARGET_LITTLE_NAME "elf32-pjl" 351 #define ELF_ARCH bfd_arch_pj 352 #define ELF_MACHINE_CODE EM_PJ 353 #define ELF_MACHINE_ALT1 EM_PJ_OLD 354 #define ELF_MAXPAGESIZE 0x1000 355 #define bfd_elf32_bfd_get_relocated_section_contents \ 356 bfd_generic_get_relocated_section_contents 357 #define bfd_elf32_bfd_reloc_type_lookup pj_elf_reloc_type_lookup 358 #define bfd_elf32_bfd_reloc_name_lookup pj_elf_reloc_name_lookup 359 #define elf_backend_final_write_processing pj_elf_final_write_processing 360 #define elf_info_to_howto pj_elf_info_to_howto 361 #include "elf32-target.h" 362