gas/
[binutils.git] / bfd / oasys.c
blob2647f82f00c3a30efb489a41029c14384181d264
1 /* BFD back-end for oasys objects.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001,
3 2002, 2003, 2004, 2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
22 #define UNDERSCORE_HACK 1
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "safe-ctype.h"
26 #include "libbfd.h"
27 #include "oasys.h"
28 #include "liboasys.h"
30 /* Read in all the section data and relocation stuff too. */
32 static bfd_boolean
33 oasys_read_record (bfd *abfd, oasys_record_union_type *record)
35 bfd_size_type amt = sizeof (record->header);
37 if (bfd_bread ((void *) record, amt, abfd) != amt)
38 return FALSE;
40 amt = record->header.length - sizeof (record->header);
41 if ((long) amt <= 0)
42 return TRUE;
43 if (bfd_bread ((void *) ((char *) record + sizeof (record->header)), amt, abfd)
44 != amt)
45 return FALSE;
46 return TRUE;
49 static size_t
50 oasys_string_length (oasys_record_union_type *record)
52 return record->header.length
53 - ((char *) record->symbol.name - (char *) record);
56 /* Slurp the symbol table by reading in all the records at the start file
57 till we get to the first section record.
59 We'll sort the symbolss into two lists, defined and undefined. The
60 undefined symbols will be placed into the table according to their
61 refno.
63 We do this by placing all undefined symbols at the front of the table
64 moving in, and the defined symbols at the end of the table moving back. */
66 static bfd_boolean
67 oasys_slurp_symbol_table (bfd *const abfd)
69 oasys_record_union_type record;
70 oasys_data_type *data = OASYS_DATA (abfd);
71 bfd_boolean loop = TRUE;
72 asymbol *dest_defined;
73 asymbol *dest;
74 char *string_ptr;
75 bfd_size_type amt;
77 if (data->symbols != NULL)
78 return TRUE;
80 /* Buy enough memory for all the symbols and all the names. */
81 amt = abfd->symcount;
82 amt *= sizeof (asymbol);
83 data->symbols = bfd_alloc (abfd, amt);
85 amt = data->symbol_string_length;
86 #ifdef UNDERSCORE_HACK
87 /* Buy 1 more char for each symbol to keep the underscore in. */
88 amt += abfd->symcount;
89 #endif
90 data->strings = bfd_alloc (abfd, amt);
92 if (!data->symbols || !data->strings)
93 return FALSE;
95 dest_defined = data->symbols + abfd->symcount - 1;
97 string_ptr = data->strings;
98 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
99 return FALSE;
100 while (loop)
102 if (! oasys_read_record (abfd, &record))
103 return FALSE;
105 switch (record.header.type)
107 case oasys_record_is_header_enum:
108 break;
109 case oasys_record_is_local_enum:
110 case oasys_record_is_symbol_enum:
112 int flag = record.header.type == (int) oasys_record_is_local_enum ?
113 (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
115 size_t length = oasys_string_length (&record);
116 switch (record.symbol.relb & RELOCATION_TYPE_BITS)
118 case RELOCATION_TYPE_ABS:
119 dest = dest_defined--;
120 dest->section = bfd_abs_section_ptr;
121 dest->flags = 0;
123 break;
124 case RELOCATION_TYPE_REL:
125 dest = dest_defined--;
126 dest->section =
127 OASYS_DATA (abfd)->sections[record.symbol.relb &
128 RELOCATION_SECT_BITS];
129 if (record.header.type == (int) oasys_record_is_local_enum)
131 dest->flags = BSF_LOCAL;
132 if (dest->section == (asection *) (~0))
134 /* It seems that sometimes internal symbols are tied up, but
135 still get output, even though there is no
136 section */
137 dest->section = 0;
140 else
141 dest->flags = flag;
142 break;
143 case RELOCATION_TYPE_UND:
144 dest = data->symbols + H_GET_16 (abfd, record.symbol.refno);
145 dest->section = bfd_und_section_ptr;
146 break;
147 case RELOCATION_TYPE_COM:
148 dest = dest_defined--;
149 dest->name = string_ptr;
150 dest->the_bfd = abfd;
151 dest->section = bfd_com_section_ptr;
152 break;
153 default:
154 dest = dest_defined--;
155 BFD_ASSERT (FALSE);
156 break;
158 dest->name = string_ptr;
159 dest->the_bfd = abfd;
160 dest->udata.p = NULL;
161 dest->value = H_GET_32 (abfd, record.symbol.value);
163 #ifdef UNDERSCORE_HACK
164 if (record.symbol.name[0] != '_')
166 string_ptr[0] = '_';
167 string_ptr++;
169 #endif
170 memcpy (string_ptr, record.symbol.name, length);
172 string_ptr[length] = 0;
173 string_ptr += length + 1;
175 break;
176 default:
177 loop = FALSE;
180 return TRUE;
183 static long
184 oasys_get_symtab_upper_bound (bfd *const abfd)
186 if (! oasys_slurp_symbol_table (abfd))
187 return -1;
189 return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *));
192 extern const bfd_target oasys_vec;
194 static long
195 oasys_canonicalize_symtab (bfd *abfd, asymbol **location)
197 asymbol *symbase;
198 unsigned int counter;
200 if (! oasys_slurp_symbol_table (abfd))
201 return -1;
203 symbase = OASYS_DATA (abfd)->symbols;
204 for (counter = 0; counter < abfd->symcount; counter++)
205 *(location++) = symbase++;
207 *location = 0;
208 return abfd->symcount;
211 /* Archive stuff. */
213 static const bfd_target *
214 oasys_archive_p (bfd *abfd)
216 oasys_archive_header_type header;
217 oasys_extarchive_header_type header_ext;
218 unsigned int i;
219 file_ptr filepos;
220 bfd_size_type amt;
222 amt = sizeof (header_ext);
223 if (bfd_seek (abfd, (file_ptr) 0, 0) != 0
224 || bfd_bread ((void *) &header_ext, amt, abfd) != amt)
226 if (bfd_get_error () != bfd_error_system_call)
227 bfd_set_error (bfd_error_wrong_format);
228 return NULL;
231 header.version = H_GET_32 (abfd, header_ext.version);
232 header.mod_count = H_GET_32 (abfd, header_ext.mod_count);
233 header.mod_tbl_offset = H_GET_32 (abfd, header_ext.mod_tbl_offset);
234 header.sym_tbl_size = H_GET_32 (abfd, header_ext.sym_tbl_size);
235 header.sym_count = H_GET_32 (abfd, header_ext.sym_count);
236 header.sym_tbl_offset = H_GET_32 (abfd, header_ext.sym_tbl_offset);
237 header.xref_count = H_GET_32 (abfd, header_ext.xref_count);
238 header.xref_lst_offset = H_GET_32 (abfd, header_ext.xref_lst_offset);
240 /* There isn't a magic number in an Oasys archive, so the best we
241 can do to verify reasonableness is to make sure that the values in
242 the header are too weird. */
244 if (header.version > 10000
245 || header.mod_count > 10000
246 || header.sym_count > 100000
247 || header.xref_count > 100000)
248 return NULL;
250 /* That all worked, let's buy the space for the header and read in
251 the headers. */
253 oasys_ar_data_type *ar;
254 oasys_module_info_type *module;
255 oasys_module_table_type record;
257 amt = sizeof (oasys_ar_data_type);
258 ar = bfd_alloc (abfd, amt);
260 amt = header.mod_count;
261 amt *= sizeof (oasys_module_info_type);
262 module = bfd_alloc (abfd, amt);
264 if (!ar || !module)
265 return NULL;
267 abfd->tdata.oasys_ar_data = ar;
268 ar->module = module;
269 ar->module_count = header.mod_count;
271 filepos = header.mod_tbl_offset;
272 for (i = 0; i < header.mod_count; i++)
274 if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
275 return NULL;
277 /* There are two ways of specifying the archive header. */
279 oasys_extmodule_table_type_b_type record_ext;
281 amt = sizeof (record_ext);
282 if (bfd_bread ((void *) &record_ext, amt, abfd) != amt)
283 return NULL;
285 record.mod_size = H_GET_32 (abfd, record_ext.mod_size);
286 record.file_offset = H_GET_32 (abfd, record_ext.file_offset);
288 record.dep_count = H_GET_32 (abfd, record_ext.dep_count);
289 record.depee_count = H_GET_32 (abfd, record_ext.depee_count);
290 record.sect_count = H_GET_32 (abfd, record_ext.sect_count);
291 record.module_name_size = H_GET_32 (abfd,
292 record_ext.mod_name_length);
294 amt = record.module_name_size;
295 module[i].name = bfd_alloc (abfd, amt + 1);
296 if (!module[i].name)
297 return NULL;
298 if (bfd_bread ((void *) module[i].name, amt, abfd) != amt)
299 return NULL;
300 module[i].name[record.module_name_size] = 0;
301 filepos += (sizeof (record_ext)
302 + record.dep_count * 4
303 + record.module_name_size + 1);
306 module[i].size = record.mod_size;
307 module[i].pos = record.file_offset;
308 module[i].abfd = 0;
311 return abfd->xvec;
314 static bfd_boolean
315 oasys_mkobject (bfd *abfd)
317 bfd_size_type amt = sizeof (oasys_data_type);
319 abfd->tdata.oasys_obj_data = bfd_alloc (abfd, amt);
321 return abfd->tdata.oasys_obj_data != NULL;
324 /* The howto table is build using the top two bits of a reloc byte to
325 index into it. The bits are PCREL,WORD/LONG. */
327 static reloc_howto_type howto_table[] =
330 HOWTO (0, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
331 HOWTO (0, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs32", TRUE, 0xffffffff, 0xffffffff, FALSE),
332 HOWTO (0, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
333 HOWTO (0, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0, "pcrel32", TRUE, 0xffffffff, 0xffffffff, FALSE)
336 /* Read in all the section data and relocation stuff too. */
338 static bfd_boolean
339 oasys_slurp_section_data (bfd *const abfd)
341 oasys_record_union_type record;
342 oasys_data_type *data = OASYS_DATA (abfd);
343 bfd_boolean loop = TRUE;
344 oasys_per_section_type *per;
345 asection *s;
346 bfd_size_type amt;
348 /* See if the data has been slurped already. */
349 for (s = abfd->sections; s != NULL; s = s->next)
351 per = oasys_per_section (s);
352 if (per->initialized)
353 return TRUE;
356 if (data->first_data_record == 0)
357 return TRUE;
359 if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
360 return FALSE;
362 while (loop)
364 if (! oasys_read_record (abfd, &record))
365 return FALSE;
367 switch (record.header.type)
369 case oasys_record_is_header_enum:
370 break;
371 case oasys_record_is_data_enum:
373 bfd_byte *src = record.data.data;
374 bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
375 bfd_byte *dst_ptr;
376 bfd_byte *dst_base_ptr;
377 unsigned int relbit;
378 unsigned int count;
379 asection *section =
380 data->sections[record.data.relb & RELOCATION_SECT_BITS];
381 bfd_vma dst_offset;
383 per = oasys_per_section (section);
385 if (! per->initialized)
387 per->data = bfd_zalloc (abfd, section->size);
388 if (!per->data)
389 return FALSE;
390 per->reloc_tail_ptr
391 = (oasys_reloc_type **) &section->relocation;
392 per->had_vma = FALSE;
393 per->initialized = TRUE;
394 section->reloc_count = 0;
395 section->flags = SEC_ALLOC;
398 dst_offset = H_GET_32 (abfd, record.data.addr);
399 if (! per->had_vma)
401 /* Take the first vma we see as the base. */
402 section->vma = dst_offset;
403 per->had_vma = TRUE;
406 dst_offset -= section->vma;
408 dst_base_ptr = oasys_per_section (section)->data;
409 dst_ptr = oasys_per_section (section)->data +
410 dst_offset;
412 if (src < end_src)
413 section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
415 while (src < end_src)
417 unsigned char mod_byte = *src++;
418 size_t gap = end_src - src;
420 count = 8;
421 if (mod_byte == 0 && gap >= 8)
423 dst_ptr[0] = src[0];
424 dst_ptr[1] = src[1];
425 dst_ptr[2] = src[2];
426 dst_ptr[3] = src[3];
427 dst_ptr[4] = src[4];
428 dst_ptr[5] = src[5];
429 dst_ptr[6] = src[6];
430 dst_ptr[7] = src[7];
431 dst_ptr += 8;
432 src += 8;
434 else
436 for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
438 if (relbit & mod_byte)
440 unsigned char reloc = *src;
441 /* This item needs to be relocated. */
442 switch (reloc & RELOCATION_TYPE_BITS)
444 case RELOCATION_TYPE_ABS:
445 break;
447 case RELOCATION_TYPE_REL:
449 /* Relocate the item relative to the section. */
450 oasys_reloc_type *r;
452 amt = sizeof (oasys_reloc_type);
453 r = bfd_alloc (abfd, amt);
454 if (!r)
455 return FALSE;
456 *(per->reloc_tail_ptr) = r;
457 per->reloc_tail_ptr = &r->next;
458 r->next = NULL;
459 /* Reference to undefined symbol. */
460 src++;
461 /* There is no symbol. */
462 r->symbol = 0;
463 /* Work out the howto. */
464 abort ();
465 r->relent.address = dst_ptr - dst_base_ptr;
466 r->relent.howto = &howto_table[reloc >> 6];
467 r->relent.sym_ptr_ptr = NULL;
468 section->reloc_count++;
470 /* Fake up the data to look like
471 it's got the -ve pc in it, this
472 makes it much easier to convert
473 into other formats. This is done
474 by hitting the addend. */
475 if (r->relent.howto->pc_relative)
476 r->relent.addend -= dst_ptr - dst_base_ptr;
478 break;
480 case RELOCATION_TYPE_UND:
482 oasys_reloc_type *r;
484 amt = sizeof (oasys_reloc_type);
485 r = bfd_alloc (abfd, amt);
486 if (!r)
487 return FALSE;
488 *(per->reloc_tail_ptr) = r;
489 per->reloc_tail_ptr = &r->next;
490 r->next = NULL;
491 /* Reference to undefined symbol. */
492 src++;
493 /* Get symbol number. */
494 r->symbol = (src[0] << 8) | src[1];
495 /* Work out the howto. */
496 abort ();
498 r->relent.addend = 0;
499 r->relent.address = dst_ptr - dst_base_ptr;
500 r->relent.howto = &howto_table[reloc >> 6];
501 r->relent.sym_ptr_ptr = NULL;
502 section->reloc_count++;
504 src += 2;
505 /* Fake up the data to look like
506 it's got the -ve pc in it, this
507 makes it much easier to convert
508 into other formats. This is done
509 by hitting the addend. */
510 if (r->relent.howto->pc_relative)
511 r->relent.addend -= dst_ptr - dst_base_ptr;
513 break;
514 case RELOCATION_TYPE_COM:
515 BFD_FAIL ();
518 *dst_ptr++ = *src++;
523 break;
524 case oasys_record_is_local_enum:
525 case oasys_record_is_symbol_enum:
526 case oasys_record_is_section_enum:
527 break;
528 default:
529 loop = FALSE;
533 return TRUE;
537 #define MAX_SECS 16
539 static const bfd_target *
540 oasys_object_p (bfd *abfd)
542 oasys_data_type *oasys;
543 oasys_data_type *save = OASYS_DATA (abfd);
544 bfd_boolean loop = TRUE;
545 bfd_boolean had_usefull = FALSE;
547 abfd->tdata.oasys_obj_data = 0;
548 oasys_mkobject (abfd);
549 oasys = OASYS_DATA (abfd);
550 memset ((void *) oasys->sections, 0xff, sizeof (oasys->sections));
552 /* Point to the start of the file. */
553 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
554 goto fail;
555 oasys->symbol_string_length = 0;
557 /* Inspect the records, but only keep the section info -
558 remember the size of the symbols. */
559 oasys->first_data_record = 0;
560 while (loop)
562 oasys_record_union_type record;
563 if (! oasys_read_record (abfd, &record))
564 goto fail;
565 if ((size_t) record.header.length < (size_t) sizeof (record.header))
566 goto fail;
568 switch ((oasys_record_enum_type) (record.header.type))
570 case oasys_record_is_header_enum:
571 had_usefull = TRUE;
572 break;
573 case oasys_record_is_symbol_enum:
574 case oasys_record_is_local_enum:
575 /* Count symbols and remember their size for a future malloc. */
576 abfd->symcount++;
577 oasys->symbol_string_length += 1 + oasys_string_length (&record);
578 had_usefull = TRUE;
579 break;
580 case oasys_record_is_section_enum:
582 asection *s;
583 char *buffer;
584 unsigned int section_number;
586 if (record.section.header.length != sizeof (record.section))
587 goto fail;
589 buffer = bfd_alloc (abfd, (bfd_size_type) 3);
590 if (!buffer)
591 goto fail;
592 section_number = record.section.relb & RELOCATION_SECT_BITS;
593 sprintf (buffer, "%u", section_number);
594 s = bfd_make_section (abfd, buffer);
595 oasys->sections[section_number] = s;
596 switch (record.section.relb & RELOCATION_TYPE_BITS)
598 case RELOCATION_TYPE_ABS:
599 case RELOCATION_TYPE_REL:
600 break;
601 case RELOCATION_TYPE_UND:
602 case RELOCATION_TYPE_COM:
603 BFD_FAIL ();
606 s->size = H_GET_32 (abfd, record.section.value);
607 s->vma = H_GET_32 (abfd, record.section.vma);
608 s->flags = 0;
609 had_usefull = TRUE;
611 break;
612 case oasys_record_is_data_enum:
613 oasys->first_data_record = bfd_tell (abfd) - record.header.length;
614 case oasys_record_is_debug_enum:
615 case oasys_record_is_module_enum:
616 case oasys_record_is_named_section_enum:
617 case oasys_record_is_end_enum:
618 if (! had_usefull)
619 goto fail;
620 loop = FALSE;
621 break;
622 default:
623 goto fail;
626 oasys->symbols = NULL;
628 /* Oasys support several architectures, but I can't see a simple way
629 to discover which one is in a particular file - we'll guess. */
630 bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
631 if (abfd->symcount != 0)
632 abfd->flags |= HAS_SYMS;
634 /* We don't know if a section has data until we've read it. */
635 oasys_slurp_section_data (abfd);
637 return abfd->xvec;
639 fail:
640 (void) bfd_release (abfd, oasys);
641 abfd->tdata.oasys_obj_data = save;
642 return NULL;
646 static void
647 oasys_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
648 asymbol *symbol,
649 symbol_info *ret)
651 bfd_symbol_info (symbol, ret);
653 if (!symbol->section)
654 ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
657 static void
658 oasys_print_symbol (bfd *abfd, void * afile, asymbol *symbol, bfd_print_symbol_type how)
660 FILE *file = (FILE *) afile;
662 switch (how)
664 case bfd_print_symbol_name:
665 case bfd_print_symbol_more:
666 fprintf (file, "%s", symbol->name);
667 break;
668 case bfd_print_symbol_all:
670 const char *section_name = symbol->section == NULL ?
671 (const char *) "*abs" : symbol->section->name;
673 bfd_print_symbol_vandf (abfd, (void *) file, symbol);
675 fprintf (file, " %-5s %s",
676 section_name,
677 symbol->name);
679 break;
683 static bfd_boolean
684 oasys_new_section_hook (bfd *abfd, asection *newsect)
686 newsect->used_by_bfd = bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
687 if (!newsect->used_by_bfd)
688 return FALSE;
689 oasys_per_section (newsect)->data = NULL;
690 oasys_per_section (newsect)->section = newsect;
691 oasys_per_section (newsect)->offset = 0;
692 oasys_per_section (newsect)->initialized = FALSE;
693 newsect->alignment_power = 1;
695 /* Turn the section string into an index. */
696 sscanf (newsect->name, "%u", &newsect->target_index);
698 return TRUE;
702 static long
703 oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
705 if (! oasys_slurp_section_data (abfd))
706 return -1;
707 return (asect->reloc_count + 1) * sizeof (arelent *);
710 static bfd_boolean
711 oasys_get_section_contents (bfd *abfd,
712 sec_ptr section,
713 void * location,
714 file_ptr offset,
715 bfd_size_type count)
717 oasys_per_section_type *p = oasys_per_section (section);
719 oasys_slurp_section_data (abfd);
721 if (! p->initialized)
722 (void) memset (location, 0, (size_t) count);
723 else
724 (void) memcpy (location, (void *) (p->data + offset), (size_t) count);
726 return TRUE;
729 static long
730 oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
731 sec_ptr section,
732 arelent **relptr,
733 asymbol **symbols ATTRIBUTE_UNUSED)
735 unsigned int reloc_count = 0;
736 oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
738 if (src != NULL)
739 abort ();
741 *relptr = NULL;
742 return section->reloc_count = reloc_count;
746 /* Writing. */
748 /* Calculate the checksum and write one record. */
750 static bfd_boolean
751 oasys_write_record (bfd *abfd,
752 oasys_record_enum_type type,
753 oasys_record_union_type *record,
754 size_t size)
756 int checksum;
757 size_t i;
758 unsigned char *ptr;
760 record->header.length = size;
761 record->header.type = (int) type;
762 record->header.check_sum = 0;
763 record->header.fill = 0;
764 ptr = (unsigned char *) &record->pad[0];
765 checksum = 0;
766 for (i = 0; i < size; i++)
767 checksum += *ptr++;
768 record->header.check_sum = 0xff & (-checksum);
769 if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size)
770 return FALSE;
771 return TRUE;
775 /* Write out all the symbols. */
777 static bfd_boolean
778 oasys_write_syms (bfd *abfd)
780 unsigned int count;
781 asymbol **generic = bfd_get_outsymbols (abfd);
782 unsigned int index = 0;
784 for (count = 0; count < bfd_get_symcount (abfd); count++)
786 oasys_symbol_record_type symbol;
787 asymbol *const g = generic[count];
788 const char *src = g->name;
789 char *dst = symbol.name;
790 unsigned int l = 0;
792 if (bfd_is_com_section (g->section))
794 symbol.relb = RELOCATION_TYPE_COM;
795 H_PUT_16 (abfd, index, symbol.refno);
796 index++;
798 else if (bfd_is_abs_section (g->section))
800 symbol.relb = RELOCATION_TYPE_ABS;
801 H_PUT_16 (abfd, 0, symbol.refno);
803 else if (bfd_is_und_section (g->section))
805 symbol.relb = RELOCATION_TYPE_UND;
806 H_PUT_16 (abfd, index, symbol.refno);
807 /* Overload the value field with the output index number */
808 index++;
810 else if (g->flags & BSF_DEBUGGING)
811 /* Throw it away. */
812 continue;
813 else
815 if (g->section == NULL)
816 /* Sometime, the oasys tools give out a symbol with illegal
817 bits in it, we'll output it in the same broken way. */
818 symbol.relb = RELOCATION_TYPE_REL | 0;
819 else
820 symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
822 H_PUT_16 (abfd, 0, symbol.refno);
825 #ifdef UNDERSCORE_HACK
826 if (src[l] == '_')
827 dst[l++] = '.';
828 #endif
829 while (src[l])
831 dst[l] = src[l];
832 l++;
835 H_PUT_32 (abfd, g->value, symbol.value);
837 if (g->flags & BSF_LOCAL)
839 if (! oasys_write_record (abfd,
840 oasys_record_is_local_enum,
841 (oasys_record_union_type *) & symbol,
842 offsetof (oasys_symbol_record_type,
843 name[0]) + l))
844 return FALSE;
846 else
848 if (! oasys_write_record (abfd,
849 oasys_record_is_symbol_enum,
850 (oasys_record_union_type *) & symbol,
851 offsetof (oasys_symbol_record_type,
852 name[0]) + l))
853 return FALSE;
855 g->value = index - 1;
858 return TRUE;
861 /* Write a section header for each section. */
863 static bfd_boolean
864 oasys_write_sections (bfd *abfd)
866 asection *s;
867 static oasys_section_record_type out;
869 for (s = abfd->sections; s != NULL; s = s->next)
871 if (!ISDIGIT (s->name[0]))
873 (*_bfd_error_handler)
874 (_("%s: can not represent section `%s' in oasys"),
875 bfd_get_filename (abfd), s->name);
876 bfd_set_error (bfd_error_nonrepresentable_section);
877 return FALSE;
879 out.relb = RELOCATION_TYPE_REL | s->target_index;
880 H_PUT_32 (abfd, s->size, out.value);
881 H_PUT_32 (abfd, s->vma, out.vma);
883 if (! oasys_write_record (abfd,
884 oasys_record_is_section_enum,
885 (oasys_record_union_type *) & out,
886 sizeof (out)))
887 return FALSE;
889 return TRUE;
892 static bfd_boolean
893 oasys_write_header (bfd *abfd)
895 /* Create and write the header. */
896 oasys_header_record_type r;
897 size_t length = strlen (abfd->filename);
899 if (length > (size_t) sizeof (r.module_name))
900 length = sizeof (r.module_name);
902 (void) memcpy (r.module_name, abfd->filename, length);
903 (void) memset (r.module_name + length, ' ', sizeof (r.module_name) - length);
905 r.version_number = OASYS_VERSION_NUMBER;
906 r.rev_number = OASYS_REV_NUMBER;
908 return oasys_write_record (abfd, oasys_record_is_header_enum,
909 (oasys_record_union_type *) & r,
910 offsetof (oasys_header_record_type,
911 description[0]));
914 static bfd_boolean
915 oasys_write_end (bfd *abfd)
917 oasys_end_record_type end;
918 unsigned char null = 0;
920 end.relb = RELOCATION_TYPE_ABS;
921 H_PUT_32 (abfd, abfd->start_address, end.entry);
922 H_PUT_16 (abfd, 0, end.fill);
923 end.zero = 0;
924 if (! oasys_write_record (abfd,
925 oasys_record_is_end_enum,
926 (oasys_record_union_type *) & end,
927 sizeof (end)))
928 return FALSE;
930 return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
933 static int
934 comp (const void * ap, const void * bp)
936 arelent *a = *((arelent **) ap);
937 arelent *b = *((arelent **) bp);
939 return a->address - b->address;
942 static bfd_boolean
943 oasys_write_data (bfd *abfd)
945 asection *s;
947 for (s = abfd->sections; s != NULL; s = s->next)
949 if (s->flags & SEC_LOAD)
951 bfd_byte *raw_data = oasys_per_section (s)->data;
952 oasys_data_record_type processed_data;
953 bfd_size_type current_byte_index = 0;
954 unsigned int relocs_to_go = s->reloc_count;
955 arelent **p = s->orelocation;
957 if (s->reloc_count != 0)
958 /* Sort the reloc records so it's easy to insert the relocs into the
959 data. */
960 qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp);
962 current_byte_index = 0;
963 processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
965 while (current_byte_index < s->size)
967 /* Scan forwards by eight bytes or however much is left and see if
968 there are any relocations going on. */
969 bfd_byte *mod = &processed_data.data[0];
970 bfd_byte *dst = &processed_data.data[1];
972 unsigned int i = 0;
973 *mod = 0;
975 H_PUT_32 (abfd, s->vma + current_byte_index,
976 processed_data.addr);
978 /* Don't start a relocation unless you're sure you can finish it
979 within the same data record. The worst case relocation is a
980 4-byte relocatable value which is split across two modification
981 bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
982 1 modification byte + 2 data = 8 bytes total). That's where
983 the magic number 8 comes from. */
984 while (current_byte_index < s->size && dst <=
985 & processed_data.data[sizeof (processed_data.data) - 8])
987 if (relocs_to_go != 0)
989 arelent *r = *p;
991 /* There is a relocation, is it for this byte ? */
992 if (r->address == current_byte_index)
993 abort ();
996 /* If this is coming from an unloadable section then copy
997 zeros. */
998 if (raw_data == NULL)
999 *dst++ = 0;
1000 else
1001 *dst++ = *raw_data++;
1003 if (++i >= 8)
1005 i = 0;
1006 mod = dst++;
1007 *mod = 0;
1009 current_byte_index++;
1012 /* Don't write a useless null modification byte. */
1013 if (dst == mod + 1)
1014 --dst;
1016 if (! (oasys_write_record
1017 (abfd, oasys_record_is_data_enum,
1018 ((oasys_record_union_type *) &processed_data),
1019 (size_t) (dst - (bfd_byte *) &processed_data))))
1020 return FALSE;
1025 return TRUE;
1028 static bfd_boolean
1029 oasys_write_object_contents (bfd *abfd)
1031 if (! oasys_write_header (abfd))
1032 return FALSE;
1033 if (! oasys_write_syms (abfd))
1034 return FALSE;
1035 if (! oasys_write_sections (abfd))
1036 return FALSE;
1037 if (! oasys_write_data (abfd))
1038 return FALSE;
1039 if (! oasys_write_end (abfd))
1040 return FALSE;
1041 return TRUE;
1044 /* Set section contents is complicated with OASYS since the format is
1045 not a byte image, but a record stream. */
1047 static bfd_boolean
1048 oasys_set_section_contents (bfd *abfd,
1049 sec_ptr section,
1050 const void * location,
1051 file_ptr offset,
1052 bfd_size_type count)
1054 if (count != 0)
1056 if (oasys_per_section (section)->data == NULL)
1058 oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
1059 if (!oasys_per_section (section)->data)
1060 return FALSE;
1062 (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
1063 location, (size_t) count);
1065 return TRUE;
1070 /* Native-level interface to symbols. */
1072 /* We read the symbols into a buffer, which is discarded when this
1073 function exits. We read the strings into a buffer large enough to
1074 hold them all plus all the cached symbol entries. */
1076 static asymbol *
1077 oasys_make_empty_symbol (bfd *abfd)
1079 bfd_size_type amt = sizeof (oasys_symbol_type);
1080 oasys_symbol_type *new = bfd_zalloc (abfd, amt);
1082 if (!new)
1083 return NULL;
1084 new->symbol.the_bfd = abfd;
1085 return &new->symbol;
1088 /* User should have checked the file flags; perhaps we should return
1089 BFD_NO_MORE_SYMBOLS if there are none? */
1091 static bfd *
1092 oasys_openr_next_archived_file (bfd *arch, bfd *prev)
1094 oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1095 oasys_module_info_type *p;
1097 /* Take the next one from the arch state, or reset. */
1098 if (prev == NULL)
1099 /* Reset the index - the first two entries are bogus. */
1100 ar->module_index = 0;
1102 p = ar->module + ar->module_index;
1103 ar->module_index++;
1105 if (ar->module_index <= ar->module_count)
1107 if (p->abfd == NULL)
1109 p->abfd = _bfd_create_empty_archive_element_shell (arch);
1110 p->abfd->origin = p->pos;
1111 p->abfd->filename = p->name;
1113 /* Fixup a pointer to this element for the member. */
1114 p->abfd->arelt_data = (void *) p;
1116 return p->abfd;
1119 bfd_set_error (bfd_error_no_more_archived_files);
1120 return NULL;
1123 static bfd_boolean
1124 oasys_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
1125 asection *section ATTRIBUTE_UNUSED,
1126 asymbol **symbols ATTRIBUTE_UNUSED,
1127 bfd_vma offset ATTRIBUTE_UNUSED,
1128 const char **filename_ptr ATTRIBUTE_UNUSED,
1129 const char **functionname_ptr ATTRIBUTE_UNUSED,
1130 unsigned int *line_ptr ATTRIBUTE_UNUSED)
1132 return FALSE;
1135 static bfd_boolean
1136 oasys_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
1137 const char **filename_ptr ATTRIBUTE_UNUSED,
1138 const char **functionname_ptr ATTRIBUTE_UNUSED,
1139 unsigned int *line_ptr ATTRIBUTE_UNUSED)
1141 return FALSE;
1144 static int
1145 oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
1147 oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1149 if (mod == NULL)
1151 bfd_set_error (bfd_error_invalid_operation);
1152 return -1;
1155 buf->st_size = mod->size;
1156 buf->st_mode = 0666;
1157 return 0;
1160 static int
1161 oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean exec ATTRIBUTE_UNUSED)
1163 return 0;
1166 #define oasys_close_and_cleanup _bfd_generic_close_and_cleanup
1167 #define oasys_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1168 #define oasys_slurp_armap bfd_true
1169 #define oasys_slurp_extended_name_table bfd_true
1170 #define oasys_construct_extended_name_table ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true)
1171 #define oasys_truncate_arname bfd_dont_truncate_arname
1172 #define oasys_write_armap ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true)
1173 #define oasys_read_ar_hdr bfd_nullvoidptr
1174 #define oasys_get_elt_at_index _bfd_generic_get_elt_at_index
1175 #define oasys_update_armap_timestamp bfd_true
1176 #define oasys_bfd_is_local_label_name bfd_generic_is_local_label_name
1177 #define oasys_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1178 #define oasys_get_lineno _bfd_nosymbols_get_lineno
1179 #define oasys_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
1180 #define oasys_read_minisymbols _bfd_generic_read_minisymbols
1181 #define oasys_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
1182 #define oasys_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
1183 #define oasys_set_arch_mach bfd_default_set_arch_mach
1184 #define oasys_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
1185 #define oasys_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
1186 #define oasys_bfd_relax_section bfd_generic_relax_section
1187 #define oasys_bfd_gc_sections bfd_generic_gc_sections
1188 #define oasys_bfd_merge_sections bfd_generic_merge_sections
1189 #define oasys_bfd_is_group_section bfd_generic_is_group_section
1190 #define oasys_bfd_discard_group bfd_generic_discard_group
1191 #define oasys_section_already_linked _bfd_generic_section_already_linked
1192 #define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1193 #define oasys_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
1194 #define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
1195 #define oasys_bfd_link_just_syms _bfd_generic_link_just_syms
1196 #define oasys_bfd_final_link _bfd_generic_final_link
1197 #define oasys_bfd_link_split_section _bfd_generic_link_split_section
1199 const bfd_target oasys_vec =
1201 "oasys", /* Name. */
1202 bfd_target_oasys_flavour,
1203 BFD_ENDIAN_BIG, /* Target byte order. */
1204 BFD_ENDIAN_BIG, /* Target headers byte order. */
1205 (HAS_RELOC | EXEC_P | /* Object flags. */
1206 HAS_LINENO | HAS_DEBUG |
1207 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1208 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1209 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */
1210 0, /* Leading underscore. */
1211 ' ', /* AR_pad_char. */
1212 16, /* AR_max_namelen. */
1213 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1214 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1215 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
1216 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1217 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1218 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
1220 {_bfd_dummy_target,
1221 oasys_object_p, /* bfd_check_format. */
1222 oasys_archive_p,
1223 _bfd_dummy_target,
1225 { /* bfd_set_format. */
1226 bfd_false,
1227 oasys_mkobject,
1228 _bfd_generic_mkarchive,
1229 bfd_false
1231 { /* bfd_write_contents. */
1232 bfd_false,
1233 oasys_write_object_contents,
1234 _bfd_write_archive_contents,
1235 bfd_false,
1238 BFD_JUMP_TABLE_GENERIC (oasys),
1239 BFD_JUMP_TABLE_COPY (_bfd_generic),
1240 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1241 BFD_JUMP_TABLE_ARCHIVE (oasys),
1242 BFD_JUMP_TABLE_SYMBOLS (oasys),
1243 BFD_JUMP_TABLE_RELOCS (oasys),
1244 BFD_JUMP_TABLE_WRITE (oasys),
1245 BFD_JUMP_TABLE_LINK (oasys),
1246 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1248 NULL,
1250 NULL