]>
Commit | Line | Data |
---|---|---|
6585e9e3 | 1 | /* BFD back-end for Motorola 88000 COFF "Binary Compatability Standard" files. |
f62fed1c | 2 | Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. |
156e3852 | 3 | Written by Cygnus Support. |
a7fe4c59 | 4 | |
156e3852 | 5 | This file is part of BFD, the Binary File Descriptor library. |
a7fe4c59 | 6 | |
156e3852 | 7 | This program is free software; you can redistribute it and/or modify |
a7fe4c59 | 8 | it under the terms of the GNU General Public License as published by |
156e3852 JG |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. | |
a7fe4c59 | 11 | |
156e3852 | 12 | This program is distributed in the hope that it will be useful, |
a7fe4c59 SC |
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 | |
156e3852 | 18 | along with this program; if not, write to the Free Software |
f62fed1c | 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
a7fe4c59 | 20 | |
156e3852 | 21 | #define M88 1 /* Customize various include files */ |
a7fe4c59 | 22 | #include "bfd.h" |
156e3852 | 23 | #include "sysdep.h" |
a7fe4c59 | 24 | #include "libbfd.h" |
9872a49c | 25 | #include "obstack.h" |
294eaca4 SC |
26 | #include "coff/m88k.h" |
27 | #include "coff/internal.h" | |
9872a49c | 28 | #include "libcoff.h" |
4cddd1c9 | 29 | |
f62fed1c ILT |
30 | static bfd_reloc_status_type m88k_special_reloc |
31 | PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); | |
32 | static void rtype2howto PARAMS ((arelent *, struct internal_reloc *)); | |
33 | static void reloc_processing | |
34 | PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *)); | |
35 | ||
36 | #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3) | |
4cddd1c9 | 37 | |
156e3852 | 38 | static bfd_reloc_status_type |
f62fed1c ILT |
39 | m88k_special_reloc (abfd, reloc_entry, symbol, data, |
40 | input_section, output_bfd, error_message) | |
6812b607 ILT |
41 | bfd *abfd; |
42 | arelent *reloc_entry; | |
f62fed1c | 43 | asymbol *symbol; |
6812b607 | 44 | PTR data; |
f62fed1c ILT |
45 | asection *input_section; |
46 | bfd *output_bfd; | |
6812b607 | 47 | char **error_message; |
4cddd1c9 | 48 | { |
f62fed1c | 49 | reloc_howto_type *howto = reloc_entry->howto; |
4cddd1c9 | 50 | |
f62fed1c ILT |
51 | switch (howto->type) |
52 | { | |
53 | case R_HVRT16: | |
54 | case R_LVRT16: | |
55 | if (output_bfd != (bfd *) NULL) | |
56 | { | |
57 | /* This is a partial relocation, and we want to apply the | |
58 | relocation to the reloc entry rather than the raw data. | |
59 | Modify the reloc inplace to reflect what we now know. */ | |
4cddd1c9 | 60 | |
f62fed1c ILT |
61 | reloc_entry->address += input_section->output_offset; |
62 | } | |
63 | else | |
64 | { | |
65 | bfd_vma output_base = 0; | |
66 | bfd_vma addr = reloc_entry->address; | |
67 | bfd_vma x = bfd_get_16 (abfd, (bfd_byte *) data + addr); | |
68 | asection *reloc_target_output_section; | |
69 | long relocation = 0; | |
4cddd1c9 | 70 | |
f62fed1c ILT |
71 | /* Work out which section the relocation is targetted at and the |
72 | initial relocation command value. */ | |
73 | ||
74 | /* Get symbol value. (Common symbols are special.) */ | |
75 | if (bfd_is_com_section (symbol->section)) | |
76 | relocation = 0; | |
77 | else | |
78 | relocation = symbol->value; | |
79 | ||
80 | reloc_target_output_section = symbol->section->output_section; | |
81 | ||
82 | /* Convert input-section-relative symbol value to absolute. */ | |
83 | if (output_bfd) | |
84 | output_base = 0; | |
85 | else | |
86 | output_base = reloc_target_output_section->vma; | |
87 | ||
88 | relocation += output_base + symbol->section->output_offset; | |
89 | ||
90 | /* Add in supplied addend. */ | |
91 | relocation += ((reloc_entry->addend << howto->bitsize) + x); | |
92 | ||
93 | reloc_entry->addend = 0; | |
4cddd1c9 | 94 | |
f62fed1c | 95 | relocation >>= (bfd_vma) howto->rightshift; |
a7fe4c59 | 96 | |
f62fed1c ILT |
97 | /* Shift everything up to where it's going to be used */ |
98 | ||
99 | relocation <<= (bfd_vma) howto->bitpos; | |
100 | ||
101 | if (relocation) | |
102 | bfd_put_16 (abfd, relocation, (unsigned char *) data + addr); | |
103 | } | |
104 | ||
105 | return bfd_reloc_ok; | |
106 | break; | |
107 | ||
108 | default: | |
109 | if (output_bfd != (bfd *) NULL) | |
110 | { | |
111 | /* This is a partial relocation, and we want to apply the | |
112 | relocation to the reloc entry rather than the raw data. | |
113 | Modify the reloc inplace to reflect what we now know. */ | |
114 | ||
115 | reloc_entry->address += input_section->output_offset; | |
116 | return bfd_reloc_ok; | |
117 | } | |
118 | break; | |
119 | } | |
120 | ||
121 | if (output_bfd == (bfd *) NULL) | |
122 | return bfd_reloc_continue; | |
123 | ||
124 | return bfd_reloc_ok; | |
125 | } | |
a7fe4c59 SC |
126 | |
127 | static reloc_howto_type howto_table[] = | |
128 | { | |
f62fed1c ILT |
129 | HOWTO (R_PCR16L, /* type */ |
130 | 02, /* rightshift */ | |
131 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
132 | 16, /* bitsize */ | |
133 | true, /* pc_relative */ | |
134 | 0, /* bitpos */ | |
135 | complain_overflow_signed, /* complain_on_overflow */ | |
136 | m88k_special_reloc, /* special_function */ | |
137 | "PCR16L", /* name */ | |
138 | false, /* partial_inplace */ | |
139 | 0x0000ffff, /* src_mask */ | |
140 | 0x0000ffff, /* dst_mask */ | |
141 | true), /* pcrel_offset */ | |
142 | ||
143 | HOWTO (R_PCR26L, /* type */ | |
144 | 02, /* rightshift */ | |
145 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
146 | 26, /* bitsize */ | |
147 | true, /* pc_relative */ | |
148 | 0, /* bitpos */ | |
149 | complain_overflow_signed, /* complain_on_overflow */ | |
150 | m88k_special_reloc, /* special_function */ | |
151 | "PCR26L", /* name */ | |
152 | false, /* partial_inplace */ | |
153 | 0x03ffffff, /* src_mask */ | |
154 | 0x03ffffff, /* dst_mask */ | |
155 | true), /* pcrel_offset */ | |
156 | ||
157 | HOWTO (R_VRT16, /* type */ | |
158 | 00, /* rightshift */ | |
159 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
160 | 16, /* bitsize */ | |
161 | false, /* pc_relative */ | |
162 | 0, /* bitpos */ | |
163 | complain_overflow_bitfield, /* complain_on_overflow */ | |
164 | m88k_special_reloc, /* special_function */ | |
165 | "VRT16", /* name */ | |
166 | false, /* partial_inplace */ | |
167 | 0x0000ffff, /* src_mask */ | |
168 | 0x0000ffff, /* dst_mask */ | |
169 | true), /* pcrel_offset */ | |
170 | ||
171 | HOWTO (R_HVRT16, /* type */ | |
172 | 16, /* rightshift */ | |
173 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
174 | 16, /* bitsize */ | |
175 | false, /* pc_relative */ | |
176 | 0, /* bitpos */ | |
177 | complain_overflow_dont, /* complain_on_overflow */ | |
178 | m88k_special_reloc, /* special_function */ | |
179 | "HVRT16", /* name */ | |
180 | false, /* partial_inplace */ | |
181 | 0x0000ffff, /* src_mask */ | |
182 | 0x0000ffff, /* dst_mask */ | |
183 | true), /* pcrel_offset */ | |
184 | ||
185 | HOWTO (R_LVRT16, /* type */ | |
186 | 00, /* rightshift */ | |
187 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
188 | 16, /* bitsize */ | |
189 | false, /* pc_relative */ | |
190 | 0, /* bitpos */ | |
191 | complain_overflow_dont, /* complain_on_overflow */ | |
192 | m88k_special_reloc, /* special_function */ | |
193 | "LVRT16", /* name */ | |
194 | false, /* partial_inplace */ | |
195 | 0x0000ffff, /* src_mask */ | |
196 | 0x0000ffff, /* dst_mask */ | |
197 | true), /* pcrel_offset */ | |
198 | ||
199 | HOWTO (R_VRT32, /* type */ | |
200 | 00, /* rightshift */ | |
201 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
202 | 32, /* bitsize */ | |
203 | false, /* pc_relative */ | |
204 | 0, /* bitpos */ | |
205 | complain_overflow_bitfield, /* complain_on_overflow */ | |
206 | m88k_special_reloc, /* special_function */ | |
207 | "VRT32", /* name */ | |
208 | false, /* partial_inplace */ | |
209 | 0xffffffff, /* src_mask */ | |
210 | 0xffffffff, /* dst_mask */ | |
211 | true), /* pcrel_offset */ | |
a7fe4c59 SC |
212 | }; |
213 | ||
f62fed1c ILT |
214 | /* Code to turn an external r_type into a pointer to an entry in the |
215 | above howto table. */ | |
216 | static void | |
217 | rtype2howto (cache_ptr, dst) | |
218 | arelent *cache_ptr; | |
219 | struct internal_reloc *dst; | |
220 | { | |
221 | if (dst->r_type >= R_PCR16L && dst->r_type <= R_VRT32) | |
222 | { | |
223 | cache_ptr->howto = howto_table + dst->r_type - R_PCR16L; | |
224 | } | |
225 | else | |
226 | { | |
227 | BFD_ASSERT (0); | |
228 | } | |
229 | } | |
230 | ||
231 | #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst) | |
232 | ||
a7fe4c59 | 233 | |
3b4f1a5d | 234 | /* Code to swap in the reloc offset */ |
f62fed1c | 235 | #define SWAP_IN_RELOC_OFFSET bfd_h_get_16 |
3b4f1a5d SC |
236 | #define SWAP_OUT_RELOC_OFFSET bfd_h_put_16 |
237 | ||
238 | ||
f62fed1c ILT |
239 | #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \ |
240 | reloc_processing(relent, reloc, symbols, abfd, section) | |
3b4f1a5d | 241 | |
f62fed1c ILT |
242 | static void |
243 | reloc_processing (relent, reloc, symbols, abfd, section) | |
244 | arelent *relent; | |
245 | struct internal_reloc *reloc; | |
246 | asymbol **symbols; | |
247 | bfd *abfd; | |
248 | asection *section; | |
249 | { | |
250 | relent->address = reloc->r_vaddr; | |
251 | rtype2howto (relent, reloc); | |
3b4f1a5d | 252 | |
f62fed1c ILT |
253 | if (((int) reloc->r_symndx) > 0) |
254 | { | |
255 | relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx]; | |
256 | } | |
257 | else | |
258 | { | |
259 | relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; | |
260 | } | |
261 | ||
262 | relent->addend = reloc->r_offset; | |
263 | relent->address -= section->vma; | |
264 | } | |
a7fe4c59 SC |
265 | |
266 | #define BADMAG(x) MC88BADMAG(x) | |
2700c3c7 | 267 | #include "coffcode.h" |
a7fe4c59 | 268 | |
5685fb50 | 269 | #undef coff_write_armap |
9872a49c | 270 | |
f62fed1c | 271 | const bfd_target m88kbcs_vec = |
a7fe4c59 | 272 | { |
3b4f1a5d | 273 | "coff-m88kbcs", /* name */ |
156e3852 | 274 | bfd_target_coff_flavour, |
9872a49c | 275 | true, /* data byte order is big */ |
a7fe4c59 SC |
276 | true, /* header byte order is big */ |
277 | ||
278 | (HAS_RELOC | EXEC_P | /* object flags */ | |
279 | HAS_LINENO | HAS_DEBUG | | |
6812b607 | 280 | HAS_SYMS | HAS_LOCALS | WP_TEXT), |
a7fe4c59 SC |
281 | |
282 | (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ | |
6585e9e3 | 283 | '_', /* leading underscore */ |
a7fe4c59 SC |
284 | '/', /* ar_pad_char */ |
285 | 15, /* ar_max_namelen */ | |
6812b607 ILT |
286 | bfd_getb64, bfd_getb_signed_64, bfd_putb64, |
287 | bfd_getb32, bfd_getb_signed_32, bfd_putb32, | |
288 | bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ | |
289 | bfd_getb64, bfd_getb_signed_64, bfd_putb64, | |
290 | bfd_getb32, bfd_getb_signed_32, bfd_putb32, | |
291 | bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ | |
a7fe4c59 | 292 | |
156e3852 JG |
293 | {_bfd_dummy_target, coff_object_p, /* bfd_check_format */ |
294 | bfd_generic_archive_p, _bfd_dummy_target}, | |
295 | {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */ | |
296 | bfd_false}, | |
297 | {bfd_false, coff_write_object_contents, /* bfd_write_contents */ | |
298 | _bfd_write_archive_contents, bfd_false}, | |
9872a49c | 299 | |
6812b607 ILT |
300 | BFD_JUMP_TABLE_GENERIC (coff), |
301 | BFD_JUMP_TABLE_COPY (coff), | |
302 | BFD_JUMP_TABLE_CORE (_bfd_nocore), | |
303 | BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), | |
304 | BFD_JUMP_TABLE_SYMBOLS (coff), | |
305 | BFD_JUMP_TABLE_RELOCS (coff), | |
306 | BFD_JUMP_TABLE_WRITE (coff), | |
307 | BFD_JUMP_TABLE_LINK (coff), | |
f62fed1c | 308 | BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), |
6812b607 | 309 | |
6585e9e3 | 310 | COFF_SWAP_TABLE, |
2b1d8a50 | 311 | }; |