xref: /openbsd/gnu/usr.bin/binutils/bfd/oasys.c (revision 007c2a45)
12159047fSniklas /* BFD back-end for oasys objects.
2c074d1c9Sdrahn    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001,
3c074d1c9Sdrahn    2002, 2003 Free Software Foundation, Inc.
42159047fSniklas    Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>.
52159047fSniklas 
62159047fSniklas    This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas 
82159047fSniklas    This program is free software; you can redistribute it and/or modify
92159047fSniklas    it under the terms of the GNU General Public License as published by
102159047fSniklas    the Free Software Foundation; either version 2 of the License, or
112159047fSniklas    (at your option) any later version.
122159047fSniklas 
132159047fSniklas    This program is distributed in the hope that it will be useful,
142159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas    GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas    You should have received a copy of the GNU General Public License
192159047fSniklas    along with this program; if not, write to the Free Software
202159047fSniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas #define UNDERSCORE_HACK 1
232159047fSniklas #include "bfd.h"
242159047fSniklas #include "sysdep.h"
25c074d1c9Sdrahn #include "safe-ctype.h"
262159047fSniklas #include "libbfd.h"
272159047fSniklas #include "oasys.h"
282159047fSniklas #include "liboasys.h"
292159047fSniklas 
30c074d1c9Sdrahn static bfd_boolean oasys_slurp_section_data
31c074d1c9Sdrahn   PARAMS ((bfd * const));
32c074d1c9Sdrahn static bfd_boolean oasys_read_record
33c074d1c9Sdrahn   PARAMS ((bfd *, oasys_record_union_type *));
34c074d1c9Sdrahn static bfd_boolean oasys_write_sections
35c074d1c9Sdrahn   PARAMS ((bfd *));
36c074d1c9Sdrahn static bfd_boolean oasys_write_record
37c074d1c9Sdrahn   PARAMS ((bfd *, oasys_record_enum_type, oasys_record_union_type *, size_t));
38c074d1c9Sdrahn static bfd_boolean oasys_write_syms
39c074d1c9Sdrahn   PARAMS ((bfd *));
40c074d1c9Sdrahn static bfd_boolean oasys_write_header
41c074d1c9Sdrahn   PARAMS ((bfd *));
42c074d1c9Sdrahn static bfd_boolean oasys_write_end
43c074d1c9Sdrahn   PARAMS ((bfd *));
44c074d1c9Sdrahn static bfd_boolean oasys_write_data
45c074d1c9Sdrahn   PARAMS ((bfd *));
46c074d1c9Sdrahn static size_t oasys_string_length
47c074d1c9Sdrahn   PARAMS ((oasys_record_union_type *));
48c074d1c9Sdrahn static bfd_boolean oasys_slurp_symbol_table
49c074d1c9Sdrahn   PARAMS ((bfd *const));
50c074d1c9Sdrahn static long int oasys_get_symtab_upper_bound
51c074d1c9Sdrahn   PARAMS ((bfd *const));
52c074d1c9Sdrahn static const bfd_target *oasys_archive_p
53c074d1c9Sdrahn   PARAMS ((bfd *));
54c074d1c9Sdrahn static bfd_boolean oasys_mkobject
55c074d1c9Sdrahn   PARAMS ((bfd *));
56c074d1c9Sdrahn static const bfd_target *oasys_object_p
57c074d1c9Sdrahn   PARAMS ((bfd *));
58c074d1c9Sdrahn static void oasys_get_symbol_info
59c074d1c9Sdrahn   PARAMS ((bfd *, asymbol *, symbol_info *));
60c074d1c9Sdrahn static void oasys_print_symbol
61c074d1c9Sdrahn   PARAMS ((bfd *, void *, asymbol *, bfd_print_symbol_type));
62c074d1c9Sdrahn static bfd_boolean oasys_new_section_hook
63c074d1c9Sdrahn   PARAMS ((bfd *, asection *));
64c074d1c9Sdrahn static long int oasys_get_reloc_upper_bound
65c074d1c9Sdrahn   PARAMS ((bfd *, sec_ptr));
66c074d1c9Sdrahn static bfd_boolean oasys_get_section_contents
67c074d1c9Sdrahn   PARAMS ((bfd *, sec_ptr, void *, file_ptr, bfd_size_type));
68c074d1c9Sdrahn static int comp
69c074d1c9Sdrahn   PARAMS ((const void *, const void *));
70c074d1c9Sdrahn static bfd_boolean oasys_write_object_contents
71c074d1c9Sdrahn   PARAMS ((bfd *));
72c074d1c9Sdrahn static bfd_boolean oasys_set_section_contents
73*007c2a45Smiod   PARAMS ((bfd *, sec_ptr, const void *, file_ptr, bfd_size_type));
74c074d1c9Sdrahn static asymbol *oasys_make_empty_symbol
75c074d1c9Sdrahn   PARAMS ((bfd *));
76c074d1c9Sdrahn static bfd *oasys_openr_next_archived_file
77c074d1c9Sdrahn   PARAMS ((bfd *, bfd *));
78c074d1c9Sdrahn static bfd_boolean oasys_find_nearest_line
79c074d1c9Sdrahn   PARAMS ((bfd *, asection *, asymbol **, bfd_vma,
80c074d1c9Sdrahn 	   const char **, const char **, unsigned int *));
81c074d1c9Sdrahn static int oasys_generic_stat_arch_elt
82c074d1c9Sdrahn   PARAMS ((bfd *, struct stat *));
83c074d1c9Sdrahn static int oasys_sizeof_headers
84c074d1c9Sdrahn   PARAMS ((bfd *, bfd_boolean));
852159047fSniklas 
86*007c2a45Smiod long oasys_canonicalize_symtab
87c074d1c9Sdrahn   PARAMS ((bfd *, asymbol **));
88c074d1c9Sdrahn long oasys_canonicalize_reloc
89c074d1c9Sdrahn   PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
902159047fSniklas 
91c074d1c9Sdrahn /* Read in all the section data and relocation stuff too.  */
922159047fSniklas 
93c074d1c9Sdrahn static bfd_boolean
oasys_read_record(abfd,record)942159047fSniklas oasys_read_record (abfd, record)
952159047fSniklas      bfd *abfd;
962159047fSniklas      oasys_record_union_type *record;
972159047fSniklas {
98c074d1c9Sdrahn   bfd_size_type amt = sizeof (record->header);
99c074d1c9Sdrahn   if (bfd_bread ((PTR) record, amt, abfd) != amt)
100c074d1c9Sdrahn     return FALSE;
1012159047fSniklas 
102c074d1c9Sdrahn   amt = record->header.length - sizeof (record->header);
103c074d1c9Sdrahn   if ((long) amt <= 0)
104c074d1c9Sdrahn     return TRUE;
105c074d1c9Sdrahn   if (bfd_bread ((PTR) ((char *) record + sizeof (record->header)), amt, abfd)
106c074d1c9Sdrahn       != amt)
107c074d1c9Sdrahn     return FALSE;
108c074d1c9Sdrahn   return TRUE;
1092159047fSniklas }
110c074d1c9Sdrahn 
1112159047fSniklas static size_t
oasys_string_length(record)1122159047fSniklas oasys_string_length (record)
1132159047fSniklas      oasys_record_union_type *record;
1142159047fSniklas {
1152159047fSniklas   return record->header.length
1162159047fSniklas     - ((char *) record->symbol.name - (char *) record);
1172159047fSniklas }
1182159047fSniklas 
1192159047fSniklas /*****************************************************************************/
1202159047fSniklas 
1212159047fSniklas /*
1222159047fSniklas 
1232159047fSniklas Slurp the symbol table by reading in all the records at the start file
1242159047fSniklas till we get to the first section record.
1252159047fSniklas 
1262159047fSniklas We'll sort the symbolss into  two lists, defined and undefined. The
1272159047fSniklas undefined symbols will be placed into the table according to their
1282159047fSniklas refno.
1292159047fSniklas 
1302159047fSniklas We do this by placing all undefined symbols at the front of the table
1312159047fSniklas moving in, and the defined symbols at the end of the table moving back.
1322159047fSniklas 
1332159047fSniklas */
1342159047fSniklas 
135c074d1c9Sdrahn static bfd_boolean
oasys_slurp_symbol_table(abfd)1362159047fSniklas oasys_slurp_symbol_table (abfd)
137c074d1c9Sdrahn      bfd *const abfd;
1382159047fSniklas {
1392159047fSniklas   oasys_record_union_type record;
1402159047fSniklas   oasys_data_type *data = OASYS_DATA (abfd);
141c074d1c9Sdrahn   bfd_boolean loop = TRUE;
1422159047fSniklas   asymbol *dest_defined;
1432159047fSniklas   asymbol *dest;
1442159047fSniklas   char *string_ptr;
145c074d1c9Sdrahn   bfd_size_type amt;
1462159047fSniklas 
1472159047fSniklas   if (data->symbols != (asymbol *) NULL)
1482159047fSniklas     {
149c074d1c9Sdrahn       return TRUE;
1502159047fSniklas     }
1512159047fSniklas   /* Buy enough memory for all the symbols and all the names */
152c074d1c9Sdrahn   amt = abfd->symcount;
153c074d1c9Sdrahn   amt *= sizeof (asymbol);
154c074d1c9Sdrahn   data->symbols = (asymbol *) bfd_alloc (abfd, amt);
155c074d1c9Sdrahn 
156c074d1c9Sdrahn   amt = data->symbol_string_length;
1572159047fSniklas #ifdef UNDERSCORE_HACK
1582159047fSniklas   /* buy 1 more char for each symbol to keep the underscore in*/
159c074d1c9Sdrahn   amt += abfd->symcount;
1602159047fSniklas #endif
161c074d1c9Sdrahn   data->strings = bfd_alloc (abfd, amt);
162c074d1c9Sdrahn 
1632159047fSniklas   if (!data->symbols || !data->strings)
164c074d1c9Sdrahn     return FALSE;
1652159047fSniklas 
1662159047fSniklas   dest_defined = data->symbols + abfd->symcount - 1;
1672159047fSniklas 
1682159047fSniklas   string_ptr = data->strings;
1692159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
170c074d1c9Sdrahn     return FALSE;
1712159047fSniklas   while (loop)
1722159047fSniklas     {
1732159047fSniklas 
1742159047fSniklas       if (! oasys_read_record (abfd, &record))
175c074d1c9Sdrahn 	return FALSE;
1762159047fSniklas       switch (record.header.type)
1772159047fSniklas 	{
1782159047fSniklas 	case oasys_record_is_header_enum:
1792159047fSniklas 	  break;
1802159047fSniklas 	case oasys_record_is_local_enum:
1812159047fSniklas 	case oasys_record_is_symbol_enum:
1822159047fSniklas 	  {
1832159047fSniklas 	    int flag = record.header.type == (int) oasys_record_is_local_enum ?
1842159047fSniklas 	    (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
1852159047fSniklas 
1862159047fSniklas 
1872159047fSniklas 	    size_t length = oasys_string_length (&record);
1882159047fSniklas 	    switch (record.symbol.relb & RELOCATION_TYPE_BITS)
1892159047fSniklas 	      {
1902159047fSniklas 	      case RELOCATION_TYPE_ABS:
1912159047fSniklas 		dest = dest_defined--;
1922159047fSniklas 		dest->section = bfd_abs_section_ptr;
1932159047fSniklas 		dest->flags = 0;
1942159047fSniklas 
1952159047fSniklas 		break;
1962159047fSniklas 	      case RELOCATION_TYPE_REL:
1972159047fSniklas 		dest = dest_defined--;
1982159047fSniklas 		dest->section =
1992159047fSniklas 		  OASYS_DATA (abfd)->sections[record.symbol.relb &
2002159047fSniklas 					      RELOCATION_SECT_BITS];
2012159047fSniklas 		if (record.header.type == (int) oasys_record_is_local_enum)
2022159047fSniklas 		  {
2032159047fSniklas 		    dest->flags = BSF_LOCAL;
2042159047fSniklas 		    if (dest->section == (asection *) (~0))
2052159047fSniklas 		      {
2062159047fSniklas 			/* It seems that sometimes internal symbols are tied up, but
2072159047fSniklas 		       still get output, even though there is no
2082159047fSniklas 		       section */
2092159047fSniklas 			dest->section = 0;
2102159047fSniklas 		      }
2112159047fSniklas 		  }
2122159047fSniklas 		else
2132159047fSniklas 		  {
2142159047fSniklas 
2152159047fSniklas 		    dest->flags = flag;
2162159047fSniklas 		  }
2172159047fSniklas 		break;
2182159047fSniklas 	      case RELOCATION_TYPE_UND:
219c074d1c9Sdrahn 		dest = data->symbols + H_GET_16 (abfd, record.symbol.refno);
2202159047fSniklas 		dest->section = bfd_und_section_ptr;
2212159047fSniklas 		break;
2222159047fSniklas 	      case RELOCATION_TYPE_COM:
2232159047fSniklas 		dest = dest_defined--;
2242159047fSniklas 		dest->name = string_ptr;
2252159047fSniklas 		dest->the_bfd = abfd;
2262159047fSniklas 
2272159047fSniklas 		dest->section = bfd_com_section_ptr;
2282159047fSniklas 
2292159047fSniklas 		break;
2302159047fSniklas 	      default:
2312159047fSniklas 		dest = dest_defined--;
2322159047fSniklas 		BFD_ASSERT (0);
2332159047fSniklas 		break;
2342159047fSniklas 	      }
2352159047fSniklas 	    dest->name = string_ptr;
2362159047fSniklas 	    dest->the_bfd = abfd;
2372159047fSniklas 	    dest->udata.p = (PTR) NULL;
238c074d1c9Sdrahn 	    dest->value = H_GET_32 (abfd, record.symbol.value);
2392159047fSniklas 
2402159047fSniklas #ifdef UNDERSCORE_HACK
2412159047fSniklas 	    if (record.symbol.name[0] != '_')
2422159047fSniklas 	      {
2432159047fSniklas 		string_ptr[0] = '_';
2442159047fSniklas 		string_ptr++;
2452159047fSniklas 	      }
2462159047fSniklas #endif
2472159047fSniklas 	    memcpy (string_ptr, record.symbol.name, length);
2482159047fSniklas 
2492159047fSniklas 
2502159047fSniklas 	    string_ptr[length] = 0;
2512159047fSniklas 	    string_ptr += length + 1;
2522159047fSniklas 	  }
2532159047fSniklas 	  break;
2542159047fSniklas 	default:
255c074d1c9Sdrahn 	  loop = FALSE;
2562159047fSniklas 	}
2572159047fSniklas     }
258c074d1c9Sdrahn   return TRUE;
2592159047fSniklas }
2602159047fSniklas 
2612159047fSniklas static long
oasys_get_symtab_upper_bound(abfd)2622159047fSniklas oasys_get_symtab_upper_bound (abfd)
263c074d1c9Sdrahn      bfd *const abfd;
2642159047fSniklas {
2652159047fSniklas   if (! oasys_slurp_symbol_table (abfd))
2662159047fSniklas     return -1;
2672159047fSniklas 
2682159047fSniklas   return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *));
2692159047fSniklas }
2702159047fSniklas 
2712159047fSniklas extern const bfd_target oasys_vec;
2722159047fSniklas 
2732159047fSniklas long
oasys_canonicalize_symtab(abfd,location)274*007c2a45Smiod oasys_canonicalize_symtab (abfd, location)
2752159047fSniklas      bfd *abfd;
2762159047fSniklas      asymbol **location;
2772159047fSniklas {
2782159047fSniklas   asymbol *symbase;
2792159047fSniklas   unsigned int counter;
280c074d1c9Sdrahn   if (! oasys_slurp_symbol_table (abfd))
2812159047fSniklas     {
2822159047fSniklas       return -1;
2832159047fSniklas     }
2842159047fSniklas   symbase = OASYS_DATA (abfd)->symbols;
2852159047fSniklas   for (counter = 0; counter < abfd->symcount; counter++)
2862159047fSniklas     {
2872159047fSniklas       *(location++) = symbase++;
2882159047fSniklas     }
2892159047fSniklas   *location = 0;
2902159047fSniklas   return abfd->symcount;
2912159047fSniklas }
2922159047fSniklas 
2932159047fSniklas /***********************************************************************
2942159047fSniklas *  archive stuff
2952159047fSniklas */
2962159047fSniklas 
2972159047fSniklas static const bfd_target *
oasys_archive_p(abfd)2982159047fSniklas oasys_archive_p (abfd)
2992159047fSniklas      bfd *abfd;
3002159047fSniklas {
3012159047fSniklas   oasys_archive_header_type header;
3022159047fSniklas   oasys_extarchive_header_type header_ext;
3032159047fSniklas   unsigned int i;
3042159047fSniklas   file_ptr filepos;
305c074d1c9Sdrahn   bfd_size_type amt;
3062159047fSniklas 
307c074d1c9Sdrahn   amt = sizeof (header_ext);
308c074d1c9Sdrahn   if (bfd_seek (abfd, (file_ptr) 0, 0) != 0
309c074d1c9Sdrahn       || bfd_bread ((PTR) &header_ext, amt, abfd) != amt)
3102159047fSniklas     {
3112159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
3122159047fSniklas 	bfd_set_error (bfd_error_wrong_format);
3132159047fSniklas       return NULL;
3142159047fSniklas     }
3152159047fSniklas 
316c074d1c9Sdrahn   header.version = H_GET_32 (abfd, header_ext.version);
317c074d1c9Sdrahn   header.mod_count = H_GET_32 (abfd, header_ext.mod_count);
318c074d1c9Sdrahn   header.mod_tbl_offset = H_GET_32 (abfd, header_ext.mod_tbl_offset);
319c074d1c9Sdrahn   header.sym_tbl_size = H_GET_32 (abfd, header_ext.sym_tbl_size);
320c074d1c9Sdrahn   header.sym_count = H_GET_32 (abfd, header_ext.sym_count);
321c074d1c9Sdrahn   header.sym_tbl_offset = H_GET_32 (abfd, header_ext.sym_tbl_offset);
322c074d1c9Sdrahn   header.xref_count = H_GET_32 (abfd, header_ext.xref_count);
323c074d1c9Sdrahn   header.xref_lst_offset = H_GET_32 (abfd, header_ext.xref_lst_offset);
3242159047fSniklas 
3252159047fSniklas   /*
3262159047fSniklas     There isn't a magic number in an Oasys archive, so the best we
327*007c2a45Smiod     can do to verify reasonableness is to make sure that the values in
3282159047fSniklas     the header are too weird
3292159047fSniklas     */
3302159047fSniklas 
3312159047fSniklas   if (header.version > 10000 ||
3322159047fSniklas       header.mod_count > 10000 ||
3332159047fSniklas       header.sym_count > 100000 ||
3342159047fSniklas       header.xref_count > 100000)
3352159047fSniklas     return (const bfd_target *) NULL;
3362159047fSniklas 
3372159047fSniklas   /*
3382159047fSniklas     That all worked, let's buy the space for the header and read in
3392159047fSniklas     the headers.
3402159047fSniklas     */
3412159047fSniklas   {
342c074d1c9Sdrahn     oasys_ar_data_type *ar;
343c074d1c9Sdrahn     oasys_module_info_type *module;
3442159047fSniklas     oasys_module_table_type record;
3452159047fSniklas 
346c074d1c9Sdrahn     amt = sizeof (oasys_ar_data_type);
347c074d1c9Sdrahn     ar = (oasys_ar_data_type *) bfd_alloc (abfd, amt);
348c074d1c9Sdrahn 
349c074d1c9Sdrahn     amt = header.mod_count;
350c074d1c9Sdrahn     amt *= sizeof (oasys_module_info_type);
351c074d1c9Sdrahn     module = (oasys_module_info_type *) bfd_alloc (abfd, amt);
352c074d1c9Sdrahn 
3532159047fSniklas     if (!ar || !module)
3542159047fSniklas       return NULL;
3552159047fSniklas 
3562159047fSniklas     abfd->tdata.oasys_ar_data = ar;
3572159047fSniklas     ar->module = module;
3582159047fSniklas     ar->module_count = header.mod_count;
3592159047fSniklas 
3602159047fSniklas     filepos = header.mod_tbl_offset;
3612159047fSniklas     for (i = 0; i < header.mod_count; i++)
3622159047fSniklas       {
3632159047fSniklas 	if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
3642159047fSniklas 	  return NULL;
3652159047fSniklas 
3662159047fSniklas 	/* There are two ways of specifying the archive header */
3672159047fSniklas 
3682159047fSniklas 	if (0)
3692159047fSniklas 	  {
3702159047fSniklas 	    oasys_extmodule_table_type_a_type record_ext;
371c074d1c9Sdrahn 
372c074d1c9Sdrahn 	    amt = sizeof (record_ext);
373c074d1c9Sdrahn 	    if (bfd_bread ((PTR) &record_ext, amt, abfd) != amt)
3742159047fSniklas 	      return NULL;
3752159047fSniklas 
376c074d1c9Sdrahn 	    record.mod_size = H_GET_32 (abfd, record_ext.mod_size);
377c074d1c9Sdrahn 	    record.file_offset = H_GET_32 (abfd, record_ext.file_offset);
3782159047fSniklas 
379c074d1c9Sdrahn 	    record.dep_count = H_GET_32 (abfd, record_ext.dep_count);
380c074d1c9Sdrahn 	    record.depee_count = H_GET_32 (abfd, record_ext.depee_count);
381c074d1c9Sdrahn 	    record.sect_count = H_GET_32 (abfd, record_ext.sect_count);
3822159047fSniklas 
383c074d1c9Sdrahn 	    module[i].name = bfd_alloc (abfd, (bfd_size_type) 33);
3842159047fSniklas 	    if (!module[i].name)
3852159047fSniklas 	      return NULL;
3862159047fSniklas 
3872159047fSniklas 	    memcpy (module[i].name, record_ext.mod_name, 33);
3882159047fSniklas 	    filepos +=
3892159047fSniklas 	      sizeof (record_ext) +
3902159047fSniklas 	      record.dep_count * 4 +
3912159047fSniklas 	      record.depee_count * 4 +
3922159047fSniklas 	      record.sect_count * 8 + 187;
3932159047fSniklas 	  }
3942159047fSniklas 	else
3952159047fSniklas 	  {
3962159047fSniklas 	    oasys_extmodule_table_type_b_type record_ext;
397c074d1c9Sdrahn 
398c074d1c9Sdrahn 	    amt = sizeof (record_ext);
399c074d1c9Sdrahn 	    if (bfd_bread ((PTR) &record_ext, amt, abfd) != amt)
4002159047fSniklas 	      return NULL;
4012159047fSniklas 
402c074d1c9Sdrahn 	    record.mod_size = H_GET_32 (abfd, record_ext.mod_size);
403c074d1c9Sdrahn 	    record.file_offset = H_GET_32 (abfd, record_ext.file_offset);
4042159047fSniklas 
405c074d1c9Sdrahn 	    record.dep_count = H_GET_32 (abfd, record_ext.dep_count);
406c074d1c9Sdrahn 	    record.depee_count = H_GET_32 (abfd, record_ext.depee_count);
407c074d1c9Sdrahn 	    record.sect_count = H_GET_32 (abfd, record_ext.sect_count);
408c074d1c9Sdrahn 	    record.module_name_size = H_GET_32 (abfd,
409c074d1c9Sdrahn 						record_ext.mod_name_length);
4102159047fSniklas 
411c074d1c9Sdrahn 	    amt = record.module_name_size;
412c074d1c9Sdrahn 	    module[i].name = bfd_alloc (abfd, amt + 1);
4132159047fSniklas 	    if (!module[i].name)
4142159047fSniklas 	      return NULL;
415c074d1c9Sdrahn 	    if (bfd_bread ((PTR) module[i].name, amt, abfd) != amt)
4162159047fSniklas 	      return NULL;
4172159047fSniklas 	    module[i].name[record.module_name_size] = 0;
418c074d1c9Sdrahn 	    filepos += (sizeof (record_ext)
419c074d1c9Sdrahn 			+ record.dep_count * 4
420c074d1c9Sdrahn 			+ record.module_name_size + 1);
4212159047fSniklas 	  }
4222159047fSniklas 
4232159047fSniklas 	module[i].size = record.mod_size;
4242159047fSniklas 	module[i].pos = record.file_offset;
4252159047fSniklas 	module[i].abfd = 0;
4262159047fSniklas       }
4272159047fSniklas   }
4282159047fSniklas   return abfd->xvec;
4292159047fSniklas }
4302159047fSniklas 
431c074d1c9Sdrahn static bfd_boolean
oasys_mkobject(abfd)4322159047fSniklas oasys_mkobject (abfd)
4332159047fSniklas      bfd *abfd;
4342159047fSniklas {
435c074d1c9Sdrahn   bfd_size_type amt = sizeof (oasys_data_type);
436c074d1c9Sdrahn   abfd->tdata.oasys_obj_data = (oasys_data_type *) bfd_alloc (abfd, amt);
437c074d1c9Sdrahn   return abfd->tdata.oasys_obj_data != NULL;
4382159047fSniklas }
4392159047fSniklas 
4402159047fSniklas #define MAX_SECS 16
4412159047fSniklas static const bfd_target *
oasys_object_p(abfd)4422159047fSniklas oasys_object_p (abfd)
4432159047fSniklas      bfd *abfd;
4442159047fSniklas {
4452159047fSniklas   oasys_data_type *oasys;
4462159047fSniklas   oasys_data_type *save = OASYS_DATA (abfd);
447c074d1c9Sdrahn   bfd_boolean loop = TRUE;
448c074d1c9Sdrahn   bfd_boolean had_usefull = FALSE;
4492159047fSniklas 
4502159047fSniklas   abfd->tdata.oasys_obj_data = 0;
4512159047fSniklas   oasys_mkobject (abfd);
4522159047fSniklas   oasys = OASYS_DATA (abfd);
4532159047fSniklas   memset ((PTR) oasys->sections, 0xff, sizeof (oasys->sections));
4542159047fSniklas 
4552159047fSniklas   /* Point to the start of the file */
4562159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
4572159047fSniklas     goto fail;
4582159047fSniklas   oasys->symbol_string_length = 0;
4592159047fSniklas   /* Inspect the records, but only keep the section info -
4602159047fSniklas      remember the size of the symbols
4612159047fSniklas      */
4622159047fSniklas   oasys->first_data_record = 0;
4632159047fSniklas   while (loop)
4642159047fSniklas     {
4652159047fSniklas       oasys_record_union_type record;
4662159047fSniklas       if (! oasys_read_record (abfd, &record))
4672159047fSniklas 	goto fail;
4682159047fSniklas       if ((size_t) record.header.length < (size_t) sizeof (record.header))
4692159047fSniklas 	goto fail;
4702159047fSniklas 
4712159047fSniklas 
4722159047fSniklas       switch ((oasys_record_enum_type) (record.header.type))
4732159047fSniklas 	{
4742159047fSniklas 	case oasys_record_is_header_enum:
475c074d1c9Sdrahn 	  had_usefull = TRUE;
4762159047fSniklas 	  break;
4772159047fSniklas 	case oasys_record_is_symbol_enum:
4782159047fSniklas 	case oasys_record_is_local_enum:
4792159047fSniklas 	  /* Count symbols and remember their size for a future malloc   */
4802159047fSniklas 	  abfd->symcount++;
4812159047fSniklas 	  oasys->symbol_string_length += 1 + oasys_string_length (&record);
482c074d1c9Sdrahn 	  had_usefull = TRUE;
4832159047fSniklas 	  break;
4842159047fSniklas 	case oasys_record_is_section_enum:
4852159047fSniklas 	  {
4862159047fSniklas 	    asection *s;
4872159047fSniklas 	    char *buffer;
4882159047fSniklas 	    unsigned int section_number;
4892159047fSniklas 	    if (record.section.header.length != sizeof (record.section))
4902159047fSniklas 	      {
4912159047fSniklas 		goto fail;
4922159047fSniklas 	      }
493c074d1c9Sdrahn 	    buffer = bfd_alloc (abfd, (bfd_size_type) 3);
4942159047fSniklas 	    if (!buffer)
4952159047fSniklas 	      goto fail;
4962159047fSniklas 	    section_number = record.section.relb & RELOCATION_SECT_BITS;
4972159047fSniklas 	    sprintf (buffer, "%u", section_number);
4982159047fSniklas 	    s = bfd_make_section (abfd, buffer);
4992159047fSniklas 	    oasys->sections[section_number] = s;
5002159047fSniklas 	    switch (record.section.relb & RELOCATION_TYPE_BITS)
5012159047fSniklas 	      {
5022159047fSniklas 	      case RELOCATION_TYPE_ABS:
5032159047fSniklas 	      case RELOCATION_TYPE_REL:
5042159047fSniklas 		break;
5052159047fSniklas 	      case RELOCATION_TYPE_UND:
5062159047fSniklas 	      case RELOCATION_TYPE_COM:
5072159047fSniklas 		BFD_FAIL ();
5082159047fSniklas 	      }
5092159047fSniklas 
510c074d1c9Sdrahn 	    s->_raw_size = H_GET_32 (abfd, record.section.value);
511c074d1c9Sdrahn 	    s->vma = H_GET_32 (abfd, record.section.vma);
5122159047fSniklas 	    s->flags = 0;
513c074d1c9Sdrahn 	    had_usefull = TRUE;
5142159047fSniklas 	  }
5152159047fSniklas 	  break;
5162159047fSniklas 	case oasys_record_is_data_enum:
5172159047fSniklas 	  oasys->first_data_record = bfd_tell (abfd) - record.header.length;
5182159047fSniklas 	case oasys_record_is_debug_enum:
5192159047fSniklas 	case oasys_record_is_module_enum:
5202159047fSniklas 	case oasys_record_is_named_section_enum:
5212159047fSniklas 	case oasys_record_is_end_enum:
522c074d1c9Sdrahn 	  if (! had_usefull)
5232159047fSniklas 	    goto fail;
524c074d1c9Sdrahn 	  loop = FALSE;
5252159047fSniklas 	  break;
5262159047fSniklas 	default:
5272159047fSniklas 	  goto fail;
5282159047fSniklas 	}
5292159047fSniklas     }
5302159047fSniklas   oasys->symbols = (asymbol *) NULL;
5312159047fSniklas   /*
5322159047fSniklas     Oasys support several architectures, but I can't see a simple way
5332159047fSniklas     to discover which one is in a particular file - we'll guess
5342159047fSniklas     */
5352159047fSniklas   bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
5362159047fSniklas   if (abfd->symcount != 0)
5372159047fSniklas     {
5382159047fSniklas       abfd->flags |= HAS_SYMS;
5392159047fSniklas     }
5402159047fSniklas 
5412159047fSniklas   /*
5422159047fSniklas     We don't know if a section has data until we've read it..
5432159047fSniklas     */
5442159047fSniklas 
5452159047fSniklas   oasys_slurp_section_data (abfd);
5462159047fSniklas 
5472159047fSniklas 
5482159047fSniklas   return abfd->xvec;
5492159047fSniklas 
5502159047fSniklas fail:
5512159047fSniklas   (void) bfd_release (abfd, oasys);
5522159047fSniklas   abfd->tdata.oasys_obj_data = save;
5532159047fSniklas   return (const bfd_target *) NULL;
5542159047fSniklas }
5552159047fSniklas 
5562159047fSniklas 
5572159047fSniklas static void
oasys_get_symbol_info(ignore_abfd,symbol,ret)5582159047fSniklas oasys_get_symbol_info (ignore_abfd, symbol, ret)
559b305b0f1Sespie      bfd *ignore_abfd ATTRIBUTE_UNUSED;
5602159047fSniklas      asymbol *symbol;
5612159047fSniklas      symbol_info *ret;
5622159047fSniklas {
5632159047fSniklas   bfd_symbol_info (symbol, ret);
5642159047fSniklas   if (!symbol->section)
5652159047fSniklas     ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
5662159047fSniklas }
5672159047fSniklas 
5682159047fSniklas static void
oasys_print_symbol(abfd,afile,symbol,how)569c074d1c9Sdrahn oasys_print_symbol (abfd, afile, symbol, how)
570c074d1c9Sdrahn      bfd *abfd;
5712159047fSniklas      PTR afile;
5722159047fSniklas      asymbol *symbol;
5732159047fSniklas      bfd_print_symbol_type how;
5742159047fSniklas {
5752159047fSniklas   FILE *file = (FILE *) afile;
5762159047fSniklas 
5772159047fSniklas   switch (how)
5782159047fSniklas     {
5792159047fSniklas     case bfd_print_symbol_name:
5802159047fSniklas     case bfd_print_symbol_more:
5812159047fSniklas       fprintf (file, "%s", symbol->name);
5822159047fSniklas       break;
5832159047fSniklas     case bfd_print_symbol_all:
5842159047fSniklas       {
585c074d1c9Sdrahn 	const char *section_name = symbol->section == (asection *) NULL ?
586c074d1c9Sdrahn 	(const char *) "*abs" : symbol->section->name;
5872159047fSniklas 
588c074d1c9Sdrahn 	bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
5892159047fSniklas 
5902159047fSniklas 	fprintf (file, " %-5s %s",
5912159047fSniklas 		 section_name,
5922159047fSniklas 		 symbol->name);
5932159047fSniklas       }
5942159047fSniklas       break;
5952159047fSniklas     }
5962159047fSniklas }
5972159047fSniklas /*
5982159047fSniklas  The howto table is build using the top two bits of a reloc byte to
5992159047fSniklas  index into it. The bits are PCREL,WORD/LONG
6002159047fSniklas */
6012159047fSniklas static reloc_howto_type howto_table[] =
6022159047fSniklas {
6032159047fSniklas 
604c074d1c9Sdrahn   HOWTO (0, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
605c074d1c9Sdrahn   HOWTO (0, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs32", TRUE, 0xffffffff, 0xffffffff, FALSE),
606c074d1c9Sdrahn   HOWTO (0, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
607c074d1c9Sdrahn   HOWTO (0, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0, "pcrel32", TRUE, 0xffffffff, 0xffffffff, FALSE)
6082159047fSniklas };
6092159047fSniklas 
6102159047fSniklas /* Read in all the section data and relocation stuff too */
611c074d1c9Sdrahn static bfd_boolean
oasys_slurp_section_data(abfd)6122159047fSniklas oasys_slurp_section_data (abfd)
613c074d1c9Sdrahn      bfd *const abfd;
6142159047fSniklas {
6152159047fSniklas   oasys_record_union_type record;
6162159047fSniklas   oasys_data_type *data = OASYS_DATA (abfd);
617c074d1c9Sdrahn   bfd_boolean loop = TRUE;
6182159047fSniklas   oasys_per_section_type *per;
6192159047fSniklas   asection *s;
620c074d1c9Sdrahn   bfd_size_type amt;
6212159047fSniklas 
6222159047fSniklas   /* See if the data has been slurped already .. */
6232159047fSniklas   for (s = abfd->sections; s != (asection *) NULL; s = s->next)
6242159047fSniklas     {
6252159047fSniklas       per = oasys_per_section (s);
626c074d1c9Sdrahn       if (per->initialized)
627c074d1c9Sdrahn 	return TRUE;
6282159047fSniklas     }
6292159047fSniklas 
6302159047fSniklas   if (data->first_data_record == 0)
631c074d1c9Sdrahn     return TRUE;
6322159047fSniklas 
6332159047fSniklas   if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
634c074d1c9Sdrahn     return FALSE;
6352159047fSniklas   while (loop)
6362159047fSniklas     {
6372159047fSniklas       if (! oasys_read_record (abfd, &record))
638c074d1c9Sdrahn 	return FALSE;
6392159047fSniklas       switch (record.header.type)
6402159047fSniklas 	{
6412159047fSniklas 	case oasys_record_is_header_enum:
6422159047fSniklas 	  break;
6432159047fSniklas 	case oasys_record_is_data_enum:
6442159047fSniklas 	  {
6452159047fSniklas 
6462159047fSniklas 	    bfd_byte *src = record.data.data;
6472159047fSniklas 	    bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
6482159047fSniklas 	    bfd_byte *dst_ptr;
6492159047fSniklas 	    bfd_byte *dst_base_ptr;
6502159047fSniklas 	    unsigned int relbit;
6512159047fSniklas 	    unsigned int count;
6522159047fSniklas 	    asection *section =
6532159047fSniklas 	    data->sections[record.data.relb & RELOCATION_SECT_BITS];
6542159047fSniklas 	    bfd_vma dst_offset;
6552159047fSniklas 
6562159047fSniklas 	    per = oasys_per_section (section);
6572159047fSniklas 
658c074d1c9Sdrahn 	    if (! per->initialized)
6592159047fSniklas 	      {
6602159047fSniklas 		per->data = (bfd_byte *) bfd_zalloc (abfd, section->_raw_size);
6612159047fSniklas 		if (!per->data)
662c074d1c9Sdrahn 		  return FALSE;
663c074d1c9Sdrahn 		per->reloc_tail_ptr
664c074d1c9Sdrahn 		  = (oasys_reloc_type **) &section->relocation;
665c074d1c9Sdrahn 		per->had_vma = FALSE;
666c074d1c9Sdrahn 		per->initialized = TRUE;
6672159047fSniklas 		section->reloc_count = 0;
6682159047fSniklas 		section->flags = SEC_ALLOC;
6692159047fSniklas 	      }
6702159047fSniklas 
671c074d1c9Sdrahn 	    dst_offset = H_GET_32 (abfd, record.data.addr);
672c074d1c9Sdrahn 	    if (! per->had_vma)
6732159047fSniklas 	      {
6742159047fSniklas 		/* Take the first vma we see as the base */
6752159047fSniklas 		section->vma = dst_offset;
676c074d1c9Sdrahn 		per->had_vma = TRUE;
6772159047fSniklas 	      }
6782159047fSniklas 
6792159047fSniklas 	    dst_offset -= section->vma;
6802159047fSniklas 
6812159047fSniklas 	    dst_base_ptr = oasys_per_section (section)->data;
6822159047fSniklas 	    dst_ptr = oasys_per_section (section)->data +
6832159047fSniklas 	      dst_offset;
6842159047fSniklas 
6852159047fSniklas 	    if (src < end_src)
6862159047fSniklas 	      {
6872159047fSniklas 		section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
6882159047fSniklas 	      }
6892159047fSniklas 	    while (src < end_src)
6902159047fSniklas 	      {
6912159047fSniklas 		unsigned char mod_byte = *src++;
6922159047fSniklas 		size_t gap = end_src - src;
6932159047fSniklas 
6942159047fSniklas 		count = 8;
6952159047fSniklas 		if (mod_byte == 0 && gap >= 8)
6962159047fSniklas 		  {
6972159047fSniklas 		    dst_ptr[0] = src[0];
6982159047fSniklas 		    dst_ptr[1] = src[1];
6992159047fSniklas 		    dst_ptr[2] = src[2];
7002159047fSniklas 		    dst_ptr[3] = src[3];
7012159047fSniklas 		    dst_ptr[4] = src[4];
7022159047fSniklas 		    dst_ptr[5] = src[5];
7032159047fSniklas 		    dst_ptr[6] = src[6];
7042159047fSniklas 		    dst_ptr[7] = src[7];
7052159047fSniklas 		    dst_ptr += 8;
7062159047fSniklas 		    src += 8;
7072159047fSniklas 		  }
7082159047fSniklas 		else
7092159047fSniklas 		  {
7102159047fSniklas 		    for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
7112159047fSniklas 		      {
7122159047fSniklas 			if (relbit & mod_byte)
7132159047fSniklas 			  {
7142159047fSniklas 			    unsigned char reloc = *src;
7152159047fSniklas 			    /* This item needs to be relocated */
7162159047fSniklas 			    switch (reloc & RELOCATION_TYPE_BITS)
7172159047fSniklas 			      {
7182159047fSniklas 			      case RELOCATION_TYPE_ABS:
7192159047fSniklas 
7202159047fSniklas 				break;
7212159047fSniklas 
7222159047fSniklas 			      case RELOCATION_TYPE_REL:
7232159047fSniklas 				{
7242159047fSniklas 				  /* Relocate the item relative to the section */
725c074d1c9Sdrahn 				  oasys_reloc_type *r;
726c074d1c9Sdrahn 
727c074d1c9Sdrahn 				  amt = sizeof (oasys_reloc_type);
728c074d1c9Sdrahn 				  r = (oasys_reloc_type *) bfd_alloc (abfd,
729c074d1c9Sdrahn 								      amt);
7302159047fSniklas 				  if (!r)
731c074d1c9Sdrahn 				    return FALSE;
7322159047fSniklas 				  *(per->reloc_tail_ptr) = r;
7332159047fSniklas 				  per->reloc_tail_ptr = &r->next;
7342159047fSniklas 				  r->next = (oasys_reloc_type *) NULL;
7352159047fSniklas 				  /* Reference to undefined symbol */
7362159047fSniklas 				  src++;
7372159047fSniklas 				  /* There is no symbol */
7382159047fSniklas 				  r->symbol = 0;
7392159047fSniklas 				  /* Work out the howto */
7402159047fSniklas 				  abort ();
7412159047fSniklas #if 0
7422159047fSniklas 				  r->relent.section =
7432159047fSniklas 				    data->sections[reloc &
7442159047fSniklas 						   RELOCATION_SECT_BITS];
7452159047fSniklas 
7462159047fSniklas 				  r->relent.addend = -
7472159047fSniklas 				    r->relent.section->vma;
7482159047fSniklas #endif
7492159047fSniklas 				  r->relent.address = dst_ptr - dst_base_ptr;
7502159047fSniklas 				  r->relent.howto = &howto_table[reloc >> 6];
7512159047fSniklas 				  r->relent.sym_ptr_ptr = (asymbol **) NULL;
7522159047fSniklas 				  section->reloc_count++;
7532159047fSniklas 
754c074d1c9Sdrahn 				  /* Fake up the data to look like
755c074d1c9Sdrahn 				     it's got the -ve pc in it, this
756c074d1c9Sdrahn 				     makes it much easier to convert
757c074d1c9Sdrahn 				     into other formats.  This is done
758c074d1c9Sdrahn 				     by hitting the addend.  */
759c074d1c9Sdrahn 				  if (r->relent.howto->pc_relative)
7602159047fSniklas 				    r->relent.addend -= dst_ptr - dst_base_ptr;
7612159047fSniklas 				}
7622159047fSniklas 				break;
7632159047fSniklas 
7642159047fSniklas 
7652159047fSniklas 			      case RELOCATION_TYPE_UND:
7662159047fSniklas 				{
767c074d1c9Sdrahn 				  oasys_reloc_type *r;
768c074d1c9Sdrahn 
769c074d1c9Sdrahn 				  amt = sizeof (oasys_reloc_type);
770c074d1c9Sdrahn 				  r = (oasys_reloc_type *) bfd_alloc (abfd,
771c074d1c9Sdrahn 								      amt);
7722159047fSniklas 				  if (!r)
773c074d1c9Sdrahn 				    return FALSE;
7742159047fSniklas 				  *(per->reloc_tail_ptr) = r;
7752159047fSniklas 				  per->reloc_tail_ptr = &r->next;
7762159047fSniklas 				  r->next = (oasys_reloc_type *) NULL;
7772159047fSniklas 				  /* Reference to undefined symbol */
7782159047fSniklas 				  src++;
7792159047fSniklas 				  /* Get symbol number */
7802159047fSniklas 				  r->symbol = (src[0] << 8) | src[1];
7812159047fSniklas 				  /* Work out the howto */
7822159047fSniklas 				  abort ();
7832159047fSniklas 
7842159047fSniklas #if 0
7852159047fSniklas 				  r->relent.section = (asection
7862159047fSniklas 						       *) NULL;
7872159047fSniklas #endif
7882159047fSniklas 				  r->relent.addend = 0;
7892159047fSniklas 				  r->relent.address = dst_ptr - dst_base_ptr;
7902159047fSniklas 				  r->relent.howto = &howto_table[reloc >> 6];
7912159047fSniklas 				  r->relent.sym_ptr_ptr = (asymbol **) NULL;
7922159047fSniklas 				  section->reloc_count++;
7932159047fSniklas 
7942159047fSniklas 				  src += 2;
795c074d1c9Sdrahn 				  /* Fake up the data to look like
796c074d1c9Sdrahn 				     it's got the -ve pc in it, this
797c074d1c9Sdrahn 				     makes it much easier to convert
798c074d1c9Sdrahn 				     into other formats.  This is done
799c074d1c9Sdrahn 				     by hitting the addend.  */
800c074d1c9Sdrahn 				  if (r->relent.howto->pc_relative)
8012159047fSniklas 				    r->relent.addend -= dst_ptr - dst_base_ptr;
8022159047fSniklas 				}
8032159047fSniklas 				break;
8042159047fSniklas 			      case RELOCATION_TYPE_COM:
8052159047fSniklas 				BFD_FAIL ();
8062159047fSniklas 			      }
8072159047fSniklas 			  }
8082159047fSniklas 			*dst_ptr++ = *src++;
8092159047fSniklas 		      }
8102159047fSniklas 		  }
8112159047fSniklas 	      }
8122159047fSniklas 	  }
8132159047fSniklas 	  break;
8142159047fSniklas 	case oasys_record_is_local_enum:
8152159047fSniklas 	case oasys_record_is_symbol_enum:
8162159047fSniklas 	case oasys_record_is_section_enum:
8172159047fSniklas 	  break;
8182159047fSniklas 	default:
819c074d1c9Sdrahn 	  loop = FALSE;
8202159047fSniklas 	}
8212159047fSniklas     }
8222159047fSniklas 
823c074d1c9Sdrahn   return TRUE;
8242159047fSniklas 
8252159047fSniklas }
8262159047fSniklas 
827c074d1c9Sdrahn static bfd_boolean
oasys_new_section_hook(abfd,newsect)8282159047fSniklas oasys_new_section_hook (abfd, newsect)
8292159047fSniklas      bfd *abfd;
8302159047fSniklas      asection *newsect;
8312159047fSniklas {
8322159047fSniklas   newsect->used_by_bfd = (PTR)
833c074d1c9Sdrahn     bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
8342159047fSniklas   if (!newsect->used_by_bfd)
835c074d1c9Sdrahn     return FALSE;
8362159047fSniklas   oasys_per_section (newsect)->data = (bfd_byte *) NULL;
8372159047fSniklas   oasys_per_section (newsect)->section = newsect;
8382159047fSniklas   oasys_per_section (newsect)->offset = 0;
839c074d1c9Sdrahn   oasys_per_section (newsect)->initialized = FALSE;
8402159047fSniklas   newsect->alignment_power = 1;
8412159047fSniklas   /* Turn the section string into an index */
8422159047fSniklas 
8432159047fSniklas   sscanf (newsect->name, "%u", &newsect->target_index);
8442159047fSniklas 
845c074d1c9Sdrahn   return TRUE;
8462159047fSniklas }
8472159047fSniklas 
8482159047fSniklas 
8492159047fSniklas static long
oasys_get_reloc_upper_bound(abfd,asect)8502159047fSniklas oasys_get_reloc_upper_bound (abfd, asect)
8512159047fSniklas      bfd *abfd;
8522159047fSniklas      sec_ptr asect;
8532159047fSniklas {
8542159047fSniklas   if (! oasys_slurp_section_data (abfd))
8552159047fSniklas     return -1;
8562159047fSniklas   return (asect->reloc_count + 1) * sizeof (arelent *);
8572159047fSniklas }
8582159047fSniklas 
859c074d1c9Sdrahn static bfd_boolean
oasys_get_section_contents(abfd,section,location,offset,count)8602159047fSniklas oasys_get_section_contents (abfd, section, location, offset, count)
8612159047fSniklas      bfd *abfd;
8622159047fSniklas      sec_ptr section;
8632159047fSniklas      PTR location;
8642159047fSniklas      file_ptr offset;
8652159047fSniklas      bfd_size_type count;
8662159047fSniklas {
867c074d1c9Sdrahn   oasys_per_section_type *p = oasys_per_section (section);
8682159047fSniklas   oasys_slurp_section_data (abfd);
869c074d1c9Sdrahn   if (! p->initialized)
8702159047fSniklas     {
871c074d1c9Sdrahn       (void) memset (location, 0, (size_t) count);
8722159047fSniklas     }
8732159047fSniklas   else
8742159047fSniklas     {
875c074d1c9Sdrahn       (void) memcpy (location, (PTR) (p->data + offset), (size_t) count);
8762159047fSniklas     }
877c074d1c9Sdrahn   return TRUE;
8782159047fSniklas }
8792159047fSniklas 
8802159047fSniklas 
8812159047fSniklas long
oasys_canonicalize_reloc(ignore_abfd,section,relptr,symbols)8822159047fSniklas oasys_canonicalize_reloc (ignore_abfd, section, relptr, symbols)
883b305b0f1Sespie      bfd *ignore_abfd ATTRIBUTE_UNUSED;
8842159047fSniklas      sec_ptr section;
8852159047fSniklas      arelent **relptr;
886b305b0f1Sespie      asymbol **symbols ATTRIBUTE_UNUSED;
8872159047fSniklas {
8882159047fSniklas   unsigned int reloc_count = 0;
8892159047fSniklas   oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
8902159047fSniklas   while (src != (oasys_reloc_type *) NULL)
8912159047fSniklas     {
8922159047fSniklas       abort ();
8932159047fSniklas 
8942159047fSniklas #if 0
8952159047fSniklas       if (src->relent.section == (asection *) NULL)
8962159047fSniklas 	{
8972159047fSniklas 	  src->relent.sym_ptr_ptr = symbols + src->symbol;
8982159047fSniklas 	}
8992159047fSniklas #endif
9002159047fSniklas 
9012159047fSniklas       *relptr++ = &src->relent;
9022159047fSniklas       src = src->next;
9032159047fSniklas       reloc_count++;
9042159047fSniklas     }
9052159047fSniklas   *relptr = (arelent *) NULL;
9062159047fSniklas   return section->reloc_count = reloc_count;
9072159047fSniklas }
9082159047fSniklas 
9092159047fSniklas 
9102159047fSniklas 
9112159047fSniklas 
9122159047fSniklas /* Writing */
9132159047fSniklas 
9142159047fSniklas 
9152159047fSniklas /* Calculate the checksum and write one record */
916c074d1c9Sdrahn static bfd_boolean
oasys_write_record(abfd,type,record,size)9172159047fSniklas oasys_write_record (abfd, type, record, size)
9182159047fSniklas      bfd *abfd;
9192159047fSniklas      oasys_record_enum_type type;
9202159047fSniklas      oasys_record_union_type *record;
9212159047fSniklas      size_t size;
9222159047fSniklas {
9232159047fSniklas   int checksum;
9242159047fSniklas   size_t i;
9252159047fSniklas   unsigned char *ptr;
9262159047fSniklas 
9272159047fSniklas   record->header.length = size;
9282159047fSniklas   record->header.type = (int) type;
9292159047fSniklas   record->header.check_sum = 0;
9302159047fSniklas   record->header.fill = 0;
9312159047fSniklas   ptr = (unsigned char *) &record->pad[0];
9322159047fSniklas   checksum = 0;
9332159047fSniklas   for (i = 0; i < size; i++)
9342159047fSniklas     {
9352159047fSniklas       checksum += *ptr++;
9362159047fSniklas     }
9372159047fSniklas   record->header.check_sum = 0xff & (-checksum);
938c074d1c9Sdrahn   if (bfd_bwrite ((PTR) record, (bfd_size_type) size, abfd) != size)
939c074d1c9Sdrahn     return FALSE;
940c074d1c9Sdrahn   return TRUE;
9412159047fSniklas }
9422159047fSniklas 
9432159047fSniklas 
9442159047fSniklas /* Write out all the symbols */
945c074d1c9Sdrahn static bfd_boolean
oasys_write_syms(abfd)9462159047fSniklas oasys_write_syms (abfd)
9472159047fSniklas      bfd *abfd;
9482159047fSniklas {
9492159047fSniklas   unsigned int count;
9502159047fSniklas   asymbol **generic = bfd_get_outsymbols (abfd);
9512159047fSniklas   unsigned int index = 0;
9522159047fSniklas   for (count = 0; count < bfd_get_symcount (abfd); count++)
9532159047fSniklas     {
9542159047fSniklas 
9552159047fSniklas       oasys_symbol_record_type symbol;
956c074d1c9Sdrahn       asymbol *const g = generic[count];
9572159047fSniklas 
958c074d1c9Sdrahn       const char *src = g->name;
9592159047fSniklas       char *dst = symbol.name;
9602159047fSniklas       unsigned int l = 0;
9612159047fSniklas 
9622159047fSniklas       if (bfd_is_com_section (g->section))
9632159047fSniklas 	{
9642159047fSniklas 	  symbol.relb = RELOCATION_TYPE_COM;
965c074d1c9Sdrahn 	  H_PUT_16 (abfd, index, symbol.refno);
9662159047fSniklas 	  index++;
9672159047fSniklas 	}
9682159047fSniklas       else if (bfd_is_abs_section (g->section))
9692159047fSniklas 	{
9702159047fSniklas 	  symbol.relb = RELOCATION_TYPE_ABS;
971c074d1c9Sdrahn 	  H_PUT_16 (abfd, 0, symbol.refno);
9722159047fSniklas 
9732159047fSniklas 	}
9742159047fSniklas       else if (bfd_is_und_section (g->section))
9752159047fSniklas 	{
9762159047fSniklas 	  symbol.relb = RELOCATION_TYPE_UND;
977c074d1c9Sdrahn 	  H_PUT_16 (abfd, index, symbol.refno);
9782159047fSniklas 	  /* Overload the value field with the output index number */
9792159047fSniklas 	  index++;
9802159047fSniklas 	}
9812159047fSniklas       else if (g->flags & BSF_DEBUGGING)
9822159047fSniklas 	{
9832159047fSniklas 	  /* throw it away */
9842159047fSniklas 	  continue;
9852159047fSniklas 	}
9862159047fSniklas       else
9872159047fSniklas 	{
9882159047fSniklas 	  if (g->section == (asection *) NULL)
9892159047fSniklas 	    {
9902159047fSniklas 	      /* Sometime, the oasys tools give out a symbol with illegal
9912159047fSniklas 	   bits in it, we'll output it in the same broken way */
9922159047fSniklas 
9932159047fSniklas 	      symbol.relb = RELOCATION_TYPE_REL | 0;
9942159047fSniklas 	    }
9952159047fSniklas 	  else
9962159047fSniklas 	    {
9972159047fSniklas 	      symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
9982159047fSniklas 	    }
999c074d1c9Sdrahn 	  H_PUT_16 (abfd, 0, symbol.refno);
10002159047fSniklas 	}
10012159047fSniklas #ifdef UNDERSCORE_HACK
10022159047fSniklas       if (src[l] == '_')
10032159047fSniklas 	dst[l++] = '.';
10042159047fSniklas #endif
10052159047fSniklas       while (src[l])
10062159047fSniklas 	{
10072159047fSniklas 	  dst[l] = src[l];
10082159047fSniklas 	  l++;
10092159047fSniklas 	}
10102159047fSniklas 
1011c074d1c9Sdrahn       H_PUT_32 (abfd, g->value, symbol.value);
10122159047fSniklas 
10132159047fSniklas 
10142159047fSniklas       if (g->flags & BSF_LOCAL)
10152159047fSniklas 	{
10162159047fSniklas 	  if (! oasys_write_record (abfd,
10172159047fSniklas 				    oasys_record_is_local_enum,
10182159047fSniklas 				    (oasys_record_union_type *) & symbol,
10192159047fSniklas 				    offsetof (oasys_symbol_record_type,
10202159047fSniklas 					      name[0]) + l))
1021c074d1c9Sdrahn 	    return FALSE;
10222159047fSniklas 	}
10232159047fSniklas       else
10242159047fSniklas 	{
10252159047fSniklas 	  if (! oasys_write_record (abfd,
10262159047fSniklas 				    oasys_record_is_symbol_enum,
10272159047fSniklas 				    (oasys_record_union_type *) & symbol,
10282159047fSniklas 				    offsetof (oasys_symbol_record_type,
10292159047fSniklas 					      name[0]) + l))
1030c074d1c9Sdrahn 	    return FALSE;
10312159047fSniklas 	}
10322159047fSniklas       g->value = index - 1;
10332159047fSniklas     }
10342159047fSniklas 
1035c074d1c9Sdrahn   return TRUE;
10362159047fSniklas }
10372159047fSniklas 
10382159047fSniklas 
10392159047fSniklas  /* Write a section header for each section */
1040c074d1c9Sdrahn static bfd_boolean
oasys_write_sections(abfd)10412159047fSniklas oasys_write_sections (abfd)
10422159047fSniklas      bfd *abfd;
10432159047fSniklas {
10442159047fSniklas   asection *s;
10452159047fSniklas   static oasys_section_record_type out;
10462159047fSniklas 
10472159047fSniklas   for (s = abfd->sections; s != (asection *) NULL; s = s->next)
10482159047fSniklas     {
1049c074d1c9Sdrahn       if (!ISDIGIT (s->name[0]))
10502159047fSniklas 	{
10512159047fSniklas 	  (*_bfd_error_handler)
1052b305b0f1Sespie 	    (_("%s: can not represent section `%s' in oasys"),
10532159047fSniklas 	     bfd_get_filename (abfd), s->name);
10542159047fSniklas 	  bfd_set_error (bfd_error_nonrepresentable_section);
1055c074d1c9Sdrahn 	  return FALSE;
10562159047fSniklas 	}
10572159047fSniklas       out.relb = RELOCATION_TYPE_REL | s->target_index;
1058c074d1c9Sdrahn       H_PUT_32 (abfd, s->_cooked_size, out.value);
1059c074d1c9Sdrahn       H_PUT_32 (abfd, s->vma, out.vma);
10602159047fSniklas 
10612159047fSniklas       if (! oasys_write_record (abfd,
10622159047fSniklas 				oasys_record_is_section_enum,
10632159047fSniklas 				(oasys_record_union_type *) & out,
10642159047fSniklas 				sizeof (out)))
1065c074d1c9Sdrahn 	return FALSE;
10662159047fSniklas     }
1067c074d1c9Sdrahn   return TRUE;
10682159047fSniklas }
10692159047fSniklas 
1070c074d1c9Sdrahn static bfd_boolean
oasys_write_header(abfd)10712159047fSniklas oasys_write_header (abfd)
10722159047fSniklas      bfd *abfd;
10732159047fSniklas {
10742159047fSniklas   /* Create and write the header */
10752159047fSniklas   oasys_header_record_type r;
10762159047fSniklas   size_t length = strlen (abfd->filename);
10772159047fSniklas   if (length > (size_t) sizeof (r.module_name))
10782159047fSniklas     {
10792159047fSniklas       length = sizeof (r.module_name);
10802159047fSniklas     }
10812159047fSniklas 
10822159047fSniklas   (void) memcpy (r.module_name,
10832159047fSniklas 		 abfd->filename,
10842159047fSniklas 		 length);
10852159047fSniklas   (void) memset (r.module_name + length,
10862159047fSniklas 		 ' ',
10872159047fSniklas 		 sizeof (r.module_name) - length);
10882159047fSniklas 
10892159047fSniklas   r.version_number = OASYS_VERSION_NUMBER;
10902159047fSniklas   r.rev_number = OASYS_REV_NUMBER;
10912159047fSniklas   if (! oasys_write_record (abfd,
10922159047fSniklas 			    oasys_record_is_header_enum,
10932159047fSniklas 			    (oasys_record_union_type *) & r,
10942159047fSniklas 			    offsetof (oasys_header_record_type,
10952159047fSniklas 				      description[0])))
1096c074d1c9Sdrahn     return FALSE;
10972159047fSniklas 
1098c074d1c9Sdrahn   return TRUE;
10992159047fSniklas }
11002159047fSniklas 
1101c074d1c9Sdrahn static bfd_boolean
oasys_write_end(abfd)11022159047fSniklas oasys_write_end (abfd)
11032159047fSniklas      bfd *abfd;
11042159047fSniklas {
11052159047fSniklas   oasys_end_record_type end;
11062159047fSniklas   unsigned char null = 0;
11072159047fSniklas   end.relb = RELOCATION_TYPE_ABS;
1108c074d1c9Sdrahn   H_PUT_32 (abfd, abfd->start_address, end.entry);
1109c074d1c9Sdrahn   H_PUT_16 (abfd, 0, end.fill);
11102159047fSniklas   end.zero = 0;
11112159047fSniklas   if (! oasys_write_record (abfd,
11122159047fSniklas 			    oasys_record_is_end_enum,
11132159047fSniklas 			    (oasys_record_union_type *) & end,
11142159047fSniklas 			    sizeof (end)))
1115c074d1c9Sdrahn     return FALSE;
1116c074d1c9Sdrahn   if (bfd_bwrite ((PTR) &null, (bfd_size_type) 1, abfd) != 1)
1117c074d1c9Sdrahn     return FALSE;
1118c074d1c9Sdrahn   return TRUE;
11192159047fSniklas }
11202159047fSniklas 
11212159047fSniklas static int
comp(ap,bp)11222159047fSniklas comp (ap, bp)
1123c074d1c9Sdrahn      const PTR ap;
1124c074d1c9Sdrahn      const PTR bp;
11252159047fSniklas {
11262159047fSniklas   arelent *a = *((arelent **) ap);
11272159047fSniklas   arelent *b = *((arelent **) bp);
11282159047fSniklas   return a->address - b->address;
11292159047fSniklas }
11302159047fSniklas 
11312159047fSniklas /*
11322159047fSniklas  Writing data..
11332159047fSniklas 
11342159047fSniklas */
1135c074d1c9Sdrahn static bfd_boolean
oasys_write_data(abfd)11362159047fSniklas oasys_write_data (abfd)
11372159047fSniklas      bfd *abfd;
11382159047fSniklas {
11392159047fSniklas   asection *s;
11402159047fSniklas   for (s = abfd->sections; s != (asection *) NULL; s = s->next)
11412159047fSniklas     {
11422159047fSniklas       if (s->flags & SEC_LOAD)
11432159047fSniklas 	{
11442159047fSniklas 	  bfd_byte *raw_data = oasys_per_section (s)->data;
11452159047fSniklas 	  oasys_data_record_type processed_data;
11462159047fSniklas 	  bfd_size_type current_byte_index = 0;
11472159047fSniklas 	  unsigned int relocs_to_go = s->reloc_count;
11482159047fSniklas 	  arelent **p = s->orelocation;
11492159047fSniklas 	  if (s->reloc_count != 0)
11502159047fSniklas 	    {
11512159047fSniklas /* Sort the reloc records so it's easy to insert the relocs into the
11522159047fSniklas 	   data */
11532159047fSniklas 
11542159047fSniklas 	      qsort (s->orelocation,
11552159047fSniklas 		     s->reloc_count,
11562159047fSniklas 		     sizeof (arelent **),
11572159047fSniklas 		     comp);
11582159047fSniklas 	    }
11592159047fSniklas 	  current_byte_index = 0;
11602159047fSniklas 	  processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
11612159047fSniklas 
11622159047fSniklas 	  while (current_byte_index < s->_cooked_size)
11632159047fSniklas 	    {
11642159047fSniklas 	      /* Scan forwards by eight bytes or however much is left and see if
11652159047fSniklas 	       there are any relocations going on */
11662159047fSniklas 	      bfd_byte *mod = &processed_data.data[0];
11672159047fSniklas 	      bfd_byte *dst = &processed_data.data[1];
11682159047fSniklas 
11692159047fSniklas 	      unsigned int i = 0;
11702159047fSniklas 	      *mod = 0;
11712159047fSniklas 
11722159047fSniklas 
1173c074d1c9Sdrahn 	      H_PUT_32 (abfd, s->vma + current_byte_index,
11742159047fSniklas 			processed_data.addr);
11752159047fSniklas 
11762159047fSniklas 	      /* Don't start a relocation unless you're sure you can finish it
11772159047fSniklas  	       within the same data record.  The worst case relocation is a
11782159047fSniklas  	       4-byte relocatable value which is split across two modification
11792159047fSniklas  	       bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
11802159047fSniklas  	       1 modification byte + 2 data = 8 bytes total).  That's where
11812159047fSniklas  	       the magic number 8 comes from.
11822159047fSniklas  	    */
11832159047fSniklas 	      while (current_byte_index < s->_raw_size && dst <=
11842159047fSniklas 		     &processed_data.data[sizeof (processed_data.data) - 8])
11852159047fSniklas 		{
11862159047fSniklas 
11872159047fSniklas 
11882159047fSniklas 		  if (relocs_to_go != 0)
11892159047fSniklas 		    {
11902159047fSniklas 		      arelent *r = *p;
11912159047fSniklas 		      reloc_howto_type *const how = r->howto;
11922159047fSniklas 		      /* There is a relocation, is it for this byte ? */
11932159047fSniklas 		      if (r->address == current_byte_index)
11942159047fSniklas 			{
11952159047fSniklas 			  unsigned char rel_byte;
11962159047fSniklas 
11972159047fSniklas 			  p++;
11982159047fSniklas 			  relocs_to_go--;
11992159047fSniklas 
12002159047fSniklas 			  *mod |= (1 << i);
12012159047fSniklas 			  if (how->pc_relative)
12022159047fSniklas 			    {
12032159047fSniklas 			      rel_byte = RELOCATION_PCREL_BIT;
12042159047fSniklas 
12052159047fSniklas 			      /* Also patch the raw data so that it doesn't have
12062159047fSniklas 			 the -ve stuff any more */
12072159047fSniklas 			      if (how->size != 2)
12082159047fSniklas 				{
12092159047fSniklas 				  bfd_put_16 (abfd,
12102159047fSniklas 					      bfd_get_16 (abfd, raw_data) +
12112159047fSniklas 					      current_byte_index, raw_data);
12122159047fSniklas 				}
12132159047fSniklas 
12142159047fSniklas 			      else
12152159047fSniklas 				{
12162159047fSniklas 				  bfd_put_32 (abfd,
12172159047fSniklas 					      bfd_get_32 (abfd, raw_data) +
12182159047fSniklas 					      current_byte_index, raw_data);
12192159047fSniklas 				}
12202159047fSniklas 			    }
12212159047fSniklas 			  else
12222159047fSniklas 			    {
12232159047fSniklas 			      rel_byte = 0;
12242159047fSniklas 			    }
12252159047fSniklas 			  if (how->size == 2)
12262159047fSniklas 			    {
12272159047fSniklas 			      rel_byte |= RELOCATION_32BIT_BIT;
12282159047fSniklas 			    }
12292159047fSniklas 
12302159047fSniklas 			  /* Is this a section relative relocation, or a symbol
12312159047fSniklas 		       relative relocation ? */
12322159047fSniklas 			  abort ();
12332159047fSniklas 
12342159047fSniklas #if 0
12352159047fSniklas 			  if (r->section != (asection *) NULL)
12362159047fSniklas 			    {
12372159047fSniklas 			      /* The relent has a section attached, so it must be section
12382159047fSniklas 			     relative */
12392159047fSniklas 			      rel_byte |= RELOCATION_TYPE_REL;
12402159047fSniklas 			      rel_byte |= r->section->output_section->target_index;
12412159047fSniklas 			      *dst++ = rel_byte;
12422159047fSniklas 			    }
12432159047fSniklas 			  else
12442159047fSniklas #endif
12452159047fSniklas 			    {
1246c074d1c9Sdrahn 			      asymbol *sym = *(r->sym_ptr_ptr);
12472159047fSniklas 
12482159047fSniklas 			      /* If this symbol has a section attached, then it
12492159047fSniklas 			     has already been resolved.  Change from a symbol
12502159047fSniklas 			     ref to a section ref */
1251c074d1c9Sdrahn 			      if (sym->section != (asection *) NULL)
12522159047fSniklas 				{
12532159047fSniklas 				  rel_byte |= RELOCATION_TYPE_REL;
12542159047fSniklas 				  rel_byte |=
1255c074d1c9Sdrahn 				    sym->section->output_section->target_index;
12562159047fSniklas 				  *dst++ = rel_byte;
12572159047fSniklas 				}
12582159047fSniklas 			      else
12592159047fSniklas 				{
12602159047fSniklas 				  rel_byte |= RELOCATION_TYPE_UND;
12612159047fSniklas 				  *dst++ = rel_byte;
12622159047fSniklas 				  /* Next two bytes are a symbol index - we can get
12632159047fSniklas 			       this from the symbol value which has been zapped
12642159047fSniklas 			       into the symbol index in the table when the
12652159047fSniklas 			       symbol table was written
12662159047fSniklas 			       */
1267c074d1c9Sdrahn 				  *dst++ = sym->value >> 8;
1268c074d1c9Sdrahn 				  *dst++ = sym->value;
12692159047fSniklas 				}
12702159047fSniklas 			    }
12712159047fSniklas #define ADVANCE { if (++i >= 8) { i = 0; mod = dst++; *mod = 0; } current_byte_index++; }
12722159047fSniklas 			  /* relocations never occur from an unloadable section,
12732159047fSniklas 		       so we can assume that raw_data is not NULL
12742159047fSniklas 		     */
12752159047fSniklas 			  *dst++ = *raw_data++;
12762159047fSniklas 			  ADVANCE
12772159047fSniklas 			    * dst++ = *raw_data++;
12782159047fSniklas 			  ADVANCE
12792159047fSniklas 			    if (how->size == 2)
12802159047fSniklas 			    {
12812159047fSniklas 			      *dst++ = *raw_data++;
12822159047fSniklas 			      ADVANCE
12832159047fSniklas 				* dst++ = *raw_data++;
12842159047fSniklas 			      ADVANCE
12852159047fSniklas 			    }
12862159047fSniklas 			  continue;
12872159047fSniklas 			}
12882159047fSniklas 		    }
12892159047fSniklas 		  /* If this is coming from an unloadable section then copy
12902159047fSniklas 		   zeros */
12912159047fSniklas 		  if (raw_data == NULL)
12922159047fSniklas 		    {
12932159047fSniklas 		      *dst++ = 0;
12942159047fSniklas 		    }
12952159047fSniklas 		  else
12962159047fSniklas 		    {
12972159047fSniklas 		      *dst++ = *raw_data++;
12982159047fSniklas 		    }
12992159047fSniklas 		  ADVANCE
13002159047fSniklas 		}
13012159047fSniklas 
13022159047fSniklas 	      /* Don't write a useless null modification byte */
13032159047fSniklas 	      if (dst == mod + 1)
13042159047fSniklas 		{
13052159047fSniklas 		  --dst;
13062159047fSniklas 		}
13072159047fSniklas 
1308c074d1c9Sdrahn 	      if (! (oasys_write_record
1309c074d1c9Sdrahn 		     (abfd, oasys_record_is_data_enum,
1310c074d1c9Sdrahn 		      ((oasys_record_union_type *) &processed_data),
1311c074d1c9Sdrahn 		      (size_t) (dst - (bfd_byte *) &processed_data))))
1312c074d1c9Sdrahn 		return FALSE;
13132159047fSniklas 	    }
13142159047fSniklas 	}
13152159047fSniklas     }
13162159047fSniklas 
1317c074d1c9Sdrahn   return TRUE;
13182159047fSniklas }
13192159047fSniklas 
1320c074d1c9Sdrahn static bfd_boolean
oasys_write_object_contents(abfd)13212159047fSniklas oasys_write_object_contents (abfd)
13222159047fSniklas      bfd *abfd;
13232159047fSniklas {
13242159047fSniklas   if (! oasys_write_header (abfd))
1325c074d1c9Sdrahn     return FALSE;
13262159047fSniklas   if (! oasys_write_syms (abfd))
1327c074d1c9Sdrahn     return FALSE;
13282159047fSniklas   if (! oasys_write_sections (abfd))
1329c074d1c9Sdrahn     return FALSE;
13302159047fSniklas   if (! oasys_write_data (abfd))
1331c074d1c9Sdrahn     return FALSE;
13322159047fSniklas   if (! oasys_write_end (abfd))
1333c074d1c9Sdrahn     return FALSE;
1334c074d1c9Sdrahn   return TRUE;
13352159047fSniklas }
13362159047fSniklas 
13372159047fSniklas 
13382159047fSniklas 
13392159047fSniklas 
13402159047fSniklas /** exec and core file sections */
13412159047fSniklas 
13422159047fSniklas /* set section contents is complicated with OASYS since the format is
13432159047fSniklas * not a byte image, but a record stream.
13442159047fSniklas */
1345c074d1c9Sdrahn static bfd_boolean
oasys_set_section_contents(abfd,section,location,offset,count)13462159047fSniklas oasys_set_section_contents (abfd, section, location, offset, count)
13472159047fSniklas      bfd *abfd;
13482159047fSniklas      sec_ptr section;
1349*007c2a45Smiod      const PTR location;
13502159047fSniklas      file_ptr offset;
13512159047fSniklas      bfd_size_type count;
13522159047fSniklas {
13532159047fSniklas   if (count != 0)
13542159047fSniklas     {
13552159047fSniklas       if (oasys_per_section (section)->data == (bfd_byte *) NULL)
13562159047fSniklas 	{
13572159047fSniklas 	  oasys_per_section (section)->data =
13582159047fSniklas 	    (bfd_byte *) (bfd_alloc (abfd, section->_cooked_size));
13592159047fSniklas 	  if (!oasys_per_section (section)->data)
1360c074d1c9Sdrahn 	    return FALSE;
13612159047fSniklas 	}
13622159047fSniklas       (void) memcpy ((PTR) (oasys_per_section (section)->data + offset),
13632159047fSniklas 		     location,
13642159047fSniklas 		     (size_t) count);
13652159047fSniklas     }
1366c074d1c9Sdrahn   return TRUE;
13672159047fSniklas }
13682159047fSniklas 
13692159047fSniklas 
13702159047fSniklas 
13712159047fSniklas /* Native-level interface to symbols. */
13722159047fSniklas 
13732159047fSniklas /* We read the symbols into a buffer, which is discarded when this
13742159047fSniklas function exits.  We read the strings into a buffer large enough to
13752159047fSniklas hold them all plus all the cached symbol entries. */
13762159047fSniklas 
13772159047fSniklas static asymbol *
oasys_make_empty_symbol(abfd)13782159047fSniklas oasys_make_empty_symbol (abfd)
13792159047fSniklas      bfd *abfd;
13802159047fSniklas {
1381c074d1c9Sdrahn   bfd_size_type amt = sizeof (oasys_symbol_type);
1382c074d1c9Sdrahn   oasys_symbol_type *new = (oasys_symbol_type *) bfd_zalloc (abfd, amt);
13832159047fSniklas   if (!new)
13842159047fSniklas     return NULL;
13852159047fSniklas   new->symbol.the_bfd = abfd;
13862159047fSniklas   return &new->symbol;
13872159047fSniklas }
13882159047fSniklas 
13892159047fSniklas 
13902159047fSniklas 
13912159047fSniklas 
13922159047fSniklas /* User should have checked the file flags; perhaps we should return
13932159047fSniklas BFD_NO_MORE_SYMBOLS if there are none? */
13942159047fSniklas 
13952159047fSniklas static bfd *
oasys_openr_next_archived_file(arch,prev)13962159047fSniklas oasys_openr_next_archived_file (arch, prev)
13972159047fSniklas      bfd *arch;
13982159047fSniklas      bfd *prev;
13992159047fSniklas {
14002159047fSniklas   oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
14012159047fSniklas   oasys_module_info_type *p;
14022159047fSniklas   /* take the next one from the arch state, or reset */
14032159047fSniklas   if (prev == (bfd *) NULL)
14042159047fSniklas     {
14052159047fSniklas       /* Reset the index - the first two entries are bogus*/
14062159047fSniklas       ar->module_index = 0;
14072159047fSniklas     }
14082159047fSniklas 
14092159047fSniklas   p = ar->module + ar->module_index;
14102159047fSniklas   ar->module_index++;
14112159047fSniklas 
14122159047fSniklas   if (ar->module_index <= ar->module_count)
14132159047fSniklas     {
14142159047fSniklas       if (p->abfd == (bfd *) NULL)
14152159047fSniklas 	{
14162159047fSniklas 	  p->abfd = _bfd_create_empty_archive_element_shell (arch);
14172159047fSniklas 	  p->abfd->origin = p->pos;
14182159047fSniklas 	  p->abfd->filename = p->name;
14192159047fSniklas 
14202159047fSniklas 	  /* Fixup a pointer to this element for the member */
14212159047fSniklas 	  p->abfd->arelt_data = (PTR) p;
14222159047fSniklas 	}
14232159047fSniklas       return p->abfd;
14242159047fSniklas     }
14252159047fSniklas   else
14262159047fSniklas     {
14272159047fSniklas       bfd_set_error (bfd_error_no_more_archived_files);
14282159047fSniklas       return (bfd *) NULL;
14292159047fSniklas     }
14302159047fSniklas }
14312159047fSniklas 
1432c074d1c9Sdrahn static bfd_boolean
oasys_find_nearest_line(abfd,section,symbols,offset,filename_ptr,functionname_ptr,line_ptr)1433c074d1c9Sdrahn oasys_find_nearest_line (abfd, section, symbols, offset,
1434c074d1c9Sdrahn 			 filename_ptr, functionname_ptr, line_ptr)
1435b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
1436b305b0f1Sespie      asection *section ATTRIBUTE_UNUSED;
1437b305b0f1Sespie      asymbol **symbols ATTRIBUTE_UNUSED;
1438b305b0f1Sespie      bfd_vma offset ATTRIBUTE_UNUSED;
1439c074d1c9Sdrahn      const char **filename_ptr ATTRIBUTE_UNUSED;
1440c074d1c9Sdrahn      const char **functionname_ptr ATTRIBUTE_UNUSED;
1441b305b0f1Sespie      unsigned int *line_ptr ATTRIBUTE_UNUSED;
14422159047fSniklas {
1443c074d1c9Sdrahn   return FALSE;
14442159047fSniklas 
14452159047fSniklas }
14462159047fSniklas 
14472159047fSniklas static int
oasys_generic_stat_arch_elt(abfd,buf)14482159047fSniklas oasys_generic_stat_arch_elt (abfd, buf)
14492159047fSniklas      bfd *abfd;
14502159047fSniklas      struct stat *buf;
14512159047fSniklas {
14522159047fSniklas   oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
14532159047fSniklas   if (mod == (oasys_module_info_type *) NULL)
14542159047fSniklas     {
14552159047fSniklas       bfd_set_error (bfd_error_invalid_operation);
14562159047fSniklas       return -1;
14572159047fSniklas     }
14582159047fSniklas   else
14592159047fSniklas     {
14602159047fSniklas       buf->st_size = mod->size;
14612159047fSniklas       buf->st_mode = 0666;
14622159047fSniklas       return 0;
14632159047fSniklas     }
14642159047fSniklas }
14652159047fSniklas 
14662159047fSniklas static int
oasys_sizeof_headers(abfd,exec)14672159047fSniklas oasys_sizeof_headers (abfd, exec)
1468b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
1469c074d1c9Sdrahn      bfd_boolean exec ATTRIBUTE_UNUSED;
14702159047fSniklas {
14712159047fSniklas   return 0;
14722159047fSniklas }
14732159047fSniklas 
14742159047fSniklas #define	oasys_close_and_cleanup _bfd_generic_close_and_cleanup
14752159047fSniklas #define oasys_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
14762159047fSniklas 
14772159047fSniklas #define oasys_slurp_armap bfd_true
14782159047fSniklas #define oasys_slurp_extended_name_table bfd_true
14792159047fSniklas #define oasys_construct_extended_name_table \
1480c074d1c9Sdrahn   ((bfd_boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
14812159047fSniklas    bfd_true)
14822159047fSniklas #define oasys_truncate_arname bfd_dont_truncate_arname
14832159047fSniklas #define oasys_write_armap \
1484c074d1c9Sdrahn   ((bfd_boolean (*) \
14852159047fSniklas     PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \
14862159047fSniklas    bfd_true)
14872159047fSniklas #define oasys_read_ar_hdr bfd_nullvoidptr
1488c88b1d6cSniklas #define oasys_get_elt_at_index _bfd_generic_get_elt_at_index
14892159047fSniklas #define oasys_update_armap_timestamp bfd_true
14902159047fSniklas 
1491b305b0f1Sespie #define oasys_bfd_is_local_label_name bfd_generic_is_local_label_name
14922159047fSniklas #define oasys_get_lineno _bfd_nosymbols_get_lineno
14932159047fSniklas #define oasys_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
14942159047fSniklas #define oasys_read_minisymbols _bfd_generic_read_minisymbols
14952159047fSniklas #define oasys_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
14962159047fSniklas 
14972159047fSniklas #define oasys_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
14982159047fSniklas 
14992159047fSniklas #define oasys_set_arch_mach bfd_default_set_arch_mach
15002159047fSniklas 
15012159047fSniklas #define oasys_get_section_contents_in_window \
15022159047fSniklas   _bfd_generic_get_section_contents_in_window
15032159047fSniklas 
15042159047fSniklas #define oasys_bfd_get_relocated_section_contents \
15052159047fSniklas   bfd_generic_get_relocated_section_contents
15062159047fSniklas #define oasys_bfd_relax_section bfd_generic_relax_section
1507b305b0f1Sespie #define oasys_bfd_gc_sections bfd_generic_gc_sections
1508c074d1c9Sdrahn #define oasys_bfd_merge_sections bfd_generic_merge_sections
1509c074d1c9Sdrahn #define oasys_bfd_discard_group bfd_generic_discard_group
15102159047fSniklas #define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1511c074d1c9Sdrahn #define oasys_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
15122159047fSniklas #define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
1513c074d1c9Sdrahn #define oasys_bfd_link_just_syms _bfd_generic_link_just_syms
15142159047fSniklas #define oasys_bfd_final_link _bfd_generic_final_link
15152159047fSniklas #define oasys_bfd_link_split_section _bfd_generic_link_split_section
15162159047fSniklas 
15172159047fSniklas /*SUPPRESS 460 */
15182159047fSniklas const bfd_target oasys_vec =
15192159047fSniklas {
15202159047fSniklas   "oasys",			/* name */
15212159047fSniklas   bfd_target_oasys_flavour,
1522c88b1d6cSniklas   BFD_ENDIAN_BIG,		/* target byte order */
1523c88b1d6cSniklas   BFD_ENDIAN_BIG,		/* target headers byte order */
15242159047fSniklas   (HAS_RELOC | EXEC_P |		/* object flags */
15252159047fSniklas    HAS_LINENO | HAS_DEBUG |
15262159047fSniklas    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
15272159047fSniklas   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
15282159047fSniklas    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* section flags */
15292159047fSniklas   0,				/* leading underscore */
15302159047fSniklas   ' ',				/* ar_pad_char */
15312159047fSniklas   16,				/* ar_max_namelen */
15322159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
15332159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
15342159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
15352159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
15362159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
15372159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
15382159047fSniklas 
15392159047fSniklas   {_bfd_dummy_target,
15402159047fSniklas    oasys_object_p,		/* bfd_check_format */
15412159047fSniklas    oasys_archive_p,
15422159047fSniklas    _bfd_dummy_target,
15432159047fSniklas   },
15442159047fSniklas   {				/* bfd_set_format */
15452159047fSniklas     bfd_false,
15462159047fSniklas     oasys_mkobject,
15472159047fSniklas     _bfd_generic_mkarchive,
15482159047fSniklas     bfd_false
15492159047fSniklas   },
15502159047fSniklas   {				/* bfd_write_contents */
15512159047fSniklas     bfd_false,
15522159047fSniklas     oasys_write_object_contents,
15532159047fSniklas     _bfd_write_archive_contents,
15542159047fSniklas     bfd_false,
15552159047fSniklas   },
15562159047fSniklas 
15572159047fSniklas   BFD_JUMP_TABLE_GENERIC (oasys),
15582159047fSniklas   BFD_JUMP_TABLE_COPY (_bfd_generic),
15592159047fSniklas   BFD_JUMP_TABLE_CORE (_bfd_nocore),
15602159047fSniklas   BFD_JUMP_TABLE_ARCHIVE (oasys),
15612159047fSniklas   BFD_JUMP_TABLE_SYMBOLS (oasys),
15622159047fSniklas   BFD_JUMP_TABLE_RELOCS (oasys),
15632159047fSniklas   BFD_JUMP_TABLE_WRITE (oasys),
15642159047fSniklas   BFD_JUMP_TABLE_LINK (oasys),
15652159047fSniklas   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
15662159047fSniklas 
1567b305b0f1Sespie   NULL,
1568b305b0f1Sespie 
15692159047fSniklas   (PTR) 0
15702159047fSniklas };
1571