1*a1ba9ba4Schristos /* Visium-specific support for 32-bit ELF. 2*a1ba9ba4Schristos 3*a1ba9ba4Schristos Copyright (C) 2003-2015 Free Software Foundation, Inc. 4*a1ba9ba4Schristos 5*a1ba9ba4Schristos This file is part of BFD, the Binary File Descriptor library. 6*a1ba9ba4Schristos 7*a1ba9ba4Schristos This program is free software; you can redistribute it and/or modify 8*a1ba9ba4Schristos it under the terms of the GNU General Public License as published by 9*a1ba9ba4Schristos the Free Software Foundation; either version 3 of the License, or 10*a1ba9ba4Schristos (at your option) any later version. 11*a1ba9ba4Schristos 12*a1ba9ba4Schristos This program is distributed in the hope that it will be useful, 13*a1ba9ba4Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 14*a1ba9ba4Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*a1ba9ba4Schristos GNU General Public License for more details. 16*a1ba9ba4Schristos 17*a1ba9ba4Schristos You should have received a copy of the GNU General Public License 18*a1ba9ba4Schristos along with this program; if not, write to the Free Software 19*a1ba9ba4Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, 20*a1ba9ba4Schristos Boston, MA 02110-1301, USA. */ 21*a1ba9ba4Schristos 22*a1ba9ba4Schristos #include "sysdep.h" 23*a1ba9ba4Schristos #include "bfd.h" 24*a1ba9ba4Schristos #include "sysdep.h" 25*a1ba9ba4Schristos #include "libbfd.h" 26*a1ba9ba4Schristos #include "elf-bfd.h" 27*a1ba9ba4Schristos #include "elf/visium.h" 28*a1ba9ba4Schristos 29*a1ba9ba4Schristos static bfd_reloc_status_type visium_elf_howto_parity_reloc 30*a1ba9ba4Schristos (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **); 31*a1ba9ba4Schristos 32*a1ba9ba4Schristos static reloc_howto_type visium_elf_howto_table[] = { 33*a1ba9ba4Schristos /* This reloc does nothing. */ 34*a1ba9ba4Schristos HOWTO (R_VISIUM_NONE, /* type */ 35*a1ba9ba4Schristos 0, /* rightshift */ 36*a1ba9ba4Schristos 3, /* size (0 = byte, 1 = short, 2 = long) */ 37*a1ba9ba4Schristos 0, /* bitsize */ 38*a1ba9ba4Schristos FALSE, /* pc_relative */ 39*a1ba9ba4Schristos 0, /* bitpos */ 40*a1ba9ba4Schristos complain_overflow_dont, /* complain_on_overflow */ 41*a1ba9ba4Schristos bfd_elf_generic_reloc, /* special_function */ 42*a1ba9ba4Schristos "R_VISIUM_NONE", /* name */ 43*a1ba9ba4Schristos FALSE, /* partial_inplace */ 44*a1ba9ba4Schristos 0, /* src_mask */ 45*a1ba9ba4Schristos 0, /* dst_mask */ 46*a1ba9ba4Schristos FALSE), /* pcrel_offset */ 47*a1ba9ba4Schristos 48*a1ba9ba4Schristos /* A 8 bit absolute relocation. */ 49*a1ba9ba4Schristos HOWTO (R_VISIUM_8, /* type */ 50*a1ba9ba4Schristos 0, /* rightshift */ 51*a1ba9ba4Schristos 0, /* size (0 = byte, 1 = short, 2 = long) */ 52*a1ba9ba4Schristos 8, /* bitsize */ 53*a1ba9ba4Schristos FALSE, /* pc_relative */ 54*a1ba9ba4Schristos 0, /* bitpos */ 55*a1ba9ba4Schristos complain_overflow_bitfield, /* complain_on_overflow */ 56*a1ba9ba4Schristos bfd_elf_generic_reloc, /* special_function */ 57*a1ba9ba4Schristos "R_VISIUM_8", /* name */ 58*a1ba9ba4Schristos FALSE, /* partial_inplace */ 59*a1ba9ba4Schristos 0x00, /* src_mask */ 60*a1ba9ba4Schristos 0xff, /* dst_mask */ 61*a1ba9ba4Schristos FALSE), /* pcrel_offset */ 62*a1ba9ba4Schristos 63*a1ba9ba4Schristos /* A 16 bit absolute relocation. */ 64*a1ba9ba4Schristos HOWTO (R_VISIUM_16, /* type */ 65*a1ba9ba4Schristos 0, /* rightshift */ 66*a1ba9ba4Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */ 67*a1ba9ba4Schristos 16, /* bitsize */ 68*a1ba9ba4Schristos FALSE, /* pc_relative */ 69*a1ba9ba4Schristos 0, /* bitpos */ 70*a1ba9ba4Schristos complain_overflow_bitfield, /* complain_on_overflow */ 71*a1ba9ba4Schristos bfd_elf_generic_reloc, /* special_function */ 72*a1ba9ba4Schristos "R_VISIUM_16", /* name */ 73*a1ba9ba4Schristos FALSE, /* partial_inplace */ 74*a1ba9ba4Schristos 0x0000, /* src_mask */ 75*a1ba9ba4Schristos 0xffff, /* dst_mask */ 76*a1ba9ba4Schristos FALSE), /* pcrel_offset */ 77*a1ba9ba4Schristos 78*a1ba9ba4Schristos /* A 32 bit absolute relocation. */ 79*a1ba9ba4Schristos HOWTO (R_VISIUM_32, /* type */ 80*a1ba9ba4Schristos 0, /* rightshift */ 81*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 82*a1ba9ba4Schristos 32, /* bitsize */ 83*a1ba9ba4Schristos FALSE, /* pc_relative */ 84*a1ba9ba4Schristos 0, /* bitpos */ 85*a1ba9ba4Schristos complain_overflow_bitfield, /* complain_on_overflow */ 86*a1ba9ba4Schristos bfd_elf_generic_reloc, /* special_function */ 87*a1ba9ba4Schristos "R_VISIUM_32", /* name */ 88*a1ba9ba4Schristos FALSE, /* partial_inplace */ 89*a1ba9ba4Schristos 0x00000000, /* src_mask */ 90*a1ba9ba4Schristos 0xffffffff, /* dst_mask */ 91*a1ba9ba4Schristos FALSE), /* pcrel_offset */ 92*a1ba9ba4Schristos 93*a1ba9ba4Schristos 94*a1ba9ba4Schristos /* A 8 bit PC relative relocation. */ 95*a1ba9ba4Schristos HOWTO (R_VISIUM_8_PCREL, /* type */ 96*a1ba9ba4Schristos 0, /* rightshift */ 97*a1ba9ba4Schristos 0, /* size (0 = byte, 1 = short, 2 = long) */ 98*a1ba9ba4Schristos 8, /* bitsize */ 99*a1ba9ba4Schristos TRUE, /* pc_relative */ 100*a1ba9ba4Schristos 0, /* bitpos */ 101*a1ba9ba4Schristos complain_overflow_bitfield, /* complain_on_overflow */ 102*a1ba9ba4Schristos bfd_elf_generic_reloc, /* special_function */ 103*a1ba9ba4Schristos "R_VISIUM_8_PCREL", /* name */ 104*a1ba9ba4Schristos FALSE, /* partial_inplace */ 105*a1ba9ba4Schristos 0x00, /* src_mask */ 106*a1ba9ba4Schristos 0xff, /* dst_mask */ 107*a1ba9ba4Schristos TRUE), /* pcrel_offset */ 108*a1ba9ba4Schristos 109*a1ba9ba4Schristos /* A 16 bit PC relative relocation. */ 110*a1ba9ba4Schristos HOWTO (R_VISIUM_16_PCREL, /* type */ 111*a1ba9ba4Schristos 0, /* rightshift */ 112*a1ba9ba4Schristos 1, /* size (0 = byte, 1 = short, 2 = long) */ 113*a1ba9ba4Schristos 16, /* bitsize */ 114*a1ba9ba4Schristos TRUE, /* pc_relative */ 115*a1ba9ba4Schristos 0, /* bitpos */ 116*a1ba9ba4Schristos complain_overflow_bitfield, /* complain_on_overflow */ 117*a1ba9ba4Schristos bfd_elf_generic_reloc, /* special_function */ 118*a1ba9ba4Schristos "R_VISIUM_16_PCREL", /* name */ 119*a1ba9ba4Schristos FALSE, /* partial inplace */ 120*a1ba9ba4Schristos 0x0000, /* src_mask */ 121*a1ba9ba4Schristos 0xffff, /* dst_mask */ 122*a1ba9ba4Schristos TRUE), /* pcrel_offset */ 123*a1ba9ba4Schristos 124*a1ba9ba4Schristos /* A 32-bit PC relative relocation. */ 125*a1ba9ba4Schristos HOWTO (R_VISIUM_32_PCREL, /* type */ 126*a1ba9ba4Schristos 0, /* rightshift */ 127*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 128*a1ba9ba4Schristos 32, /* bitsize */ 129*a1ba9ba4Schristos TRUE, /* pc_relative */ 130*a1ba9ba4Schristos 0, /* bitpos */ 131*a1ba9ba4Schristos complain_overflow_bitfield, /* complain_on_overflow */ 132*a1ba9ba4Schristos bfd_elf_generic_reloc, /* special_function */ 133*a1ba9ba4Schristos "R_VISIUM_32_PCREL", /* name */ 134*a1ba9ba4Schristos FALSE, /* partial_inplace */ 135*a1ba9ba4Schristos 0, /* src_mask */ 136*a1ba9ba4Schristos 0xffffffff, /* dst_mask */ 137*a1ba9ba4Schristos TRUE), /* pcrel_offset */ 138*a1ba9ba4Schristos 139*a1ba9ba4Schristos /* A 16-bit PC word relative offset, relative to start of instruction 140*a1ba9ba4Schristos and always in the second half of the instruction. */ 141*a1ba9ba4Schristos HOWTO (R_VISIUM_PC16, /* type */ 142*a1ba9ba4Schristos 2, /* rightshift */ 143*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 144*a1ba9ba4Schristos 16, /* bitsize */ 145*a1ba9ba4Schristos TRUE, /* pc_relative */ 146*a1ba9ba4Schristos 0, /* bitpos */ 147*a1ba9ba4Schristos complain_overflow_signed, /* complain_on_overflow */ 148*a1ba9ba4Schristos visium_elf_howto_parity_reloc, /* special_function */ 149*a1ba9ba4Schristos "R_VISIUM_PC16", /* name */ 150*a1ba9ba4Schristos FALSE, /* partial_inplace */ 151*a1ba9ba4Schristos 0x00000000, /* src_mask */ 152*a1ba9ba4Schristos 0x0000ffff, /* dst_mask */ 153*a1ba9ba4Schristos TRUE), /* pcrel_offset */ 154*a1ba9ba4Schristos 155*a1ba9ba4Schristos /* The high 16 bits of symbol value. */ 156*a1ba9ba4Schristos HOWTO (R_VISIUM_HI16, /* type */ 157*a1ba9ba4Schristos 16, /* rightshift */ 158*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 159*a1ba9ba4Schristos 16, /* bitsize */ 160*a1ba9ba4Schristos FALSE, /* pc_relative */ 161*a1ba9ba4Schristos 0, /* bitpos */ 162*a1ba9ba4Schristos complain_overflow_dont, /* complain_on_overflow */ 163*a1ba9ba4Schristos visium_elf_howto_parity_reloc, /* special_function */ 164*a1ba9ba4Schristos "R_VISIUM_HI16", /* name */ 165*a1ba9ba4Schristos FALSE, /* partial_inplace */ 166*a1ba9ba4Schristos 0x00000000, /* src_mask */ 167*a1ba9ba4Schristos 0x0000ffff, /* dst_mask */ 168*a1ba9ba4Schristos FALSE), /* pcrel_offset */ 169*a1ba9ba4Schristos 170*a1ba9ba4Schristos /* The low 16 bits of symbol value. */ 171*a1ba9ba4Schristos HOWTO (R_VISIUM_LO16, /* type */ 172*a1ba9ba4Schristos 0, /* rightshift */ 173*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 174*a1ba9ba4Schristos 16, /* bitsize */ 175*a1ba9ba4Schristos FALSE, /* pc_relative */ 176*a1ba9ba4Schristos 0, /* bitpos */ 177*a1ba9ba4Schristos complain_overflow_dont, /* complain_on_overflow */ 178*a1ba9ba4Schristos visium_elf_howto_parity_reloc, /* special_function */ 179*a1ba9ba4Schristos "R_VISIUM_LO16", /* name */ 180*a1ba9ba4Schristos FALSE, /* partial_inplace */ 181*a1ba9ba4Schristos 0x00000000, /* src_mask */ 182*a1ba9ba4Schristos 0x0000ffff, /* dst_mask */ 183*a1ba9ba4Schristos FALSE), /* pcrel_offset */ 184*a1ba9ba4Schristos 185*a1ba9ba4Schristos /* A 16 bit immediate value. */ 186*a1ba9ba4Schristos HOWTO (R_VISIUM_IM16, /* type */ 187*a1ba9ba4Schristos 0, /* rightshift */ 188*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 189*a1ba9ba4Schristos 16, /* bitsize */ 190*a1ba9ba4Schristos FALSE, /* pc_relative */ 191*a1ba9ba4Schristos 0, /* bitpos */ 192*a1ba9ba4Schristos complain_overflow_unsigned, /* complain_on_overflow */ 193*a1ba9ba4Schristos visium_elf_howto_parity_reloc, /* special_function */ 194*a1ba9ba4Schristos "R_VISIUM_IM16", /* name */ 195*a1ba9ba4Schristos FALSE, /* partial_inplace */ 196*a1ba9ba4Schristos 0x0000000, /* src_mask */ 197*a1ba9ba4Schristos 0x000ffff, /* dst_mask */ 198*a1ba9ba4Schristos FALSE), /* pcrel_offset */ 199*a1ba9ba4Schristos 200*a1ba9ba4Schristos /* The high 16 bits of symbol value, pc relative. */ 201*a1ba9ba4Schristos HOWTO (R_VISIUM_HI16_PCREL, /* type */ 202*a1ba9ba4Schristos 16, /* rightshift */ 203*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 204*a1ba9ba4Schristos 16, /* bitsize */ 205*a1ba9ba4Schristos TRUE, /* pc_relative */ 206*a1ba9ba4Schristos 0, /* bitpos */ 207*a1ba9ba4Schristos complain_overflow_dont, /* complain_on_overflow */ 208*a1ba9ba4Schristos visium_elf_howto_parity_reloc, /* special_function */ 209*a1ba9ba4Schristos "R_VISIUM_HI16_PCREL", /* name */ 210*a1ba9ba4Schristos FALSE, /* partial_inplace */ 211*a1ba9ba4Schristos 0x00000000, /* src_mask */ 212*a1ba9ba4Schristos 0x0000ffff, /* dst_mask */ 213*a1ba9ba4Schristos TRUE), /* pcrel_offset */ 214*a1ba9ba4Schristos 215*a1ba9ba4Schristos /* The low 16 bits of symbol value, pc relative. */ 216*a1ba9ba4Schristos HOWTO (R_VISIUM_LO16_PCREL, /* type */ 217*a1ba9ba4Schristos 0, /* rightshift */ 218*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 219*a1ba9ba4Schristos 16, /* bitsize */ 220*a1ba9ba4Schristos TRUE, /* pc_relative */ 221*a1ba9ba4Schristos 0, /* bitpos */ 222*a1ba9ba4Schristos complain_overflow_dont, /* complain_on_overflow */ 223*a1ba9ba4Schristos visium_elf_howto_parity_reloc, /* special_function */ 224*a1ba9ba4Schristos "R_VISIUM_LO16_PCREL", /* name */ 225*a1ba9ba4Schristos FALSE, /* partial_inplace */ 226*a1ba9ba4Schristos 0x00000000, /* src_mask */ 227*a1ba9ba4Schristos 0x0000ffff, /* dst_mask */ 228*a1ba9ba4Schristos TRUE), /* pcrel_offset */ 229*a1ba9ba4Schristos 230*a1ba9ba4Schristos /* A 16 bit immediate value, pc relative. */ 231*a1ba9ba4Schristos HOWTO (R_VISIUM_IM16_PCREL, /* type */ 232*a1ba9ba4Schristos 0, /* rightshift */ 233*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 234*a1ba9ba4Schristos 16, /* bitsize */ 235*a1ba9ba4Schristos TRUE, /* pc_relative */ 236*a1ba9ba4Schristos 0, /* bitpos */ 237*a1ba9ba4Schristos complain_overflow_unsigned, /* complain_on_overflow */ 238*a1ba9ba4Schristos visium_elf_howto_parity_reloc, /* special_function */ 239*a1ba9ba4Schristos "R_VISIUM_IM16_PCREL", /* name */ 240*a1ba9ba4Schristos FALSE, /* partial_inplace */ 241*a1ba9ba4Schristos 0x0000000, /* src_mask */ 242*a1ba9ba4Schristos 0x000ffff, /* dst_mask */ 243*a1ba9ba4Schristos TRUE), /* pcrel_offset */ 244*a1ba9ba4Schristos 245*a1ba9ba4Schristos }; 246*a1ba9ba4Schristos 247*a1ba9ba4Schristos /* GNU extension to record C++ vtable hierarchy. */ 248*a1ba9ba4Schristos static reloc_howto_type visium_elf_vtinherit_howto = 249*a1ba9ba4Schristos HOWTO (R_VISIUM_GNU_VTINHERIT, /* type */ 250*a1ba9ba4Schristos 0, /* rightshift */ 251*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 252*a1ba9ba4Schristos 0, /* bitsize */ 253*a1ba9ba4Schristos FALSE, /* pc_relative */ 254*a1ba9ba4Schristos 0, /* bitpos */ 255*a1ba9ba4Schristos complain_overflow_dont, /* complain_on_overflow */ 256*a1ba9ba4Schristos NULL, /* special_function */ 257*a1ba9ba4Schristos "R_VISIUM_GNU_VTINHERIT", /* name */ 258*a1ba9ba4Schristos FALSE, /* partial_inplace */ 259*a1ba9ba4Schristos 0, /* src_mask */ 260*a1ba9ba4Schristos 0, /* dst_mask */ 261*a1ba9ba4Schristos FALSE); /* pcrel_offset */ 262*a1ba9ba4Schristos 263*a1ba9ba4Schristos /* GNU extension to record C++ vtable member usage. */ 264*a1ba9ba4Schristos static reloc_howto_type visium_elf_vtentry_howto = 265*a1ba9ba4Schristos HOWTO (R_VISIUM_GNU_VTENTRY, /* type */ 266*a1ba9ba4Schristos 0, /* rightshift */ 267*a1ba9ba4Schristos 2, /* size (0 = byte, 1 = short, 2 = long) */ 268*a1ba9ba4Schristos 0, /* bitsize */ 269*a1ba9ba4Schristos FALSE, /* pc_relative */ 270*a1ba9ba4Schristos 0, /* bitpos */ 271*a1ba9ba4Schristos complain_overflow_dont, /* complain_on_overflow */ 272*a1ba9ba4Schristos NULL, /* special_function */ 273*a1ba9ba4Schristos "R_VISIUM_GNU_VTENTRY", /* name */ 274*a1ba9ba4Schristos FALSE, /* partial_inplace */ 275*a1ba9ba4Schristos 0, /* src_mask */ 276*a1ba9ba4Schristos 0, /* dst_mask */ 277*a1ba9ba4Schristos FALSE); /* pcrel_offset */ 278*a1ba9ba4Schristos 279*a1ba9ba4Schristos /* Map BFD reloc types to VISIUM ELF reloc types. */ 280*a1ba9ba4Schristos struct visium_reloc_map 281*a1ba9ba4Schristos { 282*a1ba9ba4Schristos bfd_reloc_code_real_type bfd_reloc_val; 283*a1ba9ba4Schristos unsigned int visium_reloc_val; 284*a1ba9ba4Schristos }; 285*a1ba9ba4Schristos 286*a1ba9ba4Schristos static const struct visium_reloc_map visium_reloc_map[] = { 287*a1ba9ba4Schristos {BFD_RELOC_NONE, R_VISIUM_NONE}, 288*a1ba9ba4Schristos {BFD_RELOC_8, R_VISIUM_8}, 289*a1ba9ba4Schristos {BFD_RELOC_16, R_VISIUM_16}, 290*a1ba9ba4Schristos {BFD_RELOC_32, R_VISIUM_32}, 291*a1ba9ba4Schristos {BFD_RELOC_8_PCREL, R_VISIUM_8_PCREL}, 292*a1ba9ba4Schristos {BFD_RELOC_16_PCREL, R_VISIUM_16_PCREL}, 293*a1ba9ba4Schristos {BFD_RELOC_32_PCREL, R_VISIUM_32_PCREL}, 294*a1ba9ba4Schristos {BFD_RELOC_VISIUM_REL16, R_VISIUM_PC16}, 295*a1ba9ba4Schristos {BFD_RELOC_VISIUM_HI16, R_VISIUM_HI16}, 296*a1ba9ba4Schristos {BFD_RELOC_VISIUM_LO16, R_VISIUM_LO16}, 297*a1ba9ba4Schristos {BFD_RELOC_VISIUM_IM16, R_VISIUM_IM16}, 298*a1ba9ba4Schristos {BFD_RELOC_VISIUM_HI16_PCREL, R_VISIUM_HI16_PCREL}, 299*a1ba9ba4Schristos {BFD_RELOC_VISIUM_LO16_PCREL, R_VISIUM_LO16_PCREL}, 300*a1ba9ba4Schristos {BFD_RELOC_VISIUM_IM16_PCREL, R_VISIUM_IM16_PCREL}, 301*a1ba9ba4Schristos {BFD_RELOC_VTABLE_INHERIT, R_VISIUM_GNU_VTINHERIT}, 302*a1ba9ba4Schristos {BFD_RELOC_VTABLE_ENTRY, R_VISIUM_GNU_VTENTRY}, 303*a1ba9ba4Schristos }; 304*a1ba9ba4Schristos 305*a1ba9ba4Schristos /* Return the parity bit for INSN shifted to its final position. */ 306*a1ba9ba4Schristos 307*a1ba9ba4Schristos static bfd_vma 308*a1ba9ba4Schristos visium_parity_bit (bfd_vma insn) 309*a1ba9ba4Schristos { 310*a1ba9ba4Schristos bfd_vma p = 0; 311*a1ba9ba4Schristos int i; 312*a1ba9ba4Schristos 313*a1ba9ba4Schristos for (i = 0; i < 31; i++) 314*a1ba9ba4Schristos { 315*a1ba9ba4Schristos p ^= (insn & 1); 316*a1ba9ba4Schristos insn >>= 1; 317*a1ba9ba4Schristos } 318*a1ba9ba4Schristos 319*a1ba9ba4Schristos return p << 31; 320*a1ba9ba4Schristos } 321*a1ba9ba4Schristos 322*a1ba9ba4Schristos /* This "special function" will only be used when the input and 323*a1ba9ba4Schristos output files have different formats ie. when generating S-records 324*a1ba9ba4Schristos directly using "--oformat srec". Otherwise we use 325*a1ba9ba4Schristos _bfd_final_link_relocate which uses a howto structure, but does 326*a1ba9ba4Schristos not use the special_function field. 327*a1ba9ba4Schristos 328*a1ba9ba4Schristos It sets instruction parity to even. This cannot be done by a howto. */ 329*a1ba9ba4Schristos 330*a1ba9ba4Schristos static bfd_reloc_status_type 331*a1ba9ba4Schristos visium_elf_howto_parity_reloc (bfd * input_bfd, arelent *reloc_entry, 332*a1ba9ba4Schristos asymbol *symbol, PTR data, 333*a1ba9ba4Schristos asection *input_section, bfd *output_bfd, 334*a1ba9ba4Schristos char **error_message ATTRIBUTE_UNUSED) 335*a1ba9ba4Schristos { 336*a1ba9ba4Schristos bfd_reloc_status_type ret; 337*a1ba9ba4Schristos bfd_vma relocation; 338*a1ba9ba4Schristos bfd_byte *inplace_address; 339*a1ba9ba4Schristos bfd_vma insn; 340*a1ba9ba4Schristos const bfd_vma signmask = 0xffff8000; 341*a1ba9ba4Schristos 342*a1ba9ba4Schristos /* This part is from bfd_elf_generic_reloc. 343*a1ba9ba4Schristos If we're relocating, and this an external symbol, we don't want 344*a1ba9ba4Schristos to change anything. */ 345*a1ba9ba4Schristos if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0) 346*a1ba9ba4Schristos { 347*a1ba9ba4Schristos reloc_entry->address += input_section->output_offset; 348*a1ba9ba4Schristos return bfd_reloc_ok; 349*a1ba9ba4Schristos } 350*a1ba9ba4Schristos 351*a1ba9ba4Schristos /* Now do the reloc in the usual way. */ 352*a1ba9ba4Schristos 353*a1ba9ba4Schristos /* Sanity check the address (offset in section). */ 354*a1ba9ba4Schristos if (reloc_entry->address > bfd_get_section_limit (input_bfd, input_section)) 355*a1ba9ba4Schristos return bfd_reloc_outofrange; 356*a1ba9ba4Schristos 357*a1ba9ba4Schristos ret = bfd_reloc_ok; 358*a1ba9ba4Schristos if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL) 359*a1ba9ba4Schristos ret = bfd_reloc_undefined; 360*a1ba9ba4Schristos 361*a1ba9ba4Schristos if (bfd_is_com_section (symbol->section) || output_bfd != (bfd *) NULL) 362*a1ba9ba4Schristos relocation = 0; 363*a1ba9ba4Schristos else 364*a1ba9ba4Schristos relocation = symbol->value; 365*a1ba9ba4Schristos 366*a1ba9ba4Schristos /* Only do this for a final link. */ 367*a1ba9ba4Schristos if (output_bfd == (bfd *) NULL) 368*a1ba9ba4Schristos { 369*a1ba9ba4Schristos relocation += symbol->section->output_section->vma; 370*a1ba9ba4Schristos relocation += symbol->section->output_offset; 371*a1ba9ba4Schristos } 372*a1ba9ba4Schristos 373*a1ba9ba4Schristos relocation += reloc_entry->addend; 374*a1ba9ba4Schristos inplace_address = (bfd_byte *) data + reloc_entry->address; 375*a1ba9ba4Schristos insn = bfd_get_32 (input_bfd, inplace_address); 376*a1ba9ba4Schristos 377*a1ba9ba4Schristos if (reloc_entry->howto->pc_relative) 378*a1ba9ba4Schristos { 379*a1ba9ba4Schristos relocation -= input_section->output_section->vma 380*a1ba9ba4Schristos + input_section->output_offset; 381*a1ba9ba4Schristos relocation -= reloc_entry->address; 382*a1ba9ba4Schristos } 383*a1ba9ba4Schristos 384*a1ba9ba4Schristos switch (reloc_entry->howto->type) 385*a1ba9ba4Schristos { 386*a1ba9ba4Schristos case R_VISIUM_PC16: 387*a1ba9ba4Schristos relocation >>= 2; 388*a1ba9ba4Schristos if (ret == bfd_reloc_ok && (relocation & signmask) != 0 389*a1ba9ba4Schristos && (relocation & signmask) != signmask) 390*a1ba9ba4Schristos ret = bfd_reloc_overflow; 391*a1ba9ba4Schristos relocation &= 0xffff; 392*a1ba9ba4Schristos break; 393*a1ba9ba4Schristos case R_VISIUM_HI16: 394*a1ba9ba4Schristos case R_VISIUM_HI16_PCREL: 395*a1ba9ba4Schristos relocation = (relocation >> 16) & 0xffff; 396*a1ba9ba4Schristos break; 397*a1ba9ba4Schristos case R_VISIUM_LO16: 398*a1ba9ba4Schristos case R_VISIUM_LO16_PCREL: 399*a1ba9ba4Schristos relocation &= 0xffff; 400*a1ba9ba4Schristos break; 401*a1ba9ba4Schristos case R_VISIUM_IM16: 402*a1ba9ba4Schristos case R_VISIUM_IM16_PCREL: 403*a1ba9ba4Schristos if (ret == bfd_reloc_ok && (relocation & 0xffff0000) != 0) 404*a1ba9ba4Schristos ret = bfd_reloc_overflow; 405*a1ba9ba4Schristos relocation &= 0xffff; 406*a1ba9ba4Schristos break; 407*a1ba9ba4Schristos } 408*a1ba9ba4Schristos insn = (insn & 0x7fff0000) | relocation; 409*a1ba9ba4Schristos insn |= visium_parity_bit (insn); 410*a1ba9ba4Schristos bfd_put_32 (input_bfd, insn, inplace_address); 411*a1ba9ba4Schristos 412*a1ba9ba4Schristos if (output_bfd != (bfd *) NULL) 413*a1ba9ba4Schristos reloc_entry->address += input_section->output_offset; 414*a1ba9ba4Schristos 415*a1ba9ba4Schristos return ret; 416*a1ba9ba4Schristos } 417*a1ba9ba4Schristos 418*a1ba9ba4Schristos static reloc_howto_type * 419*a1ba9ba4Schristos visium_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 420*a1ba9ba4Schristos bfd_reloc_code_real_type code) 421*a1ba9ba4Schristos { 422*a1ba9ba4Schristos /* Note that the visium_elf_howto_table is indexed by the R_ 423*a1ba9ba4Schristos constants. Thus, the order that the howto records appear in the 424*a1ba9ba4Schristos table *must* match the order of the relocation types defined in 425*a1ba9ba4Schristos include/elf/visium.h. */ 426*a1ba9ba4Schristos switch (code) 427*a1ba9ba4Schristos { 428*a1ba9ba4Schristos case BFD_RELOC_NONE: 429*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_NONE]; 430*a1ba9ba4Schristos case BFD_RELOC_8: 431*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_8]; 432*a1ba9ba4Schristos case BFD_RELOC_16: 433*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_16]; 434*a1ba9ba4Schristos case BFD_RELOC_32: 435*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_32]; 436*a1ba9ba4Schristos case BFD_RELOC_8_PCREL: 437*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_8_PCREL]; 438*a1ba9ba4Schristos case BFD_RELOC_16_PCREL: 439*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_16_PCREL]; 440*a1ba9ba4Schristos case BFD_RELOC_32_PCREL: 441*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_32_PCREL]; 442*a1ba9ba4Schristos case BFD_RELOC_VISIUM_REL16: 443*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_PC16]; 444*a1ba9ba4Schristos case BFD_RELOC_VISIUM_HI16: 445*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_HI16]; 446*a1ba9ba4Schristos case BFD_RELOC_VISIUM_LO16: 447*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_LO16]; 448*a1ba9ba4Schristos case BFD_RELOC_VISIUM_IM16: 449*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_IM16]; 450*a1ba9ba4Schristos case BFD_RELOC_VISIUM_HI16_PCREL: 451*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_HI16_PCREL]; 452*a1ba9ba4Schristos case BFD_RELOC_VISIUM_LO16_PCREL: 453*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_LO16_PCREL]; 454*a1ba9ba4Schristos case BFD_RELOC_VISIUM_IM16_PCREL: 455*a1ba9ba4Schristos return &visium_elf_howto_table[(int) R_VISIUM_IM16_PCREL]; 456*a1ba9ba4Schristos case BFD_RELOC_VTABLE_INHERIT: 457*a1ba9ba4Schristos return &visium_elf_vtinherit_howto; 458*a1ba9ba4Schristos case BFD_RELOC_VTABLE_ENTRY: 459*a1ba9ba4Schristos return &visium_elf_vtentry_howto; 460*a1ba9ba4Schristos default: 461*a1ba9ba4Schristos return NULL; 462*a1ba9ba4Schristos } 463*a1ba9ba4Schristos } 464*a1ba9ba4Schristos 465*a1ba9ba4Schristos static reloc_howto_type * 466*a1ba9ba4Schristos visium_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 467*a1ba9ba4Schristos { 468*a1ba9ba4Schristos unsigned int i; 469*a1ba9ba4Schristos 470*a1ba9ba4Schristos for (i = 0; 471*a1ba9ba4Schristos i < (sizeof (visium_elf_howto_table) 472*a1ba9ba4Schristos / sizeof (visium_elf_howto_table[0])); i++) 473*a1ba9ba4Schristos if (visium_elf_howto_table[i].name != NULL 474*a1ba9ba4Schristos && strcasecmp (visium_elf_howto_table[i].name, r_name) == 0) 475*a1ba9ba4Schristos return &visium_elf_howto_table[i]; 476*a1ba9ba4Schristos 477*a1ba9ba4Schristos if (strcasecmp (visium_elf_vtinherit_howto.name, r_name) == 0) 478*a1ba9ba4Schristos return &visium_elf_vtinherit_howto; 479*a1ba9ba4Schristos if (strcasecmp (visium_elf_vtentry_howto.name, r_name) == 0) 480*a1ba9ba4Schristos return &visium_elf_vtentry_howto; 481*a1ba9ba4Schristos 482*a1ba9ba4Schristos return NULL; 483*a1ba9ba4Schristos } 484*a1ba9ba4Schristos 485*a1ba9ba4Schristos /* Set the howto pointer for a VISIUM ELF reloc. */ 486*a1ba9ba4Schristos 487*a1ba9ba4Schristos static void 488*a1ba9ba4Schristos visium_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, 489*a1ba9ba4Schristos Elf_Internal_Rela *dst) 490*a1ba9ba4Schristos { 491*a1ba9ba4Schristos unsigned int r_type = ELF32_R_TYPE (dst->r_info); 492*a1ba9ba4Schristos 493*a1ba9ba4Schristos switch (r_type) 494*a1ba9ba4Schristos { 495*a1ba9ba4Schristos case R_VISIUM_GNU_VTINHERIT: 496*a1ba9ba4Schristos cache_ptr->howto = &visium_elf_vtinherit_howto; 497*a1ba9ba4Schristos break; 498*a1ba9ba4Schristos 499*a1ba9ba4Schristos case R_VISIUM_GNU_VTENTRY: 500*a1ba9ba4Schristos cache_ptr->howto = &visium_elf_vtentry_howto; 501*a1ba9ba4Schristos break; 502*a1ba9ba4Schristos 503*a1ba9ba4Schristos default: 504*a1ba9ba4Schristos if (r_type >= (unsigned int) R_VISIUM_max) 505*a1ba9ba4Schristos { 506*a1ba9ba4Schristos _bfd_error_handler (_("%B: invalid Visium reloc number: %d"), abfd, r_type); 507*a1ba9ba4Schristos r_type = 0; 508*a1ba9ba4Schristos } 509*a1ba9ba4Schristos cache_ptr->howto = &visium_elf_howto_table[r_type]; 510*a1ba9ba4Schristos break; 511*a1ba9ba4Schristos } 512*a1ba9ba4Schristos } 513*a1ba9ba4Schristos 514*a1ba9ba4Schristos /* Look through the relocs for a section during the first phase. 515*a1ba9ba4Schristos Since we don't do .gots or .plts, we just need to consider the 516*a1ba9ba4Schristos virtual table relocs for gc. */ 517*a1ba9ba4Schristos 518*a1ba9ba4Schristos static bfd_boolean 519*a1ba9ba4Schristos visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 520*a1ba9ba4Schristos asection *sec, const Elf_Internal_Rela *relocs) 521*a1ba9ba4Schristos { 522*a1ba9ba4Schristos Elf_Internal_Shdr *symtab_hdr; 523*a1ba9ba4Schristos struct elf_link_hash_entry **sym_hashes; 524*a1ba9ba4Schristos const Elf_Internal_Rela *rel; 525*a1ba9ba4Schristos const Elf_Internal_Rela *rel_end; 526*a1ba9ba4Schristos 527*a1ba9ba4Schristos if (info->relocatable) 528*a1ba9ba4Schristos return TRUE; 529*a1ba9ba4Schristos 530*a1ba9ba4Schristos symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 531*a1ba9ba4Schristos sym_hashes = elf_sym_hashes (abfd); 532*a1ba9ba4Schristos 533*a1ba9ba4Schristos rel_end = relocs + sec->reloc_count; 534*a1ba9ba4Schristos for (rel = relocs; rel < rel_end; rel++) 535*a1ba9ba4Schristos { 536*a1ba9ba4Schristos struct elf_link_hash_entry *h; 537*a1ba9ba4Schristos unsigned long r_symndx; 538*a1ba9ba4Schristos 539*a1ba9ba4Schristos r_symndx = ELF32_R_SYM (rel->r_info); 540*a1ba9ba4Schristos if (r_symndx < symtab_hdr->sh_info) 541*a1ba9ba4Schristos h = NULL; 542*a1ba9ba4Schristos else 543*a1ba9ba4Schristos { 544*a1ba9ba4Schristos h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 545*a1ba9ba4Schristos while (h->root.type == bfd_link_hash_indirect 546*a1ba9ba4Schristos || h->root.type == bfd_link_hash_warning) 547*a1ba9ba4Schristos h = (struct elf_link_hash_entry *) h->root.u.i.link; 548*a1ba9ba4Schristos } 549*a1ba9ba4Schristos 550*a1ba9ba4Schristos switch (ELF32_R_TYPE (rel->r_info)) 551*a1ba9ba4Schristos { 552*a1ba9ba4Schristos /* This relocation describes the C++ object vtable hierarchy. 553*a1ba9ba4Schristos Reconstruct it for later use during GC. */ 554*a1ba9ba4Schristos case R_VISIUM_GNU_VTINHERIT: 555*a1ba9ba4Schristos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 556*a1ba9ba4Schristos return FALSE; 557*a1ba9ba4Schristos break; 558*a1ba9ba4Schristos 559*a1ba9ba4Schristos /* This relocation describes which C++ vtable entries are actually 560*a1ba9ba4Schristos used. Record for later use during GC. */ 561*a1ba9ba4Schristos case R_VISIUM_GNU_VTENTRY: 562*a1ba9ba4Schristos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 563*a1ba9ba4Schristos return FALSE; 564*a1ba9ba4Schristos break; 565*a1ba9ba4Schristos } 566*a1ba9ba4Schristos } 567*a1ba9ba4Schristos 568*a1ba9ba4Schristos return TRUE; 569*a1ba9ba4Schristos } 570*a1ba9ba4Schristos 571*a1ba9ba4Schristos /* Relocate a VISIUM ELF section. */ 572*a1ba9ba4Schristos 573*a1ba9ba4Schristos static bfd_boolean 574*a1ba9ba4Schristos visium_elf_relocate_section (bfd *output_bfd, 575*a1ba9ba4Schristos struct bfd_link_info *info, bfd *input_bfd, 576*a1ba9ba4Schristos asection *input_section, bfd_byte *contents, 577*a1ba9ba4Schristos Elf_Internal_Rela *relocs, 578*a1ba9ba4Schristos Elf_Internal_Sym *local_syms, 579*a1ba9ba4Schristos asection **local_sections) 580*a1ba9ba4Schristos { 581*a1ba9ba4Schristos Elf_Internal_Shdr *symtab_hdr; 582*a1ba9ba4Schristos struct elf_link_hash_entry **sym_hashes; 583*a1ba9ba4Schristos Elf_Internal_Rela *rel; 584*a1ba9ba4Schristos Elf_Internal_Rela *relend; 585*a1ba9ba4Schristos 586*a1ba9ba4Schristos symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 587*a1ba9ba4Schristos sym_hashes = elf_sym_hashes (input_bfd); 588*a1ba9ba4Schristos relend = relocs + input_section->reloc_count; 589*a1ba9ba4Schristos 590*a1ba9ba4Schristos for (rel = relocs; rel < relend; rel++) 591*a1ba9ba4Schristos { 592*a1ba9ba4Schristos reloc_howto_type *howto; 593*a1ba9ba4Schristos unsigned long r_symndx; 594*a1ba9ba4Schristos Elf_Internal_Sym *sym; 595*a1ba9ba4Schristos asection *sec; 596*a1ba9ba4Schristos struct elf_link_hash_entry *h; 597*a1ba9ba4Schristos bfd_vma relocation; 598*a1ba9ba4Schristos bfd_reloc_status_type r; 599*a1ba9ba4Schristos const char *name = NULL; 600*a1ba9ba4Schristos int r_type; 601*a1ba9ba4Schristos bfd_vma insn; 602*a1ba9ba4Schristos 603*a1ba9ba4Schristos r_type = ELF32_R_TYPE (rel->r_info); 604*a1ba9ba4Schristos 605*a1ba9ba4Schristos if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY) 606*a1ba9ba4Schristos continue; 607*a1ba9ba4Schristos 608*a1ba9ba4Schristos r_symndx = ELF32_R_SYM (rel->r_info); 609*a1ba9ba4Schristos 610*a1ba9ba4Schristos howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info); 611*a1ba9ba4Schristos h = NULL; 612*a1ba9ba4Schristos sym = NULL; 613*a1ba9ba4Schristos sec = NULL; 614*a1ba9ba4Schristos 615*a1ba9ba4Schristos if (r_symndx < symtab_hdr->sh_info) 616*a1ba9ba4Schristos { 617*a1ba9ba4Schristos /* This is a local symbol. */ 618*a1ba9ba4Schristos sym = local_syms + r_symndx; 619*a1ba9ba4Schristos sec = local_sections[r_symndx]; 620*a1ba9ba4Schristos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 621*a1ba9ba4Schristos 622*a1ba9ba4Schristos name = bfd_elf_string_from_elf_section 623*a1ba9ba4Schristos (input_bfd, symtab_hdr->sh_link, sym->st_name); 624*a1ba9ba4Schristos name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; 625*a1ba9ba4Schristos } 626*a1ba9ba4Schristos else 627*a1ba9ba4Schristos { 628*a1ba9ba4Schristos bfd_boolean unresolved_reloc; 629*a1ba9ba4Schristos bfd_boolean warned, ignored; 630*a1ba9ba4Schristos 631*a1ba9ba4Schristos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 632*a1ba9ba4Schristos r_symndx, symtab_hdr, sym_hashes, 633*a1ba9ba4Schristos h, sec, relocation, 634*a1ba9ba4Schristos unresolved_reloc, warned, ignored); 635*a1ba9ba4Schristos 636*a1ba9ba4Schristos name = h->root.root.string; 637*a1ba9ba4Schristos } 638*a1ba9ba4Schristos 639*a1ba9ba4Schristos if (sec != NULL && discarded_section (sec)) 640*a1ba9ba4Schristos { 641*a1ba9ba4Schristos /* For relocs against symbols from removed linkonce sections, 642*a1ba9ba4Schristos or sections discarded by a linker script, we just want the 643*a1ba9ba4Schristos section contents zeroed. Avoid any special processing. */ 644*a1ba9ba4Schristos _bfd_clear_contents (howto, input_bfd, input_section, 645*a1ba9ba4Schristos contents + rel->r_offset); 646*a1ba9ba4Schristos 647*a1ba9ba4Schristos rel->r_info = 0; 648*a1ba9ba4Schristos rel->r_addend = 0; 649*a1ba9ba4Schristos continue; 650*a1ba9ba4Schristos } 651*a1ba9ba4Schristos 652*a1ba9ba4Schristos if (info->relocatable) 653*a1ba9ba4Schristos continue; 654*a1ba9ba4Schristos 655*a1ba9ba4Schristos switch (r_type) 656*a1ba9ba4Schristos { 657*a1ba9ba4Schristos case R_VISIUM_PC16: 658*a1ba9ba4Schristos case R_VISIUM_HI16: 659*a1ba9ba4Schristos case R_VISIUM_LO16: 660*a1ba9ba4Schristos case R_VISIUM_IM16: 661*a1ba9ba4Schristos case R_VISIUM_HI16_PCREL: 662*a1ba9ba4Schristos case R_VISIUM_LO16_PCREL: 663*a1ba9ba4Schristos case R_VISIUM_IM16_PCREL: 664*a1ba9ba4Schristos r = _bfd_final_link_relocate (howto, input_bfd, input_section, 665*a1ba9ba4Schristos contents, rel->r_offset, 666*a1ba9ba4Schristos relocation, rel->r_addend); 667*a1ba9ba4Schristos 668*a1ba9ba4Schristos /* For instruction relocations, the parity needs correcting. */ 669*a1ba9ba4Schristos if (r == bfd_reloc_ok) 670*a1ba9ba4Schristos { 671*a1ba9ba4Schristos insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 672*a1ba9ba4Schristos insn = (insn & 0x7fffffff) | visium_parity_bit (insn); 673*a1ba9ba4Schristos bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 674*a1ba9ba4Schristos } 675*a1ba9ba4Schristos break; 676*a1ba9ba4Schristos 677*a1ba9ba4Schristos default: 678*a1ba9ba4Schristos r = _bfd_final_link_relocate (howto, input_bfd, input_section, 679*a1ba9ba4Schristos contents, rel->r_offset, 680*a1ba9ba4Schristos relocation, rel->r_addend); 681*a1ba9ba4Schristos break; 682*a1ba9ba4Schristos } 683*a1ba9ba4Schristos 684*a1ba9ba4Schristos if (r != bfd_reloc_ok) 685*a1ba9ba4Schristos { 686*a1ba9ba4Schristos const char *msg = (const char *) NULL; 687*a1ba9ba4Schristos 688*a1ba9ba4Schristos switch (r) 689*a1ba9ba4Schristos { 690*a1ba9ba4Schristos case bfd_reloc_overflow: 691*a1ba9ba4Schristos r = info->callbacks->reloc_overflow 692*a1ba9ba4Schristos (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, 693*a1ba9ba4Schristos input_bfd, input_section, rel->r_offset); 694*a1ba9ba4Schristos break; 695*a1ba9ba4Schristos 696*a1ba9ba4Schristos case bfd_reloc_undefined: 697*a1ba9ba4Schristos r = info->callbacks->undefined_symbol 698*a1ba9ba4Schristos (info, name, input_bfd, input_section, rel->r_offset, TRUE); 699*a1ba9ba4Schristos break; 700*a1ba9ba4Schristos 701*a1ba9ba4Schristos case bfd_reloc_outofrange: 702*a1ba9ba4Schristos msg = _("internal error: out of range error"); 703*a1ba9ba4Schristos break; 704*a1ba9ba4Schristos 705*a1ba9ba4Schristos case bfd_reloc_notsupported: 706*a1ba9ba4Schristos msg = _("internal error: unsupported relocation error"); 707*a1ba9ba4Schristos break; 708*a1ba9ba4Schristos 709*a1ba9ba4Schristos case bfd_reloc_dangerous: 710*a1ba9ba4Schristos msg = _("internal error: dangerous relocation"); 711*a1ba9ba4Schristos break; 712*a1ba9ba4Schristos 713*a1ba9ba4Schristos default: 714*a1ba9ba4Schristos msg = _("internal error: unknown error"); 715*a1ba9ba4Schristos break; 716*a1ba9ba4Schristos } 717*a1ba9ba4Schristos 718*a1ba9ba4Schristos if (msg) 719*a1ba9ba4Schristos r = info->callbacks->warning 720*a1ba9ba4Schristos (info, msg, name, input_bfd, input_section, rel->r_offset); 721*a1ba9ba4Schristos 722*a1ba9ba4Schristos if (!r) 723*a1ba9ba4Schristos return FALSE; 724*a1ba9ba4Schristos } 725*a1ba9ba4Schristos } 726*a1ba9ba4Schristos 727*a1ba9ba4Schristos return TRUE; 728*a1ba9ba4Schristos } 729*a1ba9ba4Schristos 730*a1ba9ba4Schristos /* This function is called during section gc to discover the section a 731*a1ba9ba4Schristos to which a particular relocation refers. Return the section that 732*a1ba9ba4Schristos should be marked against GC for a given relocation. */ 733*a1ba9ba4Schristos 734*a1ba9ba4Schristos static asection * 735*a1ba9ba4Schristos visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, 736*a1ba9ba4Schristos Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, 737*a1ba9ba4Schristos Elf_Internal_Sym *sym) 738*a1ba9ba4Schristos { 739*a1ba9ba4Schristos if (h != NULL) 740*a1ba9ba4Schristos switch (ELF32_R_TYPE (rel->r_info)) 741*a1ba9ba4Schristos { 742*a1ba9ba4Schristos case R_VISIUM_GNU_VTINHERIT: 743*a1ba9ba4Schristos case R_VISIUM_GNU_VTENTRY: 744*a1ba9ba4Schristos return NULL; 745*a1ba9ba4Schristos } 746*a1ba9ba4Schristos 747*a1ba9ba4Schristos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 748*a1ba9ba4Schristos } 749*a1ba9ba4Schristos 750*a1ba9ba4Schristos static void 751*a1ba9ba4Schristos visium_elf_post_process_headers (bfd *abfd, 752*a1ba9ba4Schristos struct bfd_link_info *info ATTRIBUTE_UNUSED) 753*a1ba9ba4Schristos { 754*a1ba9ba4Schristos Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); 755*a1ba9ba4Schristos i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE; 756*a1ba9ba4Schristos i_ehdrp->e_ident[EI_ABIVERSION] = 1; 757*a1ba9ba4Schristos } 758*a1ba9ba4Schristos 759*a1ba9ba4Schristos /* Function to set the ELF flag bits. */ 760*a1ba9ba4Schristos 761*a1ba9ba4Schristos static bfd_boolean 762*a1ba9ba4Schristos visium_elf_set_private_flags (bfd *abfd, flagword flags) 763*a1ba9ba4Schristos { 764*a1ba9ba4Schristos elf_elfheader (abfd)->e_flags = flags; 765*a1ba9ba4Schristos elf_flags_init (abfd) = TRUE; 766*a1ba9ba4Schristos return TRUE; 767*a1ba9ba4Schristos } 768*a1ba9ba4Schristos 769*a1ba9ba4Schristos /* Copy backend specific data from one object module to another. */ 770*a1ba9ba4Schristos 771*a1ba9ba4Schristos static bfd_boolean 772*a1ba9ba4Schristos visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) 773*a1ba9ba4Schristos { 774*a1ba9ba4Schristos if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 775*a1ba9ba4Schristos || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 776*a1ba9ba4Schristos return TRUE; 777*a1ba9ba4Schristos 778*a1ba9ba4Schristos BFD_ASSERT (!elf_flags_init (obfd) 779*a1ba9ba4Schristos || elf_elfheader (obfd)->e_flags == 780*a1ba9ba4Schristos elf_elfheader (ibfd)->e_flags); 781*a1ba9ba4Schristos 782*a1ba9ba4Schristos elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; 783*a1ba9ba4Schristos elf_flags_init (obfd) = TRUE; 784*a1ba9ba4Schristos 785*a1ba9ba4Schristos /* Copy object attributes. */ 786*a1ba9ba4Schristos _bfd_elf_copy_obj_attributes (ibfd, obfd); 787*a1ba9ba4Schristos 788*a1ba9ba4Schristos return TRUE; 789*a1ba9ba4Schristos } 790*a1ba9ba4Schristos 791*a1ba9ba4Schristos /* Merge backend specific data from an object 792*a1ba9ba4Schristos file to the output object file when linking. */ 793*a1ba9ba4Schristos 794*a1ba9ba4Schristos static bfd_boolean 795*a1ba9ba4Schristos visium_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) 796*a1ba9ba4Schristos { 797*a1ba9ba4Schristos flagword old_flags; 798*a1ba9ba4Schristos flagword new_flags; 799*a1ba9ba4Schristos flagword mismatch; 800*a1ba9ba4Schristos const char *opt_arch = NULL; 801*a1ba9ba4Schristos const char *new_opt_with = NULL; 802*a1ba9ba4Schristos const char *old_opt_with = NULL; 803*a1ba9ba4Schristos const char *with = "with"; 804*a1ba9ba4Schristos const char *without = "without"; 805*a1ba9ba4Schristos const char *mcm = "mcm"; 806*a1ba9ba4Schristos const char *mcm24 = "mcm24"; 807*a1ba9ba4Schristos const char *gr6 = "gr6"; 808*a1ba9ba4Schristos 809*a1ba9ba4Schristos new_flags = elf_elfheader (ibfd)->e_flags; 810*a1ba9ba4Schristos old_flags = elf_elfheader (obfd)->e_flags; 811*a1ba9ba4Schristos 812*a1ba9ba4Schristos if (!elf_flags_init (obfd)) 813*a1ba9ba4Schristos { 814*a1ba9ba4Schristos /* First call, no flags set. */ 815*a1ba9ba4Schristos elf_flags_init (obfd) = TRUE; 816*a1ba9ba4Schristos elf_elfheader (obfd)->e_flags = new_flags; 817*a1ba9ba4Schristos } 818*a1ba9ba4Schristos else 819*a1ba9ba4Schristos { 820*a1ba9ba4Schristos mismatch = (new_flags ^ old_flags) 821*a1ba9ba4Schristos & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6); 822*a1ba9ba4Schristos if (mismatch & EF_VISIUM_ARCH_GR6) 823*a1ba9ba4Schristos { 824*a1ba9ba4Schristos opt_arch = gr6; 825*a1ba9ba4Schristos new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without; 826*a1ba9ba4Schristos old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without; 827*a1ba9ba4Schristos } 828*a1ba9ba4Schristos else if (mismatch & EF_VISIUM_ARCH_MCM) 829*a1ba9ba4Schristos { 830*a1ba9ba4Schristos opt_arch = mcm; 831*a1ba9ba4Schristos new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without; 832*a1ba9ba4Schristos old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without; 833*a1ba9ba4Schristos } 834*a1ba9ba4Schristos else if (mismatch & EF_VISIUM_ARCH_MCM24) 835*a1ba9ba4Schristos { 836*a1ba9ba4Schristos opt_arch = mcm24; 837*a1ba9ba4Schristos new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 838*a1ba9ba4Schristos old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 839*a1ba9ba4Schristos } 840*a1ba9ba4Schristos 841*a1ba9ba4Schristos if (mismatch) 842*a1ba9ba4Schristos _bfd_error_handler 843*a1ba9ba4Schristos (_ 844*a1ba9ba4Schristos ("%s: compiled %s -mtune=%s and linked with modules" 845*a1ba9ba4Schristos " compiled %s -mtune=%s"), 846*a1ba9ba4Schristos bfd_get_filename (ibfd), new_opt_with, opt_arch, old_opt_with, 847*a1ba9ba4Schristos opt_arch); 848*a1ba9ba4Schristos } 849*a1ba9ba4Schristos 850*a1ba9ba4Schristos return TRUE; 851*a1ba9ba4Schristos } 852*a1ba9ba4Schristos 853*a1ba9ba4Schristos static bfd_boolean 854*a1ba9ba4Schristos visium_elf_print_private_bfd_data (bfd *abfd, void *ptr) 855*a1ba9ba4Schristos { 856*a1ba9ba4Schristos FILE *file = (FILE *) ptr; 857*a1ba9ba4Schristos flagword flags; 858*a1ba9ba4Schristos 859*a1ba9ba4Schristos BFD_ASSERT (abfd != NULL && ptr != NULL); 860*a1ba9ba4Schristos 861*a1ba9ba4Schristos /* Print normal ELF private data. */ 862*a1ba9ba4Schristos _bfd_elf_print_private_bfd_data (abfd, ptr); 863*a1ba9ba4Schristos 864*a1ba9ba4Schristos flags = elf_elfheader (abfd)->e_flags; 865*a1ba9ba4Schristos fprintf (file, _("private flags = 0x%lx:"), (long) flags); 866*a1ba9ba4Schristos 867*a1ba9ba4Schristos if (flags & EF_VISIUM_ARCH_GR6) 868*a1ba9ba4Schristos fprintf (file, " -mtune=gr6"); 869*a1ba9ba4Schristos else if (flags & EF_VISIUM_ARCH_MCM) 870*a1ba9ba4Schristos fprintf (file, " -mtune=mcm"); 871*a1ba9ba4Schristos else if (flags & EF_VISIUM_ARCH_MCM24) 872*a1ba9ba4Schristos fprintf (file, " -mtune=mcm24"); 873*a1ba9ba4Schristos 874*a1ba9ba4Schristos fputc ('\n', file); 875*a1ba9ba4Schristos return TRUE; 876*a1ba9ba4Schristos } 877*a1ba9ba4Schristos 878*a1ba9ba4Schristos #define ELF_ARCH bfd_arch_visium 879*a1ba9ba4Schristos #define ELF_MACHINE_CODE EM_VISIUM 880*a1ba9ba4Schristos #define ELF_MAXPAGESIZE 1 881*a1ba9ba4Schristos 882*a1ba9ba4Schristos #define TARGET_BIG_SYM visium_elf32_vec 883*a1ba9ba4Schristos #define TARGET_BIG_NAME "elf32-visium" 884*a1ba9ba4Schristos 885*a1ba9ba4Schristos #define elf_info_to_howto_rel NULL 886*a1ba9ba4Schristos #define elf_info_to_howto visium_info_to_howto_rela 887*a1ba9ba4Schristos #define elf_backend_relocate_section visium_elf_relocate_section 888*a1ba9ba4Schristos #define elf_backend_gc_mark_hook visium_elf_gc_mark_hook 889*a1ba9ba4Schristos #define elf_backend_check_relocs visium_elf_check_relocs 890*a1ba9ba4Schristos #define elf_backend_rela_normal 1 891*a1ba9ba4Schristos 892*a1ba9ba4Schristos #define elf_backend_can_gc_sections 1 893*a1ba9ba4Schristos 894*a1ba9ba4Schristos #define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup 895*a1ba9ba4Schristos #define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup 896*a1ba9ba4Schristos 897*a1ba9ba4Schristos #define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags 898*a1ba9ba4Schristos #define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data 899*a1ba9ba4Schristos #define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data 900*a1ba9ba4Schristos #define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data 901*a1ba9ba4Schristos #define elf_backend_post_process_headers visium_elf_post_process_headers 902*a1ba9ba4Schristos 903*a1ba9ba4Schristos #include "elf32-target.h" 904