1*3d8817e4Smiod /* BFD back-end for oasys objects.
2*3d8817e4Smiod Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001,
3*3d8817e4Smiod 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4*3d8817e4Smiod Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>.
5*3d8817e4Smiod
6*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
7*3d8817e4Smiod
8*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
9*3d8817e4Smiod it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
11*3d8817e4Smiod (at your option) any later version.
12*3d8817e4Smiod
13*3d8817e4Smiod This program is distributed in the hope that it will be useful,
14*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*3d8817e4Smiod GNU General Public License for more details.
17*3d8817e4Smiod
18*3d8817e4Smiod You should have received a copy of the GNU General Public License
19*3d8817e4Smiod along with this program; if not, write to the Free Software
20*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
21*3d8817e4Smiod
22*3d8817e4Smiod #define UNDERSCORE_HACK 1
23*3d8817e4Smiod #include "bfd.h"
24*3d8817e4Smiod #include "sysdep.h"
25*3d8817e4Smiod #include "safe-ctype.h"
26*3d8817e4Smiod #include "libbfd.h"
27*3d8817e4Smiod #include "oasys.h"
28*3d8817e4Smiod #include "liboasys.h"
29*3d8817e4Smiod
30*3d8817e4Smiod /* Read in all the section data and relocation stuff too. */
31*3d8817e4Smiod
32*3d8817e4Smiod static bfd_boolean
oasys_read_record(bfd * abfd,oasys_record_union_type * record)33*3d8817e4Smiod oasys_read_record (bfd *abfd, oasys_record_union_type *record)
34*3d8817e4Smiod {
35*3d8817e4Smiod bfd_size_type amt = sizeof (record->header);
36*3d8817e4Smiod
37*3d8817e4Smiod if (bfd_bread ((void *) record, amt, abfd) != amt)
38*3d8817e4Smiod return FALSE;
39*3d8817e4Smiod
40*3d8817e4Smiod amt = record->header.length - sizeof (record->header);
41*3d8817e4Smiod if ((long) amt <= 0)
42*3d8817e4Smiod return TRUE;
43*3d8817e4Smiod if (bfd_bread ((void *) ((char *) record + sizeof (record->header)), amt, abfd)
44*3d8817e4Smiod != amt)
45*3d8817e4Smiod return FALSE;
46*3d8817e4Smiod return TRUE;
47*3d8817e4Smiod }
48*3d8817e4Smiod
49*3d8817e4Smiod static size_t
oasys_string_length(oasys_record_union_type * record)50*3d8817e4Smiod oasys_string_length (oasys_record_union_type *record)
51*3d8817e4Smiod {
52*3d8817e4Smiod return record->header.length
53*3d8817e4Smiod - ((char *) record->symbol.name - (char *) record);
54*3d8817e4Smiod }
55*3d8817e4Smiod
56*3d8817e4Smiod /* Slurp the symbol table by reading in all the records at the start file
57*3d8817e4Smiod till we get to the first section record.
58*3d8817e4Smiod
59*3d8817e4Smiod We'll sort the symbolss into two lists, defined and undefined. The
60*3d8817e4Smiod undefined symbols will be placed into the table according to their
61*3d8817e4Smiod refno.
62*3d8817e4Smiod
63*3d8817e4Smiod We do this by placing all undefined symbols at the front of the table
64*3d8817e4Smiod moving in, and the defined symbols at the end of the table moving back. */
65*3d8817e4Smiod
66*3d8817e4Smiod static bfd_boolean
oasys_slurp_symbol_table(bfd * const abfd)67*3d8817e4Smiod oasys_slurp_symbol_table (bfd *const abfd)
68*3d8817e4Smiod {
69*3d8817e4Smiod oasys_record_union_type record;
70*3d8817e4Smiod oasys_data_type *data = OASYS_DATA (abfd);
71*3d8817e4Smiod bfd_boolean loop = TRUE;
72*3d8817e4Smiod asymbol *dest_defined;
73*3d8817e4Smiod asymbol *dest;
74*3d8817e4Smiod char *string_ptr;
75*3d8817e4Smiod bfd_size_type amt;
76*3d8817e4Smiod
77*3d8817e4Smiod if (data->symbols != NULL)
78*3d8817e4Smiod return TRUE;
79*3d8817e4Smiod
80*3d8817e4Smiod /* Buy enough memory for all the symbols and all the names. */
81*3d8817e4Smiod amt = abfd->symcount;
82*3d8817e4Smiod amt *= sizeof (asymbol);
83*3d8817e4Smiod data->symbols = bfd_alloc (abfd, amt);
84*3d8817e4Smiod
85*3d8817e4Smiod amt = data->symbol_string_length;
86*3d8817e4Smiod #ifdef UNDERSCORE_HACK
87*3d8817e4Smiod /* Buy 1 more char for each symbol to keep the underscore in. */
88*3d8817e4Smiod amt += abfd->symcount;
89*3d8817e4Smiod #endif
90*3d8817e4Smiod data->strings = bfd_alloc (abfd, amt);
91*3d8817e4Smiod
92*3d8817e4Smiod if (!data->symbols || !data->strings)
93*3d8817e4Smiod return FALSE;
94*3d8817e4Smiod
95*3d8817e4Smiod dest_defined = data->symbols + abfd->symcount - 1;
96*3d8817e4Smiod
97*3d8817e4Smiod string_ptr = data->strings;
98*3d8817e4Smiod if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
99*3d8817e4Smiod return FALSE;
100*3d8817e4Smiod while (loop)
101*3d8817e4Smiod {
102*3d8817e4Smiod if (! oasys_read_record (abfd, &record))
103*3d8817e4Smiod return FALSE;
104*3d8817e4Smiod
105*3d8817e4Smiod switch (record.header.type)
106*3d8817e4Smiod {
107*3d8817e4Smiod case oasys_record_is_header_enum:
108*3d8817e4Smiod break;
109*3d8817e4Smiod case oasys_record_is_local_enum:
110*3d8817e4Smiod case oasys_record_is_symbol_enum:
111*3d8817e4Smiod {
112*3d8817e4Smiod int flag = record.header.type == (int) oasys_record_is_local_enum ?
113*3d8817e4Smiod (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
114*3d8817e4Smiod
115*3d8817e4Smiod size_t length = oasys_string_length (&record);
116*3d8817e4Smiod switch (record.symbol.relb & RELOCATION_TYPE_BITS)
117*3d8817e4Smiod {
118*3d8817e4Smiod case RELOCATION_TYPE_ABS:
119*3d8817e4Smiod dest = dest_defined--;
120*3d8817e4Smiod dest->section = bfd_abs_section_ptr;
121*3d8817e4Smiod dest->flags = 0;
122*3d8817e4Smiod
123*3d8817e4Smiod break;
124*3d8817e4Smiod case RELOCATION_TYPE_REL:
125*3d8817e4Smiod dest = dest_defined--;
126*3d8817e4Smiod dest->section =
127*3d8817e4Smiod OASYS_DATA (abfd)->sections[record.symbol.relb &
128*3d8817e4Smiod RELOCATION_SECT_BITS];
129*3d8817e4Smiod if (record.header.type == (int) oasys_record_is_local_enum)
130*3d8817e4Smiod {
131*3d8817e4Smiod dest->flags = BSF_LOCAL;
132*3d8817e4Smiod if (dest->section == (asection *) (~0))
133*3d8817e4Smiod {
134*3d8817e4Smiod /* It seems that sometimes internal symbols are tied up, but
135*3d8817e4Smiod still get output, even though there is no
136*3d8817e4Smiod section */
137*3d8817e4Smiod dest->section = 0;
138*3d8817e4Smiod }
139*3d8817e4Smiod }
140*3d8817e4Smiod else
141*3d8817e4Smiod dest->flags = flag;
142*3d8817e4Smiod break;
143*3d8817e4Smiod case RELOCATION_TYPE_UND:
144*3d8817e4Smiod dest = data->symbols + H_GET_16 (abfd, record.symbol.refno);
145*3d8817e4Smiod dest->section = bfd_und_section_ptr;
146*3d8817e4Smiod break;
147*3d8817e4Smiod case RELOCATION_TYPE_COM:
148*3d8817e4Smiod dest = dest_defined--;
149*3d8817e4Smiod dest->name = string_ptr;
150*3d8817e4Smiod dest->the_bfd = abfd;
151*3d8817e4Smiod dest->section = bfd_com_section_ptr;
152*3d8817e4Smiod break;
153*3d8817e4Smiod default:
154*3d8817e4Smiod dest = dest_defined--;
155*3d8817e4Smiod BFD_ASSERT (FALSE);
156*3d8817e4Smiod break;
157*3d8817e4Smiod }
158*3d8817e4Smiod dest->name = string_ptr;
159*3d8817e4Smiod dest->the_bfd = abfd;
160*3d8817e4Smiod dest->udata.p = NULL;
161*3d8817e4Smiod dest->value = H_GET_32 (abfd, record.symbol.value);
162*3d8817e4Smiod
163*3d8817e4Smiod #ifdef UNDERSCORE_HACK
164*3d8817e4Smiod if (record.symbol.name[0] != '_')
165*3d8817e4Smiod {
166*3d8817e4Smiod string_ptr[0] = '_';
167*3d8817e4Smiod string_ptr++;
168*3d8817e4Smiod }
169*3d8817e4Smiod #endif
170*3d8817e4Smiod memcpy (string_ptr, record.symbol.name, length);
171*3d8817e4Smiod
172*3d8817e4Smiod string_ptr[length] = 0;
173*3d8817e4Smiod string_ptr += length + 1;
174*3d8817e4Smiod }
175*3d8817e4Smiod break;
176*3d8817e4Smiod default:
177*3d8817e4Smiod loop = FALSE;
178*3d8817e4Smiod }
179*3d8817e4Smiod }
180*3d8817e4Smiod return TRUE;
181*3d8817e4Smiod }
182*3d8817e4Smiod
183*3d8817e4Smiod static long
oasys_get_symtab_upper_bound(bfd * const abfd)184*3d8817e4Smiod oasys_get_symtab_upper_bound (bfd *const abfd)
185*3d8817e4Smiod {
186*3d8817e4Smiod if (! oasys_slurp_symbol_table (abfd))
187*3d8817e4Smiod return -1;
188*3d8817e4Smiod
189*3d8817e4Smiod return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *));
190*3d8817e4Smiod }
191*3d8817e4Smiod
192*3d8817e4Smiod extern const bfd_target oasys_vec;
193*3d8817e4Smiod
194*3d8817e4Smiod static long
oasys_canonicalize_symtab(bfd * abfd,asymbol ** location)195*3d8817e4Smiod oasys_canonicalize_symtab (bfd *abfd, asymbol **location)
196*3d8817e4Smiod {
197*3d8817e4Smiod asymbol *symbase;
198*3d8817e4Smiod unsigned int counter;
199*3d8817e4Smiod
200*3d8817e4Smiod if (! oasys_slurp_symbol_table (abfd))
201*3d8817e4Smiod return -1;
202*3d8817e4Smiod
203*3d8817e4Smiod symbase = OASYS_DATA (abfd)->symbols;
204*3d8817e4Smiod for (counter = 0; counter < abfd->symcount; counter++)
205*3d8817e4Smiod *(location++) = symbase++;
206*3d8817e4Smiod
207*3d8817e4Smiod *location = 0;
208*3d8817e4Smiod return abfd->symcount;
209*3d8817e4Smiod }
210*3d8817e4Smiod
211*3d8817e4Smiod /* Archive stuff. */
212*3d8817e4Smiod
213*3d8817e4Smiod static const bfd_target *
oasys_archive_p(bfd * abfd)214*3d8817e4Smiod oasys_archive_p (bfd *abfd)
215*3d8817e4Smiod {
216*3d8817e4Smiod oasys_archive_header_type header;
217*3d8817e4Smiod oasys_extarchive_header_type header_ext;
218*3d8817e4Smiod unsigned int i;
219*3d8817e4Smiod file_ptr filepos;
220*3d8817e4Smiod bfd_size_type amt;
221*3d8817e4Smiod
222*3d8817e4Smiod amt = sizeof (header_ext);
223*3d8817e4Smiod if (bfd_seek (abfd, (file_ptr) 0, 0) != 0
224*3d8817e4Smiod || bfd_bread ((void *) &header_ext, amt, abfd) != amt)
225*3d8817e4Smiod {
226*3d8817e4Smiod if (bfd_get_error () != bfd_error_system_call)
227*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
228*3d8817e4Smiod return NULL;
229*3d8817e4Smiod }
230*3d8817e4Smiod
231*3d8817e4Smiod header.version = H_GET_32 (abfd, header_ext.version);
232*3d8817e4Smiod header.mod_count = H_GET_32 (abfd, header_ext.mod_count);
233*3d8817e4Smiod header.mod_tbl_offset = H_GET_32 (abfd, header_ext.mod_tbl_offset);
234*3d8817e4Smiod header.sym_tbl_size = H_GET_32 (abfd, header_ext.sym_tbl_size);
235*3d8817e4Smiod header.sym_count = H_GET_32 (abfd, header_ext.sym_count);
236*3d8817e4Smiod header.sym_tbl_offset = H_GET_32 (abfd, header_ext.sym_tbl_offset);
237*3d8817e4Smiod header.xref_count = H_GET_32 (abfd, header_ext.xref_count);
238*3d8817e4Smiod header.xref_lst_offset = H_GET_32 (abfd, header_ext.xref_lst_offset);
239*3d8817e4Smiod
240*3d8817e4Smiod /* There isn't a magic number in an Oasys archive, so the best we
241*3d8817e4Smiod can do to verify reasonableness is to make sure that the values in
242*3d8817e4Smiod the header are too weird. */
243*3d8817e4Smiod
244*3d8817e4Smiod if (header.version > 10000
245*3d8817e4Smiod || header.mod_count > 10000
246*3d8817e4Smiod || header.sym_count > 100000
247*3d8817e4Smiod || header.xref_count > 100000)
248*3d8817e4Smiod return NULL;
249*3d8817e4Smiod
250*3d8817e4Smiod /* That all worked, let's buy the space for the header and read in
251*3d8817e4Smiod the headers. */
252*3d8817e4Smiod {
253*3d8817e4Smiod oasys_ar_data_type *ar;
254*3d8817e4Smiod oasys_module_info_type *module;
255*3d8817e4Smiod oasys_module_table_type record;
256*3d8817e4Smiod
257*3d8817e4Smiod amt = sizeof (oasys_ar_data_type);
258*3d8817e4Smiod ar = bfd_alloc (abfd, amt);
259*3d8817e4Smiod
260*3d8817e4Smiod amt = header.mod_count;
261*3d8817e4Smiod amt *= sizeof (oasys_module_info_type);
262*3d8817e4Smiod module = bfd_alloc (abfd, amt);
263*3d8817e4Smiod
264*3d8817e4Smiod if (!ar || !module)
265*3d8817e4Smiod return NULL;
266*3d8817e4Smiod
267*3d8817e4Smiod abfd->tdata.oasys_ar_data = ar;
268*3d8817e4Smiod ar->module = module;
269*3d8817e4Smiod ar->module_count = header.mod_count;
270*3d8817e4Smiod
271*3d8817e4Smiod filepos = header.mod_tbl_offset;
272*3d8817e4Smiod for (i = 0; i < header.mod_count; i++)
273*3d8817e4Smiod {
274*3d8817e4Smiod if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
275*3d8817e4Smiod return NULL;
276*3d8817e4Smiod
277*3d8817e4Smiod /* There are two ways of specifying the archive header. */
278*3d8817e4Smiod {
279*3d8817e4Smiod oasys_extmodule_table_type_b_type record_ext;
280*3d8817e4Smiod
281*3d8817e4Smiod amt = sizeof (record_ext);
282*3d8817e4Smiod if (bfd_bread ((void *) &record_ext, amt, abfd) != amt)
283*3d8817e4Smiod return NULL;
284*3d8817e4Smiod
285*3d8817e4Smiod record.mod_size = H_GET_32 (abfd, record_ext.mod_size);
286*3d8817e4Smiod record.file_offset = H_GET_32 (abfd, record_ext.file_offset);
287*3d8817e4Smiod
288*3d8817e4Smiod record.dep_count = H_GET_32 (abfd, record_ext.dep_count);
289*3d8817e4Smiod record.depee_count = H_GET_32 (abfd, record_ext.depee_count);
290*3d8817e4Smiod record.sect_count = H_GET_32 (abfd, record_ext.sect_count);
291*3d8817e4Smiod record.module_name_size = H_GET_32 (abfd,
292*3d8817e4Smiod record_ext.mod_name_length);
293*3d8817e4Smiod
294*3d8817e4Smiod amt = record.module_name_size;
295*3d8817e4Smiod module[i].name = bfd_alloc (abfd, amt + 1);
296*3d8817e4Smiod if (!module[i].name)
297*3d8817e4Smiod return NULL;
298*3d8817e4Smiod if (bfd_bread ((void *) module[i].name, amt, abfd) != amt)
299*3d8817e4Smiod return NULL;
300*3d8817e4Smiod module[i].name[record.module_name_size] = 0;
301*3d8817e4Smiod filepos += (sizeof (record_ext)
302*3d8817e4Smiod + record.dep_count * 4
303*3d8817e4Smiod + record.module_name_size + 1);
304*3d8817e4Smiod }
305*3d8817e4Smiod
306*3d8817e4Smiod module[i].size = record.mod_size;
307*3d8817e4Smiod module[i].pos = record.file_offset;
308*3d8817e4Smiod module[i].abfd = 0;
309*3d8817e4Smiod }
310*3d8817e4Smiod }
311*3d8817e4Smiod return abfd->xvec;
312*3d8817e4Smiod }
313*3d8817e4Smiod
314*3d8817e4Smiod static bfd_boolean
oasys_mkobject(bfd * abfd)315*3d8817e4Smiod oasys_mkobject (bfd *abfd)
316*3d8817e4Smiod {
317*3d8817e4Smiod bfd_size_type amt = sizeof (oasys_data_type);
318*3d8817e4Smiod
319*3d8817e4Smiod abfd->tdata.oasys_obj_data = bfd_alloc (abfd, amt);
320*3d8817e4Smiod
321*3d8817e4Smiod return abfd->tdata.oasys_obj_data != NULL;
322*3d8817e4Smiod }
323*3d8817e4Smiod
324*3d8817e4Smiod /* The howto table is build using the top two bits of a reloc byte to
325*3d8817e4Smiod index into it. The bits are PCREL,WORD/LONG. */
326*3d8817e4Smiod
327*3d8817e4Smiod static reloc_howto_type howto_table[] =
328*3d8817e4Smiod {
329*3d8817e4Smiod
330*3d8817e4Smiod HOWTO (0, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
331*3d8817e4Smiod HOWTO (0, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs32", TRUE, 0xffffffff, 0xffffffff, FALSE),
332*3d8817e4Smiod HOWTO (0, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
333*3d8817e4Smiod HOWTO (0, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0, "pcrel32", TRUE, 0xffffffff, 0xffffffff, FALSE)
334*3d8817e4Smiod };
335*3d8817e4Smiod
336*3d8817e4Smiod /* Read in all the section data and relocation stuff too. */
337*3d8817e4Smiod
338*3d8817e4Smiod static bfd_boolean
oasys_slurp_section_data(bfd * const abfd)339*3d8817e4Smiod oasys_slurp_section_data (bfd *const abfd)
340*3d8817e4Smiod {
341*3d8817e4Smiod oasys_record_union_type record;
342*3d8817e4Smiod oasys_data_type *data = OASYS_DATA (abfd);
343*3d8817e4Smiod bfd_boolean loop = TRUE;
344*3d8817e4Smiod oasys_per_section_type *per;
345*3d8817e4Smiod asection *s;
346*3d8817e4Smiod bfd_size_type amt;
347*3d8817e4Smiod
348*3d8817e4Smiod /* See if the data has been slurped already. */
349*3d8817e4Smiod for (s = abfd->sections; s != NULL; s = s->next)
350*3d8817e4Smiod {
351*3d8817e4Smiod per = oasys_per_section (s);
352*3d8817e4Smiod if (per->initialized)
353*3d8817e4Smiod return TRUE;
354*3d8817e4Smiod }
355*3d8817e4Smiod
356*3d8817e4Smiod if (data->first_data_record == 0)
357*3d8817e4Smiod return TRUE;
358*3d8817e4Smiod
359*3d8817e4Smiod if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
360*3d8817e4Smiod return FALSE;
361*3d8817e4Smiod
362*3d8817e4Smiod while (loop)
363*3d8817e4Smiod {
364*3d8817e4Smiod if (! oasys_read_record (abfd, &record))
365*3d8817e4Smiod return FALSE;
366*3d8817e4Smiod
367*3d8817e4Smiod switch (record.header.type)
368*3d8817e4Smiod {
369*3d8817e4Smiod case oasys_record_is_header_enum:
370*3d8817e4Smiod break;
371*3d8817e4Smiod case oasys_record_is_data_enum:
372*3d8817e4Smiod {
373*3d8817e4Smiod bfd_byte *src = record.data.data;
374*3d8817e4Smiod bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
375*3d8817e4Smiod bfd_byte *dst_ptr;
376*3d8817e4Smiod bfd_byte *dst_base_ptr;
377*3d8817e4Smiod unsigned int relbit;
378*3d8817e4Smiod unsigned int count;
379*3d8817e4Smiod asection *section =
380*3d8817e4Smiod data->sections[record.data.relb & RELOCATION_SECT_BITS];
381*3d8817e4Smiod bfd_vma dst_offset;
382*3d8817e4Smiod
383*3d8817e4Smiod per = oasys_per_section (section);
384*3d8817e4Smiod
385*3d8817e4Smiod if (! per->initialized)
386*3d8817e4Smiod {
387*3d8817e4Smiod arelent **relpp;
388*3d8817e4Smiod
389*3d8817e4Smiod per->data = bfd_zalloc (abfd, section->size);
390*3d8817e4Smiod if (!per->data)
391*3d8817e4Smiod return FALSE;
392*3d8817e4Smiod relpp = §ion->relocation;
393*3d8817e4Smiod per->reloc_tail_ptr = (oasys_reloc_type **) relpp;
394*3d8817e4Smiod per->had_vma = FALSE;
395*3d8817e4Smiod per->initialized = TRUE;
396*3d8817e4Smiod section->reloc_count = 0;
397*3d8817e4Smiod section->flags = SEC_ALLOC;
398*3d8817e4Smiod }
399*3d8817e4Smiod
400*3d8817e4Smiod dst_offset = H_GET_32 (abfd, record.data.addr);
401*3d8817e4Smiod if (! per->had_vma)
402*3d8817e4Smiod {
403*3d8817e4Smiod /* Take the first vma we see as the base. */
404*3d8817e4Smiod section->vma = dst_offset;
405*3d8817e4Smiod per->had_vma = TRUE;
406*3d8817e4Smiod }
407*3d8817e4Smiod
408*3d8817e4Smiod dst_offset -= section->vma;
409*3d8817e4Smiod
410*3d8817e4Smiod dst_base_ptr = oasys_per_section (section)->data;
411*3d8817e4Smiod dst_ptr = oasys_per_section (section)->data +
412*3d8817e4Smiod dst_offset;
413*3d8817e4Smiod
414*3d8817e4Smiod if (src < end_src)
415*3d8817e4Smiod section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
416*3d8817e4Smiod
417*3d8817e4Smiod while (src < end_src)
418*3d8817e4Smiod {
419*3d8817e4Smiod unsigned char mod_byte = *src++;
420*3d8817e4Smiod size_t gap = end_src - src;
421*3d8817e4Smiod
422*3d8817e4Smiod count = 8;
423*3d8817e4Smiod if (mod_byte == 0 && gap >= 8)
424*3d8817e4Smiod {
425*3d8817e4Smiod dst_ptr[0] = src[0];
426*3d8817e4Smiod dst_ptr[1] = src[1];
427*3d8817e4Smiod dst_ptr[2] = src[2];
428*3d8817e4Smiod dst_ptr[3] = src[3];
429*3d8817e4Smiod dst_ptr[4] = src[4];
430*3d8817e4Smiod dst_ptr[5] = src[5];
431*3d8817e4Smiod dst_ptr[6] = src[6];
432*3d8817e4Smiod dst_ptr[7] = src[7];
433*3d8817e4Smiod dst_ptr += 8;
434*3d8817e4Smiod src += 8;
435*3d8817e4Smiod }
436*3d8817e4Smiod else
437*3d8817e4Smiod {
438*3d8817e4Smiod for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
439*3d8817e4Smiod {
440*3d8817e4Smiod if (relbit & mod_byte)
441*3d8817e4Smiod {
442*3d8817e4Smiod unsigned char reloc = *src;
443*3d8817e4Smiod /* This item needs to be relocated. */
444*3d8817e4Smiod switch (reloc & RELOCATION_TYPE_BITS)
445*3d8817e4Smiod {
446*3d8817e4Smiod case RELOCATION_TYPE_ABS:
447*3d8817e4Smiod break;
448*3d8817e4Smiod
449*3d8817e4Smiod case RELOCATION_TYPE_REL:
450*3d8817e4Smiod {
451*3d8817e4Smiod /* Relocate the item relative to the section. */
452*3d8817e4Smiod oasys_reloc_type *r;
453*3d8817e4Smiod
454*3d8817e4Smiod amt = sizeof (oasys_reloc_type);
455*3d8817e4Smiod r = bfd_alloc (abfd, amt);
456*3d8817e4Smiod if (!r)
457*3d8817e4Smiod return FALSE;
458*3d8817e4Smiod *(per->reloc_tail_ptr) = r;
459*3d8817e4Smiod per->reloc_tail_ptr = &r->next;
460*3d8817e4Smiod r->next = NULL;
461*3d8817e4Smiod /* Reference to undefined symbol. */
462*3d8817e4Smiod src++;
463*3d8817e4Smiod /* There is no symbol. */
464*3d8817e4Smiod r->symbol = 0;
465*3d8817e4Smiod /* Work out the howto. */
466*3d8817e4Smiod abort ();
467*3d8817e4Smiod r->relent.address = dst_ptr - dst_base_ptr;
468*3d8817e4Smiod r->relent.howto = &howto_table[reloc >> 6];
469*3d8817e4Smiod r->relent.sym_ptr_ptr = NULL;
470*3d8817e4Smiod section->reloc_count++;
471*3d8817e4Smiod
472*3d8817e4Smiod /* Fake up the data to look like
473*3d8817e4Smiod it's got the -ve pc in it, this
474*3d8817e4Smiod makes it much easier to convert
475*3d8817e4Smiod into other formats. This is done
476*3d8817e4Smiod by hitting the addend. */
477*3d8817e4Smiod if (r->relent.howto->pc_relative)
478*3d8817e4Smiod r->relent.addend -= dst_ptr - dst_base_ptr;
479*3d8817e4Smiod }
480*3d8817e4Smiod break;
481*3d8817e4Smiod
482*3d8817e4Smiod case RELOCATION_TYPE_UND:
483*3d8817e4Smiod {
484*3d8817e4Smiod oasys_reloc_type *r;
485*3d8817e4Smiod
486*3d8817e4Smiod amt = sizeof (oasys_reloc_type);
487*3d8817e4Smiod r = bfd_alloc (abfd, amt);
488*3d8817e4Smiod if (!r)
489*3d8817e4Smiod return FALSE;
490*3d8817e4Smiod *(per->reloc_tail_ptr) = r;
491*3d8817e4Smiod per->reloc_tail_ptr = &r->next;
492*3d8817e4Smiod r->next = NULL;
493*3d8817e4Smiod /* Reference to undefined symbol. */
494*3d8817e4Smiod src++;
495*3d8817e4Smiod /* Get symbol number. */
496*3d8817e4Smiod r->symbol = (src[0] << 8) | src[1];
497*3d8817e4Smiod /* Work out the howto. */
498*3d8817e4Smiod abort ();
499*3d8817e4Smiod
500*3d8817e4Smiod r->relent.addend = 0;
501*3d8817e4Smiod r->relent.address = dst_ptr - dst_base_ptr;
502*3d8817e4Smiod r->relent.howto = &howto_table[reloc >> 6];
503*3d8817e4Smiod r->relent.sym_ptr_ptr = NULL;
504*3d8817e4Smiod section->reloc_count++;
505*3d8817e4Smiod
506*3d8817e4Smiod src += 2;
507*3d8817e4Smiod /* Fake up the data to look like
508*3d8817e4Smiod it's got the -ve pc in it, this
509*3d8817e4Smiod makes it much easier to convert
510*3d8817e4Smiod into other formats. This is done
511*3d8817e4Smiod by hitting the addend. */
512*3d8817e4Smiod if (r->relent.howto->pc_relative)
513*3d8817e4Smiod r->relent.addend -= dst_ptr - dst_base_ptr;
514*3d8817e4Smiod }
515*3d8817e4Smiod break;
516*3d8817e4Smiod case RELOCATION_TYPE_COM:
517*3d8817e4Smiod BFD_FAIL ();
518*3d8817e4Smiod }
519*3d8817e4Smiod }
520*3d8817e4Smiod *dst_ptr++ = *src++;
521*3d8817e4Smiod }
522*3d8817e4Smiod }
523*3d8817e4Smiod }
524*3d8817e4Smiod }
525*3d8817e4Smiod break;
526*3d8817e4Smiod case oasys_record_is_local_enum:
527*3d8817e4Smiod case oasys_record_is_symbol_enum:
528*3d8817e4Smiod case oasys_record_is_section_enum:
529*3d8817e4Smiod break;
530*3d8817e4Smiod default:
531*3d8817e4Smiod loop = FALSE;
532*3d8817e4Smiod }
533*3d8817e4Smiod }
534*3d8817e4Smiod
535*3d8817e4Smiod return TRUE;
536*3d8817e4Smiod
537*3d8817e4Smiod }
538*3d8817e4Smiod
539*3d8817e4Smiod #define MAX_SECS 16
540*3d8817e4Smiod
541*3d8817e4Smiod static const bfd_target *
oasys_object_p(bfd * abfd)542*3d8817e4Smiod oasys_object_p (bfd *abfd)
543*3d8817e4Smiod {
544*3d8817e4Smiod oasys_data_type *oasys;
545*3d8817e4Smiod oasys_data_type *save = OASYS_DATA (abfd);
546*3d8817e4Smiod bfd_boolean loop = TRUE;
547*3d8817e4Smiod bfd_boolean had_usefull = FALSE;
548*3d8817e4Smiod
549*3d8817e4Smiod abfd->tdata.oasys_obj_data = 0;
550*3d8817e4Smiod oasys_mkobject (abfd);
551*3d8817e4Smiod oasys = OASYS_DATA (abfd);
552*3d8817e4Smiod memset ((void *) oasys->sections, 0xff, sizeof (oasys->sections));
553*3d8817e4Smiod
554*3d8817e4Smiod /* Point to the start of the file. */
555*3d8817e4Smiod if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
556*3d8817e4Smiod goto fail;
557*3d8817e4Smiod oasys->symbol_string_length = 0;
558*3d8817e4Smiod
559*3d8817e4Smiod /* Inspect the records, but only keep the section info -
560*3d8817e4Smiod remember the size of the symbols. */
561*3d8817e4Smiod oasys->first_data_record = 0;
562*3d8817e4Smiod while (loop)
563*3d8817e4Smiod {
564*3d8817e4Smiod oasys_record_union_type record;
565*3d8817e4Smiod if (! oasys_read_record (abfd, &record))
566*3d8817e4Smiod goto fail;
567*3d8817e4Smiod if ((size_t) record.header.length < (size_t) sizeof (record.header))
568*3d8817e4Smiod goto fail;
569*3d8817e4Smiod
570*3d8817e4Smiod switch ((oasys_record_enum_type) (record.header.type))
571*3d8817e4Smiod {
572*3d8817e4Smiod case oasys_record_is_header_enum:
573*3d8817e4Smiod had_usefull = TRUE;
574*3d8817e4Smiod break;
575*3d8817e4Smiod case oasys_record_is_symbol_enum:
576*3d8817e4Smiod case oasys_record_is_local_enum:
577*3d8817e4Smiod /* Count symbols and remember their size for a future malloc. */
578*3d8817e4Smiod abfd->symcount++;
579*3d8817e4Smiod oasys->symbol_string_length += 1 + oasys_string_length (&record);
580*3d8817e4Smiod had_usefull = TRUE;
581*3d8817e4Smiod break;
582*3d8817e4Smiod case oasys_record_is_section_enum:
583*3d8817e4Smiod {
584*3d8817e4Smiod asection *s;
585*3d8817e4Smiod char *buffer;
586*3d8817e4Smiod unsigned int section_number;
587*3d8817e4Smiod
588*3d8817e4Smiod if (record.section.header.length != sizeof (record.section))
589*3d8817e4Smiod goto fail;
590*3d8817e4Smiod
591*3d8817e4Smiod buffer = bfd_alloc (abfd, (bfd_size_type) 3);
592*3d8817e4Smiod if (!buffer)
593*3d8817e4Smiod goto fail;
594*3d8817e4Smiod section_number = record.section.relb & RELOCATION_SECT_BITS;
595*3d8817e4Smiod sprintf (buffer, "%u", section_number);
596*3d8817e4Smiod s = bfd_make_section (abfd, buffer);
597*3d8817e4Smiod oasys->sections[section_number] = s;
598*3d8817e4Smiod switch (record.section.relb & RELOCATION_TYPE_BITS)
599*3d8817e4Smiod {
600*3d8817e4Smiod case RELOCATION_TYPE_ABS:
601*3d8817e4Smiod case RELOCATION_TYPE_REL:
602*3d8817e4Smiod break;
603*3d8817e4Smiod case RELOCATION_TYPE_UND:
604*3d8817e4Smiod case RELOCATION_TYPE_COM:
605*3d8817e4Smiod BFD_FAIL ();
606*3d8817e4Smiod }
607*3d8817e4Smiod
608*3d8817e4Smiod s->size = H_GET_32 (abfd, record.section.value);
609*3d8817e4Smiod s->vma = H_GET_32 (abfd, record.section.vma);
610*3d8817e4Smiod s->flags = 0;
611*3d8817e4Smiod had_usefull = TRUE;
612*3d8817e4Smiod }
613*3d8817e4Smiod break;
614*3d8817e4Smiod case oasys_record_is_data_enum:
615*3d8817e4Smiod oasys->first_data_record = bfd_tell (abfd) - record.header.length;
616*3d8817e4Smiod case oasys_record_is_debug_enum:
617*3d8817e4Smiod case oasys_record_is_module_enum:
618*3d8817e4Smiod case oasys_record_is_named_section_enum:
619*3d8817e4Smiod case oasys_record_is_end_enum:
620*3d8817e4Smiod if (! had_usefull)
621*3d8817e4Smiod goto fail;
622*3d8817e4Smiod loop = FALSE;
623*3d8817e4Smiod break;
624*3d8817e4Smiod default:
625*3d8817e4Smiod goto fail;
626*3d8817e4Smiod }
627*3d8817e4Smiod }
628*3d8817e4Smiod oasys->symbols = NULL;
629*3d8817e4Smiod
630*3d8817e4Smiod /* Oasys support several architectures, but I can't see a simple way
631*3d8817e4Smiod to discover which one is in a particular file - we'll guess. */
632*3d8817e4Smiod bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
633*3d8817e4Smiod if (abfd->symcount != 0)
634*3d8817e4Smiod abfd->flags |= HAS_SYMS;
635*3d8817e4Smiod
636*3d8817e4Smiod /* We don't know if a section has data until we've read it. */
637*3d8817e4Smiod oasys_slurp_section_data (abfd);
638*3d8817e4Smiod
639*3d8817e4Smiod return abfd->xvec;
640*3d8817e4Smiod
641*3d8817e4Smiod fail:
642*3d8817e4Smiod (void) bfd_release (abfd, oasys);
643*3d8817e4Smiod abfd->tdata.oasys_obj_data = save;
644*3d8817e4Smiod return NULL;
645*3d8817e4Smiod }
646*3d8817e4Smiod
647*3d8817e4Smiod
648*3d8817e4Smiod static void
oasys_get_symbol_info(bfd * ignore_abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)649*3d8817e4Smiod oasys_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
650*3d8817e4Smiod asymbol *symbol,
651*3d8817e4Smiod symbol_info *ret)
652*3d8817e4Smiod {
653*3d8817e4Smiod bfd_symbol_info (symbol, ret);
654*3d8817e4Smiod
655*3d8817e4Smiod if (!symbol->section)
656*3d8817e4Smiod ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
657*3d8817e4Smiod }
658*3d8817e4Smiod
659*3d8817e4Smiod static void
oasys_print_symbol(bfd * abfd,void * afile,asymbol * symbol,bfd_print_symbol_type how)660*3d8817e4Smiod oasys_print_symbol (bfd *abfd, void * afile, asymbol *symbol, bfd_print_symbol_type how)
661*3d8817e4Smiod {
662*3d8817e4Smiod FILE *file = (FILE *) afile;
663*3d8817e4Smiod
664*3d8817e4Smiod switch (how)
665*3d8817e4Smiod {
666*3d8817e4Smiod case bfd_print_symbol_name:
667*3d8817e4Smiod case bfd_print_symbol_more:
668*3d8817e4Smiod fprintf (file, "%s", symbol->name);
669*3d8817e4Smiod break;
670*3d8817e4Smiod case bfd_print_symbol_all:
671*3d8817e4Smiod {
672*3d8817e4Smiod const char *section_name = symbol->section == NULL ?
673*3d8817e4Smiod (const char *) "*abs" : symbol->section->name;
674*3d8817e4Smiod
675*3d8817e4Smiod bfd_print_symbol_vandf (abfd, (void *) file, symbol);
676*3d8817e4Smiod
677*3d8817e4Smiod fprintf (file, " %-5s %s",
678*3d8817e4Smiod section_name,
679*3d8817e4Smiod symbol->name);
680*3d8817e4Smiod }
681*3d8817e4Smiod break;
682*3d8817e4Smiod }
683*3d8817e4Smiod }
684*3d8817e4Smiod
685*3d8817e4Smiod static bfd_boolean
oasys_new_section_hook(bfd * abfd,asection * newsect)686*3d8817e4Smiod oasys_new_section_hook (bfd *abfd, asection *newsect)
687*3d8817e4Smiod {
688*3d8817e4Smiod newsect->used_by_bfd = bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
689*3d8817e4Smiod if (!newsect->used_by_bfd)
690*3d8817e4Smiod return FALSE;
691*3d8817e4Smiod oasys_per_section (newsect)->data = NULL;
692*3d8817e4Smiod oasys_per_section (newsect)->section = newsect;
693*3d8817e4Smiod oasys_per_section (newsect)->offset = 0;
694*3d8817e4Smiod oasys_per_section (newsect)->initialized = FALSE;
695*3d8817e4Smiod newsect->alignment_power = 1;
696*3d8817e4Smiod
697*3d8817e4Smiod /* Turn the section string into an index. */
698*3d8817e4Smiod sscanf (newsect->name, "%u", &newsect->target_index);
699*3d8817e4Smiod
700*3d8817e4Smiod return TRUE;
701*3d8817e4Smiod }
702*3d8817e4Smiod
703*3d8817e4Smiod
704*3d8817e4Smiod static long
oasys_get_reloc_upper_bound(bfd * abfd,sec_ptr asect)705*3d8817e4Smiod oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
706*3d8817e4Smiod {
707*3d8817e4Smiod if (! oasys_slurp_section_data (abfd))
708*3d8817e4Smiod return -1;
709*3d8817e4Smiod return (asect->reloc_count + 1) * sizeof (arelent *);
710*3d8817e4Smiod }
711*3d8817e4Smiod
712*3d8817e4Smiod static bfd_boolean
oasys_get_section_contents(bfd * abfd,sec_ptr section,void * location,file_ptr offset,bfd_size_type count)713*3d8817e4Smiod oasys_get_section_contents (bfd *abfd,
714*3d8817e4Smiod sec_ptr section,
715*3d8817e4Smiod void * location,
716*3d8817e4Smiod file_ptr offset,
717*3d8817e4Smiod bfd_size_type count)
718*3d8817e4Smiod {
719*3d8817e4Smiod oasys_per_section_type *p = oasys_per_section (section);
720*3d8817e4Smiod
721*3d8817e4Smiod oasys_slurp_section_data (abfd);
722*3d8817e4Smiod
723*3d8817e4Smiod if (! p->initialized)
724*3d8817e4Smiod (void) memset (location, 0, (size_t) count);
725*3d8817e4Smiod else
726*3d8817e4Smiod (void) memcpy (location, (void *) (p->data + offset), (size_t) count);
727*3d8817e4Smiod
728*3d8817e4Smiod return TRUE;
729*3d8817e4Smiod }
730*3d8817e4Smiod
731*3d8817e4Smiod static long
oasys_canonicalize_reloc(bfd * ignore_abfd ATTRIBUTE_UNUSED,sec_ptr section,arelent ** relptr,asymbol ** symbols ATTRIBUTE_UNUSED)732*3d8817e4Smiod oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
733*3d8817e4Smiod sec_ptr section,
734*3d8817e4Smiod arelent **relptr,
735*3d8817e4Smiod asymbol **symbols ATTRIBUTE_UNUSED)
736*3d8817e4Smiod {
737*3d8817e4Smiod unsigned int reloc_count = 0;
738*3d8817e4Smiod oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
739*3d8817e4Smiod
740*3d8817e4Smiod if (src != NULL)
741*3d8817e4Smiod abort ();
742*3d8817e4Smiod
743*3d8817e4Smiod *relptr = NULL;
744*3d8817e4Smiod return section->reloc_count = reloc_count;
745*3d8817e4Smiod }
746*3d8817e4Smiod
747*3d8817e4Smiod
748*3d8817e4Smiod /* Writing. */
749*3d8817e4Smiod
750*3d8817e4Smiod /* Calculate the checksum and write one record. */
751*3d8817e4Smiod
752*3d8817e4Smiod static bfd_boolean
oasys_write_record(bfd * abfd,oasys_record_enum_type type,oasys_record_union_type * record,size_t size)753*3d8817e4Smiod oasys_write_record (bfd *abfd,
754*3d8817e4Smiod oasys_record_enum_type type,
755*3d8817e4Smiod oasys_record_union_type *record,
756*3d8817e4Smiod size_t size)
757*3d8817e4Smiod {
758*3d8817e4Smiod int checksum;
759*3d8817e4Smiod size_t i;
760*3d8817e4Smiod unsigned char *ptr;
761*3d8817e4Smiod
762*3d8817e4Smiod record->header.length = size;
763*3d8817e4Smiod record->header.type = (int) type;
764*3d8817e4Smiod record->header.check_sum = 0;
765*3d8817e4Smiod record->header.fill = 0;
766*3d8817e4Smiod ptr = (unsigned char *) &record->pad[0];
767*3d8817e4Smiod checksum = 0;
768*3d8817e4Smiod for (i = 0; i < size; i++)
769*3d8817e4Smiod checksum += *ptr++;
770*3d8817e4Smiod record->header.check_sum = 0xff & (-checksum);
771*3d8817e4Smiod if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size)
772*3d8817e4Smiod return FALSE;
773*3d8817e4Smiod return TRUE;
774*3d8817e4Smiod }
775*3d8817e4Smiod
776*3d8817e4Smiod
777*3d8817e4Smiod /* Write out all the symbols. */
778*3d8817e4Smiod
779*3d8817e4Smiod static bfd_boolean
oasys_write_syms(bfd * abfd)780*3d8817e4Smiod oasys_write_syms (bfd *abfd)
781*3d8817e4Smiod {
782*3d8817e4Smiod unsigned int count;
783*3d8817e4Smiod asymbol **generic = bfd_get_outsymbols (abfd);
784*3d8817e4Smiod unsigned int index = 0;
785*3d8817e4Smiod
786*3d8817e4Smiod for (count = 0; count < bfd_get_symcount (abfd); count++)
787*3d8817e4Smiod {
788*3d8817e4Smiod oasys_symbol_record_type symbol;
789*3d8817e4Smiod asymbol *const g = generic[count];
790*3d8817e4Smiod const char *src = g->name;
791*3d8817e4Smiod char *dst = symbol.name;
792*3d8817e4Smiod unsigned int l = 0;
793*3d8817e4Smiod
794*3d8817e4Smiod if (bfd_is_com_section (g->section))
795*3d8817e4Smiod {
796*3d8817e4Smiod symbol.relb = RELOCATION_TYPE_COM;
797*3d8817e4Smiod H_PUT_16 (abfd, index, symbol.refno);
798*3d8817e4Smiod index++;
799*3d8817e4Smiod }
800*3d8817e4Smiod else if (bfd_is_abs_section (g->section))
801*3d8817e4Smiod {
802*3d8817e4Smiod symbol.relb = RELOCATION_TYPE_ABS;
803*3d8817e4Smiod H_PUT_16 (abfd, 0, symbol.refno);
804*3d8817e4Smiod }
805*3d8817e4Smiod else if (bfd_is_und_section (g->section))
806*3d8817e4Smiod {
807*3d8817e4Smiod symbol.relb = RELOCATION_TYPE_UND;
808*3d8817e4Smiod H_PUT_16 (abfd, index, symbol.refno);
809*3d8817e4Smiod /* Overload the value field with the output index number */
810*3d8817e4Smiod index++;
811*3d8817e4Smiod }
812*3d8817e4Smiod else if (g->flags & BSF_DEBUGGING)
813*3d8817e4Smiod /* Throw it away. */
814*3d8817e4Smiod continue;
815*3d8817e4Smiod else
816*3d8817e4Smiod {
817*3d8817e4Smiod if (g->section == NULL)
818*3d8817e4Smiod /* Sometime, the oasys tools give out a symbol with illegal
819*3d8817e4Smiod bits in it, we'll output it in the same broken way. */
820*3d8817e4Smiod symbol.relb = RELOCATION_TYPE_REL | 0;
821*3d8817e4Smiod else
822*3d8817e4Smiod symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
823*3d8817e4Smiod
824*3d8817e4Smiod H_PUT_16 (abfd, 0, symbol.refno);
825*3d8817e4Smiod }
826*3d8817e4Smiod
827*3d8817e4Smiod #ifdef UNDERSCORE_HACK
828*3d8817e4Smiod if (src[l] == '_')
829*3d8817e4Smiod dst[l++] = '.';
830*3d8817e4Smiod #endif
831*3d8817e4Smiod while (src[l])
832*3d8817e4Smiod {
833*3d8817e4Smiod dst[l] = src[l];
834*3d8817e4Smiod l++;
835*3d8817e4Smiod }
836*3d8817e4Smiod
837*3d8817e4Smiod H_PUT_32 (abfd, g->value, symbol.value);
838*3d8817e4Smiod
839*3d8817e4Smiod if (g->flags & BSF_LOCAL)
840*3d8817e4Smiod {
841*3d8817e4Smiod if (! oasys_write_record (abfd,
842*3d8817e4Smiod oasys_record_is_local_enum,
843*3d8817e4Smiod (oasys_record_union_type *) & symbol,
844*3d8817e4Smiod offsetof (oasys_symbol_record_type,
845*3d8817e4Smiod name[0]) + l))
846*3d8817e4Smiod return FALSE;
847*3d8817e4Smiod }
848*3d8817e4Smiod else
849*3d8817e4Smiod {
850*3d8817e4Smiod if (! oasys_write_record (abfd,
851*3d8817e4Smiod oasys_record_is_symbol_enum,
852*3d8817e4Smiod (oasys_record_union_type *) & symbol,
853*3d8817e4Smiod offsetof (oasys_symbol_record_type,
854*3d8817e4Smiod name[0]) + l))
855*3d8817e4Smiod return FALSE;
856*3d8817e4Smiod }
857*3d8817e4Smiod g->value = index - 1;
858*3d8817e4Smiod }
859*3d8817e4Smiod
860*3d8817e4Smiod return TRUE;
861*3d8817e4Smiod }
862*3d8817e4Smiod
863*3d8817e4Smiod /* Write a section header for each section. */
864*3d8817e4Smiod
865*3d8817e4Smiod static bfd_boolean
oasys_write_sections(bfd * abfd)866*3d8817e4Smiod oasys_write_sections (bfd *abfd)
867*3d8817e4Smiod {
868*3d8817e4Smiod asection *s;
869*3d8817e4Smiod static oasys_section_record_type out;
870*3d8817e4Smiod
871*3d8817e4Smiod for (s = abfd->sections; s != NULL; s = s->next)
872*3d8817e4Smiod {
873*3d8817e4Smiod if (!ISDIGIT (s->name[0]))
874*3d8817e4Smiod {
875*3d8817e4Smiod (*_bfd_error_handler)
876*3d8817e4Smiod (_("%s: can not represent section `%s' in oasys"),
877*3d8817e4Smiod bfd_get_filename (abfd), s->name);
878*3d8817e4Smiod bfd_set_error (bfd_error_nonrepresentable_section);
879*3d8817e4Smiod return FALSE;
880*3d8817e4Smiod }
881*3d8817e4Smiod out.relb = RELOCATION_TYPE_REL | s->target_index;
882*3d8817e4Smiod H_PUT_32 (abfd, s->size, out.value);
883*3d8817e4Smiod H_PUT_32 (abfd, s->vma, out.vma);
884*3d8817e4Smiod
885*3d8817e4Smiod if (! oasys_write_record (abfd,
886*3d8817e4Smiod oasys_record_is_section_enum,
887*3d8817e4Smiod (oasys_record_union_type *) & out,
888*3d8817e4Smiod sizeof (out)))
889*3d8817e4Smiod return FALSE;
890*3d8817e4Smiod }
891*3d8817e4Smiod return TRUE;
892*3d8817e4Smiod }
893*3d8817e4Smiod
894*3d8817e4Smiod static bfd_boolean
oasys_write_header(bfd * abfd)895*3d8817e4Smiod oasys_write_header (bfd *abfd)
896*3d8817e4Smiod {
897*3d8817e4Smiod /* Create and write the header. */
898*3d8817e4Smiod oasys_header_record_type r;
899*3d8817e4Smiod size_t length = strlen (abfd->filename);
900*3d8817e4Smiod
901*3d8817e4Smiod if (length > (size_t) sizeof (r.module_name))
902*3d8817e4Smiod length = sizeof (r.module_name);
903*3d8817e4Smiod
904*3d8817e4Smiod (void) memcpy (r.module_name, abfd->filename, length);
905*3d8817e4Smiod (void) memset (r.module_name + length, ' ', sizeof (r.module_name) - length);
906*3d8817e4Smiod
907*3d8817e4Smiod r.version_number = OASYS_VERSION_NUMBER;
908*3d8817e4Smiod r.rev_number = OASYS_REV_NUMBER;
909*3d8817e4Smiod
910*3d8817e4Smiod return oasys_write_record (abfd, oasys_record_is_header_enum,
911*3d8817e4Smiod (oasys_record_union_type *) & r,
912*3d8817e4Smiod offsetof (oasys_header_record_type,
913*3d8817e4Smiod description[0]));
914*3d8817e4Smiod }
915*3d8817e4Smiod
916*3d8817e4Smiod static bfd_boolean
oasys_write_end(bfd * abfd)917*3d8817e4Smiod oasys_write_end (bfd *abfd)
918*3d8817e4Smiod {
919*3d8817e4Smiod oasys_end_record_type end;
920*3d8817e4Smiod unsigned char null = 0;
921*3d8817e4Smiod
922*3d8817e4Smiod end.relb = RELOCATION_TYPE_ABS;
923*3d8817e4Smiod H_PUT_32 (abfd, abfd->start_address, end.entry);
924*3d8817e4Smiod H_PUT_16 (abfd, 0, end.fill);
925*3d8817e4Smiod end.zero = 0;
926*3d8817e4Smiod if (! oasys_write_record (abfd,
927*3d8817e4Smiod oasys_record_is_end_enum,
928*3d8817e4Smiod (oasys_record_union_type *) & end,
929*3d8817e4Smiod sizeof (end)))
930*3d8817e4Smiod return FALSE;
931*3d8817e4Smiod
932*3d8817e4Smiod return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
933*3d8817e4Smiod }
934*3d8817e4Smiod
935*3d8817e4Smiod static int
comp(const void * ap,const void * bp)936*3d8817e4Smiod comp (const void * ap, const void * bp)
937*3d8817e4Smiod {
938*3d8817e4Smiod arelent *a = *((arelent **) ap);
939*3d8817e4Smiod arelent *b = *((arelent **) bp);
940*3d8817e4Smiod
941*3d8817e4Smiod return a->address - b->address;
942*3d8817e4Smiod }
943*3d8817e4Smiod
944*3d8817e4Smiod static bfd_boolean
oasys_write_data(bfd * abfd)945*3d8817e4Smiod oasys_write_data (bfd *abfd)
946*3d8817e4Smiod {
947*3d8817e4Smiod asection *s;
948*3d8817e4Smiod
949*3d8817e4Smiod for (s = abfd->sections; s != NULL; s = s->next)
950*3d8817e4Smiod {
951*3d8817e4Smiod if (s->flags & SEC_LOAD)
952*3d8817e4Smiod {
953*3d8817e4Smiod bfd_byte *raw_data = oasys_per_section (s)->data;
954*3d8817e4Smiod oasys_data_record_type processed_data;
955*3d8817e4Smiod bfd_size_type current_byte_index = 0;
956*3d8817e4Smiod unsigned int relocs_to_go = s->reloc_count;
957*3d8817e4Smiod arelent **p = s->orelocation;
958*3d8817e4Smiod
959*3d8817e4Smiod if (s->reloc_count != 0)
960*3d8817e4Smiod /* Sort the reloc records so it's easy to insert the relocs into the
961*3d8817e4Smiod data. */
962*3d8817e4Smiod qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp);
963*3d8817e4Smiod
964*3d8817e4Smiod current_byte_index = 0;
965*3d8817e4Smiod processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
966*3d8817e4Smiod
967*3d8817e4Smiod while (current_byte_index < s->size)
968*3d8817e4Smiod {
969*3d8817e4Smiod /* Scan forwards by eight bytes or however much is left and see if
970*3d8817e4Smiod there are any relocations going on. */
971*3d8817e4Smiod bfd_byte *mod = &processed_data.data[0];
972*3d8817e4Smiod bfd_byte *dst = &processed_data.data[1];
973*3d8817e4Smiod
974*3d8817e4Smiod unsigned int i = 0;
975*3d8817e4Smiod *mod = 0;
976*3d8817e4Smiod
977*3d8817e4Smiod H_PUT_32 (abfd, s->vma + current_byte_index,
978*3d8817e4Smiod processed_data.addr);
979*3d8817e4Smiod
980*3d8817e4Smiod /* Don't start a relocation unless you're sure you can finish it
981*3d8817e4Smiod within the same data record. The worst case relocation is a
982*3d8817e4Smiod 4-byte relocatable value which is split across two modification
983*3d8817e4Smiod bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
984*3d8817e4Smiod 1 modification byte + 2 data = 8 bytes total). That's where
985*3d8817e4Smiod the magic number 8 comes from. */
986*3d8817e4Smiod while (current_byte_index < s->size && dst <=
987*3d8817e4Smiod & processed_data.data[sizeof (processed_data.data) - 8])
988*3d8817e4Smiod {
989*3d8817e4Smiod if (relocs_to_go != 0)
990*3d8817e4Smiod {
991*3d8817e4Smiod arelent *r = *p;
992*3d8817e4Smiod
993*3d8817e4Smiod /* There is a relocation, is it for this byte ? */
994*3d8817e4Smiod if (r->address == current_byte_index)
995*3d8817e4Smiod abort ();
996*3d8817e4Smiod }
997*3d8817e4Smiod
998*3d8817e4Smiod /* If this is coming from an unloadable section then copy
999*3d8817e4Smiod zeros. */
1000*3d8817e4Smiod if (raw_data == NULL)
1001*3d8817e4Smiod *dst++ = 0;
1002*3d8817e4Smiod else
1003*3d8817e4Smiod *dst++ = *raw_data++;
1004*3d8817e4Smiod
1005*3d8817e4Smiod if (++i >= 8)
1006*3d8817e4Smiod {
1007*3d8817e4Smiod i = 0;
1008*3d8817e4Smiod mod = dst++;
1009*3d8817e4Smiod *mod = 0;
1010*3d8817e4Smiod }
1011*3d8817e4Smiod current_byte_index++;
1012*3d8817e4Smiod }
1013*3d8817e4Smiod
1014*3d8817e4Smiod /* Don't write a useless null modification byte. */
1015*3d8817e4Smiod if (dst == mod + 1)
1016*3d8817e4Smiod --dst;
1017*3d8817e4Smiod
1018*3d8817e4Smiod if (! (oasys_write_record
1019*3d8817e4Smiod (abfd, oasys_record_is_data_enum,
1020*3d8817e4Smiod ((oasys_record_union_type *) &processed_data),
1021*3d8817e4Smiod (size_t) (dst - (bfd_byte *) &processed_data))))
1022*3d8817e4Smiod return FALSE;
1023*3d8817e4Smiod }
1024*3d8817e4Smiod }
1025*3d8817e4Smiod }
1026*3d8817e4Smiod
1027*3d8817e4Smiod return TRUE;
1028*3d8817e4Smiod }
1029*3d8817e4Smiod
1030*3d8817e4Smiod static bfd_boolean
oasys_write_object_contents(bfd * abfd)1031*3d8817e4Smiod oasys_write_object_contents (bfd *abfd)
1032*3d8817e4Smiod {
1033*3d8817e4Smiod if (! oasys_write_header (abfd))
1034*3d8817e4Smiod return FALSE;
1035*3d8817e4Smiod if (! oasys_write_syms (abfd))
1036*3d8817e4Smiod return FALSE;
1037*3d8817e4Smiod if (! oasys_write_sections (abfd))
1038*3d8817e4Smiod return FALSE;
1039*3d8817e4Smiod if (! oasys_write_data (abfd))
1040*3d8817e4Smiod return FALSE;
1041*3d8817e4Smiod if (! oasys_write_end (abfd))
1042*3d8817e4Smiod return FALSE;
1043*3d8817e4Smiod return TRUE;
1044*3d8817e4Smiod }
1045*3d8817e4Smiod
1046*3d8817e4Smiod /* Set section contents is complicated with OASYS since the format is
1047*3d8817e4Smiod not a byte image, but a record stream. */
1048*3d8817e4Smiod
1049*3d8817e4Smiod static bfd_boolean
oasys_set_section_contents(bfd * abfd,sec_ptr section,const void * location,file_ptr offset,bfd_size_type count)1050*3d8817e4Smiod oasys_set_section_contents (bfd *abfd,
1051*3d8817e4Smiod sec_ptr section,
1052*3d8817e4Smiod const void * location,
1053*3d8817e4Smiod file_ptr offset,
1054*3d8817e4Smiod bfd_size_type count)
1055*3d8817e4Smiod {
1056*3d8817e4Smiod if (count != 0)
1057*3d8817e4Smiod {
1058*3d8817e4Smiod if (oasys_per_section (section)->data == NULL)
1059*3d8817e4Smiod {
1060*3d8817e4Smiod oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
1061*3d8817e4Smiod if (!oasys_per_section (section)->data)
1062*3d8817e4Smiod return FALSE;
1063*3d8817e4Smiod }
1064*3d8817e4Smiod (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
1065*3d8817e4Smiod location, (size_t) count);
1066*3d8817e4Smiod }
1067*3d8817e4Smiod return TRUE;
1068*3d8817e4Smiod }
1069*3d8817e4Smiod
1070*3d8817e4Smiod
1071*3d8817e4Smiod
1072*3d8817e4Smiod /* Native-level interface to symbols. */
1073*3d8817e4Smiod
1074*3d8817e4Smiod /* We read the symbols into a buffer, which is discarded when this
1075*3d8817e4Smiod function exits. We read the strings into a buffer large enough to
1076*3d8817e4Smiod hold them all plus all the cached symbol entries. */
1077*3d8817e4Smiod
1078*3d8817e4Smiod static asymbol *
oasys_make_empty_symbol(bfd * abfd)1079*3d8817e4Smiod oasys_make_empty_symbol (bfd *abfd)
1080*3d8817e4Smiod {
1081*3d8817e4Smiod bfd_size_type amt = sizeof (oasys_symbol_type);
1082*3d8817e4Smiod oasys_symbol_type *new = bfd_zalloc (abfd, amt);
1083*3d8817e4Smiod
1084*3d8817e4Smiod if (!new)
1085*3d8817e4Smiod return NULL;
1086*3d8817e4Smiod new->symbol.the_bfd = abfd;
1087*3d8817e4Smiod return &new->symbol;
1088*3d8817e4Smiod }
1089*3d8817e4Smiod
1090*3d8817e4Smiod /* User should have checked the file flags; perhaps we should return
1091*3d8817e4Smiod BFD_NO_MORE_SYMBOLS if there are none? */
1092*3d8817e4Smiod
1093*3d8817e4Smiod static bfd *
oasys_openr_next_archived_file(bfd * arch,bfd * prev)1094*3d8817e4Smiod oasys_openr_next_archived_file (bfd *arch, bfd *prev)
1095*3d8817e4Smiod {
1096*3d8817e4Smiod oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1097*3d8817e4Smiod oasys_module_info_type *p;
1098*3d8817e4Smiod
1099*3d8817e4Smiod /* Take the next one from the arch state, or reset. */
1100*3d8817e4Smiod if (prev == NULL)
1101*3d8817e4Smiod /* Reset the index - the first two entries are bogus. */
1102*3d8817e4Smiod ar->module_index = 0;
1103*3d8817e4Smiod
1104*3d8817e4Smiod p = ar->module + ar->module_index;
1105*3d8817e4Smiod ar->module_index++;
1106*3d8817e4Smiod
1107*3d8817e4Smiod if (ar->module_index <= ar->module_count)
1108*3d8817e4Smiod {
1109*3d8817e4Smiod if (p->abfd == NULL)
1110*3d8817e4Smiod {
1111*3d8817e4Smiod p->abfd = _bfd_create_empty_archive_element_shell (arch);
1112*3d8817e4Smiod p->abfd->origin = p->pos;
1113*3d8817e4Smiod p->abfd->filename = p->name;
1114*3d8817e4Smiod
1115*3d8817e4Smiod /* Fixup a pointer to this element for the member. */
1116*3d8817e4Smiod p->abfd->arelt_data = (void *) p;
1117*3d8817e4Smiod }
1118*3d8817e4Smiod return p->abfd;
1119*3d8817e4Smiod }
1120*3d8817e4Smiod
1121*3d8817e4Smiod bfd_set_error (bfd_error_no_more_archived_files);
1122*3d8817e4Smiod return NULL;
1123*3d8817e4Smiod }
1124*3d8817e4Smiod
1125*3d8817e4Smiod static bfd_boolean
oasys_find_nearest_line(bfd * abfd ATTRIBUTE_UNUSED,asection * section ATTRIBUTE_UNUSED,asymbol ** symbols ATTRIBUTE_UNUSED,bfd_vma offset ATTRIBUTE_UNUSED,const char ** filename_ptr ATTRIBUTE_UNUSED,const char ** functionname_ptr ATTRIBUTE_UNUSED,unsigned int * line_ptr ATTRIBUTE_UNUSED)1126*3d8817e4Smiod oasys_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
1127*3d8817e4Smiod asection *section ATTRIBUTE_UNUSED,
1128*3d8817e4Smiod asymbol **symbols ATTRIBUTE_UNUSED,
1129*3d8817e4Smiod bfd_vma offset ATTRIBUTE_UNUSED,
1130*3d8817e4Smiod const char **filename_ptr ATTRIBUTE_UNUSED,
1131*3d8817e4Smiod const char **functionname_ptr ATTRIBUTE_UNUSED,
1132*3d8817e4Smiod unsigned int *line_ptr ATTRIBUTE_UNUSED)
1133*3d8817e4Smiod {
1134*3d8817e4Smiod return FALSE;
1135*3d8817e4Smiod }
1136*3d8817e4Smiod
1137*3d8817e4Smiod static bfd_boolean
oasys_find_inliner_info(bfd * abfd ATTRIBUTE_UNUSED,const char ** filename_ptr ATTRIBUTE_UNUSED,const char ** functionname_ptr ATTRIBUTE_UNUSED,unsigned int * line_ptr ATTRIBUTE_UNUSED)1138*3d8817e4Smiod oasys_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
1139*3d8817e4Smiod const char **filename_ptr ATTRIBUTE_UNUSED,
1140*3d8817e4Smiod const char **functionname_ptr ATTRIBUTE_UNUSED,
1141*3d8817e4Smiod unsigned int *line_ptr ATTRIBUTE_UNUSED)
1142*3d8817e4Smiod {
1143*3d8817e4Smiod return FALSE;
1144*3d8817e4Smiod }
1145*3d8817e4Smiod
1146*3d8817e4Smiod static int
oasys_generic_stat_arch_elt(bfd * abfd,struct stat * buf)1147*3d8817e4Smiod oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
1148*3d8817e4Smiod {
1149*3d8817e4Smiod oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1150*3d8817e4Smiod
1151*3d8817e4Smiod if (mod == NULL)
1152*3d8817e4Smiod {
1153*3d8817e4Smiod bfd_set_error (bfd_error_invalid_operation);
1154*3d8817e4Smiod return -1;
1155*3d8817e4Smiod }
1156*3d8817e4Smiod
1157*3d8817e4Smiod buf->st_size = mod->size;
1158*3d8817e4Smiod buf->st_mode = 0666;
1159*3d8817e4Smiod return 0;
1160*3d8817e4Smiod }
1161*3d8817e4Smiod
1162*3d8817e4Smiod static int
oasys_sizeof_headers(bfd * abfd ATTRIBUTE_UNUSED,bfd_boolean exec ATTRIBUTE_UNUSED)1163*3d8817e4Smiod oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean exec ATTRIBUTE_UNUSED)
1164*3d8817e4Smiod {
1165*3d8817e4Smiod return 0;
1166*3d8817e4Smiod }
1167*3d8817e4Smiod
1168*3d8817e4Smiod #define oasys_close_and_cleanup _bfd_generic_close_and_cleanup
1169*3d8817e4Smiod #define oasys_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1170*3d8817e4Smiod #define oasys_slurp_armap bfd_true
1171*3d8817e4Smiod #define oasys_slurp_extended_name_table bfd_true
1172*3d8817e4Smiod #define oasys_construct_extended_name_table ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true)
1173*3d8817e4Smiod #define oasys_truncate_arname bfd_dont_truncate_arname
1174*3d8817e4Smiod #define oasys_write_armap ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true)
1175*3d8817e4Smiod #define oasys_read_ar_hdr bfd_nullvoidptr
1176*3d8817e4Smiod #define oasys_get_elt_at_index _bfd_generic_get_elt_at_index
1177*3d8817e4Smiod #define oasys_update_armap_timestamp bfd_true
1178*3d8817e4Smiod #define oasys_bfd_is_local_label_name bfd_generic_is_local_label_name
1179*3d8817e4Smiod #define oasys_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1180*3d8817e4Smiod #define oasys_get_lineno _bfd_nosymbols_get_lineno
1181*3d8817e4Smiod #define oasys_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
1182*3d8817e4Smiod #define oasys_read_minisymbols _bfd_generic_read_minisymbols
1183*3d8817e4Smiod #define oasys_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
1184*3d8817e4Smiod #define oasys_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
1185*3d8817e4Smiod #define oasys_set_arch_mach bfd_default_set_arch_mach
1186*3d8817e4Smiod #define oasys_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
1187*3d8817e4Smiod #define oasys_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
1188*3d8817e4Smiod #define oasys_bfd_relax_section bfd_generic_relax_section
1189*3d8817e4Smiod #define oasys_bfd_gc_sections bfd_generic_gc_sections
1190*3d8817e4Smiod #define oasys_bfd_merge_sections bfd_generic_merge_sections
1191*3d8817e4Smiod #define oasys_bfd_is_group_section bfd_generic_is_group_section
1192*3d8817e4Smiod #define oasys_bfd_discard_group bfd_generic_discard_group
1193*3d8817e4Smiod #define oasys_section_already_linked _bfd_generic_section_already_linked
1194*3d8817e4Smiod #define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1195*3d8817e4Smiod #define oasys_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
1196*3d8817e4Smiod #define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
1197*3d8817e4Smiod #define oasys_bfd_link_just_syms _bfd_generic_link_just_syms
1198*3d8817e4Smiod #define oasys_bfd_final_link _bfd_generic_final_link
1199*3d8817e4Smiod #define oasys_bfd_link_split_section _bfd_generic_link_split_section
1200*3d8817e4Smiod
1201*3d8817e4Smiod const bfd_target oasys_vec =
1202*3d8817e4Smiod {
1203*3d8817e4Smiod "oasys", /* Name. */
1204*3d8817e4Smiod bfd_target_oasys_flavour,
1205*3d8817e4Smiod BFD_ENDIAN_BIG, /* Target byte order. */
1206*3d8817e4Smiod BFD_ENDIAN_BIG, /* Target headers byte order. */
1207*3d8817e4Smiod (HAS_RELOC | EXEC_P | /* Object flags. */
1208*3d8817e4Smiod HAS_LINENO | HAS_DEBUG |
1209*3d8817e4Smiod HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1210*3d8817e4Smiod (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1211*3d8817e4Smiod | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */
1212*3d8817e4Smiod 0, /* Leading underscore. */
1213*3d8817e4Smiod ' ', /* AR_pad_char. */
1214*3d8817e4Smiod 16, /* AR_max_namelen. */
1215*3d8817e4Smiod bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1216*3d8817e4Smiod bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1217*3d8817e4Smiod bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
1218*3d8817e4Smiod bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1219*3d8817e4Smiod bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1220*3d8817e4Smiod bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
1221*3d8817e4Smiod
1222*3d8817e4Smiod {_bfd_dummy_target,
1223*3d8817e4Smiod oasys_object_p, /* bfd_check_format. */
1224*3d8817e4Smiod oasys_archive_p,
1225*3d8817e4Smiod _bfd_dummy_target,
1226*3d8817e4Smiod },
1227*3d8817e4Smiod { /* bfd_set_format. */
1228*3d8817e4Smiod bfd_false,
1229*3d8817e4Smiod oasys_mkobject,
1230*3d8817e4Smiod _bfd_generic_mkarchive,
1231*3d8817e4Smiod bfd_false
1232*3d8817e4Smiod },
1233*3d8817e4Smiod { /* bfd_write_contents. */
1234*3d8817e4Smiod bfd_false,
1235*3d8817e4Smiod oasys_write_object_contents,
1236*3d8817e4Smiod _bfd_write_archive_contents,
1237*3d8817e4Smiod bfd_false,
1238*3d8817e4Smiod },
1239*3d8817e4Smiod
1240*3d8817e4Smiod BFD_JUMP_TABLE_GENERIC (oasys),
1241*3d8817e4Smiod BFD_JUMP_TABLE_COPY (_bfd_generic),
1242*3d8817e4Smiod BFD_JUMP_TABLE_CORE (_bfd_nocore),
1243*3d8817e4Smiod BFD_JUMP_TABLE_ARCHIVE (oasys),
1244*3d8817e4Smiod BFD_JUMP_TABLE_SYMBOLS (oasys),
1245*3d8817e4Smiod BFD_JUMP_TABLE_RELOCS (oasys),
1246*3d8817e4Smiod BFD_JUMP_TABLE_WRITE (oasys),
1247*3d8817e4Smiod BFD_JUMP_TABLE_LINK (oasys),
1248*3d8817e4Smiod BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1249*3d8817e4Smiod
1250*3d8817e4Smiod NULL,
1251*3d8817e4Smiod
1252*3d8817e4Smiod NULL
1253*3d8817e4Smiod };
1254