Home | History | Annotate | Download | only in bfd
      1 /* BFD back-end for oasys objects.
      2    Copyright (C) 1990-2014 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 	if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
    276 	  return NULL;
    277 
    278 	/* There are two ways of specifying the archive header.  */
    279 	  {
    280 	    oasys_extmodule_table_type_b_type record_ext;
    281 
    282 	    amt = sizeof (record_ext);
    283 	    if (bfd_bread ((void *) &record_ext, amt, abfd) != amt)
    284 	      return NULL;
    285 
    286 	    record.mod_size = H_GET_32 (abfd, record_ext.mod_size);
    287 	    record.file_offset = H_GET_32 (abfd, record_ext.file_offset);
    288 
    289 	    record.dep_count = H_GET_32 (abfd, record_ext.dep_count);
    290 	    record.depee_count = H_GET_32 (abfd, record_ext.depee_count);
    291 	    record.sect_count = H_GET_32 (abfd, record_ext.sect_count);
    292 	    record.module_name_size = H_GET_32 (abfd,
    293 						record_ext.mod_name_length);
    294 
    295 	    amt = record.module_name_size;
    296 	    module[i].name = bfd_alloc (abfd, amt + 1);
    297 	    if (!module[i].name)
    298 	      return NULL;
    299 	    if (bfd_bread ((void *) module[i].name, amt, abfd) != amt)
    300 	      return NULL;
    301 	    module[i].name[record.module_name_size] = 0;
    302 	    filepos += (sizeof (record_ext)
    303 			+ record.dep_count * 4
    304 			+ record.module_name_size + 1);
    305 	  }
    306 
    307 	module[i].size = record.mod_size;
    308 	module[i].pos = record.file_offset;
    309 	module[i].abfd = 0;
    310       }
    311   }
    312   return abfd->xvec;
    313 }
    314 
    315 static bfd_boolean
    316 oasys_mkobject (bfd *abfd)
    317 {
    318   bfd_size_type amt = sizeof (oasys_data_type);
    319 
    320   abfd->tdata.oasys_obj_data = bfd_alloc (abfd, amt);
    321 
    322   return abfd->tdata.oasys_obj_data != NULL;
    323 }
    324 
    325 /* The howto table is build using the top two bits of a reloc byte to
    326    index into it. The bits are PCREL,WORD/LONG.  */
    327 
    328 static reloc_howto_type howto_table[] =
    329 {
    330 
    331   HOWTO (0, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    332   HOWTO (0, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs32",   TRUE, 0xffffffff, 0xffffffff, FALSE),
    333   HOWTO (0, 0, 1, 16, TRUE,  0, complain_overflow_signed,   0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    334   HOWTO (0, 0, 2, 32, TRUE,  0, complain_overflow_signed,   0, "pcrel32", TRUE, 0xffffffff, 0xffffffff, FALSE)
    335 };
    336 
    337 /* Read in all the section data and relocation stuff too.  */
    338 
    339 static bfd_boolean
    340 oasys_slurp_section_data (bfd *const abfd)
    341 {
    342   oasys_record_union_type record;
    343   oasys_data_type *data = OASYS_DATA (abfd);
    344   bfd_boolean loop = TRUE;
    345   oasys_per_section_type *per;
    346   asection *s;
    347   bfd_size_type amt;
    348 
    349   /* See if the data has been slurped already.  */
    350   for (s = abfd->sections; s != NULL; s = s->next)
    351     {
    352       per = oasys_per_section (s);
    353       if (per->initialized)
    354 	return TRUE;
    355     }
    356 
    357   if (data->first_data_record == 0)
    358     return TRUE;
    359 
    360   if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
    361     return FALSE;
    362 
    363   while (loop)
    364     {
    365       if (! oasys_read_record (abfd, &record))
    366 	return FALSE;
    367 
    368       switch (record.header.type)
    369 	{
    370 	case oasys_record_is_header_enum:
    371 	  break;
    372 	case oasys_record_is_data_enum:
    373 	  {
    374 	    bfd_byte *src = record.data.data;
    375 	    bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
    376 	    bfd_byte *dst_ptr;
    377 	    bfd_byte *dst_base_ptr;
    378 	    unsigned int relbit;
    379 	    unsigned int count;
    380 	    asection *section =
    381 	    data->sections[record.data.relb & RELOCATION_SECT_BITS];
    382 	    bfd_vma dst_offset;
    383 
    384 	    per = oasys_per_section (section);
    385 
    386 	    if (! per->initialized)
    387 	      {
    388 		arelent **relpp;
    389 
    390 		per->data = bfd_zalloc (abfd, section->size);
    391 		if (!per->data)
    392 		  return FALSE;
    393 		relpp = &section->relocation;
    394 		per->reloc_tail_ptr = (oasys_reloc_type **) relpp;
    395 		per->had_vma = FALSE;
    396 		per->initialized = TRUE;
    397 		section->reloc_count = 0;
    398 		section->flags = SEC_ALLOC;
    399 	      }
    400 
    401 	    dst_offset = H_GET_32 (abfd, record.data.addr);
    402 	    if (! per->had_vma)
    403 	      {
    404 		/* Take the first vma we see as the base.  */
    405 		section->vma = dst_offset;
    406 		per->had_vma = TRUE;
    407 	      }
    408 
    409 	    dst_offset -= section->vma;
    410 
    411 	    dst_base_ptr = oasys_per_section (section)->data;
    412 	    dst_ptr = oasys_per_section (section)->data +
    413 	      dst_offset;
    414 
    415 	    if (src < end_src)
    416 	      section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
    417 
    418 	    while (src < end_src)
    419 	      {
    420 		unsigned char mod_byte = *src++;
    421 		size_t gap = end_src - src;
    422 
    423 		count = 8;
    424 		if (mod_byte == 0 && gap >= 8)
    425 		  {
    426 		    dst_ptr[0] = src[0];
    427 		    dst_ptr[1] = src[1];
    428 		    dst_ptr[2] = src[2];
    429 		    dst_ptr[3] = src[3];
    430 		    dst_ptr[4] = src[4];
    431 		    dst_ptr[5] = src[5];
    432 		    dst_ptr[6] = src[6];
    433 		    dst_ptr[7] = src[7];
    434 		    dst_ptr += 8;
    435 		    src += 8;
    436 		  }
    437 		else
    438 		  {
    439 		    for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
    440 		      {
    441 			if (relbit & mod_byte)
    442 			  {
    443 			    unsigned char reloc = *src;
    444 			    /* This item needs to be relocated.  */
    445 			    switch (reloc & RELOCATION_TYPE_BITS)
    446 			      {
    447 			      case RELOCATION_TYPE_ABS:
    448 				break;
    449 
    450 			      case RELOCATION_TYPE_REL:
    451 				{
    452 				  /* Relocate the item relative to the section.  */
    453 				  oasys_reloc_type *r;
    454 
    455 				  amt = sizeof (oasys_reloc_type);
    456 				  r = bfd_alloc (abfd, amt);
    457 				  if (!r)
    458 				    return FALSE;
    459 				  *(per->reloc_tail_ptr) = r;
    460 				  per->reloc_tail_ptr = &r->next;
    461 				  r->next = NULL;
    462 				  /* Reference to undefined symbol.  */
    463 				  src++;
    464 				  /* There is no symbol.  */
    465 				  r->symbol = 0;
    466 				  /* Work out the howto.  */
    467 				  abort ();
    468 				  r->relent.address = dst_ptr - dst_base_ptr;
    469 				  r->relent.howto = &howto_table[reloc >> 6];
    470 				  r->relent.sym_ptr_ptr = NULL;
    471 				  section->reloc_count++;
    472 
    473 				  /* Fake up the data to look like
    474 				     it's got the -ve pc in it, this
    475 				     makes it much easier to convert
    476 				     into other formats.  This is done
    477 				     by hitting the addend.  */
    478 				  if (r->relent.howto->pc_relative)
    479 				    r->relent.addend -= dst_ptr - dst_base_ptr;
    480 				}
    481 				break;
    482 
    483 			      case RELOCATION_TYPE_UND:
    484 				{
    485 				  oasys_reloc_type *r;
    486 
    487 				  amt = sizeof (oasys_reloc_type);
    488 				  r = bfd_alloc (abfd, amt);
    489 				  if (!r)
    490 				    return FALSE;
    491 				  *(per->reloc_tail_ptr) = r;
    492 				  per->reloc_tail_ptr = &r->next;
    493 				  r->next = NULL;
    494 				  /* Reference to undefined symbol.  */
    495 				  src++;
    496 				  /* Get symbol number.  */
    497 				  r->symbol = (src[0] << 8) | src[1];
    498 				  /* Work out the howto.  */
    499 				  abort ();
    500 
    501 				  r->relent.addend = 0;
    502 				  r->relent.address = dst_ptr - dst_base_ptr;
    503 				  r->relent.howto = &howto_table[reloc >> 6];
    504 				  r->relent.sym_ptr_ptr = NULL;
    505 				  section->reloc_count++;
    506 
    507 				  src += 2;
    508 				  /* Fake up the data to look like
    509 				     it's got the -ve pc in it, this
    510 				     makes it much easier to convert
    511 				     into other formats.  This is done
    512 				     by hitting the addend.  */
    513 				  if (r->relent.howto->pc_relative)
    514 				    r->relent.addend -= dst_ptr - dst_base_ptr;
    515 				}
    516 				break;
    517 			      case RELOCATION_TYPE_COM:
    518 				BFD_FAIL ();
    519 			      }
    520 			  }
    521 			*dst_ptr++ = *src++;
    522 		      }
    523 		  }
    524 	      }
    525 	  }
    526 	  break;
    527 	case oasys_record_is_local_enum:
    528 	case oasys_record_is_symbol_enum:
    529 	case oasys_record_is_section_enum:
    530 	  break;
    531 	default:
    532 	  loop = FALSE;
    533 	}
    534     }
    535 
    536   return TRUE;
    537 
    538 }
    539 
    540 #define MAX_SECS 16
    541 
    542 static const bfd_target *
    543 oasys_object_p (bfd *abfd)
    544 {
    545   oasys_data_type *oasys;
    546   oasys_data_type *save = OASYS_DATA (abfd);
    547   bfd_boolean loop = TRUE;
    548   bfd_boolean had_usefull = FALSE;
    549 
    550   abfd->tdata.oasys_obj_data = 0;
    551   oasys_mkobject (abfd);
    552   oasys = OASYS_DATA (abfd);
    553   memset ((void *) oasys->sections, 0xff, sizeof (oasys->sections));
    554 
    555   /* Point to the start of the file.  */
    556   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    557     goto fail;
    558   oasys->symbol_string_length = 0;
    559 
    560   /* Inspect the records, but only keep the section info -
    561      remember the size of the symbols.  */
    562   oasys->first_data_record = 0;
    563   while (loop)
    564     {
    565       oasys_record_union_type record;
    566       if (! oasys_read_record (abfd, &record))
    567 	goto fail;
    568       if ((size_t) record.header.length < (size_t) sizeof (record.header))
    569 	goto fail;
    570 
    571       switch ((oasys_record_enum_type) (record.header.type))
    572 	{
    573 	case oasys_record_is_header_enum:
    574 	  had_usefull = TRUE;
    575 	  break;
    576 	case oasys_record_is_symbol_enum:
    577 	case oasys_record_is_local_enum:
    578 	  /* Count symbols and remember their size for a future malloc.  */
    579 	  abfd->symcount++;
    580 	  oasys->symbol_string_length += 1 + oasys_string_length (&record);
    581 	  had_usefull = TRUE;
    582 	  break;
    583 	case oasys_record_is_section_enum:
    584 	  {
    585 	    asection *s;
    586 	    char *buffer;
    587 	    unsigned int section_number;
    588 
    589 	    if (record.section.header.length != sizeof (record.section))
    590 	      goto fail;
    591 
    592 	    buffer = bfd_alloc (abfd, (bfd_size_type) 3);
    593 	    if (!buffer)
    594 	      goto fail;
    595 	    section_number = record.section.relb & RELOCATION_SECT_BITS;
    596 	    sprintf (buffer, "%u", section_number);
    597 	    s = bfd_make_section (abfd, buffer);
    598 	    oasys->sections[section_number] = s;
    599 	    switch (record.section.relb & RELOCATION_TYPE_BITS)
    600 	      {
    601 	      case RELOCATION_TYPE_ABS:
    602 	      case RELOCATION_TYPE_REL:
    603 		break;
    604 	      case RELOCATION_TYPE_UND:
    605 	      case RELOCATION_TYPE_COM:
    606 		BFD_FAIL ();
    607 	      }
    608 
    609 	    s->size = H_GET_32 (abfd, record.section.value);
    610 	    s->vma = H_GET_32 (abfd, record.section.vma);
    611 	    s->flags = 0;
    612 	    had_usefull = TRUE;
    613 	  }
    614 	  break;
    615 	case oasys_record_is_data_enum:
    616 	  oasys->first_data_record = bfd_tell (abfd) - record.header.length;
    617 	case oasys_record_is_debug_enum:
    618 	case oasys_record_is_module_enum:
    619 	case oasys_record_is_named_section_enum:
    620 	case oasys_record_is_end_enum:
    621 	  if (! had_usefull)
    622 	    goto fail;
    623 	  loop = FALSE;
    624 	  break;
    625 	default:
    626 	  goto fail;
    627 	}
    628     }
    629   oasys->symbols = NULL;
    630 
    631   /* Oasys support several architectures, but I can't see a simple way
    632      to discover which one is in a particular file - we'll guess.  */
    633   bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
    634   if (abfd->symcount != 0)
    635     abfd->flags |= HAS_SYMS;
    636 
    637   /* We don't know if a section has data until we've read it.  */
    638   oasys_slurp_section_data (abfd);
    639 
    640   return abfd->xvec;
    641 
    642 fail:
    643   (void) bfd_release (abfd, oasys);
    644   abfd->tdata.oasys_obj_data = save;
    645   return NULL;
    646 }
    647 
    648 
    649 static void
    650 oasys_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
    651 		       asymbol *symbol,
    652 		       symbol_info *ret)
    653 {
    654   bfd_symbol_info (symbol, ret);
    655 
    656   if (!symbol->section)
    657     ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
    658 }
    659 
    660 static void
    661 oasys_print_symbol (bfd *abfd, void * afile, asymbol *symbol, bfd_print_symbol_type how)
    662 {
    663   FILE *file = (FILE *) afile;
    664 
    665   switch (how)
    666     {
    667     case bfd_print_symbol_name:
    668     case bfd_print_symbol_more:
    669       fprintf (file, "%s", symbol->name);
    670       break;
    671     case bfd_print_symbol_all:
    672       {
    673 	const char *section_name = symbol->section == NULL ?
    674 	(const char *) "*abs" : symbol->section->name;
    675 
    676 	bfd_print_symbol_vandf (abfd, (void *) file, symbol);
    677 
    678 	fprintf (file, " %-5s %s",
    679 		 section_name,
    680 		 symbol->name);
    681       }
    682       break;
    683     }
    684 }
    685 
    686 static bfd_boolean
    687 oasys_new_section_hook (bfd *abfd, asection *newsect)
    688 {
    689   if (!newsect->used_by_bfd)
    690     {
    691       newsect->used_by_bfd
    692 	= bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
    693       if (!newsect->used_by_bfd)
    694 	return FALSE;
    695     }
    696   oasys_per_section (newsect)->data = NULL;
    697   oasys_per_section (newsect)->section = newsect;
    698   oasys_per_section (newsect)->offset = 0;
    699   oasys_per_section (newsect)->initialized = FALSE;
    700   newsect->alignment_power = 1;
    701 
    702   /* Turn the section string into an index.  */
    703   sscanf (newsect->name, "%u", &newsect->target_index);
    704 
    705   return _bfd_generic_new_section_hook (abfd, newsect);
    706 }
    707 
    708 
    709 static long
    710 oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
    711 {
    712   if (! oasys_slurp_section_data (abfd))
    713     return -1;
    714   return (asect->reloc_count + 1) * sizeof (arelent *);
    715 }
    716 
    717 static bfd_boolean
    718 oasys_get_section_contents (bfd *abfd,
    719 			    sec_ptr section,
    720 			    void * location,
    721 			    file_ptr offset,
    722 			    bfd_size_type count)
    723 {
    724   oasys_per_section_type *p = oasys_per_section (section);
    725 
    726   oasys_slurp_section_data (abfd);
    727 
    728   if (! p->initialized)
    729     (void) memset (location, 0, (size_t) count);
    730   else
    731     (void) memcpy (location, (void *) (p->data + offset), (size_t) count);
    732 
    733   return TRUE;
    734 }
    735 
    736 static long
    737 oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
    738 			  sec_ptr section,
    739 			  arelent **relptr,
    740 			  asymbol **symbols ATTRIBUTE_UNUSED)
    741 {
    742   unsigned int reloc_count = 0;
    743   oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
    744 
    745   if (src != NULL)
    746     abort ();
    747 
    748   *relptr = NULL;
    749   return section->reloc_count = reloc_count;
    750 }
    751 
    752 
    753 /* Writing.  */
    754 
    755 /* Calculate the checksum and write one record.  */
    756 
    757 static bfd_boolean
    758 oasys_write_record (bfd *abfd,
    759 		    oasys_record_enum_type type,
    760 		    oasys_record_union_type *record,
    761 		    size_t size)
    762 {
    763   int checksum;
    764   size_t i;
    765   unsigned char *ptr;
    766 
    767   record->header.length = size;
    768   record->header.type = (int) type;
    769   record->header.check_sum = 0;
    770   record->header.fill = 0;
    771   ptr = (unsigned char *) &record->pad[0];
    772   checksum = 0;
    773   for (i = 0; i < size; i++)
    774     checksum += *ptr++;
    775   record->header.check_sum = 0xff & (-checksum);
    776   if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size)
    777     return FALSE;
    778   return TRUE;
    779 }
    780 
    781 
    782 /* Write out all the symbols.  */
    783 
    784 static bfd_boolean
    785 oasys_write_syms (bfd *abfd)
    786 {
    787   unsigned int count;
    788   asymbol **generic = bfd_get_outsymbols (abfd);
    789   unsigned int sym_index = 0;
    790 
    791   for (count = 0; count < bfd_get_symcount (abfd); count++)
    792     {
    793       oasys_symbol_record_type symbol;
    794       asymbol *const g = generic[count];
    795       const char *src = g->name;
    796       char *dst = symbol.name;
    797       unsigned int l = 0;
    798 
    799       if (bfd_is_com_section (g->section))
    800 	{
    801 	  symbol.relb = RELOCATION_TYPE_COM;
    802 	  H_PUT_16 (abfd, sym_index, symbol.refno);
    803 	  sym_index++;
    804 	}
    805       else if (bfd_is_abs_section (g->section))
    806 	{
    807 	  symbol.relb = RELOCATION_TYPE_ABS;
    808 	  H_PUT_16 (abfd, 0, symbol.refno);
    809 	}
    810       else if (bfd_is_und_section (g->section))
    811 	{
    812 	  symbol.relb = RELOCATION_TYPE_UND;
    813 	  H_PUT_16 (abfd, sym_index, symbol.refno);
    814 	  /* Overload the value field with the output sym_index number */
    815 	  sym_index++;
    816 	}
    817       else if (g->flags & BSF_DEBUGGING)
    818 	/* Throw it away.  */
    819 	continue;
    820       else
    821 	{
    822 	  if (g->section == NULL)
    823 	    /* Sometime, the oasys tools give out a symbol with illegal
    824 	       bits in it, we'll output it in the same broken way.  */
    825 	    symbol.relb = RELOCATION_TYPE_REL | 0;
    826 	  else
    827 	    symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
    828 
    829 	  H_PUT_16 (abfd, 0, symbol.refno);
    830 	}
    831 
    832 #ifdef UNDERSCORE_HACK
    833       if (src[l] == '_')
    834 	dst[l++] = '.';
    835 #endif
    836       while (src[l])
    837 	{
    838 	  dst[l] = src[l];
    839 	  l++;
    840 	}
    841 
    842       H_PUT_32 (abfd, g->value, symbol.value);
    843 
    844       if (g->flags & BSF_LOCAL)
    845 	{
    846 	  if (! oasys_write_record (abfd,
    847 				    oasys_record_is_local_enum,
    848 				    (oasys_record_union_type *) & symbol,
    849 				    offsetof (oasys_symbol_record_type,
    850 					      name[0]) + l))
    851 	    return FALSE;
    852 	}
    853       else
    854 	{
    855 	  if (! oasys_write_record (abfd,
    856 				    oasys_record_is_symbol_enum,
    857 				    (oasys_record_union_type *) & symbol,
    858 				    offsetof (oasys_symbol_record_type,
    859 					      name[0]) + l))
    860 	    return FALSE;
    861 	}
    862       g->value = sym_index - 1;
    863     }
    864 
    865   return TRUE;
    866 }
    867 
    868 /* Write a section header for each section.  */
    869 
    870 static bfd_boolean
    871 oasys_write_sections (bfd *abfd)
    872 {
    873   asection *s;
    874   static oasys_section_record_type out;
    875 
    876   for (s = abfd->sections; s != NULL; s = s->next)
    877     {
    878       if (!ISDIGIT (s->name[0]))
    879 	{
    880 	  (*_bfd_error_handler)
    881 	    (_("%s: can not represent section `%s' in oasys"),
    882 	     bfd_get_filename (abfd), s->name);
    883 	  bfd_set_error (bfd_error_nonrepresentable_section);
    884 	  return FALSE;
    885 	}
    886       out.relb = RELOCATION_TYPE_REL | s->target_index;
    887       H_PUT_32 (abfd, s->size, out.value);
    888       H_PUT_32 (abfd, s->vma, out.vma);
    889 
    890       if (! oasys_write_record (abfd,
    891 				oasys_record_is_section_enum,
    892 				(oasys_record_union_type *) & out,
    893 				sizeof (out)))
    894 	return FALSE;
    895     }
    896   return TRUE;
    897 }
    898 
    899 static bfd_boolean
    900 oasys_write_header (bfd *abfd)
    901 {
    902   /* Create and write the header.  */
    903   oasys_header_record_type r;
    904   size_t length = strlen (abfd->filename);
    905 
    906   if (length > (size_t) sizeof (r.module_name))
    907     length = sizeof (r.module_name);
    908   else if (length < (size_t) sizeof (r.module_name))
    909     (void) memset (r.module_name + length, ' ',
    910 		   sizeof (r.module_name) - length);
    911 
    912   (void) memcpy (r.module_name, abfd->filename, length);
    913 
    914   r.version_number = OASYS_VERSION_NUMBER;
    915   r.rev_number = OASYS_REV_NUMBER;
    916 
    917   return oasys_write_record (abfd, oasys_record_is_header_enum,
    918 			     (oasys_record_union_type *) & r,
    919 			     offsetof (oasys_header_record_type,
    920 				       description[0]));
    921 }
    922 
    923 static bfd_boolean
    924 oasys_write_end (bfd *abfd)
    925 {
    926   oasys_end_record_type end;
    927   unsigned char null = 0;
    928 
    929   end.relb = RELOCATION_TYPE_ABS;
    930   H_PUT_32 (abfd, abfd->start_address, end.entry);
    931   H_PUT_16 (abfd, 0, end.fill);
    932   end.zero = 0;
    933   if (! oasys_write_record (abfd,
    934 			    oasys_record_is_end_enum,
    935 			    (oasys_record_union_type *) & end,
    936 			    sizeof (end)))
    937     return FALSE;
    938 
    939   return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
    940 }
    941 
    942 static int
    943 comp (const void * ap, const void * bp)
    944 {
    945   arelent *a = *((arelent **) ap);
    946   arelent *b = *((arelent **) bp);
    947 
    948   return a->address - b->address;
    949 }
    950 
    951 static bfd_boolean
    952 oasys_write_data (bfd *abfd)
    953 {
    954   asection *s;
    955 
    956   for (s = abfd->sections; s != NULL; s = s->next)
    957     {
    958       if (s->flags & SEC_LOAD)
    959 	{
    960 	  bfd_byte *raw_data = oasys_per_section (s)->data;
    961 	  oasys_data_record_type processed_data;
    962 	  bfd_size_type current_byte_index = 0;
    963 	  unsigned int relocs_to_go = s->reloc_count;
    964 	  arelent **p = s->orelocation;
    965 
    966 	  if (s->reloc_count != 0)
    967 	    /* Sort the reloc records so it's easy to insert the relocs into the
    968 	       data.  */
    969 	    qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp);
    970 
    971 	  current_byte_index = 0;
    972 	  processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
    973 
    974 	  while (current_byte_index < s->size)
    975 	    {
    976 	      /* Scan forwards by eight bytes or however much is left and see if
    977 	       there are any relocations going on.  */
    978 	      bfd_byte *mod = &processed_data.data[0];
    979 	      bfd_byte *dst = &processed_data.data[1];
    980 
    981 	      unsigned int i = 0;
    982 	      *mod = 0;
    983 
    984 	      H_PUT_32 (abfd, s->vma + current_byte_index,
    985 			processed_data.addr);
    986 
    987 	      /* Don't start a relocation unless you're sure you can finish it
    988 		 within the same data record.  The worst case relocation is a
    989 		 4-byte relocatable value which is split across two modification
    990 		 bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
    991 		 1 modification byte + 2 data = 8 bytes total).  That's where
    992 		 the magic number 8 comes from.  */
    993 	      while (current_byte_index < s->size && dst <=
    994 		     & processed_data.data[sizeof (processed_data.data) - 8])
    995 		{
    996 		  if (relocs_to_go != 0)
    997 		    {
    998 		      arelent *r = *p;
    999 
   1000 		      /* There is a relocation, is it for this byte ?  */
   1001 		      if (r->address == current_byte_index)
   1002 			abort ();
   1003 		    }
   1004 
   1005 		  /* If this is coming from an unloadable section then copy
   1006 		     zeros.  */
   1007 		  if (raw_data == NULL)
   1008 		    *dst++ = 0;
   1009 		  else
   1010 		    *dst++ = *raw_data++;
   1011 
   1012 		  if (++i >= 8)
   1013 		    {
   1014 		      i = 0;
   1015 		      mod = dst++;
   1016 		      *mod = 0;
   1017 		    }
   1018 		  current_byte_index++;
   1019 		}
   1020 
   1021 	      /* Don't write a useless null modification byte.  */
   1022 	      if (dst == mod + 1)
   1023 		--dst;
   1024 
   1025 	      if (! (oasys_write_record
   1026 		     (abfd, oasys_record_is_data_enum,
   1027 		      ((oasys_record_union_type *) &processed_data),
   1028 		      (size_t) (dst - (bfd_byte *) &processed_data))))
   1029 		return FALSE;
   1030 	    }
   1031 	}
   1032     }
   1033 
   1034   return TRUE;
   1035 }
   1036 
   1037 static bfd_boolean
   1038 oasys_write_object_contents (bfd *abfd)
   1039 {
   1040   if (! oasys_write_header (abfd))
   1041     return FALSE;
   1042   if (! oasys_write_syms (abfd))
   1043     return FALSE;
   1044   if (! oasys_write_sections (abfd))
   1045     return FALSE;
   1046   if (! oasys_write_data (abfd))
   1047     return FALSE;
   1048   if (! oasys_write_end (abfd))
   1049     return FALSE;
   1050   return TRUE;
   1051 }
   1052 
   1053 /* Set section contents is complicated with OASYS since the format is
   1054    not a byte image, but a record stream.  */
   1055 
   1056 static bfd_boolean
   1057 oasys_set_section_contents (bfd *abfd,
   1058 			    sec_ptr section,
   1059 			    const void * location,
   1060 			    file_ptr offset,
   1061 			    bfd_size_type count)
   1062 {
   1063   if (count != 0)
   1064     {
   1065       if (oasys_per_section (section)->data == NULL)
   1066 	{
   1067 	  oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
   1068 	  if (!oasys_per_section (section)->data)
   1069 	    return FALSE;
   1070 	}
   1071       (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
   1072 		     location, (size_t) count);
   1073     }
   1074   return TRUE;
   1075 }
   1076 
   1077 
   1078 
   1079 /* Native-level interface to symbols.  */
   1080 
   1081 /* We read the symbols into a buffer, which is discarded when this
   1082    function exits.  We read the strings into a buffer large enough to
   1083    hold them all plus all the cached symbol entries.  */
   1084 
   1085 static asymbol *
   1086 oasys_make_empty_symbol (bfd *abfd)
   1087 {
   1088   bfd_size_type amt = sizeof (oasys_symbol_type);
   1089   oasys_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt);
   1090 
   1091   if (!new_symbol_type)
   1092     return NULL;
   1093   new_symbol_type->symbol.the_bfd = abfd;
   1094   return &new_symbol_type->symbol;
   1095 }
   1096 
   1097 /* User should have checked the file flags; perhaps we should return
   1098    BFD_NO_MORE_SYMBOLS if there are none?  */
   1099 
   1100 static bfd *
   1101 oasys_openr_next_archived_file (bfd *arch, bfd *prev)
   1102 {
   1103   oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
   1104   oasys_module_info_type *p;
   1105 
   1106   /* Take the next one from the arch state, or reset.  */
   1107   if (prev == NULL)
   1108     /* Reset the index - the first two entries are bogus.  */
   1109     ar->module_index = 0;
   1110 
   1111   p = ar->module + ar->module_index;
   1112   ar->module_index++;
   1113 
   1114   if (ar->module_index <= ar->module_count)
   1115     {
   1116       if (p->abfd == NULL)
   1117 	{
   1118 	  p->abfd = _bfd_create_empty_archive_element_shell (arch);
   1119 	  p->abfd->origin = p->pos;
   1120 	  p->abfd->filename = xstrdup (p->name);
   1121 
   1122 	  /* Fixup a pointer to this element for the member.  */
   1123 	  p->abfd->arelt_data = (void *) p;
   1124 	}
   1125       return p->abfd;
   1126     }
   1127 
   1128   bfd_set_error (bfd_error_no_more_archived_files);
   1129   return NULL;
   1130 }
   1131 
   1132 #define oasys_find_nearest_line _bfd_nosymbols_find_nearest_line
   1133 #define oasys_find_line         _bfd_nosymbols_find_line
   1134 #define oasys_find_inliner_info _bfd_nosymbols_find_inliner_info
   1135 
   1136 static int
   1137 oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
   1138 {
   1139   oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
   1140 
   1141   if (mod == NULL)
   1142     {
   1143       bfd_set_error (bfd_error_invalid_operation);
   1144       return -1;
   1145     }
   1146 
   1147   buf->st_size = mod->size;
   1148   buf->st_mode = 0666;
   1149   return 0;
   1150 }
   1151 
   1152 static int
   1153 oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
   1154 		      struct bfd_link_info *info ATTRIBUTE_UNUSED)
   1155 {
   1156   return 0;
   1157 }
   1158 
   1159 #define	oasys_close_and_cleanup                    _bfd_generic_close_and_cleanup
   1160 #define oasys_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
   1161 #define oasys_slurp_armap                          bfd_true
   1162 #define oasys_slurp_extended_name_table            bfd_true
   1163 #define oasys_construct_extended_name_table        ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true)
   1164 #define oasys_truncate_arname                      bfd_dont_truncate_arname
   1165 #define oasys_write_armap                          ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true)
   1166 #define oasys_read_ar_hdr                          bfd_nullvoidptr
   1167 #define oasys_write_ar_hdr ((bfd_boolean (*) (bfd *, bfd *)) bfd_false)
   1168 #define oasys_get_elt_at_index                     _bfd_generic_get_elt_at_index
   1169 #define oasys_update_armap_timestamp               bfd_true
   1170 #define oasys_bfd_is_local_label_name              bfd_generic_is_local_label_name
   1171 #define oasys_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
   1172 #define oasys_get_lineno                           _bfd_nosymbols_get_lineno
   1173 #define oasys_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
   1174 #define oasys_read_minisymbols                     _bfd_generic_read_minisymbols
   1175 #define oasys_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
   1176 #define oasys_bfd_reloc_type_lookup                _bfd_norelocs_bfd_reloc_type_lookup
   1177 #define oasys_bfd_reloc_name_lookup          _bfd_norelocs_bfd_reloc_name_lookup
   1178 #define oasys_set_arch_mach                        bfd_default_set_arch_mach
   1179 #define oasys_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
   1180 #define oasys_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
   1181 #define oasys_bfd_relax_section                    bfd_generic_relax_section
   1182 #define oasys_bfd_gc_sections                      bfd_generic_gc_sections
   1183 #define oasys_bfd_lookup_section_flags             bfd_generic_lookup_section_flags
   1184 #define oasys_bfd_merge_sections                   bfd_generic_merge_sections
   1185 #define oasys_bfd_is_group_section                 bfd_generic_is_group_section
   1186 #define oasys_bfd_discard_group                    bfd_generic_discard_group
   1187 #define oasys_section_already_linked               _bfd_generic_section_already_linked
   1188 #define oasys_bfd_define_common_symbol             bfd_generic_define_common_symbol
   1189 #define oasys_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
   1190 #define oasys_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
   1191 #define oasys_bfd_link_just_syms                   _bfd_generic_link_just_syms
   1192 #define oasys_bfd_copy_link_hash_symbol_type \
   1193   _bfd_generic_copy_link_hash_symbol_type
   1194 #define oasys_bfd_final_link                       _bfd_generic_final_link
   1195 #define oasys_bfd_link_split_section               _bfd_generic_link_split_section
   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