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