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 4 Free Software Foundation, Inc. 5 Written by Cygnus Support. 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23 #define M88 1 /* Customize various include files */ 24 #include "bfd.h" 25 #include "sysdep.h" 26 #include "libbfd.h" 27 #include "coff/m88k.h" 28 #include "coff/internal.h" 29 #include "libcoff.h" 30 31 static bfd_boolean m88k_is_local_label_name PARAMS ((bfd *, const char *)); 32 static bfd_reloc_status_type m88k_special_reloc 33 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 34 static void rtype2howto PARAMS ((arelent *, struct internal_reloc *)); 35 static 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 47 static bfd_boolean 48 m88k_is_local_label_name (abfd, name) 49 bfd *abfd ATTRIBUTE_UNUSED; 50 const char *name; 51 { 52 return name[0] == '@'; 53 } 54 55 static bfd_reloc_status_type 56 m88k_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 149 static 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. */ 238 static void 239 rtype2howto (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 262 static void 263 reloc_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 #include "coffcode.h" 288 289 #undef coff_write_armap 290 291 CREATE_BIG_COFF_TARGET_VEC (m88kbcs_vec, "coff-m88kbcs", 0, 0, '_', NULL, COFF_SWAP_TABLE) 292