1 /* BFD back-end for Motorola 88000 COFF "Binary Compatibility Standard" files. 2 Copyright (C) 1990-2014 Free Software Foundation, Inc. 3 Written by Cygnus Support. 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 #define M88 1 /* Customize various include files */ 23 #include "sysdep.h" 24 #include "bfd.h" 25 #include "libbfd.h" 26 #include "coff/m88k.h" 27 #include "coff/internal.h" 28 #include "libcoff.h" 29 30 static bfd_reloc_status_type m88k_special_reloc 31 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 32 33 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3) 34 35 #define GET_SCNHDR_NRELOC H_GET_32 36 #define GET_SCNHDR_NLNNO H_GET_32 37 38 /* On coff-m88k, local labels start with '@'. */ 39 40 #define coff_bfd_is_local_label_name m88k_is_local_label_name 41 42 static bfd_boolean 43 m88k_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name) 44 { 45 return name[0] == '@'; 46 } 47 48 static bfd_reloc_status_type 49 m88k_special_reloc (bfd *abfd, 50 arelent *reloc_entry, 51 asymbol *symbol, 52 void * data, 53 asection *input_section, 54 bfd *output_bfd, 55 char **error_message ATTRIBUTE_UNUSED) 56 { 57 reloc_howto_type *howto = reloc_entry->howto; 58 59 switch (howto->type) 60 { 61 case R_HVRT16: 62 case R_LVRT16: 63 if (output_bfd != (bfd *) NULL) 64 { 65 /* This is a partial relocation, and we want to apply the 66 relocation to the reloc entry rather than the raw data. 67 Modify the reloc inplace to reflect what we now know. */ 68 69 reloc_entry->address += input_section->output_offset; 70 } 71 else 72 { 73 bfd_vma output_base = 0; 74 bfd_vma addr = reloc_entry->address; 75 bfd_vma x = bfd_get_16 (abfd, (bfd_byte *) data + addr); 76 asection *reloc_target_output_section; 77 long relocation = 0; 78 79 /* Work out which section the relocation is targeted at and the 80 initial relocation command value. */ 81 82 /* Get symbol value. (Common symbols are special.) */ 83 if (bfd_is_com_section (symbol->section)) 84 relocation = 0; 85 else 86 relocation = symbol->value; 87 88 reloc_target_output_section = symbol->section->output_section; 89 90 /* Convert input-section-relative symbol value to absolute. */ 91 if (output_bfd) 92 output_base = 0; 93 else 94 output_base = reloc_target_output_section->vma; 95 96 relocation += output_base + symbol->section->output_offset; 97 98 /* Add in supplied addend. */ 99 relocation += ((reloc_entry->addend << howto->bitsize) + x); 100 101 reloc_entry->addend = 0; 102 103 relocation >>= (bfd_vma) howto->rightshift; 104 105 /* Shift everything up to where it's going to be used */ 106 107 relocation <<= (bfd_vma) howto->bitpos; 108 109 if (relocation) 110 bfd_put_16 (abfd, (bfd_vma) relocation, 111 (unsigned char *) data + addr); 112 } 113 114 /* If we are not producing relocatable output, return an error if 115 the symbol is not defined. */ 116 if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL) 117 return bfd_reloc_undefined; 118 119 return bfd_reloc_ok; 120 121 default: 122 if (output_bfd != (bfd *) NULL) 123 { 124 /* This is a partial relocation, and we want to apply the 125 relocation to the reloc entry rather than the raw data. 126 Modify the reloc inplace to reflect what we now know. */ 127 128 reloc_entry->address += input_section->output_offset; 129 return bfd_reloc_ok; 130 } 131 break; 132 } 133 134 if (output_bfd == (bfd *) NULL) 135 return bfd_reloc_continue; 136 137 return bfd_reloc_ok; 138 } 139 140 static reloc_howto_type howto_table[] = 141 { 142 HOWTO (R_PCR16L, /* type */ 143 02, /* rightshift */ 144 1, /* size (0 = byte, 1 = short, 2 = long) */ 145 16, /* bitsize */ 146 TRUE, /* pc_relative */ 147 0, /* bitpos */ 148 complain_overflow_signed, /* complain_on_overflow */ 149 m88k_special_reloc, /* special_function */ 150 "PCR16L", /* name */ 151 FALSE, /* partial_inplace */ 152 0x0000ffff, /* src_mask */ 153 0x0000ffff, /* dst_mask */ 154 TRUE), /* pcrel_offset */ 155 156 HOWTO (R_PCR26L, /* type */ 157 02, /* rightshift */ 158 2, /* size (0 = byte, 1 = short, 2 = long) */ 159 26, /* bitsize */ 160 TRUE, /* pc_relative */ 161 0, /* bitpos */ 162 complain_overflow_signed, /* complain_on_overflow */ 163 m88k_special_reloc, /* special_function */ 164 "PCR26L", /* name */ 165 FALSE, /* partial_inplace */ 166 0x03ffffff, /* src_mask */ 167 0x03ffffff, /* dst_mask */ 168 TRUE), /* pcrel_offset */ 169 170 HOWTO (R_VRT16, /* type */ 171 00, /* rightshift */ 172 1, /* size (0 = byte, 1 = short, 2 = long) */ 173 16, /* bitsize */ 174 FALSE, /* pc_relative */ 175 0, /* bitpos */ 176 complain_overflow_bitfield, /* complain_on_overflow */ 177 m88k_special_reloc, /* special_function */ 178 "VRT16", /* name */ 179 FALSE, /* partial_inplace */ 180 0x0000ffff, /* src_mask */ 181 0x0000ffff, /* dst_mask */ 182 TRUE), /* pcrel_offset */ 183 184 HOWTO (R_HVRT16, /* type */ 185 16, /* rightshift */ 186 1, /* size (0 = byte, 1 = short, 2 = long) */ 187 16, /* bitsize */ 188 FALSE, /* pc_relative */ 189 0, /* bitpos */ 190 complain_overflow_dont, /* complain_on_overflow */ 191 m88k_special_reloc, /* special_function */ 192 "HVRT16", /* name */ 193 FALSE, /* partial_inplace */ 194 0x0000ffff, /* src_mask */ 195 0x0000ffff, /* dst_mask */ 196 TRUE), /* pcrel_offset */ 197 198 HOWTO (R_LVRT16, /* type */ 199 00, /* rightshift */ 200 1, /* size (0 = byte, 1 = short, 2 = long) */ 201 16, /* bitsize */ 202 FALSE, /* pc_relative */ 203 0, /* bitpos */ 204 complain_overflow_dont, /* complain_on_overflow */ 205 m88k_special_reloc, /* special_function */ 206 "LVRT16", /* name */ 207 FALSE, /* partial_inplace */ 208 0x0000ffff, /* src_mask */ 209 0x0000ffff, /* dst_mask */ 210 TRUE), /* pcrel_offset */ 211 212 HOWTO (R_VRT32, /* type */ 213 00, /* rightshift */ 214 2, /* size (0 = byte, 1 = short, 2 = long) */ 215 32, /* bitsize */ 216 FALSE, /* pc_relative */ 217 0, /* bitpos */ 218 complain_overflow_bitfield, /* complain_on_overflow */ 219 m88k_special_reloc, /* special_function */ 220 "VRT32", /* name */ 221 FALSE, /* partial_inplace */ 222 0xffffffff, /* src_mask */ 223 0xffffffff, /* dst_mask */ 224 TRUE), /* pcrel_offset */ 225 }; 226 227 /* Code to turn an external r_type into a pointer to an entry in the 228 above howto table. */ 229 static void 230 rtype2howto (arelent *cache_ptr, struct internal_reloc *dst) 231 { 232 if (dst->r_type >= R_PCR16L && dst->r_type <= R_VRT32) 233 { 234 cache_ptr->howto = howto_table + dst->r_type - R_PCR16L; 235 } 236 else 237 { 238 BFD_ASSERT (0); 239 } 240 } 241 242 #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst) 243 244 /* Code to swap in the reloc offset */ 245 #define SWAP_IN_RELOC_OFFSET H_GET_16 246 #define SWAP_OUT_RELOC_OFFSET H_PUT_16 247 248 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \ 249 reloc_processing(relent, reloc, symbols, abfd, section) 250 251 static void 252 reloc_processing (arelent *relent, 253 struct internal_reloc *reloc, 254 asymbol **symbols, 255 bfd *abfd, 256 asection *section) 257 { 258 relent->address = reloc->r_vaddr; 259 rtype2howto (relent, reloc); 260 261 if (((int) reloc->r_symndx) > 0) 262 { 263 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx]; 264 } 265 else 266 { 267 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; 268 } 269 270 relent->addend = reloc->r_offset; 271 relent->address -= section->vma; 272 } 273 274 #define BADMAG(x) MC88BADMAG(x) 275 276 #ifndef bfd_pe_print_pdata 277 #define bfd_pe_print_pdata NULL 278 #endif 279 280 #include "coffcode.h" 281 282 #undef coff_write_armap 283 284 CREATE_BIG_COFF_TARGET_VEC (m88k_coff_bcs_vec, "coff-m88kbcs", 0, 0, '_', NULL, COFF_SWAP_TABLE) 285