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