1/* picoJava specific support for 32-bit ELF 2 Copyright 1999, 2000, 2001, 2002, 2005, 2007 3 Free Software Foundation, Inc. 4 Contributed by Steve Chamberlan of Transmeta (sac@pobox.com). 5 6 This file is part of BFD, the Binary File Descriptor library. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 MA 02110-1301, USA. */ 22 23#include "sysdep.h" 24#include "bfd.h" 25#include "bfdlink.h" 26#include "libbfd.h" 27#include "elf-bfd.h" 28#include "elf/pj.h" 29 30/* This function is used for normal relocs. This is like the COFF 31 function, and is almost certainly incorrect for other ELF targets. */ 32 33static bfd_reloc_status_type 34pj_elf_reloc (bfd *abfd, 35 arelent *reloc_entry, 36 asymbol *symbol_in, 37 void * data, 38 asection *input_section, 39 bfd *output_bfd, 40 char **error_message ATTRIBUTE_UNUSED) 41{ 42 unsigned long insn; 43 bfd_vma sym_value; 44 enum elf_pj_reloc_type r_type; 45 bfd_vma addr = reloc_entry->address; 46 bfd_byte *hit_data = addr + (bfd_byte *) data; 47 48 r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type; 49 50 if (output_bfd != NULL) 51 { 52 /* Partial linking--do nothing. */ 53 reloc_entry->address += input_section->output_offset; 54 return bfd_reloc_ok; 55 } 56 57 if (symbol_in != NULL 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 112static reloc_howto_type pj_elf_howto_table[] = 113{ 114 /* No relocation. */ 115 HOWTO (R_PJ_NONE, /* type */ 116 0, /* rightshift */ 117 0, /* size (0 = byte, 1 = short, 2 = long) */ 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 2, /* size (0 = byte, 1 = short, 2 = long) */ 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 2, /* size (0 = byte, 1 = short, 2 = long) */ 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 1, /* size (0 = byte, 1 = short, 2 = long) */ 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 2, /* size (0 = byte, 1 = short, 2 = long) */ 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 1, /* size (0 = byte, 1 = short, 2 = long) */ 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 1, /* size (0 = byte, 1 = short, 2 = long) */ 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 2, /* size (0 = byte, 1 = short, 2 = long) */ 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 2, /* size (0 = byte, 1 = short, 2 = long) */ 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 258struct 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 266static 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 283static reloc_howto_type * 284pj_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 296static reloc_howto_type * 297pj_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 314static void 315pj_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, 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 BFD_ASSERT (r < (unsigned int) R_PJ_max); 324 325 cache_ptr->howto = &pj_elf_howto_table[r]; 326} 327 328/* Take this moment to fill in the special picoJava bits in the 329 e_flags field. */ 330 331static void 332pj_elf_final_write_processing (bfd *abfd, 333 bfd_boolean linker ATTRIBUTE_UNUSED) 334{ 335 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_ARCH; 336 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_GNUCALLS; 337} 338 339#define TARGET_BIG_SYM bfd_elf32_pj_vec 340#define TARGET_BIG_NAME "elf32-pj" 341#define TARGET_LITTLE_SYM bfd_elf32_pjl_vec 342#define TARGET_LITTLE_NAME "elf32-pjl" 343#define ELF_ARCH bfd_arch_pj 344#define ELF_MACHINE_CODE EM_PJ 345#define ELF_MACHINE_ALT1 EM_PJ_OLD 346#define ELF_MAXPAGESIZE 0x1000 347#define bfd_elf32_bfd_get_relocated_section_contents \ 348 bfd_generic_get_relocated_section_contents 349#define bfd_elf32_bfd_reloc_type_lookup pj_elf_reloc_type_lookup 350#define bfd_elf32_bfd_reloc_name_lookup pj_elf_reloc_name_lookup 351#define elf_backend_final_write_processing pj_elf_final_write_processing 352#define elf_info_to_howto pj_elf_info_to_howto 353#include "elf32-target.h" 354