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