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