1999-09-06 Donn Terry <donn@interix.com>
[binutils.git] / bfd / oasys.c
blobe69053b82823d315af19b9b58fa8c4e58192086d
1 /* BFD back-end for oasys objects.
2 Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
3 Free Software Foundation, Inc.
4 Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>.
6 This file is part of BFD, the Binary File Descriptor library.
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 2 of the License, or
11 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #define UNDERSCORE_HACK 1
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include <ctype.h>
26 #include "libbfd.h"
27 #include "oasys.h"
28 #include "liboasys.h"
30 /* XXX - FIXME. offsetof belongs in the system-specific files in
31 ../include/sys. */
32 /* Define offsetof for those systems which lack it */
34 #ifndef offsetof
35 #define offsetof(type, identifier) (size_t) &(((type *) 0)->identifier)
36 #endif
38 static boolean oasys_read_record PARAMS ((bfd *,
39 oasys_record_union_type *));
40 static boolean oasys_write_sections PARAMS ((bfd *));
41 static boolean oasys_write_record PARAMS ((bfd *,
42 oasys_record_enum_type,
43 oasys_record_union_type *,
44 size_t));
45 static boolean oasys_write_syms PARAMS ((bfd *));
46 static boolean oasys_write_header PARAMS ((bfd *));
47 static boolean oasys_write_end PARAMS ((bfd *));
48 static boolean oasys_write_data PARAMS ((bfd *));
50 /* Read in all the section data and relocation stuff too */
51 PROTO (static boolean, oasys_slurp_section_data, (bfd * CONST abfd));
53 static boolean
54 oasys_read_record (abfd, record)
55 bfd *abfd;
56 oasys_record_union_type *record;
58 if (bfd_read ((PTR) record, 1, sizeof (record->header), abfd)
59 != sizeof (record->header))
60 return false;
62 if ((size_t) record->header.length <= (size_t) sizeof (record->header))
63 return true;
64 if (bfd_read ((PTR) (((char *) record) + sizeof (record->header)),
65 1, record->header.length - sizeof (record->header),
66 abfd)
67 != record->header.length - sizeof (record->header))
68 return false;
69 return true;
71 static size_t
72 oasys_string_length (record)
73 oasys_record_union_type *record;
75 return record->header.length
76 - ((char *) record->symbol.name - (char *) record);
79 /*****************************************************************************/
83 Slurp the symbol table by reading in all the records at the start file
84 till we get to the first section record.
86 We'll sort the symbolss into two lists, defined and undefined. The
87 undefined symbols will be placed into the table according to their
88 refno.
90 We do this by placing all undefined symbols at the front of the table
91 moving in, and the defined symbols at the end of the table moving back.
95 static boolean
96 oasys_slurp_symbol_table (abfd)
97 bfd *CONST abfd;
99 oasys_record_union_type record;
100 oasys_data_type *data = OASYS_DATA (abfd);
101 boolean loop = true;
102 asymbol *dest_defined;
103 asymbol *dest;
104 char *string_ptr;
107 if (data->symbols != (asymbol *) NULL)
109 return true;
111 /* Buy enough memory for all the symbols and all the names */
112 data->symbols =
113 (asymbol *) bfd_alloc (abfd, sizeof (asymbol) * abfd->symcount);
114 #ifdef UNDERSCORE_HACK
115 /* buy 1 more char for each symbol to keep the underscore in*/
116 data->strings = bfd_alloc (abfd, data->symbol_string_length +
117 abfd->symcount);
118 #else
119 data->strings = bfd_alloc (abfd, data->symbol_string_length);
120 #endif
121 if (!data->symbols || !data->strings)
122 return false;
124 dest_defined = data->symbols + abfd->symcount - 1;
126 string_ptr = data->strings;
127 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
128 return false;
129 while (loop)
132 if (! oasys_read_record (abfd, &record))
133 return false;
134 switch (record.header.type)
136 case oasys_record_is_header_enum:
137 break;
138 case oasys_record_is_local_enum:
139 case oasys_record_is_symbol_enum:
141 int flag = record.header.type == (int) oasys_record_is_local_enum ?
142 (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
145 size_t length = oasys_string_length (&record);
146 switch (record.symbol.relb & RELOCATION_TYPE_BITS)
148 case RELOCATION_TYPE_ABS:
149 dest = dest_defined--;
150 dest->section = bfd_abs_section_ptr;
151 dest->flags = 0;
153 break;
154 case RELOCATION_TYPE_REL:
155 dest = dest_defined--;
156 dest->section =
157 OASYS_DATA (abfd)->sections[record.symbol.relb &
158 RELOCATION_SECT_BITS];
159 if (record.header.type == (int) oasys_record_is_local_enum)
161 dest->flags = BSF_LOCAL;
162 if (dest->section == (asection *) (~0))
164 /* It seems that sometimes internal symbols are tied up, but
165 still get output, even though there is no
166 section */
167 dest->section = 0;
170 else
173 dest->flags = flag;
175 break;
176 case RELOCATION_TYPE_UND:
177 dest = data->symbols + bfd_h_get_16 (abfd, record.symbol.refno);
178 dest->section = bfd_und_section_ptr;
179 break;
180 case RELOCATION_TYPE_COM:
181 dest = dest_defined--;
182 dest->name = string_ptr;
183 dest->the_bfd = abfd;
185 dest->section = bfd_com_section_ptr;
187 break;
188 default:
189 dest = dest_defined--;
190 BFD_ASSERT (0);
191 break;
193 dest->name = string_ptr;
194 dest->the_bfd = abfd;
195 dest->udata.p = (PTR) NULL;
196 dest->value = bfd_h_get_32 (abfd, record.symbol.value);
198 #ifdef UNDERSCORE_HACK
199 if (record.symbol.name[0] != '_')
201 string_ptr[0] = '_';
202 string_ptr++;
204 #endif
205 memcpy (string_ptr, record.symbol.name, length);
208 string_ptr[length] = 0;
209 string_ptr += length + 1;
211 break;
212 default:
213 loop = false;
216 return true;
219 static long
220 oasys_get_symtab_upper_bound (abfd)
221 bfd *CONST abfd;
223 if (! oasys_slurp_symbol_table (abfd))
224 return -1;
226 return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *));
232 extern const bfd_target oasys_vec;
234 long
235 oasys_get_symtab (abfd, location)
236 bfd *abfd;
237 asymbol **location;
239 asymbol *symbase;
240 unsigned int counter;
241 if (oasys_slurp_symbol_table (abfd) == false)
243 return -1;
245 symbase = OASYS_DATA (abfd)->symbols;
246 for (counter = 0; counter < abfd->symcount; counter++)
248 *(location++) = symbase++;
250 *location = 0;
251 return abfd->symcount;
254 /***********************************************************************
255 * archive stuff
258 static const bfd_target *
259 oasys_archive_p (abfd)
260 bfd *abfd;
262 oasys_archive_header_type header;
263 oasys_extarchive_header_type header_ext;
264 unsigned int i;
265 file_ptr filepos;
267 if (bfd_seek (abfd, (file_ptr) 0, false) != 0
268 || (bfd_read ((PTR) & header_ext, 1, sizeof (header_ext), abfd)
269 != sizeof (header_ext)))
271 if (bfd_get_error () != bfd_error_system_call)
272 bfd_set_error (bfd_error_wrong_format);
273 return NULL;
276 header.version = bfd_h_get_32 (abfd, header_ext.version);
277 header.mod_count = bfd_h_get_32 (abfd, header_ext.mod_count);
278 header.mod_tbl_offset = bfd_h_get_32 (abfd, header_ext.mod_tbl_offset);
279 header.sym_tbl_size = bfd_h_get_32 (abfd, header_ext.sym_tbl_size);
280 header.sym_count = bfd_h_get_32 (abfd, header_ext.sym_count);
281 header.sym_tbl_offset = bfd_h_get_32 (abfd, header_ext.sym_tbl_offset);
282 header.xref_count = bfd_h_get_32 (abfd, header_ext.xref_count);
283 header.xref_lst_offset = bfd_h_get_32 (abfd, header_ext.xref_lst_offset);
286 There isn't a magic number in an Oasys archive, so the best we
287 can do to verify reasnableness is to make sure that the values in
288 the header are too weird
291 if (header.version > 10000 ||
292 header.mod_count > 10000 ||
293 header.sym_count > 100000 ||
294 header.xref_count > 100000)
295 return (const bfd_target *) NULL;
298 That all worked, let's buy the space for the header and read in
299 the headers.
302 oasys_ar_data_type *ar =
303 (oasys_ar_data_type *) bfd_alloc (abfd, sizeof (oasys_ar_data_type));
305 oasys_module_info_type *module =
306 (oasys_module_info_type *)
307 bfd_alloc (abfd, sizeof (oasys_module_info_type) * header.mod_count);
308 oasys_module_table_type record;
310 if (!ar || !module)
311 return NULL;
313 abfd->tdata.oasys_ar_data = ar;
314 ar->module = module;
315 ar->module_count = header.mod_count;
317 filepos = header.mod_tbl_offset;
318 for (i = 0; i < header.mod_count; i++)
320 if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
321 return NULL;
323 /* There are two ways of specifying the archive header */
325 if (0)
327 oasys_extmodule_table_type_a_type record_ext;
328 if (bfd_read ((PTR) & record_ext, 1, sizeof (record_ext), abfd)
329 != sizeof (record_ext))
330 return NULL;
332 record.mod_size = bfd_h_get_32 (abfd, record_ext.mod_size);
333 record.file_offset = bfd_h_get_32 (abfd, record_ext.file_offset);
335 record.dep_count = bfd_h_get_32 (abfd, record_ext.dep_count);
336 record.depee_count = bfd_h_get_32 (abfd, record_ext.depee_count);
337 record.sect_count = bfd_h_get_32 (abfd, record_ext.sect_count);
339 module[i].name = bfd_alloc (abfd, 33);
340 if (!module[i].name)
341 return NULL;
343 memcpy (module[i].name, record_ext.mod_name, 33);
344 filepos +=
345 sizeof (record_ext) +
346 record.dep_count * 4 +
347 record.depee_count * 4 +
348 record.sect_count * 8 + 187;
350 else
352 oasys_extmodule_table_type_b_type record_ext;
353 if (bfd_read ((PTR) & record_ext, 1, sizeof (record_ext), abfd)
354 != sizeof (record_ext))
355 return NULL;
357 record.mod_size = bfd_h_get_32 (abfd, record_ext.mod_size);
358 record.file_offset = bfd_h_get_32 (abfd, record_ext.file_offset);
360 record.dep_count = bfd_h_get_32 (abfd, record_ext.dep_count);
361 record.depee_count = bfd_h_get_32 (abfd, record_ext.depee_count);
362 record.sect_count = bfd_h_get_32 (abfd, record_ext.sect_count);
363 record.module_name_size = bfd_h_get_32 (abfd, record_ext.mod_name_length);
365 module[i].name = bfd_alloc (abfd, record.module_name_size + 1);
366 if (!module[i].name)
367 return NULL;
368 if (bfd_read ((PTR) module[i].name, 1, record.module_name_size,
369 abfd)
370 != record.module_name_size)
371 return NULL;
372 module[i].name[record.module_name_size] = 0;
373 filepos +=
374 sizeof (record_ext) +
375 record.dep_count * 4 +
376 record.module_name_size + 1;
381 module[i].size = record.mod_size;
382 module[i].pos = record.file_offset;
383 module[i].abfd = 0;
387 return abfd->xvec;
390 static boolean
391 oasys_mkobject (abfd)
392 bfd *abfd;
395 abfd->tdata.oasys_obj_data = (oasys_data_type *) bfd_alloc (abfd, sizeof (oasys_data_type));
396 return abfd->tdata.oasys_obj_data ? true : false;
399 #define MAX_SECS 16
400 static const bfd_target *
401 oasys_object_p (abfd)
402 bfd *abfd;
404 oasys_data_type *oasys;
405 oasys_data_type *save = OASYS_DATA (abfd);
406 boolean loop = true;
407 boolean had_usefull = false;
409 abfd->tdata.oasys_obj_data = 0;
410 oasys_mkobject (abfd);
411 oasys = OASYS_DATA (abfd);
412 memset ((PTR) oasys->sections, 0xff, sizeof (oasys->sections));
414 /* Point to the start of the file */
415 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
416 goto fail;
417 oasys->symbol_string_length = 0;
418 /* Inspect the records, but only keep the section info -
419 remember the size of the symbols
421 oasys->first_data_record = 0;
422 while (loop)
424 oasys_record_union_type record;
425 if (! oasys_read_record (abfd, &record))
426 goto fail;
427 if ((size_t) record.header.length < (size_t) sizeof (record.header))
428 goto fail;
431 switch ((oasys_record_enum_type) (record.header.type))
433 case oasys_record_is_header_enum:
434 had_usefull = true;
435 break;
436 case oasys_record_is_symbol_enum:
437 case oasys_record_is_local_enum:
438 /* Count symbols and remember their size for a future malloc */
439 abfd->symcount++;
440 oasys->symbol_string_length += 1 + oasys_string_length (&record);
441 had_usefull = true;
442 break;
443 case oasys_record_is_section_enum:
445 asection *s;
446 char *buffer;
447 unsigned int section_number;
448 if (record.section.header.length != sizeof (record.section))
450 goto fail;
452 buffer = bfd_alloc (abfd, 3);
453 if (!buffer)
454 goto fail;
455 section_number = record.section.relb & RELOCATION_SECT_BITS;
456 sprintf (buffer, "%u", section_number);
457 s = bfd_make_section (abfd, buffer);
458 oasys->sections[section_number] = s;
459 switch (record.section.relb & RELOCATION_TYPE_BITS)
461 case RELOCATION_TYPE_ABS:
462 case RELOCATION_TYPE_REL:
463 break;
464 case RELOCATION_TYPE_UND:
465 case RELOCATION_TYPE_COM:
466 BFD_FAIL ();
469 s->_raw_size = bfd_h_get_32 (abfd, record.section.value);
470 s->vma = bfd_h_get_32 (abfd, record.section.vma);
471 s->flags = 0;
472 had_usefull = true;
474 break;
475 case oasys_record_is_data_enum:
476 oasys->first_data_record = bfd_tell (abfd) - record.header.length;
477 case oasys_record_is_debug_enum:
478 case oasys_record_is_module_enum:
479 case oasys_record_is_named_section_enum:
480 case oasys_record_is_end_enum:
481 if (had_usefull == false)
482 goto fail;
483 loop = false;
484 break;
485 default:
486 goto fail;
489 oasys->symbols = (asymbol *) NULL;
491 Oasys support several architectures, but I can't see a simple way
492 to discover which one is in a particular file - we'll guess
494 bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
495 if (abfd->symcount != 0)
497 abfd->flags |= HAS_SYMS;
501 We don't know if a section has data until we've read it..
504 oasys_slurp_section_data (abfd);
507 return abfd->xvec;
509 fail:
510 (void) bfd_release (abfd, oasys);
511 abfd->tdata.oasys_obj_data = save;
512 return (const bfd_target *) NULL;
516 static void
517 oasys_get_symbol_info (ignore_abfd, symbol, ret)
518 bfd *ignore_abfd ATTRIBUTE_UNUSED;
519 asymbol *symbol;
520 symbol_info *ret;
522 bfd_symbol_info (symbol, ret);
523 if (!symbol->section)
524 ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
527 static void
528 oasys_print_symbol (ignore_abfd, afile, symbol, how)
529 bfd *ignore_abfd ATTRIBUTE_UNUSED;
530 PTR afile;
531 asymbol *symbol;
532 bfd_print_symbol_type how;
534 FILE *file = (FILE *) afile;
536 switch (how)
538 case bfd_print_symbol_name:
539 case bfd_print_symbol_more:
540 fprintf (file, "%s", symbol->name);
541 break;
542 case bfd_print_symbol_all:
544 CONST char *section_name = symbol->section == (asection *) NULL ?
545 (CONST char *) "*abs" : symbol->section->name;
547 bfd_print_symbol_vandf ((PTR) file, symbol);
549 fprintf (file, " %-5s %s",
550 section_name,
551 symbol->name);
553 break;
557 The howto table is build using the top two bits of a reloc byte to
558 index into it. The bits are PCREL,WORD/LONG
560 static reloc_howto_type howto_table[] =
563 HOWTO (0, 0, 1, 16, false, 0, complain_overflow_bitfield, 0, "abs16", true, 0x0000ffff, 0x0000ffff, false),
564 HOWTO (0, 0, 2, 32, false, 0, complain_overflow_bitfield, 0, "abs32", true, 0xffffffff, 0xffffffff, false),
565 HOWTO (0, 0, 1, 16, true, 0, complain_overflow_signed, 0, "pcrel16", true, 0x0000ffff, 0x0000ffff, false),
566 HOWTO (0, 0, 2, 32, true, 0, complain_overflow_signed, 0, "pcrel32", true, 0xffffffff, 0xffffffff, false)
569 /* Read in all the section data and relocation stuff too */
570 static boolean
571 oasys_slurp_section_data (abfd)
572 bfd *CONST abfd;
574 oasys_record_union_type record;
575 oasys_data_type *data = OASYS_DATA (abfd);
576 boolean loop = true;
578 oasys_per_section_type *per;
580 asection *s;
582 /* See if the data has been slurped already .. */
583 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
585 per = oasys_per_section (s);
586 if (per->initialized == true)
587 return true;
590 if (data->first_data_record == 0)
591 return true;
593 if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
594 return false;
595 while (loop)
597 if (! oasys_read_record (abfd, &record))
598 return false;
599 switch (record.header.type)
601 case oasys_record_is_header_enum:
602 break;
603 case oasys_record_is_data_enum:
606 bfd_byte *src = record.data.data;
607 bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
608 bfd_byte *dst_ptr;
609 bfd_byte *dst_base_ptr;
610 unsigned int relbit;
611 unsigned int count;
612 asection *section =
613 data->sections[record.data.relb & RELOCATION_SECT_BITS];
614 bfd_vma dst_offset;
616 per = oasys_per_section (section);
618 if (per->initialized == false)
620 per->data = (bfd_byte *) bfd_zalloc (abfd, section->_raw_size);
621 if (!per->data)
622 return false;
623 per->reloc_tail_ptr = (oasys_reloc_type **) & (section->relocation);
624 per->had_vma = false;
625 per->initialized = true;
626 section->reloc_count = 0;
627 section->flags = SEC_ALLOC;
630 dst_offset = bfd_h_get_32 (abfd, record.data.addr);
631 if (per->had_vma == false)
633 /* Take the first vma we see as the base */
634 section->vma = dst_offset;
635 per->had_vma = true;
638 dst_offset -= section->vma;
640 dst_base_ptr = oasys_per_section (section)->data;
641 dst_ptr = oasys_per_section (section)->data +
642 dst_offset;
644 if (src < end_src)
646 section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
648 while (src < end_src)
650 unsigned char mod_byte = *src++;
651 size_t gap = end_src - src;
653 count = 8;
654 if (mod_byte == 0 && gap >= 8)
656 dst_ptr[0] = src[0];
657 dst_ptr[1] = src[1];
658 dst_ptr[2] = src[2];
659 dst_ptr[3] = src[3];
660 dst_ptr[4] = src[4];
661 dst_ptr[5] = src[5];
662 dst_ptr[6] = src[6];
663 dst_ptr[7] = src[7];
664 dst_ptr += 8;
665 src += 8;
667 else
669 for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
671 if (relbit & mod_byte)
673 unsigned char reloc = *src;
674 /* This item needs to be relocated */
675 switch (reloc & RELOCATION_TYPE_BITS)
677 case RELOCATION_TYPE_ABS:
679 break;
681 case RELOCATION_TYPE_REL:
683 /* Relocate the item relative to the section */
684 oasys_reloc_type *r =
685 (oasys_reloc_type *)
686 bfd_alloc (abfd,
687 sizeof (oasys_reloc_type));
688 if (!r)
689 return false;
690 *(per->reloc_tail_ptr) = r;
691 per->reloc_tail_ptr = &r->next;
692 r->next = (oasys_reloc_type *) NULL;
693 /* Reference to undefined symbol */
694 src++;
695 /* There is no symbol */
696 r->symbol = 0;
697 /* Work out the howto */
698 abort ();
699 #if 0
700 r->relent.section =
701 data->sections[reloc &
702 RELOCATION_SECT_BITS];
704 r->relent.addend = -
705 r->relent.section->vma;
706 #endif
707 r->relent.address = dst_ptr - dst_base_ptr;
708 r->relent.howto = &howto_table[reloc >> 6];
709 r->relent.sym_ptr_ptr = (asymbol **) NULL;
710 section->reloc_count++;
712 /* Fake up the data to look like it's got the -ve pc in it, this makes
713 it much easier to convert into other formats. This is done by
714 hitting the addend.
716 if (r->relent.howto->pc_relative == true)
718 r->relent.addend -= dst_ptr - dst_base_ptr;
723 break;
726 case RELOCATION_TYPE_UND:
728 oasys_reloc_type *r =
729 (oasys_reloc_type *)
730 bfd_alloc (abfd,
731 sizeof (oasys_reloc_type));
732 if (!r)
733 return false;
734 *(per->reloc_tail_ptr) = r;
735 per->reloc_tail_ptr = &r->next;
736 r->next = (oasys_reloc_type *) NULL;
737 /* Reference to undefined symbol */
738 src++;
739 /* Get symbol number */
740 r->symbol = (src[0] << 8) | src[1];
741 /* Work out the howto */
742 abort ();
744 #if 0
745 r->relent.section = (asection
746 *) NULL;
747 #endif
748 r->relent.addend = 0;
749 r->relent.address = dst_ptr - dst_base_ptr;
750 r->relent.howto = &howto_table[reloc >> 6];
751 r->relent.sym_ptr_ptr = (asymbol **) NULL;
752 section->reloc_count++;
754 src += 2;
755 /* Fake up the data to look like it's got the -ve pc in it, this makes
756 it much easier to convert into other formats. This is done by
757 hitting the addend.
759 if (r->relent.howto->pc_relative == true)
761 r->relent.addend -= dst_ptr - dst_base_ptr;
767 break;
768 case RELOCATION_TYPE_COM:
769 BFD_FAIL ();
772 *dst_ptr++ = *src++;
777 break;
778 case oasys_record_is_local_enum:
779 case oasys_record_is_symbol_enum:
780 case oasys_record_is_section_enum:
781 break;
782 default:
783 loop = false;
787 return true;
791 static boolean
792 oasys_new_section_hook (abfd, newsect)
793 bfd *abfd;
794 asection *newsect;
796 newsect->used_by_bfd = (PTR)
797 bfd_alloc (abfd, sizeof (oasys_per_section_type));
798 if (!newsect->used_by_bfd)
799 return false;
800 oasys_per_section (newsect)->data = (bfd_byte *) NULL;
801 oasys_per_section (newsect)->section = newsect;
802 oasys_per_section (newsect)->offset = 0;
803 oasys_per_section (newsect)->initialized = false;
804 newsect->alignment_power = 1;
805 /* Turn the section string into an index */
807 sscanf (newsect->name, "%u", &newsect->target_index);
809 return true;
813 static long
814 oasys_get_reloc_upper_bound (abfd, asect)
815 bfd *abfd;
816 sec_ptr asect;
818 if (! oasys_slurp_section_data (abfd))
819 return -1;
820 return (asect->reloc_count + 1) * sizeof (arelent *);
823 static boolean
824 oasys_get_section_contents (abfd, section, location, offset, count)
825 bfd *abfd;
826 sec_ptr section;
827 PTR location;
828 file_ptr offset;
829 bfd_size_type count;
831 oasys_per_section_type *p = (oasys_per_section_type *) section->used_by_bfd;
832 oasys_slurp_section_data (abfd);
833 if (p->initialized == false)
835 (void) memset (location, 0, (int) count);
837 else
839 (void) memcpy (location, (PTR) (p->data + offset), (int) count);
841 return true;
845 long
846 oasys_canonicalize_reloc (ignore_abfd, section, relptr, symbols)
847 bfd *ignore_abfd ATTRIBUTE_UNUSED;
848 sec_ptr section;
849 arelent **relptr;
850 asymbol **symbols ATTRIBUTE_UNUSED;
852 unsigned int reloc_count = 0;
853 oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
854 while (src != (oasys_reloc_type *) NULL)
856 abort ();
858 #if 0
859 if (src->relent.section == (asection *) NULL)
861 src->relent.sym_ptr_ptr = symbols + src->symbol;
863 #endif
865 *relptr++ = &src->relent;
866 src = src->next;
867 reloc_count++;
869 *relptr = (arelent *) NULL;
870 return section->reloc_count = reloc_count;
876 /* Writing */
879 /* Calculate the checksum and write one record */
880 static boolean
881 oasys_write_record (abfd, type, record, size)
882 bfd *abfd;
883 oasys_record_enum_type type;
884 oasys_record_union_type *record;
885 size_t size;
887 int checksum;
888 size_t i;
889 unsigned char *ptr;
891 record->header.length = size;
892 record->header.type = (int) type;
893 record->header.check_sum = 0;
894 record->header.fill = 0;
895 ptr = (unsigned char *) &record->pad[0];
896 checksum = 0;
897 for (i = 0; i < size; i++)
899 checksum += *ptr++;
901 record->header.check_sum = 0xff & (-checksum);
902 if (bfd_write ((PTR) record, 1, size, abfd) != size)
903 return false;
904 return true;
908 /* Write out all the symbols */
909 static boolean
910 oasys_write_syms (abfd)
911 bfd *abfd;
913 unsigned int count;
914 asymbol **generic = bfd_get_outsymbols (abfd);
915 unsigned int index = 0;
916 for (count = 0; count < bfd_get_symcount (abfd); count++)
919 oasys_symbol_record_type symbol;
920 asymbol *CONST g = generic[count];
922 CONST char *src = g->name;
923 char *dst = symbol.name;
924 unsigned int l = 0;
926 if (bfd_is_com_section (g->section))
928 symbol.relb = RELOCATION_TYPE_COM;
929 bfd_h_put_16 (abfd, index, symbol.refno);
930 index++;
932 else if (bfd_is_abs_section (g->section))
934 symbol.relb = RELOCATION_TYPE_ABS;
935 bfd_h_put_16 (abfd, 0, symbol.refno);
938 else if (bfd_is_und_section (g->section))
940 symbol.relb = RELOCATION_TYPE_UND;
941 bfd_h_put_16 (abfd, index, symbol.refno);
942 /* Overload the value field with the output index number */
943 index++;
945 else if (g->flags & BSF_DEBUGGING)
947 /* throw it away */
948 continue;
950 else
952 if (g->section == (asection *) NULL)
954 /* Sometime, the oasys tools give out a symbol with illegal
955 bits in it, we'll output it in the same broken way */
957 symbol.relb = RELOCATION_TYPE_REL | 0;
959 else
961 symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
963 bfd_h_put_16 (abfd, 0, symbol.refno);
965 #ifdef UNDERSCORE_HACK
966 if (src[l] == '_')
967 dst[l++] = '.';
968 #endif
969 while (src[l])
971 dst[l] = src[l];
972 l++;
975 bfd_h_put_32 (abfd, g->value, symbol.value);
978 if (g->flags & BSF_LOCAL)
980 if (! oasys_write_record (abfd,
981 oasys_record_is_local_enum,
982 (oasys_record_union_type *) & symbol,
983 offsetof (oasys_symbol_record_type,
984 name[0]) + l))
985 return false;
987 else
989 if (! oasys_write_record (abfd,
990 oasys_record_is_symbol_enum,
991 (oasys_record_union_type *) & symbol,
992 offsetof (oasys_symbol_record_type,
993 name[0]) + l))
994 return false;
996 g->value = index - 1;
999 return true;
1003 /* Write a section header for each section */
1004 static boolean
1005 oasys_write_sections (abfd)
1006 bfd *abfd;
1008 asection *s;
1009 static oasys_section_record_type out;
1011 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
1013 if (!isdigit ((unsigned char) s->name[0]))
1015 (*_bfd_error_handler)
1016 (_("%s: can not represent section `%s' in oasys"),
1017 bfd_get_filename (abfd), s->name);
1018 bfd_set_error (bfd_error_nonrepresentable_section);
1019 return false;
1021 out.relb = RELOCATION_TYPE_REL | s->target_index;
1022 bfd_h_put_32 (abfd, s->_cooked_size, out.value);
1023 bfd_h_put_32 (abfd, s->vma, out.vma);
1025 if (! oasys_write_record (abfd,
1026 oasys_record_is_section_enum,
1027 (oasys_record_union_type *) & out,
1028 sizeof (out)))
1029 return false;
1031 return true;
1034 static boolean
1035 oasys_write_header (abfd)
1036 bfd *abfd;
1038 /* Create and write the header */
1039 oasys_header_record_type r;
1040 size_t length = strlen (abfd->filename);
1041 if (length > (size_t) sizeof (r.module_name))
1043 length = sizeof (r.module_name);
1046 (void) memcpy (r.module_name,
1047 abfd->filename,
1048 length);
1049 (void) memset (r.module_name + length,
1050 ' ',
1051 sizeof (r.module_name) - length);
1053 r.version_number = OASYS_VERSION_NUMBER;
1054 r.rev_number = OASYS_REV_NUMBER;
1055 if (! oasys_write_record (abfd,
1056 oasys_record_is_header_enum,
1057 (oasys_record_union_type *) & r,
1058 offsetof (oasys_header_record_type,
1059 description[0])))
1060 return false;
1062 return true;
1065 static boolean
1066 oasys_write_end (abfd)
1067 bfd *abfd;
1069 oasys_end_record_type end;
1070 unsigned char null = 0;
1071 end.relb = RELOCATION_TYPE_ABS;
1072 bfd_h_put_32 (abfd, abfd->start_address, end.entry);
1073 bfd_h_put_16 (abfd, 0, end.fill);
1074 end.zero = 0;
1075 if (! oasys_write_record (abfd,
1076 oasys_record_is_end_enum,
1077 (oasys_record_union_type *) & end,
1078 sizeof (end)))
1079 return false;
1080 if (bfd_write ((PTR) & null, 1, 1, abfd) != 1)
1081 return false;
1082 return true;
1085 static int
1086 comp (ap, bp)
1087 CONST PTR ap;
1088 CONST PTR bp;
1090 arelent *a = *((arelent **) ap);
1091 arelent *b = *((arelent **) bp);
1092 return a->address - b->address;
1096 Writing data..
1099 static boolean
1100 oasys_write_data (abfd)
1101 bfd *abfd;
1103 asection *s;
1104 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
1106 if (s->flags & SEC_LOAD)
1108 bfd_byte *raw_data = oasys_per_section (s)->data;
1109 oasys_data_record_type processed_data;
1110 bfd_size_type current_byte_index = 0;
1111 unsigned int relocs_to_go = s->reloc_count;
1112 arelent **p = s->orelocation;
1113 if (s->reloc_count != 0)
1115 /* Sort the reloc records so it's easy to insert the relocs into the
1116 data */
1118 qsort (s->orelocation,
1119 s->reloc_count,
1120 sizeof (arelent **),
1121 comp);
1123 current_byte_index = 0;
1124 processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
1126 while (current_byte_index < s->_cooked_size)
1128 /* Scan forwards by eight bytes or however much is left and see if
1129 there are any relocations going on */
1130 bfd_byte *mod = &processed_data.data[0];
1131 bfd_byte *dst = &processed_data.data[1];
1133 unsigned int i = 0;
1134 *mod = 0;
1137 bfd_h_put_32 (abfd, s->vma + current_byte_index,
1138 processed_data.addr);
1140 /* Don't start a relocation unless you're sure you can finish it
1141 within the same data record. The worst case relocation is a
1142 4-byte relocatable value which is split across two modification
1143 bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
1144 1 modification byte + 2 data = 8 bytes total). That's where
1145 the magic number 8 comes from.
1147 while (current_byte_index < s->_raw_size && dst <=
1148 &processed_data.data[sizeof (processed_data.data) - 8])
1152 if (relocs_to_go != 0)
1154 arelent *r = *p;
1155 reloc_howto_type *const how = r->howto;
1156 /* There is a relocation, is it for this byte ? */
1157 if (r->address == current_byte_index)
1159 unsigned char rel_byte;
1161 p++;
1162 relocs_to_go--;
1164 *mod |= (1 << i);
1165 if (how->pc_relative)
1167 rel_byte = RELOCATION_PCREL_BIT;
1169 /* Also patch the raw data so that it doesn't have
1170 the -ve stuff any more */
1171 if (how->size != 2)
1173 bfd_put_16 (abfd,
1174 bfd_get_16 (abfd, raw_data) +
1175 current_byte_index, raw_data);
1178 else
1180 bfd_put_32 (abfd,
1181 bfd_get_32 (abfd, raw_data) +
1182 current_byte_index, raw_data);
1185 else
1187 rel_byte = 0;
1189 if (how->size == 2)
1191 rel_byte |= RELOCATION_32BIT_BIT;
1194 /* Is this a section relative relocation, or a symbol
1195 relative relocation ? */
1196 abort ();
1198 #if 0
1199 if (r->section != (asection *) NULL)
1201 /* The relent has a section attached, so it must be section
1202 relative */
1203 rel_byte |= RELOCATION_TYPE_REL;
1204 rel_byte |= r->section->output_section->target_index;
1205 *dst++ = rel_byte;
1207 else
1208 #endif
1210 asymbol *p = *(r->sym_ptr_ptr);
1212 /* If this symbol has a section attached, then it
1213 has already been resolved. Change from a symbol
1214 ref to a section ref */
1215 if (p->section != (asection *) NULL)
1217 rel_byte |= RELOCATION_TYPE_REL;
1218 rel_byte |=
1219 p->section->output_section->target_index;
1220 *dst++ = rel_byte;
1222 else
1224 rel_byte |= RELOCATION_TYPE_UND;
1225 *dst++ = rel_byte;
1226 /* Next two bytes are a symbol index - we can get
1227 this from the symbol value which has been zapped
1228 into the symbol index in the table when the
1229 symbol table was written
1231 *dst++ = p->value >> 8;
1232 *dst++ = p->value;
1235 #define ADVANCE { if (++i >= 8) { i = 0; mod = dst++; *mod = 0; } current_byte_index++; }
1236 /* relocations never occur from an unloadable section,
1237 so we can assume that raw_data is not NULL
1239 *dst++ = *raw_data++;
1240 ADVANCE
1241 * dst++ = *raw_data++;
1242 ADVANCE
1243 if (how->size == 2)
1245 *dst++ = *raw_data++;
1246 ADVANCE
1247 * dst++ = *raw_data++;
1248 ADVANCE
1250 continue;
1253 /* If this is coming from an unloadable section then copy
1254 zeros */
1255 if (raw_data == NULL)
1257 *dst++ = 0;
1259 else
1261 *dst++ = *raw_data++;
1263 ADVANCE
1266 /* Don't write a useless null modification byte */
1267 if (dst == mod + 1)
1269 --dst;
1272 if (! oasys_write_record (abfd,
1273 oasys_record_is_data_enum,
1274 ((oasys_record_union_type *)
1275 & processed_data),
1276 dst - (bfd_byte *) & processed_data))
1277 return false;
1282 return true;
1285 static boolean
1286 oasys_write_object_contents (abfd)
1287 bfd *abfd;
1289 if (! oasys_write_header (abfd))
1290 return false;
1291 if (! oasys_write_syms (abfd))
1292 return false;
1293 if (! oasys_write_sections (abfd))
1294 return false;
1295 if (! oasys_write_data (abfd))
1296 return false;
1297 if (! oasys_write_end (abfd))
1298 return false;
1299 return true;
1305 /** exec and core file sections */
1307 /* set section contents is complicated with OASYS since the format is
1308 * not a byte image, but a record stream.
1310 static boolean
1311 oasys_set_section_contents (abfd, section, location, offset, count)
1312 bfd *abfd;
1313 sec_ptr section;
1314 PTR location;
1315 file_ptr offset;
1316 bfd_size_type count;
1318 if (count != 0)
1320 if (oasys_per_section (section)->data == (bfd_byte *) NULL)
1322 oasys_per_section (section)->data =
1323 (bfd_byte *) (bfd_alloc (abfd, section->_cooked_size));
1324 if (!oasys_per_section (section)->data)
1325 return false;
1327 (void) memcpy ((PTR) (oasys_per_section (section)->data + offset),
1328 location,
1329 (size_t) count);
1331 return true;
1336 /* Native-level interface to symbols. */
1338 /* We read the symbols into a buffer, which is discarded when this
1339 function exits. We read the strings into a buffer large enough to
1340 hold them all plus all the cached symbol entries. */
1342 static asymbol *
1343 oasys_make_empty_symbol (abfd)
1344 bfd *abfd;
1347 oasys_symbol_type *new =
1348 (oasys_symbol_type *) bfd_zalloc (abfd, sizeof (oasys_symbol_type));
1349 if (!new)
1350 return NULL;
1351 new->symbol.the_bfd = abfd;
1352 return &new->symbol;
1358 /* User should have checked the file flags; perhaps we should return
1359 BFD_NO_MORE_SYMBOLS if there are none? */
1361 static bfd *
1362 oasys_openr_next_archived_file (arch, prev)
1363 bfd *arch;
1364 bfd *prev;
1366 oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1367 oasys_module_info_type *p;
1368 /* take the next one from the arch state, or reset */
1369 if (prev == (bfd *) NULL)
1371 /* Reset the index - the first two entries are bogus*/
1372 ar->module_index = 0;
1375 p = ar->module + ar->module_index;
1376 ar->module_index++;
1378 if (ar->module_index <= ar->module_count)
1380 if (p->abfd == (bfd *) NULL)
1382 p->abfd = _bfd_create_empty_archive_element_shell (arch);
1383 p->abfd->origin = p->pos;
1384 p->abfd->filename = p->name;
1386 /* Fixup a pointer to this element for the member */
1387 p->abfd->arelt_data = (PTR) p;
1389 return p->abfd;
1391 else
1393 bfd_set_error (bfd_error_no_more_archived_files);
1394 return (bfd *) NULL;
1398 static boolean
1399 oasys_find_nearest_line (abfd,
1400 section,
1401 symbols,
1402 offset,
1403 filename_ptr,
1404 functionname_ptr,
1405 line_ptr)
1406 bfd *abfd ATTRIBUTE_UNUSED;
1407 asection *section ATTRIBUTE_UNUSED;
1408 asymbol **symbols ATTRIBUTE_UNUSED;
1409 bfd_vma offset ATTRIBUTE_UNUSED;
1410 char **filename_ptr ATTRIBUTE_UNUSED;
1411 char **functionname_ptr ATTRIBUTE_UNUSED;
1412 unsigned int *line_ptr ATTRIBUTE_UNUSED;
1414 return false;
1418 static int
1419 oasys_generic_stat_arch_elt (abfd, buf)
1420 bfd *abfd;
1421 struct stat *buf;
1423 oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1424 if (mod == (oasys_module_info_type *) NULL)
1426 bfd_set_error (bfd_error_invalid_operation);
1427 return -1;
1429 else
1431 buf->st_size = mod->size;
1432 buf->st_mode = 0666;
1433 return 0;
1437 static int
1438 oasys_sizeof_headers (abfd, exec)
1439 bfd *abfd ATTRIBUTE_UNUSED;
1440 boolean exec ATTRIBUTE_UNUSED;
1442 return 0;
1445 #define oasys_close_and_cleanup _bfd_generic_close_and_cleanup
1446 #define oasys_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1448 #define oasys_slurp_armap bfd_true
1449 #define oasys_slurp_extended_name_table bfd_true
1450 #define oasys_construct_extended_name_table \
1451 ((boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
1452 bfd_true)
1453 #define oasys_truncate_arname bfd_dont_truncate_arname
1454 #define oasys_write_armap \
1455 ((boolean (*) \
1456 PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \
1457 bfd_true)
1458 #define oasys_read_ar_hdr bfd_nullvoidptr
1459 #define oasys_get_elt_at_index _bfd_generic_get_elt_at_index
1460 #define oasys_update_armap_timestamp bfd_true
1462 #define oasys_bfd_is_local_label_name bfd_generic_is_local_label_name
1463 #define oasys_get_lineno _bfd_nosymbols_get_lineno
1464 #define oasys_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
1465 #define oasys_read_minisymbols _bfd_generic_read_minisymbols
1466 #define oasys_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
1468 #define oasys_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
1470 #define oasys_set_arch_mach bfd_default_set_arch_mach
1472 #define oasys_get_section_contents_in_window \
1473 _bfd_generic_get_section_contents_in_window
1475 #define oasys_bfd_get_relocated_section_contents \
1476 bfd_generic_get_relocated_section_contents
1477 #define oasys_bfd_relax_section bfd_generic_relax_section
1478 #define oasys_bfd_gc_sections bfd_generic_gc_sections
1479 #define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1480 #define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
1481 #define oasys_bfd_final_link _bfd_generic_final_link
1482 #define oasys_bfd_link_split_section _bfd_generic_link_split_section
1484 /*SUPPRESS 460 */
1485 const bfd_target oasys_vec =
1487 "oasys", /* name */
1488 bfd_target_oasys_flavour,
1489 BFD_ENDIAN_BIG, /* target byte order */
1490 BFD_ENDIAN_BIG, /* target headers byte order */
1491 (HAS_RELOC | EXEC_P | /* object flags */
1492 HAS_LINENO | HAS_DEBUG |
1493 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1494 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1495 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1496 0, /* leading underscore */
1497 ' ', /* ar_pad_char */
1498 16, /* ar_max_namelen */
1499 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1500 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1501 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1502 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1503 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1504 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
1506 {_bfd_dummy_target,
1507 oasys_object_p, /* bfd_check_format */
1508 oasys_archive_p,
1509 _bfd_dummy_target,
1511 { /* bfd_set_format */
1512 bfd_false,
1513 oasys_mkobject,
1514 _bfd_generic_mkarchive,
1515 bfd_false
1517 { /* bfd_write_contents */
1518 bfd_false,
1519 oasys_write_object_contents,
1520 _bfd_write_archive_contents,
1521 bfd_false,
1524 BFD_JUMP_TABLE_GENERIC (oasys),
1525 BFD_JUMP_TABLE_COPY (_bfd_generic),
1526 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1527 BFD_JUMP_TABLE_ARCHIVE (oasys),
1528 BFD_JUMP_TABLE_SYMBOLS (oasys),
1529 BFD_JUMP_TABLE_RELOCS (oasys),
1530 BFD_JUMP_TABLE_WRITE (oasys),
1531 BFD_JUMP_TABLE_LINK (oasys),
1532 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1534 NULL,
1536 (PTR) 0