1/* BFD back-end for oasys objects.
2   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001,
3   2002, 2003, 2004, 2005, 2006 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  if (!newsect->used_by_bfd)
689    {
690      newsect->used_by_bfd
691	= bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
692      if (!newsect->used_by_bfd)
693	return FALSE;
694    }
695  oasys_per_section (newsect)->data = NULL;
696  oasys_per_section (newsect)->section = newsect;
697  oasys_per_section (newsect)->offset = 0;
698  oasys_per_section (newsect)->initialized = FALSE;
699  newsect->alignment_power = 1;
700
701  /* Turn the section string into an index.  */
702  sscanf (newsect->name, "%u", &newsect->target_index);
703
704  return _bfd_generic_new_section_hook (abfd, newsect);
705}
706
707
708static long
709oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
710{
711  if (! oasys_slurp_section_data (abfd))
712    return -1;
713  return (asect->reloc_count + 1) * sizeof (arelent *);
714}
715
716static bfd_boolean
717oasys_get_section_contents (bfd *abfd,
718			    sec_ptr section,
719			    void * location,
720			    file_ptr offset,
721			    bfd_size_type count)
722{
723  oasys_per_section_type *p = oasys_per_section (section);
724
725  oasys_slurp_section_data (abfd);
726
727  if (! p->initialized)
728    (void) memset (location, 0, (size_t) count);
729  else
730    (void) memcpy (location, (void *) (p->data + offset), (size_t) count);
731
732  return TRUE;
733}
734
735static long
736oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
737			  sec_ptr section,
738			  arelent **relptr,
739			  asymbol **symbols ATTRIBUTE_UNUSED)
740{
741  unsigned int reloc_count = 0;
742  oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
743
744  if (src != NULL)
745    abort ();
746
747  *relptr = NULL;
748  return section->reloc_count = reloc_count;
749}
750
751
752/* Writing.  */
753
754/* Calculate the checksum and write one record.  */
755
756static bfd_boolean
757oasys_write_record (bfd *abfd,
758		    oasys_record_enum_type type,
759		    oasys_record_union_type *record,
760		    size_t size)
761{
762  int checksum;
763  size_t i;
764  unsigned char *ptr;
765
766  record->header.length = size;
767  record->header.type = (int) type;
768  record->header.check_sum = 0;
769  record->header.fill = 0;
770  ptr = (unsigned char *) &record->pad[0];
771  checksum = 0;
772  for (i = 0; i < size; i++)
773    checksum += *ptr++;
774  record->header.check_sum = 0xff & (-checksum);
775  if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size)
776    return FALSE;
777  return TRUE;
778}
779
780
781/* Write out all the symbols.  */
782
783static bfd_boolean
784oasys_write_syms (bfd *abfd)
785{
786  unsigned int count;
787  asymbol **generic = bfd_get_outsymbols (abfd);
788  unsigned int index = 0;
789
790  for (count = 0; count < bfd_get_symcount (abfd); count++)
791    {
792      oasys_symbol_record_type symbol;
793      asymbol *const g = generic[count];
794      const char *src = g->name;
795      char *dst = symbol.name;
796      unsigned int l = 0;
797
798      if (bfd_is_com_section (g->section))
799	{
800	  symbol.relb = RELOCATION_TYPE_COM;
801	  H_PUT_16 (abfd, index, symbol.refno);
802	  index++;
803	}
804      else if (bfd_is_abs_section (g->section))
805	{
806	  symbol.relb = RELOCATION_TYPE_ABS;
807	  H_PUT_16 (abfd, 0, symbol.refno);
808	}
809      else if (bfd_is_und_section (g->section))
810	{
811	  symbol.relb = RELOCATION_TYPE_UND;
812	  H_PUT_16 (abfd, index, symbol.refno);
813	  /* Overload the value field with the output index number */
814	  index++;
815	}
816      else if (g->flags & BSF_DEBUGGING)
817	/* Throw it away.  */
818	continue;
819      else
820	{
821	  if (g->section == NULL)
822	    /* Sometime, the oasys tools give out a symbol with illegal
823	       bits in it, we'll output it in the same broken way.  */
824	    symbol.relb = RELOCATION_TYPE_REL | 0;
825	  else
826	    symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
827
828	  H_PUT_16 (abfd, 0, symbol.refno);
829	}
830
831#ifdef UNDERSCORE_HACK
832      if (src[l] == '_')
833	dst[l++] = '.';
834#endif
835      while (src[l])
836	{
837	  dst[l] = src[l];
838	  l++;
839	}
840
841      H_PUT_32 (abfd, g->value, symbol.value);
842
843      if (g->flags & BSF_LOCAL)
844	{
845	  if (! oasys_write_record (abfd,
846				    oasys_record_is_local_enum,
847				    (oasys_record_union_type *) & symbol,
848				    offsetof (oasys_symbol_record_type,
849					      name[0]) + l))
850	    return FALSE;
851	}
852      else
853	{
854	  if (! oasys_write_record (abfd,
855				    oasys_record_is_symbol_enum,
856				    (oasys_record_union_type *) & symbol,
857				    offsetof (oasys_symbol_record_type,
858					      name[0]) + l))
859	    return FALSE;
860	}
861      g->value = index - 1;
862    }
863
864  return TRUE;
865}
866
867/* Write a section header for each section.  */
868
869static bfd_boolean
870oasys_write_sections (bfd *abfd)
871{
872  asection *s;
873  static oasys_section_record_type out;
874
875  for (s = abfd->sections; s != NULL; s = s->next)
876    {
877      if (!ISDIGIT (s->name[0]))
878	{
879	  (*_bfd_error_handler)
880	    (_("%s: can not represent section `%s' in oasys"),
881	     bfd_get_filename (abfd), s->name);
882	  bfd_set_error (bfd_error_nonrepresentable_section);
883	  return FALSE;
884	}
885      out.relb = RELOCATION_TYPE_REL | s->target_index;
886      H_PUT_32 (abfd, s->size, out.value);
887      H_PUT_32 (abfd, s->vma, out.vma);
888
889      if (! oasys_write_record (abfd,
890				oasys_record_is_section_enum,
891				(oasys_record_union_type *) & out,
892				sizeof (out)))
893	return FALSE;
894    }
895  return TRUE;
896}
897
898static bfd_boolean
899oasys_write_header (bfd *abfd)
900{
901  /* Create and write the header.  */
902  oasys_header_record_type r;
903  size_t length = strlen (abfd->filename);
904
905  if (length > (size_t) sizeof (r.module_name))
906    length = sizeof (r.module_name);
907
908  (void) memcpy (r.module_name, abfd->filename, length);
909  (void) memset (r.module_name + length, ' ', sizeof (r.module_name) - length);
910
911  r.version_number = OASYS_VERSION_NUMBER;
912  r.rev_number = OASYS_REV_NUMBER;
913
914  return oasys_write_record (abfd, oasys_record_is_header_enum,
915			     (oasys_record_union_type *) & r,
916			     offsetof (oasys_header_record_type,
917				       description[0]));
918}
919
920static bfd_boolean
921oasys_write_end (bfd *abfd)
922{
923  oasys_end_record_type end;
924  unsigned char null = 0;
925
926  end.relb = RELOCATION_TYPE_ABS;
927  H_PUT_32 (abfd, abfd->start_address, end.entry);
928  H_PUT_16 (abfd, 0, end.fill);
929  end.zero = 0;
930  if (! oasys_write_record (abfd,
931			    oasys_record_is_end_enum,
932			    (oasys_record_union_type *) & end,
933			    sizeof (end)))
934    return FALSE;
935
936  return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
937}
938
939static int
940comp (const void * ap, const void * bp)
941{
942  arelent *a = *((arelent **) ap);
943  arelent *b = *((arelent **) bp);
944
945  return a->address - b->address;
946}
947
948static bfd_boolean
949oasys_write_data (bfd *abfd)
950{
951  asection *s;
952
953  for (s = abfd->sections; s != NULL; s = s->next)
954    {
955      if (s->flags & SEC_LOAD)
956	{
957	  bfd_byte *raw_data = oasys_per_section (s)->data;
958	  oasys_data_record_type processed_data;
959	  bfd_size_type current_byte_index = 0;
960	  unsigned int relocs_to_go = s->reloc_count;
961	  arelent **p = s->orelocation;
962
963	  if (s->reloc_count != 0)
964	    /* Sort the reloc records so it's easy to insert the relocs into the
965	       data.  */
966	    qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp);
967
968	  current_byte_index = 0;
969	  processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
970
971	  while (current_byte_index < s->size)
972	    {
973	      /* Scan forwards by eight bytes or however much is left and see if
974	       there are any relocations going on.  */
975	      bfd_byte *mod = &processed_data.data[0];
976	      bfd_byte *dst = &processed_data.data[1];
977
978	      unsigned int i = 0;
979	      *mod = 0;
980
981	      H_PUT_32 (abfd, s->vma + current_byte_index,
982			processed_data.addr);
983
984	      /* Don't start a relocation unless you're sure you can finish it
985		 within the same data record.  The worst case relocation is a
986		 4-byte relocatable value which is split across two modification
987		 bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
988		 1 modification byte + 2 data = 8 bytes total).  That's where
989		 the magic number 8 comes from.  */
990	      while (current_byte_index < s->size && dst <=
991		     & processed_data.data[sizeof (processed_data.data) - 8])
992		{
993		  if (relocs_to_go != 0)
994		    {
995		      arelent *r = *p;
996
997		      /* There is a relocation, is it for this byte ?  */
998		      if (r->address == current_byte_index)
999			abort ();
1000		    }
1001
1002		  /* If this is coming from an unloadable section then copy
1003		     zeros.  */
1004		  if (raw_data == NULL)
1005		    *dst++ = 0;
1006		  else
1007		    *dst++ = *raw_data++;
1008
1009		  if (++i >= 8)
1010		    {
1011		      i = 0;
1012		      mod = dst++;
1013		      *mod = 0;
1014		    }
1015		  current_byte_index++;
1016		}
1017
1018	      /* Don't write a useless null modification byte.  */
1019	      if (dst == mod + 1)
1020		--dst;
1021
1022	      if (! (oasys_write_record
1023		     (abfd, oasys_record_is_data_enum,
1024		      ((oasys_record_union_type *) &processed_data),
1025		      (size_t) (dst - (bfd_byte *) &processed_data))))
1026		return FALSE;
1027	    }
1028	}
1029    }
1030
1031  return TRUE;
1032}
1033
1034static bfd_boolean
1035oasys_write_object_contents (bfd *abfd)
1036{
1037  if (! oasys_write_header (abfd))
1038    return FALSE;
1039  if (! oasys_write_syms (abfd))
1040    return FALSE;
1041  if (! oasys_write_sections (abfd))
1042    return FALSE;
1043  if (! oasys_write_data (abfd))
1044    return FALSE;
1045  if (! oasys_write_end (abfd))
1046    return FALSE;
1047  return TRUE;
1048}
1049
1050/* Set section contents is complicated with OASYS since the format is
1051   not a byte image, but a record stream.  */
1052
1053static bfd_boolean
1054oasys_set_section_contents (bfd *abfd,
1055			    sec_ptr section,
1056			    const void * location,
1057			    file_ptr offset,
1058			    bfd_size_type count)
1059{
1060  if (count != 0)
1061    {
1062      if (oasys_per_section (section)->data == NULL)
1063	{
1064	  oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
1065	  if (!oasys_per_section (section)->data)
1066	    return FALSE;
1067	}
1068      (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
1069		     location, (size_t) count);
1070    }
1071  return TRUE;
1072}
1073
1074
1075
1076/* Native-level interface to symbols.  */
1077
1078/* We read the symbols into a buffer, which is discarded when this
1079   function exits.  We read the strings into a buffer large enough to
1080   hold them all plus all the cached symbol entries.  */
1081
1082static asymbol *
1083oasys_make_empty_symbol (bfd *abfd)
1084{
1085  bfd_size_type amt = sizeof (oasys_symbol_type);
1086  oasys_symbol_type *new = bfd_zalloc (abfd, amt);
1087
1088  if (!new)
1089    return NULL;
1090  new->symbol.the_bfd = abfd;
1091  return &new->symbol;
1092}
1093
1094/* User should have checked the file flags; perhaps we should return
1095   BFD_NO_MORE_SYMBOLS if there are none?  */
1096
1097static bfd *
1098oasys_openr_next_archived_file (bfd *arch, bfd *prev)
1099{
1100  oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1101  oasys_module_info_type *p;
1102
1103  /* Take the next one from the arch state, or reset.  */
1104  if (prev == NULL)
1105    /* Reset the index - the first two entries are bogus.  */
1106    ar->module_index = 0;
1107
1108  p = ar->module + ar->module_index;
1109  ar->module_index++;
1110
1111  if (ar->module_index <= ar->module_count)
1112    {
1113      if (p->abfd == NULL)
1114	{
1115	  p->abfd = _bfd_create_empty_archive_element_shell (arch);
1116	  p->abfd->origin = p->pos;
1117	  p->abfd->filename = p->name;
1118
1119	  /* Fixup a pointer to this element for the member.  */
1120	  p->abfd->arelt_data = (void *) p;
1121	}
1122      return p->abfd;
1123    }
1124
1125  bfd_set_error (bfd_error_no_more_archived_files);
1126  return NULL;
1127}
1128
1129static bfd_boolean
1130oasys_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
1131			 asection *section ATTRIBUTE_UNUSED,
1132			 asymbol **symbols ATTRIBUTE_UNUSED,
1133			 bfd_vma offset ATTRIBUTE_UNUSED,
1134			 const char **filename_ptr ATTRIBUTE_UNUSED,
1135			 const char **functionname_ptr ATTRIBUTE_UNUSED,
1136			 unsigned int *line_ptr ATTRIBUTE_UNUSED)
1137{
1138  return FALSE;
1139}
1140
1141static bfd_boolean
1142oasys_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
1143			 const char **filename_ptr ATTRIBUTE_UNUSED,
1144			 const char **functionname_ptr ATTRIBUTE_UNUSED,
1145			 unsigned int *line_ptr ATTRIBUTE_UNUSED)
1146{
1147  return FALSE;
1148}
1149
1150static int
1151oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
1152{
1153  oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1154
1155  if (mod == NULL)
1156    {
1157      bfd_set_error (bfd_error_invalid_operation);
1158      return -1;
1159    }
1160
1161  buf->st_size = mod->size;
1162  buf->st_mode = 0666;
1163  return 0;
1164}
1165
1166static int
1167oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1168		      struct bfd_link_info *info ATTRIBUTE_UNUSED)
1169{
1170  return 0;
1171}
1172
1173#define	oasys_close_and_cleanup                    _bfd_generic_close_and_cleanup
1174#define oasys_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
1175#define oasys_slurp_armap                          bfd_true
1176#define oasys_slurp_extended_name_table            bfd_true
1177#define oasys_construct_extended_name_table        ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true)
1178#define oasys_truncate_arname                      bfd_dont_truncate_arname
1179#define oasys_write_armap                          ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true)
1180#define oasys_read_ar_hdr                          bfd_nullvoidptr
1181#define oasys_get_elt_at_index                     _bfd_generic_get_elt_at_index
1182#define oasys_update_armap_timestamp               bfd_true
1183#define oasys_bfd_is_local_label_name              bfd_generic_is_local_label_name
1184#define oasys_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1185#define oasys_get_lineno                           _bfd_nosymbols_get_lineno
1186#define oasys_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
1187#define oasys_read_minisymbols                     _bfd_generic_read_minisymbols
1188#define oasys_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
1189#define oasys_bfd_reloc_type_lookup                _bfd_norelocs_bfd_reloc_type_lookup
1190#define oasys_set_arch_mach                        bfd_default_set_arch_mach
1191#define oasys_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
1192#define oasys_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
1193#define oasys_bfd_relax_section                    bfd_generic_relax_section
1194#define oasys_bfd_gc_sections                      bfd_generic_gc_sections
1195#define oasys_bfd_merge_sections                   bfd_generic_merge_sections
1196#define oasys_bfd_is_group_section                 bfd_generic_is_group_section
1197#define oasys_bfd_discard_group                    bfd_generic_discard_group
1198#define oasys_section_already_linked               _bfd_generic_section_already_linked
1199#define oasys_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
1200#define oasys_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
1201#define oasys_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
1202#define oasys_bfd_link_just_syms                   _bfd_generic_link_just_syms
1203#define oasys_bfd_final_link                       _bfd_generic_final_link
1204#define oasys_bfd_link_split_section               _bfd_generic_link_split_section
1205
1206const bfd_target oasys_vec =
1207{
1208  "oasys",			/* Name.  */
1209  bfd_target_oasys_flavour,
1210  BFD_ENDIAN_BIG,		/* Target byte order.  */
1211  BFD_ENDIAN_BIG,		/* Target headers byte order.  */
1212  (HAS_RELOC | EXEC_P |		/* Object flags.  */
1213   HAS_LINENO | HAS_DEBUG |
1214   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1215  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1216   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1217  0,				/* Leading underscore.  */
1218  ' ',				/* AR_pad_char.  */
1219  16,				/* AR_max_namelen.  */
1220  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1221  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1222  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1223  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1224  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1225  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
1226
1227  {_bfd_dummy_target,
1228   oasys_object_p,		/* bfd_check_format.  */
1229   oasys_archive_p,
1230   _bfd_dummy_target,
1231  },
1232  {				/* bfd_set_format.  */
1233    bfd_false,
1234    oasys_mkobject,
1235    _bfd_generic_mkarchive,
1236    bfd_false
1237  },
1238  {				/* bfd_write_contents.  */
1239    bfd_false,
1240    oasys_write_object_contents,
1241    _bfd_write_archive_contents,
1242    bfd_false,
1243  },
1244
1245  BFD_JUMP_TABLE_GENERIC (oasys),
1246  BFD_JUMP_TABLE_COPY (_bfd_generic),
1247  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1248  BFD_JUMP_TABLE_ARCHIVE (oasys),
1249  BFD_JUMP_TABLE_SYMBOLS (oasys),
1250  BFD_JUMP_TABLE_RELOCS (oasys),
1251  BFD_JUMP_TABLE_WRITE (oasys),
1252  BFD_JUMP_TABLE_LINK (oasys),
1253  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1254
1255  NULL,
1256
1257  NULL
1258};
1259