1 /* picoJava specific support for 32-bit ELF 2 Copyright 1999, 2000, 2001, 2002, 2005 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 2 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, MA 02110-1301, USA. */ 20 21 #include "bfd.h" 22 #include "sysdep.h" 23 #include "bfdlink.h" 24 #include "libbfd.h" 25 #include "elf-bfd.h" 26 #include "elf/pj.h" 27 28 /* This function is used for normal relocs. This is like the COFF 29 function, and is almost certainly incorrect for other ELF targets. */ 30 31 static bfd_reloc_status_type 32 pj_elf_reloc (bfd *abfd, 33 arelent *reloc_entry, 34 asymbol *symbol_in, 35 void * data, 36 asection *input_section, 37 bfd *output_bfd, 38 char **error_message ATTRIBUTE_UNUSED) 39 { 40 unsigned long insn; 41 bfd_vma sym_value; 42 enum elf_pj_reloc_type r_type; 43 bfd_vma addr = reloc_entry->address; 44 bfd_byte *hit_data = addr + (bfd_byte *) data; 45 46 r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type; 47 48 if (output_bfd != NULL) 49 { 50 /* Partial linking--do nothing. */ 51 reloc_entry->address += input_section->output_offset; 52 return bfd_reloc_ok; 53 } 54 55 if (symbol_in != NULL 56 && bfd_is_und_section (symbol_in->section)) 57 return bfd_reloc_undefined; 58 59 if (bfd_is_com_section (symbol_in->section)) 60 sym_value = 0; 61 else 62 sym_value = (symbol_in->value + 63 symbol_in->section->output_section->vma + 64 symbol_in->section->output_offset); 65 66 switch (r_type) 67 { 68 case R_PJ_DATA_DIR32: 69 insn = bfd_get_32 (abfd, hit_data); 70 insn += sym_value + reloc_entry->addend; 71 bfd_put_32 (abfd, (bfd_vma) insn, hit_data); 72 break; 73 74 /* Relocations in code are always bigendian, no matter what the 75 data endianness is. */ 76 77 case R_PJ_CODE_DIR32: 78 insn = bfd_getb32 (hit_data); 79 insn += sym_value + reloc_entry->addend; 80 bfd_putb32 ((bfd_vma) insn, hit_data); 81 break; 82 83 case R_PJ_CODE_REL16: 84 insn = bfd_getb16 (hit_data); 85 insn += sym_value + reloc_entry->addend 86 - (input_section->output_section->vma 87 + input_section->output_offset); 88 bfd_putb16 ((bfd_vma) insn, hit_data); 89 break; 90 case R_PJ_CODE_LO16: 91 insn = bfd_getb16 (hit_data); 92 insn += sym_value + reloc_entry->addend; 93 bfd_putb16 ((bfd_vma) insn, hit_data); 94 break; 95 96 case R_PJ_CODE_HI16: 97 insn = bfd_getb16 (hit_data); 98 insn += (sym_value + reloc_entry->addend) >> 16; 99 bfd_putb16 ((bfd_vma) insn, hit_data); 100 break; 101 102 default: 103 abort (); 104 break; 105 } 106 107 return bfd_reloc_ok; 108 } 109 110 static reloc_howto_type pj_elf_howto_table[] = 111 { 112 /* No relocation. */ 113 HOWTO (R_PJ_NONE, /* type */ 114 0, /* rightshift */ 115 0, /* size (0 = byte, 1 = short, 2 = long) */ 116 0, /* bitsize */ 117 FALSE, /* pc_relative */ 118 0, /* bitpos */ 119 complain_overflow_dont, /* complain_on_overflow */ 120 pj_elf_reloc, /* special_function */ 121 "R_PJ_NONE", /* name */ 122 FALSE, /* partial_inplace */ 123 0, /* src_mask */ 124 0, /* dst_mask */ 125 FALSE), /* pcrel_offset */ 126 127 /* 32 bit absolute relocation. Setting partial_inplace to TRUE and 128 src_mask to a non-zero value is similar to the COFF toolchain. */ 129 HOWTO (R_PJ_DATA_DIR32, /* type */ 130 0, /* rightshift */ 131 2, /* size (0 = byte, 1 = short, 2 = long) */ 132 32, /* bitsize */ 133 FALSE, /* pc_relative */ 134 0, /* bitpos */ 135 complain_overflow_bitfield, /* complain_on_overflow */ 136 pj_elf_reloc, /* special_function */ 137 "R_PJ_DIR32", /* name */ 138 TRUE, /* partial_inplace */ 139 0xffffffff, /* src_mask */ 140 0xffffffff, /* dst_mask */ 141 FALSE), /* pcrel_offset */ 142 143 /* 32 bit PC relative relocation. */ 144 HOWTO (R_PJ_CODE_REL32, /* type */ 145 0, /* rightshift */ 146 2, /* size (0 = byte, 1 = short, 2 = long) */ 147 32, /* bitsize */ 148 TRUE, /* pc_relative */ 149 0, /* bitpos */ 150 complain_overflow_signed, /* complain_on_overflow */ 151 pj_elf_reloc, /* special_function */ 152 "R_PJ_REL32", /* name */ 153 FALSE, /* partial_inplace */ 154 0, /* src_mask */ 155 0xffffffff, /* dst_mask */ 156 TRUE), /* pcrel_offset */ 157 158 /* 16 bit PC relative relocation. */ 159 HOWTO (R_PJ_CODE_REL16, /* type */ 160 0, /* rightshift */ 161 1, /* size (0 = byte, 1 = short, 2 = long) */ 162 16, /* bitsize */ 163 TRUE, /* pc_relative */ 164 0, /* bitpos */ 165 complain_overflow_signed, /* complain_on_overf6w */ 166 pj_elf_reloc, /* special_function */ 167 "R_PJ_REL16", /* name */ 168 FALSE, /* partial_inplace */ 169 0xffff, /* src_mask */ 170 0xffff, /* dst_mask */ 171 TRUE), /* pcrel_offset */ 172 EMPTY_HOWTO (4), 173 EMPTY_HOWTO (5), 174 HOWTO (R_PJ_CODE_DIR32, /* type */ 175 0, /* rightshift */ 176 2, /* size (0 = byte, 1 = short, 2 = long) */ 177 32, /* bitsize */ 178 FALSE, /* pc_relative */ 179 0, /* bitpos */ 180 complain_overflow_bitfield, /* complain_on_overflow */ 181 pj_elf_reloc, /* special_function */ 182 "R_PJ_CODE_DIR32", /* name */ 183 TRUE, /* partial_inplace */ 184 0xffffffff, /* src_mask */ 185 0xffffffff, /* dst_mask */ 186 FALSE), /* pcrel_offset */ 187 188 EMPTY_HOWTO (7), 189 EMPTY_HOWTO (8), 190 EMPTY_HOWTO (9), 191 EMPTY_HOWTO (10), 192 EMPTY_HOWTO (11), 193 EMPTY_HOWTO (12), 194 195 HOWTO (R_PJ_CODE_LO16, /* type */ 196 0, /* rightshift */ 197 1, /* size (0 = byte, 1 = short, 2 = long) */ 198 16, /* bitsize */ 199 FALSE, /* pc_relative */ 200 0, /* bitpos */ 201 complain_overflow_unsigned, /* complain_on_overflow */ 202 pj_elf_reloc, /* special_function */ 203 "R_PJ_LO16", /* name */ 204 FALSE, /* partial_inplace */ 205 0xffff, /* src_mask */ 206 0xffff, /* dst_mask */ 207 TRUE), /* pcrel_offset */ 208 209 HOWTO (R_PJ_CODE_HI16, /* type */ 210 16, /* rightshift */ 211 1, /* size (0 = byte, 1 = short, 2 = long) */ 212 16, /* bitsize */ 213 FALSE, /* pc_relative */ 214 0, /* bitpos */ 215 complain_overflow_unsigned, /* complain_on_overflow */ 216 pj_elf_reloc, /* special_function */ 217 "R_PJ_HI16", /* name */ 218 FALSE, /* partial_inplace */ 219 0xffff, /* src_mask */ 220 0xffff, /* dst_mask */ 221 TRUE), /* pcrel_offset */ 222 223 /* GNU extension to record C++ vtable hierarchy. */ 224 HOWTO (R_PJ_GNU_VTINHERIT, /* type */ 225 0, /* rightshift */ 226 2, /* size (0 = byte, 1 = short, 2 = long) */ 227 0, /* bitsize */ 228 FALSE, /* pc_relative */ 229 0, /* bitpos */ 230 complain_overflow_dont, /* complain_on_overflow */ 231 NULL, /* special_function */ 232 "R_PJ_GNU_VTINHERIT", /* name */ 233 FALSE, /* partial_inplace */ 234 0, /* src_mask */ 235 0, /* dst_mask */ 236 FALSE), /* pcrel_offset */ 237 238 /* GNU extension to record C++ vtable member usage. */ 239 HOWTO (R_PJ_GNU_VTENTRY, /* type */ 240 0, /* rightshift */ 241 2, /* size (0 = byte, 1 = short, 2 = long) */ 242 0, /* bitsize */ 243 FALSE, /* pc_relative */ 244 0, /* bitpos */ 245 complain_overflow_dont, /* complain_on_overflow */ 246 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 247 "R_PJ_GNU_VTENTRY", /* name */ 248 FALSE, /* partial_inplace */ 249 0, /* src_mask */ 250 0, /* dst_mask */ 251 FALSE), /* pcrel_offset */ 252 }; 253 254 /* This structure is used to map BFD reloc codes to PJ ELF relocs. */ 255 256 struct elf_reloc_map 257 { 258 bfd_reloc_code_real_type bfd_reloc_val; 259 unsigned char elf_reloc_val; 260 }; 261 262 /* An array mapping BFD reloc codes to PJ ELF relocs. */ 263 264 static const struct elf_reloc_map pj_reloc_map[] = 265 { 266 { BFD_RELOC_NONE, R_PJ_NONE }, 267 { BFD_RELOC_32, R_PJ_DATA_DIR32 }, 268 { BFD_RELOC_PJ_CODE_DIR16, R_PJ_CODE_DIR16 }, 269 { BFD_RELOC_PJ_CODE_DIR32, R_PJ_CODE_DIR32 }, 270 { BFD_RELOC_PJ_CODE_LO16, R_PJ_CODE_LO16 }, 271 { BFD_RELOC_PJ_CODE_HI16, R_PJ_CODE_HI16 }, 272 { BFD_RELOC_PJ_CODE_REL32, R_PJ_CODE_REL32 }, 273 { BFD_RELOC_PJ_CODE_REL16, R_PJ_CODE_REL16 }, 274 { BFD_RELOC_VTABLE_INHERIT, R_PJ_GNU_VTINHERIT }, 275 { BFD_RELOC_VTABLE_ENTRY, R_PJ_GNU_VTENTRY }, 276 }; 277 278 /* Given a BFD reloc code, return the howto structure for the 279 corresponding PJ ELf reloc. */ 280 281 static reloc_howto_type * 282 pj_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 283 bfd_reloc_code_real_type code) 284 { 285 unsigned int i; 286 287 for (i = 0; i < sizeof (pj_reloc_map) / sizeof (struct elf_reloc_map); i++) 288 if (pj_reloc_map[i].bfd_reloc_val == code) 289 return & pj_elf_howto_table[(int) pj_reloc_map[i].elf_reloc_val]; 290 291 return NULL; 292 } 293 294 /* Given an ELF reloc, fill in the howto field of a relent. */ 295 296 static void 297 pj_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, 298 arelent *cache_ptr, 299 Elf_Internal_Rela *dst) 300 { 301 unsigned int r; 302 303 r = ELF32_R_TYPE (dst->r_info); 304 305 BFD_ASSERT (r < (unsigned int) R_PJ_max); 306 307 cache_ptr->howto = &pj_elf_howto_table[r]; 308 } 309 310 /* Take this moment to fill in the special picoJava bits in the 311 e_flags field. */ 312 313 static void 314 pj_elf_final_write_processing (bfd *abfd, 315 bfd_boolean linker ATTRIBUTE_UNUSED) 316 { 317 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_ARCH; 318 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_GNUCALLS; 319 } 320 321 #define TARGET_BIG_SYM bfd_elf32_pj_vec 322 #define TARGET_BIG_NAME "elf32-pj" 323 #define TARGET_LITTLE_SYM bfd_elf32_pjl_vec 324 #define TARGET_LITTLE_NAME "elf32-pjl" 325 #define ELF_ARCH bfd_arch_pj 326 #define ELF_MACHINE_CODE EM_PJ 327 #define ELF_MACHINE_ALT1 EM_PJ_OLD 328 #define ELF_MAXPAGESIZE 0x1000 329 #define bfd_elf32_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 330 #define bfd_elf32_bfd_reloc_type_lookup pj_elf_reloc_type_lookup 331 #define elf_backend_final_write_processing pj_elf_final_write_processing 332 #define elf_info_to_howto pj_elf_info_to_howto 333 #include "elf32-target.h" 334