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