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
oasys_read_record(bfd * abfd,oasys_record_union_type * record)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
oasys_string_length(oasys_record_union_type * record)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
oasys_slurp_symbol_table(bfd * const abfd)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
oasys_get_symtab_upper_bound(bfd * const abfd)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
oasys_canonicalize_symtab(bfd * abfd,asymbol ** location)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 *
oasys_archive_p(bfd * abfd)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
oasys_mkobject(bfd * abfd)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
oasys_slurp_section_data(bfd * const abfd)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 		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;
396 	      }
397 
398 	    dst_offset = H_GET_32 (abfd, record.data.addr);
399 	    if (! per->had_vma)
400 	      {
401 		/* Take the first vma we see as the base.  */
402 		section->vma = dst_offset;
403 		per->had_vma = TRUE;
404 	      }
405 
406 	    dst_offset -= section->vma;
407 
408 	    dst_base_ptr = oasys_per_section (section)->data;
409 	    dst_ptr = oasys_per_section (section)->data +
410 	      dst_offset;
411 
412 	    if (src < end_src)
413 	      section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
414 
415 	    while (src < end_src)
416 	      {
417 		unsigned char mod_byte = *src++;
418 		size_t gap = end_src - src;
419 
420 		count = 8;
421 		if (mod_byte == 0 && gap >= 8)
422 		  {
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;
433 		  }
434 		else
435 		  {
436 		    for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
437 		      {
438 			if (relbit & mod_byte)
439 			  {
440 			    unsigned char reloc = *src;
441 			    /* This item needs to be relocated.  */
442 			    switch (reloc & RELOCATION_TYPE_BITS)
443 			      {
444 			      case RELOCATION_TYPE_ABS:
445 				break;
446 
447 			      case RELOCATION_TYPE_REL:
448 				{
449 				  /* Relocate the item relative to the section.  */
450 				  oasys_reloc_type *r;
451 
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++;
469 
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;
477 				}
478 				break;
479 
480 			      case RELOCATION_TYPE_UND:
481 				{
482 				  oasys_reloc_type *r;
483 
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 ();
497 
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++;
503 
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;
512 				}
513 				break;
514 			      case RELOCATION_TYPE_COM:
515 				BFD_FAIL ();
516 			      }
517 			  }
518 			*dst_ptr++ = *src++;
519 		      }
520 		  }
521 	      }
522 	  }
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;
530 	}
531     }
532 
533   return TRUE;
534 
535 }
536 
537 #define MAX_SECS 16
538 
539 static const bfd_target *
oasys_object_p(bfd * abfd)540 oasys_object_p (bfd *abfd)
541 {
542   oasys_data_type *oasys;
543   oasys_data_type *save = OASYS_DATA (abfd);
544   bfd_boolean loop = TRUE;
545   bfd_boolean had_usefull = FALSE;
546 
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));
551 
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;
556 
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)
561     {
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;
567 
568       switch ((oasys_record_enum_type) (record.header.type))
569 	{
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:
581 	  {
582 	    asection *s;
583 	    char *buffer;
584 	    unsigned int section_number;
585 
586 	    if (record.section.header.length != sizeof (record.section))
587 	      goto fail;
588 
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)
597 	      {
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 ();
604 	      }
605 
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;
610 	  }
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;
624 	}
625     }
626   oasys->symbols = NULL;
627 
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;
633 
634   /* We don't know if a section has data until we've read it.  */
635   oasys_slurp_section_data (abfd);
636 
637   return abfd->xvec;
638 
639 fail:
640   (void) bfd_release (abfd, oasys);
641   abfd->tdata.oasys_obj_data = save;
642   return NULL;
643 }
644 
645 
646 static void
oasys_get_symbol_info(bfd * ignore_abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)647 oasys_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
648 		       asymbol *symbol,
649 		       symbol_info *ret)
650 {
651   bfd_symbol_info (symbol, ret);
652 
653   if (!symbol->section)
654     ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
655 }
656 
657 static void
oasys_print_symbol(bfd * abfd,void * afile,asymbol * symbol,bfd_print_symbol_type how)658 oasys_print_symbol (bfd *abfd, void * afile, asymbol *symbol, bfd_print_symbol_type how)
659 {
660   FILE *file = (FILE *) afile;
661 
662   switch (how)
663     {
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:
669       {
670 	const char *section_name = symbol->section == NULL ?
671 	(const char *) "*abs" : symbol->section->name;
672 
673 	bfd_print_symbol_vandf (abfd, (void *) file, symbol);
674 
675 	fprintf (file, " %-5s %s",
676 		 section_name,
677 		 symbol->name);
678       }
679       break;
680     }
681 }
682 
683 static bfd_boolean
oasys_new_section_hook(bfd * abfd,asection * newsect)684 oasys_new_section_hook (bfd *abfd, asection *newsect)
685 {
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;
694 
695   /* Turn the section string into an index.  */
696   sscanf (newsect->name, "%u", &newsect->target_index);
697 
698   return TRUE;
699 }
700 
701 
702 static long
oasys_get_reloc_upper_bound(bfd * abfd,sec_ptr asect)703 oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
704 {
705   if (! oasys_slurp_section_data (abfd))
706     return -1;
707   return (asect->reloc_count + 1) * sizeof (arelent *);
708 }
709 
710 static bfd_boolean
oasys_get_section_contents(bfd * abfd,sec_ptr section,void * location,file_ptr offset,bfd_size_type count)711 oasys_get_section_contents (bfd *abfd,
712 			    sec_ptr section,
713 			    void * location,
714 			    file_ptr offset,
715 			    bfd_size_type count)
716 {
717   oasys_per_section_type *p = oasys_per_section (section);
718 
719   oasys_slurp_section_data (abfd);
720 
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);
725 
726   return TRUE;
727 }
728 
729 static long
oasys_canonicalize_reloc(bfd * ignore_abfd ATTRIBUTE_UNUSED,sec_ptr section,arelent ** relptr,asymbol ** symbols ATTRIBUTE_UNUSED)730 oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
731 			  sec_ptr section,
732 			  arelent **relptr,
733 			  asymbol **symbols ATTRIBUTE_UNUSED)
734 {
735   unsigned int reloc_count = 0;
736   oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
737 
738   if (src != NULL)
739     abort ();
740 
741   *relptr = NULL;
742   return section->reloc_count = reloc_count;
743 }
744 
745 
746 /* Writing.  */
747 
748 /* Calculate the checksum and write one record.  */
749 
750 static bfd_boolean
oasys_write_record(bfd * abfd,oasys_record_enum_type type,oasys_record_union_type * record,size_t size)751 oasys_write_record (bfd *abfd,
752 		    oasys_record_enum_type type,
753 		    oasys_record_union_type *record,
754 		    size_t size)
755 {
756   int checksum;
757   size_t i;
758   unsigned char *ptr;
759 
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;
772 }
773 
774 
775 /* Write out all the symbols.  */
776 
777 static bfd_boolean
oasys_write_syms(bfd * abfd)778 oasys_write_syms (bfd *abfd)
779 {
780   unsigned int count;
781   asymbol **generic = bfd_get_outsymbols (abfd);
782   unsigned int index = 0;
783 
784   for (count = 0; count < bfd_get_symcount (abfd); count++)
785     {
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;
791 
792       if (bfd_is_com_section (g->section))
793 	{
794 	  symbol.relb = RELOCATION_TYPE_COM;
795 	  H_PUT_16 (abfd, index, symbol.refno);
796 	  index++;
797 	}
798       else if (bfd_is_abs_section (g->section))
799 	{
800 	  symbol.relb = RELOCATION_TYPE_ABS;
801 	  H_PUT_16 (abfd, 0, symbol.refno);
802 	}
803       else if (bfd_is_und_section (g->section))
804 	{
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++;
809 	}
810       else if (g->flags & BSF_DEBUGGING)
811 	/* Throw it away.  */
812 	continue;
813       else
814 	{
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;
821 
822 	  H_PUT_16 (abfd, 0, symbol.refno);
823 	}
824 
825 #ifdef UNDERSCORE_HACK
826       if (src[l] == '_')
827 	dst[l++] = '.';
828 #endif
829       while (src[l])
830 	{
831 	  dst[l] = src[l];
832 	  l++;
833 	}
834 
835       H_PUT_32 (abfd, g->value, symbol.value);
836 
837       if (g->flags & BSF_LOCAL)
838 	{
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;
845 	}
846       else
847 	{
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;
854 	}
855       g->value = index - 1;
856     }
857 
858   return TRUE;
859 }
860 
861 /* Write a section header for each section.  */
862 
863 static bfd_boolean
oasys_write_sections(bfd * abfd)864 oasys_write_sections (bfd *abfd)
865 {
866   asection *s;
867   static oasys_section_record_type out;
868 
869   for (s = abfd->sections; s != NULL; s = s->next)
870     {
871       if (!ISDIGIT (s->name[0]))
872 	{
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;
878 	}
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);
882 
883       if (! oasys_write_record (abfd,
884 				oasys_record_is_section_enum,
885 				(oasys_record_union_type *) & out,
886 				sizeof (out)))
887 	return FALSE;
888     }
889   return TRUE;
890 }
891 
892 static bfd_boolean
oasys_write_header(bfd * abfd)893 oasys_write_header (bfd *abfd)
894 {
895   /* Create and write the header.  */
896   oasys_header_record_type r;
897   size_t length = strlen (abfd->filename);
898 
899   if (length > (size_t) sizeof (r.module_name))
900     length = sizeof (r.module_name);
901 
902   (void) memcpy (r.module_name, abfd->filename, length);
903   (void) memset (r.module_name + length, ' ', sizeof (r.module_name) - length);
904 
905   r.version_number = OASYS_VERSION_NUMBER;
906   r.rev_number = OASYS_REV_NUMBER;
907 
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]));
912 }
913 
914 static bfd_boolean
oasys_write_end(bfd * abfd)915 oasys_write_end (bfd *abfd)
916 {
917   oasys_end_record_type end;
918   unsigned char null = 0;
919 
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;
929 
930   return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
931 }
932 
933 static int
comp(const void * ap,const void * bp)934 comp (const void * ap, const void * bp)
935 {
936   arelent *a = *((arelent **) ap);
937   arelent *b = *((arelent **) bp);
938 
939   return a->address - b->address;
940 }
941 
942 static bfd_boolean
oasys_write_data(bfd * abfd)943 oasys_write_data (bfd *abfd)
944 {
945   asection *s;
946 
947   for (s = abfd->sections; s != NULL; s = s->next)
948     {
949       if (s->flags & SEC_LOAD)
950 	{
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;
956 
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);
961 
962 	  current_byte_index = 0;
963 	  processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
964 
965 	  while (current_byte_index < s->size)
966 	    {
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];
971 
972 	      unsigned int i = 0;
973 	      *mod = 0;
974 
975 	      H_PUT_32 (abfd, s->vma + current_byte_index,
976 			processed_data.addr);
977 
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])
986 		{
987 		  if (relocs_to_go != 0)
988 		    {
989 		      arelent *r = *p;
990 
991 		      /* There is a relocation, is it for this byte ?  */
992 		      if (r->address == current_byte_index)
993 			abort ();
994 		    }
995 
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++;
1002 
1003 		  if (++i >= 8)
1004 		    {
1005 		      i = 0;
1006 		      mod = dst++;
1007 		      *mod = 0;
1008 		    }
1009 		  current_byte_index++;
1010 		}
1011 
1012 	      /* Don't write a useless null modification byte.  */
1013 	      if (dst == mod + 1)
1014 		--dst;
1015 
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;
1021 	    }
1022 	}
1023     }
1024 
1025   return TRUE;
1026 }
1027 
1028 static bfd_boolean
oasys_write_object_contents(bfd * abfd)1029 oasys_write_object_contents (bfd *abfd)
1030 {
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;
1042 }
1043 
1044 /* Set section contents is complicated with OASYS since the format is
1045    not a byte image, but a record stream.  */
1046 
1047 static bfd_boolean
oasys_set_section_contents(bfd * abfd,sec_ptr section,const void * location,file_ptr offset,bfd_size_type count)1048 oasys_set_section_contents (bfd *abfd,
1049 			    sec_ptr section,
1050 			    const void * location,
1051 			    file_ptr offset,
1052 			    bfd_size_type count)
1053 {
1054   if (count != 0)
1055     {
1056       if (oasys_per_section (section)->data == NULL)
1057 	{
1058 	  oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
1059 	  if (!oasys_per_section (section)->data)
1060 	    return FALSE;
1061 	}
1062       (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
1063 		     location, (size_t) count);
1064     }
1065   return TRUE;
1066 }
1067 
1068 
1069 
1070 /* Native-level interface to symbols.  */
1071 
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.  */
1075 
1076 static asymbol *
oasys_make_empty_symbol(bfd * abfd)1077 oasys_make_empty_symbol (bfd *abfd)
1078 {
1079   bfd_size_type amt = sizeof (oasys_symbol_type);
1080   oasys_symbol_type *new = bfd_zalloc (abfd, amt);
1081 
1082   if (!new)
1083     return NULL;
1084   new->symbol.the_bfd = abfd;
1085   return &new->symbol;
1086 }
1087 
1088 /* User should have checked the file flags; perhaps we should return
1089    BFD_NO_MORE_SYMBOLS if there are none?  */
1090 
1091 static bfd *
oasys_openr_next_archived_file(bfd * arch,bfd * prev)1092 oasys_openr_next_archived_file (bfd *arch, bfd *prev)
1093 {
1094   oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1095   oasys_module_info_type *p;
1096 
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;
1101 
1102   p = ar->module + ar->module_index;
1103   ar->module_index++;
1104 
1105   if (ar->module_index <= ar->module_count)
1106     {
1107       if (p->abfd == NULL)
1108 	{
1109 	  p->abfd = _bfd_create_empty_archive_element_shell (arch);
1110 	  p->abfd->origin = p->pos;
1111 	  p->abfd->filename = p->name;
1112 
1113 	  /* Fixup a pointer to this element for the member.  */
1114 	  p->abfd->arelt_data = (void *) p;
1115 	}
1116       return p->abfd;
1117     }
1118 
1119   bfd_set_error (bfd_error_no_more_archived_files);
1120   return NULL;
1121 }
1122 
1123 static bfd_boolean
oasys_find_nearest_line(bfd * abfd ATTRIBUTE_UNUSED,asection * section ATTRIBUTE_UNUSED,asymbol ** symbols ATTRIBUTE_UNUSED,bfd_vma offset ATTRIBUTE_UNUSED,const char ** filename_ptr ATTRIBUTE_UNUSED,const char ** functionname_ptr ATTRIBUTE_UNUSED,unsigned int * line_ptr ATTRIBUTE_UNUSED)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)
1131 {
1132   return FALSE;
1133 }
1134 
1135 static bfd_boolean
oasys_find_inliner_info(bfd * abfd ATTRIBUTE_UNUSED,const char ** filename_ptr ATTRIBUTE_UNUSED,const char ** functionname_ptr ATTRIBUTE_UNUSED,unsigned int * line_ptr ATTRIBUTE_UNUSED)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)
1140 {
1141   return FALSE;
1142 }
1143 
1144 static int
oasys_generic_stat_arch_elt(bfd * abfd,struct stat * buf)1145 oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
1146 {
1147   oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1148 
1149   if (mod == NULL)
1150     {
1151       bfd_set_error (bfd_error_invalid_operation);
1152       return -1;
1153     }
1154 
1155   buf->st_size = mod->size;
1156   buf->st_mode = 0666;
1157   return 0;
1158 }
1159 
1160 static int
oasys_sizeof_headers(bfd * abfd ATTRIBUTE_UNUSED,bfd_boolean exec ATTRIBUTE_UNUSED)1161 oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean exec ATTRIBUTE_UNUSED)
1162 {
1163   return 0;
1164 }
1165 
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
1198 
1199 const bfd_target oasys_vec =
1200 {
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.  */
1219 
1220   {_bfd_dummy_target,
1221    oasys_object_p,		/* bfd_check_format.  */
1222    oasys_archive_p,
1223    _bfd_dummy_target,
1224   },
1225   {				/* bfd_set_format.  */
1226     bfd_false,
1227     oasys_mkobject,
1228     _bfd_generic_mkarchive,
1229     bfd_false
1230   },
1231   {				/* bfd_write_contents.  */
1232     bfd_false,
1233     oasys_write_object_contents,
1234     _bfd_write_archive_contents,
1235     bfd_false,
1236   },
1237 
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),
1247 
1248   NULL,
1249 
1250   NULL
1251 };
1252