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