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