133965Sjdp/* BFD back-end for ieee-695 objects.
278828Sobrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3218822Sdim   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
433965Sjdp   Free Software Foundation, Inc.
533965Sjdp
633965Sjdp   Written by Steve Chamberlain of Cygnus Support.
733965Sjdp
891041Sobrien   This file is part of BFD, the Binary File Descriptor library.
933965Sjdp
1091041Sobrien   This program is free software; you can redistribute it and/or modify
1191041Sobrien   it under the terms of the GNU General Public License as published by
1291041Sobrien   the Free Software Foundation; either version 2 of the License, or
1391041Sobrien   (at your option) any later version.
1433965Sjdp
1591041Sobrien   This program is distributed in the hope that it will be useful,
1691041Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1791041Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1891041Sobrien   GNU General Public License for more details.
1933965Sjdp
2091041Sobrien   You should have received a copy of the GNU General Public License
2191041Sobrien   along with this program; if not, write to the Free Software
22218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2333965Sjdp
2433965Sjdp#define KEEPMINUSPCININST 0
2533965Sjdp
2633965Sjdp/* IEEE 695 format is a stream of records, which we parse using a simple one-
2733965Sjdp   token (which is one byte in this lexicon) lookahead recursive decent
2833965Sjdp   parser.  */
2933965Sjdp
30218822Sdim#include "sysdep.h"
3133965Sjdp#include "bfd.h"
3233965Sjdp#include "libbfd.h"
3333965Sjdp#include "ieee.h"
3433965Sjdp#include "libieee.h"
3589857Sobrien#include "safe-ctype.h"
3633965Sjdp
3789857Sobrienstruct output_buffer_struct
3889857Sobrien{
3989857Sobrien  unsigned char *ptrp;
4089857Sobrien  int buffer;
4189857Sobrien};
4260484Sobrien
43218822Sdimstatic unsigned char *output_ptr_start;
44218822Sdimstatic unsigned char *output_ptr;
45218822Sdimstatic unsigned char *output_ptr_end;
46218822Sdimstatic unsigned char *input_ptr_start;
47218822Sdimstatic unsigned char *input_ptr;
48218822Sdimstatic unsigned char *input_ptr_end;
49218822Sdimstatic bfd *input_bfd;
50218822Sdimstatic bfd *output_bfd;
51218822Sdimstatic int output_buffer;
5233965Sjdp
53218822Sdim
54218822Sdimstatic void block (void);
55218822Sdim
5633965Sjdp/* Functions for writing to ieee files in the strange way that the
57218822Sdim   standard requires.  */
5833965Sjdp
59130561Sobrienstatic bfd_boolean
60218822Sdimieee_write_byte (bfd *abfd, int barg)
6133965Sjdp{
6233965Sjdp  bfd_byte byte;
6333965Sjdp
6433965Sjdp  byte = barg;
65218822Sdim  if (bfd_bwrite ((void *) &byte, (bfd_size_type) 1, abfd) != 1)
66130561Sobrien    return FALSE;
67130561Sobrien  return TRUE;
6833965Sjdp}
6933965Sjdp
70130561Sobrienstatic bfd_boolean
71218822Sdimieee_write_2bytes (bfd *abfd, int bytes)
7233965Sjdp{
7333965Sjdp  bfd_byte buffer[2];
7433965Sjdp
7533965Sjdp  buffer[0] = bytes >> 8;
7633965Sjdp  buffer[1] = bytes & 0xff;
77218822Sdim  if (bfd_bwrite ((void *) buffer, (bfd_size_type) 2, abfd) != 2)
78130561Sobrien    return FALSE;
79130561Sobrien  return TRUE;
8033965Sjdp}
8133965Sjdp
82130561Sobrienstatic bfd_boolean
83218822Sdimieee_write_int (bfd *abfd, bfd_vma value)
8433965Sjdp{
8533965Sjdp  if (value <= 127)
8633965Sjdp    {
8733965Sjdp      if (! ieee_write_byte (abfd, (bfd_byte) value))
88130561Sobrien	return FALSE;
8933965Sjdp    }
9033965Sjdp  else
9133965Sjdp    {
9233965Sjdp      unsigned int length;
9333965Sjdp
94130561Sobrien      /* How many significant bytes ?  */
95130561Sobrien      /* FIXME FOR LONGER INTS.  */
9633965Sjdp      if (value & 0xff000000)
9733965Sjdp	length = 4;
9833965Sjdp      else if (value & 0x00ff0000)
9933965Sjdp	length = 3;
10033965Sjdp      else if (value & 0x0000ff00)
10133965Sjdp	length = 2;
10233965Sjdp      else
10333965Sjdp	length = 1;
10433965Sjdp
10533965Sjdp      if (! ieee_write_byte (abfd,
10633965Sjdp			     (bfd_byte) ((int) ieee_number_repeat_start_enum
10733965Sjdp					 + length)))
108130561Sobrien	return FALSE;
10933965Sjdp      switch (length)
11033965Sjdp	{
11133965Sjdp	case 4:
11233965Sjdp	  if (! ieee_write_byte (abfd, (bfd_byte) (value >> 24)))
113130561Sobrien	    return FALSE;
11433965Sjdp	  /* Fall through.  */
11533965Sjdp	case 3:
11633965Sjdp	  if (! ieee_write_byte (abfd, (bfd_byte) (value >> 16)))
117130561Sobrien	    return FALSE;
11833965Sjdp	  /* Fall through.  */
11933965Sjdp	case 2:
12033965Sjdp	  if (! ieee_write_byte (abfd, (bfd_byte) (value >> 8)))
121130561Sobrien	    return FALSE;
12233965Sjdp	  /* Fall through.  */
12333965Sjdp	case 1:
12433965Sjdp	  if (! ieee_write_byte (abfd, (bfd_byte) (value)))
125130561Sobrien	    return FALSE;
12633965Sjdp	}
12733965Sjdp    }
12833965Sjdp
129130561Sobrien  return TRUE;
13033965Sjdp}
13133965Sjdp
132130561Sobrienstatic bfd_boolean
133218822Sdimieee_write_id (bfd *abfd, const char *id)
13433965Sjdp{
13533965Sjdp  size_t length = strlen (id);
13633965Sjdp
13733965Sjdp  if (length <= 127)
13833965Sjdp    {
13933965Sjdp      if (! ieee_write_byte (abfd, (bfd_byte) length))
140130561Sobrien	return FALSE;
14133965Sjdp    }
14233965Sjdp  else if (length < 255)
14333965Sjdp    {
14433965Sjdp      if (! ieee_write_byte (abfd, ieee_extension_length_1_enum)
14533965Sjdp	  || ! ieee_write_byte (abfd, (bfd_byte) length))
146130561Sobrien	return FALSE;
14733965Sjdp    }
14833965Sjdp  else if (length < 65535)
14933965Sjdp    {
15033965Sjdp      if (! ieee_write_byte (abfd, ieee_extension_length_2_enum)
15133965Sjdp	  || ! ieee_write_2bytes (abfd, (int) length))
152130561Sobrien	return FALSE;
15333965Sjdp    }
15433965Sjdp  else
15533965Sjdp    {
15633965Sjdp      (*_bfd_error_handler)
15760484Sobrien	(_("%s: string too long (%d chars, max 65535)"),
15833965Sjdp	 bfd_get_filename (abfd), length);
15933965Sjdp      bfd_set_error (bfd_error_invalid_operation);
160130561Sobrien      return FALSE;
16133965Sjdp    }
16233965Sjdp
163218822Sdim  if (bfd_bwrite ((void *) id, (bfd_size_type) length, abfd) != length)
164130561Sobrien    return FALSE;
165130561Sobrien  return TRUE;
16633965Sjdp}
16733965Sjdp
168130561Sobrien/* Functions for reading from ieee files in the strange way that the
169130561Sobrien   standard requires.  */
17033965Sjdp
171218822Sdim#define this_byte(ieee)           *((ieee)->input_p)
172218822Sdim#define next_byte(ieee)            ((ieee)->input_p++)
17333965Sjdp#define this_byte_and_next(ieee) (*((ieee)->input_p++))
17433965Sjdp
17533965Sjdpstatic unsigned short
176218822Sdimread_2bytes (common_header_type *ieee)
17733965Sjdp{
17833965Sjdp  unsigned char c1 = this_byte_and_next (ieee);
17933965Sjdp  unsigned char c2 = this_byte_and_next (ieee);
180130561Sobrien
18133965Sjdp  return (c1 << 8) | c2;
18233965Sjdp}
18333965Sjdp
18433965Sjdpstatic void
185218822Sdimbfd_get_string (common_header_type *ieee, char *string, size_t length)
18633965Sjdp{
18733965Sjdp  size_t i;
188130561Sobrien
18933965Sjdp  for (i = 0; i < length; i++)
190130561Sobrien    string[i] = this_byte_and_next (ieee);
19133965Sjdp}
19233965Sjdp
19333965Sjdpstatic char *
194218822Sdimread_id (common_header_type *ieee)
19533965Sjdp{
19633965Sjdp  size_t length;
19733965Sjdp  char *string;
198130561Sobrien
19933965Sjdp  length = this_byte_and_next (ieee);
20033965Sjdp  if (length <= 0x7f)
201218822Sdim    /* Simple string of length 0 to 127.  */
202218822Sdim    ;
203218822Sdim
20433965Sjdp  else if (length == 0xde)
205218822Sdim    /* Length is next byte, allowing 0..255.  */
206218822Sdim    length = this_byte_and_next (ieee);
207218822Sdim
20833965Sjdp  else if (length == 0xdf)
20933965Sjdp    {
210130561Sobrien      /* Length is next two bytes, allowing 0..65535.  */
21133965Sjdp      length = this_byte_and_next (ieee);
21233965Sjdp      length = (length * 256) + this_byte_and_next (ieee);
21333965Sjdp    }
214130561Sobrien
215130561Sobrien  /* Buy memory and read string.  */
21689857Sobrien  string = bfd_alloc (ieee->abfd, (bfd_size_type) length + 1);
21733965Sjdp  if (!string)
21833965Sjdp    return NULL;
21933965Sjdp  bfd_get_string (ieee, string, length);
22033965Sjdp  string[length] = 0;
22133965Sjdp  return string;
22233965Sjdp}
22333965Sjdp
224130561Sobrienstatic bfd_boolean
225218822Sdimieee_write_expression (bfd *abfd,
226218822Sdim		       bfd_vma value,
227218822Sdim		       asymbol *symbol,
228218822Sdim		       bfd_boolean pcrel,
229218822Sdim		       unsigned int index)
23033965Sjdp{
23133965Sjdp  unsigned int term_count = 0;
23233965Sjdp
23333965Sjdp  if (value != 0)
23433965Sjdp    {
23533965Sjdp      if (! ieee_write_int (abfd, value))
236130561Sobrien	return FALSE;
23733965Sjdp      term_count++;
23833965Sjdp    }
23933965Sjdp
240130561Sobrien  /* Badly formatted binaries can have a missing symbol,
241130561Sobrien     so test here to prevent a seg fault.  */
242130561Sobrien  if (symbol != NULL)
24333965Sjdp    {
244130561Sobrien      if (bfd_is_com_section (symbol->section)
245130561Sobrien	  || bfd_is_und_section (symbol->section))
24633965Sjdp	{
247130561Sobrien	  /* Def of a common symbol.  */
248130561Sobrien	  if (! ieee_write_byte (abfd, ieee_variable_X_enum)
24933965Sjdp	      || ! ieee_write_int (abfd, symbol->value))
250130561Sobrien	    return FALSE;
251130561Sobrien	  term_count ++;
25233965Sjdp	}
253130561Sobrien      else if (! bfd_is_abs_section (symbol->section))
25433965Sjdp	{
255130561Sobrien	  /* Ref to defined symbol -  */
256130561Sobrien	  if (symbol->flags & BSF_GLOBAL)
25733965Sjdp	    {
258130561Sobrien	      if (! ieee_write_byte (abfd, ieee_variable_I_enum)
259130561Sobrien		  || ! ieee_write_int (abfd, symbol->value))
260130561Sobrien		return FALSE;
26133965Sjdp	      term_count++;
26233965Sjdp	    }
263130561Sobrien	  else if (symbol->flags & (BSF_LOCAL | BSF_SECTION_SYM))
264130561Sobrien	    {
265130561Sobrien	      /* This is a reference to a defined local symbol.  We can
266130561Sobrien		 easily do a local as a section+offset.  */
267130561Sobrien	      if (! ieee_write_byte (abfd, ieee_variable_R_enum)
268130561Sobrien		  || ! ieee_write_byte (abfd,
269130561Sobrien					(bfd_byte) (symbol->section->index
270130561Sobrien						    + IEEE_SECTION_NUMBER_BASE)))
271130561Sobrien		return FALSE;
272130561Sobrien
273130561Sobrien	      term_count++;
274130561Sobrien	      if (symbol->value != 0)
275130561Sobrien		{
276130561Sobrien		  if (! ieee_write_int (abfd, symbol->value))
277130561Sobrien		    return FALSE;
278130561Sobrien		  term_count++;
279130561Sobrien		}
280130561Sobrien	    }
281130561Sobrien	  else
282130561Sobrien	    {
283130561Sobrien	      (*_bfd_error_handler)
284130561Sobrien		(_("%s: unrecognized symbol `%s' flags 0x%x"),
285130561Sobrien		 bfd_get_filename (abfd), bfd_asymbol_name (symbol),
286130561Sobrien		 symbol->flags);
287130561Sobrien	      bfd_set_error (bfd_error_invalid_operation);
288130561Sobrien	      return FALSE;
289130561Sobrien	    }
29033965Sjdp	}
29133965Sjdp    }
29233965Sjdp
29333965Sjdp  if (pcrel)
29433965Sjdp    {
295130561Sobrien      /* Subtract the pc from here by asking for PC of this section.  */
29633965Sjdp      if (! ieee_write_byte (abfd, ieee_variable_P_enum)
29733965Sjdp	  || ! ieee_write_byte (abfd,
29833965Sjdp				(bfd_byte) (index + IEEE_SECTION_NUMBER_BASE))
29933965Sjdp	  || ! ieee_write_byte (abfd, ieee_function_minus_enum))
300130561Sobrien	return FALSE;
30133965Sjdp    }
30233965Sjdp
30333965Sjdp  /* Handle the degenerate case of a 0 address.  */
30433965Sjdp  if (term_count == 0)
305130561Sobrien    if (! ieee_write_int (abfd, (bfd_vma) 0))
306130561Sobrien      return FALSE;
30733965Sjdp
30833965Sjdp  while (term_count > 1)
30933965Sjdp    {
31033965Sjdp      if (! ieee_write_byte (abfd, ieee_function_plus_enum))
311130561Sobrien	return FALSE;
31233965Sjdp      term_count--;
31333965Sjdp    }
31433965Sjdp
315130561Sobrien  return TRUE;
31633965Sjdp}
31733965Sjdp
318130561Sobrien/* Writes any integer into the buffer supplied and always takes 5 bytes.  */
31933965Sjdp
32033965Sjdpstatic void
321218822Sdimieee_write_int5 (bfd_byte *buffer, bfd_vma value)
32233965Sjdp{
32333965Sjdp  buffer[0] = (bfd_byte) ieee_number_repeat_4_enum;
32433965Sjdp  buffer[1] = (value >> 24) & 0xff;
32533965Sjdp  buffer[2] = (value >> 16) & 0xff;
32633965Sjdp  buffer[3] = (value >> 8) & 0xff;
32733965Sjdp  buffer[4] = (value >> 0) & 0xff;
32833965Sjdp}
32933965Sjdp
330130561Sobrienstatic bfd_boolean
331218822Sdimieee_write_int5_out (bfd *abfd, bfd_vma value)
33233965Sjdp{
33333965Sjdp  bfd_byte b[5];
33433965Sjdp
33533965Sjdp  ieee_write_int5 (b, value);
336218822Sdim  if (bfd_bwrite ((void *) b, (bfd_size_type) 5, abfd) != 5)
337130561Sobrien    return FALSE;
338130561Sobrien  return TRUE;
33933965Sjdp}
34033965Sjdp
341130561Sobrienstatic bfd_boolean
342218822Sdimparse_int (common_header_type *ieee, bfd_vma *value_ptr)
34333965Sjdp{
34433965Sjdp  int value = this_byte (ieee);
34533965Sjdp  int result;
346130561Sobrien
34733965Sjdp  if (value >= 0 && value <= 127)
34833965Sjdp    {
34933965Sjdp      *value_ptr = value;
35033965Sjdp      next_byte (ieee);
351130561Sobrien      return TRUE;
35233965Sjdp    }
35333965Sjdp  else if (value >= 0x80 && value <= 0x88)
35433965Sjdp    {
35533965Sjdp      unsigned int count = value & 0xf;
356130561Sobrien
35733965Sjdp      result = 0;
35833965Sjdp      next_byte (ieee);
35933965Sjdp      while (count)
36033965Sjdp	{
36133965Sjdp	  result = (result << 8) | this_byte_and_next (ieee);
36233965Sjdp	  count--;
36333965Sjdp	}
36433965Sjdp      *value_ptr = result;
365130561Sobrien      return TRUE;
36633965Sjdp    }
367130561Sobrien  return FALSE;
36833965Sjdp}
36933965Sjdp
37033965Sjdpstatic int
371218822Sdimparse_i (common_header_type *ieee, bfd_boolean *ok)
37233965Sjdp{
373218822Sdim  bfd_vma x = 0;
37433965Sjdp  *ok = parse_int (ieee, &x);
37533965Sjdp  return x;
37633965Sjdp}
37733965Sjdp
37833965Sjdpstatic bfd_vma
379218822Sdimmust_parse_int (common_header_type *ieee)
38033965Sjdp{
381218822Sdim  bfd_vma result = 0;
382104834Sobrien  BFD_ASSERT (parse_int (ieee, &result));
38333965Sjdp  return result;
38433965Sjdp}
38533965Sjdp
38633965Sjdptypedef struct
38733965Sjdp{
38833965Sjdp  bfd_vma value;
38933965Sjdp  asection *section;
39033965Sjdp  ieee_symbol_index_type symbol;
39133965Sjdp} ieee_value_type;
39233965Sjdp
39333965Sjdp
39433965Sjdp#if KEEPMINUSPCININST
39533965Sjdp
39633965Sjdp#define SRC_MASK(arg) arg
397130561Sobrien#define PCREL_OFFSET FALSE
39833965Sjdp
39933965Sjdp#else
40033965Sjdp
40133965Sjdp#define SRC_MASK(arg) 0
402130561Sobrien#define PCREL_OFFSET TRUE
40333965Sjdp
40433965Sjdp#endif
40533965Sjdp
40633965Sjdpstatic reloc_howto_type abs32_howto =
40733965Sjdp  HOWTO (1,
40833965Sjdp	 0,
40933965Sjdp	 2,
41033965Sjdp	 32,
411130561Sobrien	 FALSE,
41233965Sjdp	 0,
41333965Sjdp	 complain_overflow_bitfield,
41433965Sjdp	 0,
41533965Sjdp	 "abs32",
416130561Sobrien	 TRUE,
41733965Sjdp	 0xffffffff,
41833965Sjdp	 0xffffffff,
419130561Sobrien	 FALSE);
42033965Sjdp
42133965Sjdpstatic reloc_howto_type abs16_howto =
42233965Sjdp  HOWTO (1,
42333965Sjdp	 0,
42433965Sjdp	 1,
42533965Sjdp	 16,
426130561Sobrien	 FALSE,
42733965Sjdp	 0,
42833965Sjdp	 complain_overflow_bitfield,
42933965Sjdp	 0,
43033965Sjdp	 "abs16",
431130561Sobrien	 TRUE,
43233965Sjdp	 0x0000ffff,
43333965Sjdp	 0x0000ffff,
434130561Sobrien	 FALSE);
43533965Sjdp
43633965Sjdpstatic reloc_howto_type abs8_howto =
43733965Sjdp  HOWTO (1,
43833965Sjdp	 0,
43933965Sjdp	 0,
44033965Sjdp	 8,
441130561Sobrien	 FALSE,
44233965Sjdp	 0,
44333965Sjdp	 complain_overflow_bitfield,
44433965Sjdp	 0,
44533965Sjdp	 "abs8",
446130561Sobrien	 TRUE,
44733965Sjdp	 0x000000ff,
44833965Sjdp	 0x000000ff,
449130561Sobrien	 FALSE);
45033965Sjdp
45133965Sjdpstatic reloc_howto_type rel32_howto =
45233965Sjdp  HOWTO (1,
45333965Sjdp	 0,
45433965Sjdp	 2,
45533965Sjdp	 32,
456130561Sobrien	 TRUE,
45733965Sjdp	 0,
45833965Sjdp	 complain_overflow_signed,
45933965Sjdp	 0,
46033965Sjdp	 "rel32",
461130561Sobrien	 TRUE,
46233965Sjdp	 SRC_MASK (0xffffffff),
46333965Sjdp	 0xffffffff,
46433965Sjdp	 PCREL_OFFSET);
46533965Sjdp
46633965Sjdpstatic reloc_howto_type rel16_howto =
46733965Sjdp  HOWTO (1,
46833965Sjdp	 0,
46933965Sjdp	 1,
47033965Sjdp	 16,
471130561Sobrien	 TRUE,
47233965Sjdp	 0,
47333965Sjdp	 complain_overflow_signed,
47433965Sjdp	 0,
47533965Sjdp	 "rel16",
476130561Sobrien	 TRUE,
47733965Sjdp	 SRC_MASK (0x0000ffff),
47833965Sjdp	 0x0000ffff,
47933965Sjdp	 PCREL_OFFSET);
48033965Sjdp
48133965Sjdpstatic reloc_howto_type rel8_howto =
48233965Sjdp  HOWTO (1,
48333965Sjdp	 0,
48433965Sjdp	 0,
48533965Sjdp	 8,
486130561Sobrien	 TRUE,
48733965Sjdp	 0,
48833965Sjdp	 complain_overflow_signed,
48933965Sjdp	 0,
49033965Sjdp	 "rel8",
491130561Sobrien	 TRUE,
49233965Sjdp	 SRC_MASK (0x000000ff),
49333965Sjdp	 0x000000ff,
49433965Sjdp	 PCREL_OFFSET);
49533965Sjdp
49633965Sjdpstatic ieee_symbol_index_type NOSYMBOL = {0, 0};
49733965Sjdp
49833965Sjdpstatic void
499218822Sdimparse_expression (ieee_data_type *ieee,
500218822Sdim		  bfd_vma *value,
501218822Sdim		  ieee_symbol_index_type *symbol,
502218822Sdim		  bfd_boolean *pcrel,
503218822Sdim		  unsigned int *extra,
504218822Sdim		  asection **section)
50533965Sjdp
50633965Sjdp{
507218822Sdim  bfd_boolean loop = TRUE;
508218822Sdim  ieee_value_type stack[10];
509218822Sdim  ieee_value_type *sp = stack;
510218822Sdim  asection *dummy;
511218822Sdim
51233965Sjdp#define POS sp[1]
51333965Sjdp#define TOS sp[0]
51433965Sjdp#define NOS sp[-1]
51533965Sjdp#define INC sp++;
51633965Sjdp#define DEC sp--;
51733965Sjdp
518130561Sobrien  /* The stack pointer always points to the next unused location.  */
519218822Sdim#define PUSH(x,y,z) TOS.symbol = x; TOS.section = y; TOS.value = z; INC;
520218822Sdim#define POP(x,y,z)  DEC; x = TOS.symbol; y = TOS.section; z = TOS.value;
52133965Sjdp
52289857Sobrien  while (loop && ieee->h.input_p < ieee->h.last_byte)
52333965Sjdp    {
52433965Sjdp      switch (this_byte (&(ieee->h)))
52533965Sjdp	{
52633965Sjdp	case ieee_variable_P_enum:
527130561Sobrien	  /* P variable, current program counter for section n.  */
52833965Sjdp	  {
52933965Sjdp	    int section_n;
530130561Sobrien
53133965Sjdp	    next_byte (&(ieee->h));
532130561Sobrien	    *pcrel = TRUE;
53333965Sjdp	    section_n = must_parse_int (&(ieee->h));
53433965Sjdp	    PUSH (NOSYMBOL, bfd_abs_section_ptr, 0);
53533965Sjdp	    break;
53633965Sjdp	  }
53733965Sjdp	case ieee_variable_L_enum:
538130561Sobrien	  /* L variable  address of section N.  */
53933965Sjdp	  next_byte (&(ieee->h));
54033965Sjdp	  PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0);
54133965Sjdp	  break;
54233965Sjdp	case ieee_variable_R_enum:
543130561Sobrien	  /* R variable, logical address of section module.  */
544130561Sobrien	  /* FIXME, this should be different to L.  */
54533965Sjdp	  next_byte (&(ieee->h));
54633965Sjdp	  PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0);
54733965Sjdp	  break;
54833965Sjdp	case ieee_variable_S_enum:
549130561Sobrien	  /* S variable, size in MAUS of section module.  */
55033965Sjdp	  next_byte (&(ieee->h));
55133965Sjdp	  PUSH (NOSYMBOL,
55233965Sjdp		0,
553218822Sdim		ieee->section_table[must_parse_int (&(ieee->h))]->size);
55433965Sjdp	  break;
55533965Sjdp	case ieee_variable_I_enum:
556130561Sobrien	  /* Push the address of variable n.  */
55733965Sjdp	  {
55833965Sjdp	    ieee_symbol_index_type sy;
559218822Sdim
56033965Sjdp	    next_byte (&(ieee->h));
56133965Sjdp	    sy.index = (int) must_parse_int (&(ieee->h));
56233965Sjdp	    sy.letter = 'I';
56333965Sjdp
56433965Sjdp	    PUSH (sy, bfd_abs_section_ptr, 0);
56533965Sjdp	  }
56633965Sjdp	  break;
56733965Sjdp	case ieee_variable_X_enum:
568130561Sobrien	  /* Push the address of external variable n.  */
56933965Sjdp	  {
57033965Sjdp	    ieee_symbol_index_type sy;
571218822Sdim
57233965Sjdp	    next_byte (&(ieee->h));
57333965Sjdp	    sy.index = (int) (must_parse_int (&(ieee->h)));
57433965Sjdp	    sy.letter = 'X';
57533965Sjdp
57633965Sjdp	    PUSH (sy, bfd_und_section_ptr, 0);
57733965Sjdp	  }
57833965Sjdp	  break;
57933965Sjdp	case ieee_function_minus_enum:
58033965Sjdp	  {
58133965Sjdp	    bfd_vma value1, value2;
58233965Sjdp	    asection *section1, *section_dummy;
58333965Sjdp	    ieee_symbol_index_type sy;
584218822Sdim
58533965Sjdp	    next_byte (&(ieee->h));
58633965Sjdp
58733965Sjdp	    POP (sy, section1, value1);
58833965Sjdp	    POP (sy, section_dummy, value2);
58933965Sjdp	    PUSH (sy, section1 ? section1 : section_dummy, value2 - value1);
59033965Sjdp	  }
59133965Sjdp	  break;
59233965Sjdp	case ieee_function_plus_enum:
59333965Sjdp	  {
59433965Sjdp	    bfd_vma value1, value2;
59533965Sjdp	    asection *section1;
59633965Sjdp	    asection *section2;
59733965Sjdp	    ieee_symbol_index_type sy1;
59833965Sjdp	    ieee_symbol_index_type sy2;
599218822Sdim
60033965Sjdp	    next_byte (&(ieee->h));
60133965Sjdp
60233965Sjdp	    POP (sy1, section1, value1);
60333965Sjdp	    POP (sy2, section2, value2);
60433965Sjdp	    PUSH (sy1.letter ? sy1 : sy2,
60533965Sjdp		  bfd_is_abs_section (section1) ? section2 : section1,
60633965Sjdp		  value1 + value2);
60733965Sjdp	  }
60833965Sjdp	  break;
60933965Sjdp	default:
61033965Sjdp	  {
61133965Sjdp	    bfd_vma va;
612218822Sdim
61333965Sjdp	    BFD_ASSERT (this_byte (&(ieee->h)) < (int) ieee_variable_A_enum
61433965Sjdp		    || this_byte (&(ieee->h)) > (int) ieee_variable_Z_enum);
61533965Sjdp	    if (parse_int (&(ieee->h), &va))
61633965Sjdp	      {
61733965Sjdp		PUSH (NOSYMBOL, bfd_abs_section_ptr, va);
61833965Sjdp	      }
61933965Sjdp	    else
620218822Sdim	      /* Thats all that we can understand.  */
621218822Sdim	      loop = FALSE;
62233965Sjdp	  }
62333965Sjdp	}
62433965Sjdp    }
62589857Sobrien
62689857Sobrien  /* As far as I can see there is a bug in the Microtec IEEE output
62789857Sobrien     which I'm using to scan, whereby the comma operator is omitted
62889857Sobrien     sometimes in an expression, giving expressions with too many
62989857Sobrien     terms.  We can tell if that's the case by ensuring that
63089857Sobrien     sp == stack here.  If not, then we've pushed something too far,
63189857Sobrien     so we keep adding.  */
63289857Sobrien  while (sp != stack + 1)
63389857Sobrien    {
63489857Sobrien      asection *section1;
63589857Sobrien      ieee_symbol_index_type sy1;
636218822Sdim
63789857Sobrien      POP (sy1, section1, *extra);
63889857Sobrien    }
63989857Sobrien
64089857Sobrien  POP (*symbol, dummy, *value);
64189857Sobrien  if (section)
64289857Sobrien    *section = dummy;
64333965Sjdp}
64433965Sjdp
64533965Sjdp
64689857Sobrien#define ieee_seek(ieee, offset) \
64789857Sobrien  do								\
64889857Sobrien    {								\
64989857Sobrien      ieee->h.input_p = ieee->h.first_byte + offset;		\
65089857Sobrien      ieee->h.last_byte = (ieee->h.first_byte			\
65189857Sobrien			   + ieee_part_after (ieee, offset));	\
65289857Sobrien    }								\
65389857Sobrien  while (0)
65433965Sjdp
65589857Sobrien#define ieee_pos(ieee) \
65689857Sobrien  (ieee->h.input_p - ieee->h.first_byte)
65733965Sjdp
65889857Sobrien/* Find the first part of the ieee file after HERE.  */
65989857Sobrien
66089857Sobrienstatic file_ptr
661218822Sdimieee_part_after (ieee_data_type *ieee, file_ptr here)
66289857Sobrien{
66389857Sobrien  int part;
66489857Sobrien  file_ptr after = ieee->w.r.me_record;
66589857Sobrien
66689857Sobrien  /* File parts can come in any order, except that module end is
66789857Sobrien     guaranteed to be last (and the header first).  */
66889857Sobrien  for (part = 0; part < N_W_VARIABLES; part++)
66989857Sobrien    if (ieee->w.offset[part] > here && after > ieee->w.offset[part])
67089857Sobrien      after = ieee->w.offset[part];
67189857Sobrien
67289857Sobrien  return after;
67389857Sobrien}
67489857Sobrien
67533965Sjdpstatic unsigned int last_index;
676130561Sobrienstatic char last_type;		/* Is the index for an X or a D.  */
67733965Sjdp
67833965Sjdpstatic ieee_symbol_type *
679218822Sdimget_symbol (bfd *abfd ATTRIBUTE_UNUSED,
680218822Sdim	    ieee_data_type *ieee,
681218822Sdim	    ieee_symbol_type *last_symbol,
682218822Sdim	    unsigned int *symbol_count,
683218822Sdim	    ieee_symbol_type ***pptr,
684218822Sdim	    unsigned int *max_index,
685218822Sdim	    int this_type)
68633965Sjdp{
687130561Sobrien  /* Need a new symbol.  */
68833965Sjdp  unsigned int new_index = must_parse_int (&(ieee->h));
689130561Sobrien
69033965Sjdp  if (new_index != last_index || this_type != last_type)
69133965Sjdp    {
69289857Sobrien      ieee_symbol_type *new_symbol;
69389857Sobrien      bfd_size_type amt = sizeof (ieee_symbol_type);
69489857Sobrien
695218822Sdim      new_symbol = bfd_alloc (ieee->h.abfd, amt);
69633965Sjdp      if (!new_symbol)
69733965Sjdp	return NULL;
69833965Sjdp
69933965Sjdp      new_symbol->index = new_index;
70033965Sjdp      last_index = new_index;
70133965Sjdp      (*symbol_count)++;
70233965Sjdp      **pptr = new_symbol;
70333965Sjdp      *pptr = &new_symbol->next;
70433965Sjdp      if (new_index > *max_index)
705130561Sobrien	*max_index = new_index;
706130561Sobrien
70733965Sjdp      last_type = this_type;
70833965Sjdp      new_symbol->symbol.section = bfd_abs_section_ptr;
70933965Sjdp      return new_symbol;
71033965Sjdp    }
71133965Sjdp  return last_symbol;
71233965Sjdp}
71333965Sjdp
714130561Sobrienstatic bfd_boolean
715218822Sdimieee_slurp_external_symbols (bfd *abfd)
71633965Sjdp{
71733965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
71833965Sjdp  file_ptr offset = ieee->w.r.external_part;
71933965Sjdp
72033965Sjdp  ieee_symbol_type **prev_symbols_ptr = &ieee->external_symbols;
72133965Sjdp  ieee_symbol_type **prev_reference_ptr = &ieee->external_reference;
722218822Sdim  ieee_symbol_type *symbol = NULL;
72333965Sjdp  unsigned int symbol_count = 0;
724130561Sobrien  bfd_boolean loop = TRUE;
725218822Sdim
72633965Sjdp  last_index = 0xffffff;
727130561Sobrien  ieee->symbol_table_full = TRUE;
72833965Sjdp
72989857Sobrien  ieee_seek (ieee, offset);
73033965Sjdp
73133965Sjdp  while (loop)
73233965Sjdp    {
73333965Sjdp      switch (this_byte (&(ieee->h)))
73433965Sjdp	{
73533965Sjdp	case ieee_nn_record:
73633965Sjdp	  next_byte (&(ieee->h));
73733965Sjdp
73833965Sjdp	  symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
739218822Sdim			       & prev_symbols_ptr,
740218822Sdim			       & ieee->external_symbol_max_index, 'I');
74133965Sjdp	  if (symbol == NULL)
742130561Sobrien	    return FALSE;
74333965Sjdp
74433965Sjdp	  symbol->symbol.the_bfd = abfd;
74533965Sjdp	  symbol->symbol.name = read_id (&(ieee->h));
746218822Sdim	  symbol->symbol.udata.p = NULL;
74733965Sjdp	  symbol->symbol.flags = BSF_NO_FLAGS;
74833965Sjdp	  break;
74933965Sjdp	case ieee_external_symbol_enum:
75033965Sjdp	  next_byte (&(ieee->h));
75133965Sjdp
75233965Sjdp	  symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
75333965Sjdp			       &prev_symbols_ptr,
75433965Sjdp			       &ieee->external_symbol_max_index, 'D');
75533965Sjdp	  if (symbol == NULL)
756130561Sobrien	    return FALSE;
75733965Sjdp
75833965Sjdp	  BFD_ASSERT (symbol->index >= ieee->external_symbol_min_index);
75933965Sjdp
76033965Sjdp	  symbol->symbol.the_bfd = abfd;
76133965Sjdp	  symbol->symbol.name = read_id (&(ieee->h));
762218822Sdim	  symbol->symbol.udata.p = NULL;
76333965Sjdp	  symbol->symbol.flags = BSF_NO_FLAGS;
76433965Sjdp	  break;
76533965Sjdp	case ieee_attribute_record_enum >> 8:
76633965Sjdp	  {
76733965Sjdp	    unsigned int symbol_name_index;
76833965Sjdp	    unsigned int symbol_type_index;
76933965Sjdp	    unsigned int symbol_attribute_def;
770218822Sdim	    bfd_vma value = 0;
771218822Sdim
77289857Sobrien	    switch (read_2bytes (&ieee->h))
77333965Sjdp	      {
77433965Sjdp	      case ieee_attribute_record_enum:
77533965Sjdp		symbol_name_index = must_parse_int (&(ieee->h));
77633965Sjdp		symbol_type_index = must_parse_int (&(ieee->h));
77733965Sjdp		symbol_attribute_def = must_parse_int (&(ieee->h));
77833965Sjdp		switch (symbol_attribute_def)
77933965Sjdp		  {
78033965Sjdp		  case 8:
78133965Sjdp		  case 19:
78233965Sjdp		    parse_int (&ieee->h, &value);
78333965Sjdp		    break;
78433965Sjdp		  default:
78533965Sjdp		    (*_bfd_error_handler)
786218822Sdim		      (_("%B: unimplemented ATI record %u for symbol %u"),
787218822Sdim		       abfd, symbol_attribute_def, symbol_name_index);
78833965Sjdp		    bfd_set_error (bfd_error_bad_value);
789130561Sobrien		    return FALSE;
79033965Sjdp		    break;
79133965Sjdp		  }
79233965Sjdp		break;
79333965Sjdp	      case ieee_external_reference_info_record_enum:
794130561Sobrien		/* Skip over ATX record.  */
79533965Sjdp		parse_int (&(ieee->h), &value);
79633965Sjdp		parse_int (&(ieee->h), &value);
79733965Sjdp		parse_int (&(ieee->h), &value);
79833965Sjdp		parse_int (&(ieee->h), &value);
79933965Sjdp		break;
80060484Sobrien	      case ieee_atn_record_enum:
80160484Sobrien		/* We may get call optimization information here,
80260484Sobrien		   which we just ignore.  The format is
803130561Sobrien		   {$F1}${CE}{index}{$00}{$3F}{$3F}{#_of_ASNs}.  */
80460484Sobrien		parse_int (&ieee->h, &value);
80560484Sobrien		parse_int (&ieee->h, &value);
80660484Sobrien		parse_int (&ieee->h, &value);
80760484Sobrien		if (value != 0x3f)
80860484Sobrien		  {
80960484Sobrien		    (*_bfd_error_handler)
810218822Sdim		      (_("%B: unexpected ATN type %d in external part"),
811218822Sdim			 abfd, (int) value);
81260484Sobrien		    bfd_set_error (bfd_error_bad_value);
813130561Sobrien		    return FALSE;
81460484Sobrien		  }
81560484Sobrien		parse_int (&ieee->h, &value);
81660484Sobrien		parse_int (&ieee->h, &value);
81760484Sobrien		while (value > 0)
81860484Sobrien		  {
81960484Sobrien		    bfd_vma val1;
82060484Sobrien
82160484Sobrien		    --value;
82260484Sobrien
82389857Sobrien		    switch (read_2bytes (&ieee->h))
82460484Sobrien		      {
82560484Sobrien		      case ieee_asn_record_enum:
82660484Sobrien			parse_int (&ieee->h, &val1);
82760484Sobrien			parse_int (&ieee->h, &val1);
82860484Sobrien			break;
82960484Sobrien
83060484Sobrien		      default:
83160484Sobrien			(*_bfd_error_handler)
832218822Sdim			  (_("%B: unexpected type after ATN"), abfd);
83360484Sobrien			bfd_set_error (bfd_error_bad_value);
834130561Sobrien			return FALSE;
83560484Sobrien		      }
83660484Sobrien		  }
83733965Sjdp	      }
83833965Sjdp	  }
83933965Sjdp	  break;
84033965Sjdp	case ieee_value_record_enum >> 8:
84133965Sjdp	  {
84233965Sjdp	    unsigned int symbol_name_index;
84333965Sjdp	    ieee_symbol_index_type symbol_ignore;
844130561Sobrien	    bfd_boolean pcrel_ignore;
84533965Sjdp	    unsigned int extra;
846218822Sdim
84733965Sjdp	    next_byte (&(ieee->h));
84833965Sjdp	    next_byte (&(ieee->h));
84933965Sjdp
85033965Sjdp	    symbol_name_index = must_parse_int (&(ieee->h));
85133965Sjdp	    parse_expression (ieee,
85233965Sjdp			      &symbol->symbol.value,
85333965Sjdp			      &symbol_ignore,
85433965Sjdp			      &pcrel_ignore,
85533965Sjdp			      &extra,
85633965Sjdp			      &symbol->symbol.section);
85733965Sjdp
85860484Sobrien	    /* Fully linked IEEE-695 files tend to give every symbol
85960484Sobrien               an absolute value.  Try to convert that back into a
86060484Sobrien               section relative value.  FIXME: This won't always to
86160484Sobrien               the right thing.  */
86260484Sobrien	    if (bfd_is_abs_section (symbol->symbol.section)
86360484Sobrien		&& (abfd->flags & HAS_RELOC) == 0)
86460484Sobrien	      {
86560484Sobrien		bfd_vma val;
86660484Sobrien		asection *s;
86760484Sobrien
86860484Sobrien		val = symbol->symbol.value;
86960484Sobrien		for (s = abfd->sections; s != NULL; s = s->next)
87060484Sobrien		  {
871218822Sdim		    if (val >= s->vma && val < s->vma + s->size)
87260484Sobrien		      {
87360484Sobrien			symbol->symbol.section = s;
87460484Sobrien			symbol->symbol.value -= s->vma;
87560484Sobrien			break;
87660484Sobrien		      }
87760484Sobrien		  }
87860484Sobrien	      }
87960484Sobrien
88033965Sjdp	    symbol->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
88133965Sjdp
88233965Sjdp	  }
88333965Sjdp	  break;
88433965Sjdp	case ieee_weak_external_reference_enum:
88533965Sjdp	  {
88633965Sjdp	    bfd_vma size;
88733965Sjdp	    bfd_vma value;
888218822Sdim
88933965Sjdp	    next_byte (&(ieee->h));
890130561Sobrien	    /* Throw away the external reference index.  */
89133965Sjdp	    (void) must_parse_int (&(ieee->h));
892130561Sobrien	    /* Fetch the default size if not resolved.  */
89333965Sjdp	    size = must_parse_int (&(ieee->h));
894130561Sobrien	    /* Fetch the default value if available.  */
895104834Sobrien	    if (! parse_int (&(ieee->h), &value))
896218822Sdim	      value = 0;
897130561Sobrien	    /* This turns into a common.  */
89833965Sjdp	    symbol->symbol.section = bfd_com_section_ptr;
89933965Sjdp	    symbol->symbol.value = size;
90033965Sjdp	  }
90133965Sjdp	  break;
90233965Sjdp
90333965Sjdp	case ieee_external_reference_enum:
90433965Sjdp	  next_byte (&(ieee->h));
90533965Sjdp
90633965Sjdp	  symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
90733965Sjdp			       &prev_reference_ptr,
90833965Sjdp			       &ieee->external_reference_max_index, 'X');
90933965Sjdp	  if (symbol == NULL)
910130561Sobrien	    return FALSE;
91133965Sjdp
91233965Sjdp	  symbol->symbol.the_bfd = abfd;
91333965Sjdp	  symbol->symbol.name = read_id (&(ieee->h));
914218822Sdim	  symbol->symbol.udata.p = NULL;
91533965Sjdp	  symbol->symbol.section = bfd_und_section_ptr;
91633965Sjdp	  symbol->symbol.value = (bfd_vma) 0;
91733965Sjdp	  symbol->symbol.flags = 0;
91833965Sjdp
91933965Sjdp	  BFD_ASSERT (symbol->index >= ieee->external_reference_min_index);
92033965Sjdp	  break;
92133965Sjdp
92233965Sjdp	default:
923130561Sobrien	  loop = FALSE;
92433965Sjdp	}
92533965Sjdp    }
92633965Sjdp
92733965Sjdp  if (ieee->external_symbol_max_index != 0)
92833965Sjdp    {
92933965Sjdp      ieee->external_symbol_count =
93033965Sjdp	ieee->external_symbol_max_index -
93133965Sjdp	ieee->external_symbol_min_index + 1;
93233965Sjdp    }
93333965Sjdp  else
934218822Sdim    ieee->external_symbol_count = 0;
93533965Sjdp
93633965Sjdp  if (ieee->external_reference_max_index != 0)
93733965Sjdp    {
93833965Sjdp      ieee->external_reference_count =
93933965Sjdp	ieee->external_reference_max_index -
94033965Sjdp	ieee->external_reference_min_index + 1;
94133965Sjdp    }
94233965Sjdp  else
943218822Sdim    ieee->external_reference_count = 0;
94433965Sjdp
94533965Sjdp  abfd->symcount =
94633965Sjdp    ieee->external_reference_count + ieee->external_symbol_count;
94733965Sjdp
94833965Sjdp  if (symbol_count != abfd->symcount)
949218822Sdim    /* There are gaps in the table -- */
950218822Sdim    ieee->symbol_table_full = FALSE;
95133965Sjdp
952218822Sdim  *prev_symbols_ptr   = NULL;
953218822Sdim  *prev_reference_ptr = NULL;
95433965Sjdp
955130561Sobrien  return TRUE;
95633965Sjdp}
95733965Sjdp
958130561Sobrienstatic bfd_boolean
959218822Sdimieee_slurp_symbol_table (bfd *abfd)
96033965Sjdp{
961104834Sobrien  if (! IEEE_DATA (abfd)->read_symbols)
96233965Sjdp    {
96333965Sjdp      if (! ieee_slurp_external_symbols (abfd))
964130561Sobrien	return FALSE;
965130561Sobrien      IEEE_DATA (abfd)->read_symbols = TRUE;
96633965Sjdp    }
967130561Sobrien  return TRUE;
96833965Sjdp}
96933965Sjdp
97089857Sobrienstatic long
971218822Sdimieee_get_symtab_upper_bound (bfd *abfd)
97233965Sjdp{
97333965Sjdp  if (! ieee_slurp_symbol_table (abfd))
97433965Sjdp    return -1;
97533965Sjdp
97633965Sjdp  return (abfd->symcount != 0) ?
97733965Sjdp    (abfd->symcount + 1) * (sizeof (ieee_symbol_type *)) : 0;
97833965Sjdp}
97933965Sjdp
980130561Sobrien/* Move from our internal lists to the canon table, and insert in
981130561Sobrien   symbol index order.  */
98233965Sjdp
98333965Sjdpextern const bfd_target ieee_vec;
98433965Sjdp
98589857Sobrienstatic long
986218822Sdimieee_canonicalize_symtab (bfd *abfd, asymbol **location)
98733965Sjdp{
98833965Sjdp  ieee_symbol_type *symp;
98933965Sjdp  static bfd dummy_bfd;
99033965Sjdp  static asymbol empty_symbol =
99160484Sobrien  {
99260484Sobrien    &dummy_bfd,
99360484Sobrien    " ieee empty",
99460484Sobrien    (symvalue) 0,
99560484Sobrien    BSF_DEBUGGING,
99660484Sobrien    bfd_abs_section_ptr
99760484Sobrien#ifdef __STDC__
99860484Sobrien    /* K&R compilers can't initialise unions.  */
99960484Sobrien    , { 0 }
100060484Sobrien#endif
100160484Sobrien  };
100233965Sjdp
100333965Sjdp  if (abfd->symcount)
100433965Sjdp    {
100533965Sjdp      ieee_data_type *ieee = IEEE_DATA (abfd);
1006218822Sdim
100733965Sjdp      dummy_bfd.xvec = &ieee_vec;
100833965Sjdp      if (! ieee_slurp_symbol_table (abfd))
100933965Sjdp	return -1;
101033965Sjdp
1011104834Sobrien      if (! ieee->symbol_table_full)
101233965Sjdp	{
1013130561Sobrien	  /* Arrgh - there are gaps in the table, run through and fill them
1014130561Sobrien	     up with pointers to a null place.  */
101533965Sjdp	  unsigned int i;
1016130561Sobrien
101733965Sjdp	  for (i = 0; i < abfd->symcount; i++)
1018130561Sobrien	    location[i] = &empty_symbol;
101933965Sjdp	}
102033965Sjdp
102133965Sjdp      ieee->external_symbol_base_offset = -ieee->external_symbol_min_index;
102233965Sjdp      for (symp = IEEE_DATA (abfd)->external_symbols;
102333965Sjdp	   symp != (ieee_symbol_type *) NULL;
102433965Sjdp	   symp = symp->next)
1025130561Sobrien	/* Place into table at correct index locations.  */
1026130561Sobrien	location[symp->index + ieee->external_symbol_base_offset] = &symp->symbol;
102733965Sjdp
1028130561Sobrien      /* The external refs are indexed in a bit.  */
102933965Sjdp      ieee->external_reference_base_offset =
103033965Sjdp	-ieee->external_reference_min_index + ieee->external_symbol_count;
103133965Sjdp
103233965Sjdp      for (symp = IEEE_DATA (abfd)->external_reference;
103333965Sjdp	   symp != (ieee_symbol_type *) NULL;
103433965Sjdp	   symp = symp->next)
1035130561Sobrien	location[symp->index + ieee->external_reference_base_offset] =
1036130561Sobrien	  &symp->symbol;
1037130561Sobrien    }
103833965Sjdp
103933965Sjdp  if (abfd->symcount)
1040130561Sobrien    location[abfd->symcount] = (asymbol *) NULL;
1041130561Sobrien
104233965Sjdp  return abfd->symcount;
104333965Sjdp}
104433965Sjdp
104533965Sjdpstatic asection *
1046218822Sdimget_section_entry (bfd *abfd, ieee_data_type *ieee, unsigned int index)
104733965Sjdp{
104833965Sjdp  if (index >= ieee->section_table_size)
104933965Sjdp    {
105033965Sjdp      unsigned int c, i;
105133965Sjdp      asection **n;
105289857Sobrien      bfd_size_type amt;
105333965Sjdp
105433965Sjdp      c = ieee->section_table_size;
105533965Sjdp      if (c == 0)
105633965Sjdp	c = 20;
105733965Sjdp      while (c <= index)
105833965Sjdp	c *= 2;
105933965Sjdp
106089857Sobrien      amt = c;
106189857Sobrien      amt *= sizeof (asection *);
1062218822Sdim      n = bfd_realloc (ieee->section_table, amt);
106333965Sjdp      if (n == NULL)
106433965Sjdp	return NULL;
106533965Sjdp
106633965Sjdp      for (i = ieee->section_table_size; i < c; i++)
106733965Sjdp	n[i] = NULL;
106833965Sjdp
106933965Sjdp      ieee->section_table = n;
107033965Sjdp      ieee->section_table_size = c;
107133965Sjdp    }
107233965Sjdp
107333965Sjdp  if (ieee->section_table[index] == (asection *) NULL)
107433965Sjdp    {
107589857Sobrien      char *tmp = bfd_alloc (abfd, (bfd_size_type) 11);
107633965Sjdp      asection *section;
107733965Sjdp
107833965Sjdp      if (!tmp)
107933965Sjdp	return NULL;
108033965Sjdp      sprintf (tmp, " fsec%4d", index);
108133965Sjdp      section = bfd_make_section (abfd, tmp);
108233965Sjdp      ieee->section_table[index] = section;
108333965Sjdp      section->target_index = index;
108433965Sjdp      ieee->section_table[index] = section;
108533965Sjdp    }
108633965Sjdp  return ieee->section_table[index];
108733965Sjdp}
108833965Sjdp
108933965Sjdpstatic void
1090218822Sdimieee_slurp_sections (bfd *abfd)
109133965Sjdp{
109233965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
109333965Sjdp  file_ptr offset = ieee->w.r.section_part;
109433965Sjdp  char *name;
109533965Sjdp
109633965Sjdp  if (offset != 0)
109733965Sjdp    {
109833965Sjdp      bfd_byte section_type[3];
1099218822Sdim
110089857Sobrien      ieee_seek (ieee, offset);
1101130561Sobrien      while (TRUE)
110233965Sjdp	{
110333965Sjdp	  switch (this_byte (&(ieee->h)))
110433965Sjdp	    {
110533965Sjdp	    case ieee_section_type_enum:
110633965Sjdp	      {
110789857Sobrien		asection *section;
110833965Sjdp		unsigned int section_index;
1109218822Sdim
111033965Sjdp		next_byte (&(ieee->h));
111133965Sjdp		section_index = must_parse_int (&(ieee->h));
111233965Sjdp
111333965Sjdp		section = get_section_entry (abfd, ieee, section_index);
111433965Sjdp
111533965Sjdp		section_type[0] = this_byte_and_next (&(ieee->h));
111633965Sjdp
111733965Sjdp		/* Set minimal section attributes. Attributes are
1118130561Sobrien		   extended later, based on section contents.  */
111933965Sjdp		switch (section_type[0])
112033965Sjdp		  {
112133965Sjdp		  case 0xC1:
1122130561Sobrien		    /* Normal attributes for absolute sections.  */
112333965Sjdp		    section_type[1] = this_byte (&(ieee->h));
112433965Sjdp		    section->flags = SEC_ALLOC;
112533965Sjdp		    switch (section_type[1])
112633965Sjdp		      {
1127218822Sdim			/* AS Absolute section attributes.  */
1128218822Sdim		      case 0xD3:
112933965Sjdp			next_byte (&(ieee->h));
113033965Sjdp			section_type[2] = this_byte (&(ieee->h));
113133965Sjdp			switch (section_type[2])
113233965Sjdp			  {
113333965Sjdp			  case 0xD0:
1134130561Sobrien			    /* Normal code.  */
113533965Sjdp			    next_byte (&(ieee->h));
113633965Sjdp			    section->flags |= SEC_CODE;
113733965Sjdp			    break;
113833965Sjdp			  case 0xC4:
1139130561Sobrien			    /* Normal data.  */
114033965Sjdp			    next_byte (&(ieee->h));
114133965Sjdp			    section->flags |= SEC_DATA;
114233965Sjdp			    break;
114333965Sjdp			  case 0xD2:
114433965Sjdp			    next_byte (&(ieee->h));
1145130561Sobrien			    /* Normal rom data.  */
114633965Sjdp			    section->flags |= SEC_ROM | SEC_DATA;
114733965Sjdp			    break;
114833965Sjdp			  default:
114933965Sjdp			    break;
115033965Sjdp			  }
115133965Sjdp		      }
115233965Sjdp		    break;
1153218822Sdim
1154218822Sdim		    /* Named relocatable sections (type C).  */
1155218822Sdim		  case 0xC3:
115633965Sjdp		    section_type[1] = this_byte (&(ieee->h));
115733965Sjdp		    section->flags = SEC_ALLOC;
115833965Sjdp		    switch (section_type[1])
115933965Sjdp		      {
1160130561Sobrien		      case 0xD0:	/* Normal code (CP).  */
116133965Sjdp			next_byte (&(ieee->h));
116233965Sjdp			section->flags |= SEC_CODE;
116333965Sjdp			break;
1164130561Sobrien		      case 0xC4:	/* Normal data (CD).  */
116533965Sjdp			next_byte (&(ieee->h));
116633965Sjdp			section->flags |= SEC_DATA;
116733965Sjdp			break;
1168130561Sobrien		      case 0xD2:	/* Normal rom data (CR).  */
116933965Sjdp			next_byte (&(ieee->h));
117033965Sjdp			section->flags |= SEC_ROM | SEC_DATA;
117133965Sjdp			break;
117233965Sjdp		      default:
117333965Sjdp			break;
117433965Sjdp		      }
117533965Sjdp		  }
117633965Sjdp
1177130561Sobrien		/* Read section name, use it if non empty.  */
117833965Sjdp		name = read_id (&ieee->h);
117933965Sjdp		if (name[0])
118033965Sjdp		  section->name = name;
118133965Sjdp
1182130561Sobrien		/* Skip these fields, which we don't care about.  */
118333965Sjdp		{
118433965Sjdp		  bfd_vma parent, brother, context;
1185218822Sdim
118633965Sjdp		  parse_int (&(ieee->h), &parent);
118733965Sjdp		  parse_int (&(ieee->h), &brother);
118833965Sjdp		  parse_int (&(ieee->h), &context);
118933965Sjdp		}
119033965Sjdp	      }
119133965Sjdp	      break;
119233965Sjdp	    case ieee_section_alignment_enum:
119333965Sjdp	      {
119433965Sjdp		unsigned int section_index;
119533965Sjdp		bfd_vma value;
119633965Sjdp		asection *section;
1197218822Sdim
119833965Sjdp		next_byte (&(ieee->h));
119933965Sjdp		section_index = must_parse_int (&ieee->h);
120033965Sjdp		section = get_section_entry (abfd, ieee, section_index);
120133965Sjdp		if (section_index > ieee->section_count)
1202218822Sdim		  ieee->section_count = section_index;
1203218822Sdim
120433965Sjdp		section->alignment_power =
120533965Sjdp		  bfd_log2 (must_parse_int (&ieee->h));
120633965Sjdp		(void) parse_int (&(ieee->h), &value);
120733965Sjdp	      }
120833965Sjdp	      break;
120933965Sjdp	    case ieee_e2_first_byte_enum:
121033965Sjdp	      {
121189857Sobrien		asection *section;
121289857Sobrien		ieee_record_enum_type t;
121333965Sjdp
121489857Sobrien		t = (ieee_record_enum_type) (read_2bytes (&(ieee->h)));
121533965Sjdp		switch (t)
121633965Sjdp		  {
121733965Sjdp		  case ieee_section_size_enum:
121833965Sjdp		    section = ieee->section_table[must_parse_int (&(ieee->h))];
1219218822Sdim		    section->size = must_parse_int (&(ieee->h));
122033965Sjdp		    break;
122133965Sjdp		  case ieee_physical_region_size_enum:
122233965Sjdp		    section = ieee->section_table[must_parse_int (&(ieee->h))];
1223218822Sdim		    section->size = must_parse_int (&(ieee->h));
122433965Sjdp		    break;
122533965Sjdp		  case ieee_region_base_address_enum:
122633965Sjdp		    section = ieee->section_table[must_parse_int (&(ieee->h))];
122733965Sjdp		    section->vma = must_parse_int (&(ieee->h));
122833965Sjdp		    section->lma = section->vma;
122933965Sjdp		    break;
123033965Sjdp		  case ieee_mau_size_enum:
123133965Sjdp		    must_parse_int (&(ieee->h));
123233965Sjdp		    must_parse_int (&(ieee->h));
123333965Sjdp		    break;
123433965Sjdp		  case ieee_m_value_enum:
123533965Sjdp		    must_parse_int (&(ieee->h));
123633965Sjdp		    must_parse_int (&(ieee->h));
123733965Sjdp		    break;
123833965Sjdp		  case ieee_section_base_address_enum:
123933965Sjdp		    section = ieee->section_table[must_parse_int (&(ieee->h))];
124033965Sjdp		    section->vma = must_parse_int (&(ieee->h));
124133965Sjdp		    section->lma = section->vma;
124233965Sjdp		    break;
124333965Sjdp		  case ieee_section_offset_enum:
124433965Sjdp		    (void) must_parse_int (&(ieee->h));
124533965Sjdp		    (void) must_parse_int (&(ieee->h));
124633965Sjdp		    break;
124733965Sjdp		  default:
124833965Sjdp		    return;
124933965Sjdp		  }
125033965Sjdp	      }
125133965Sjdp	      break;
125233965Sjdp	    default:
125333965Sjdp	      return;
125433965Sjdp	    }
125533965Sjdp	}
125633965Sjdp    }
125733965Sjdp}
125833965Sjdp
125933965Sjdp/* Make a section for the debugging information, if any.  We don't try
126033965Sjdp   to interpret the debugging information; we just point the section
126133965Sjdp   at the area in the file so that program which understand can dig it
126233965Sjdp   out.  */
126333965Sjdp
1264130561Sobrienstatic bfd_boolean
1265218822Sdimieee_slurp_debug (bfd *abfd)
126633965Sjdp{
126733965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
126833965Sjdp  asection *sec;
126960484Sobrien  file_ptr debug_end;
1270218822Sdim  flagword flags;
127133965Sjdp
127233965Sjdp  if (ieee->w.r.debug_information_part == 0)
1273130561Sobrien    return TRUE;
127433965Sjdp
1275218822Sdim  flags = SEC_DEBUGGING | SEC_HAS_CONTENTS;
1276218822Sdim  sec = bfd_make_section_with_flags (abfd, ".debug", flags);
127733965Sjdp  if (sec == NULL)
1278130561Sobrien    return FALSE;
127933965Sjdp  sec->filepos = ieee->w.r.debug_information_part;
128033965Sjdp
128189857Sobrien  debug_end = ieee_part_after (ieee, ieee->w.r.debug_information_part);
1282218822Sdim  sec->size = debug_end - ieee->w.r.debug_information_part;
128360484Sobrien
1284130561Sobrien  return TRUE;
128533965Sjdp}
128633965Sjdp
1287130561Sobrien/* Archive stuff.  */
128833965Sjdp
1289218822Sdimstatic const bfd_target *
1290218822Sdimieee_archive_p (bfd *abfd)
129133965Sjdp{
129233965Sjdp  char *library;
129333965Sjdp  unsigned int i;
129433965Sjdp  unsigned char buffer[512];
129533965Sjdp  file_ptr buffer_offset = 0;
129633965Sjdp  ieee_ar_data_type *save = abfd->tdata.ieee_ar_data;
129733965Sjdp  ieee_ar_data_type *ieee;
129889857Sobrien  bfd_size_type alc_elts;
129933965Sjdp  ieee_ar_obstack_type *elts = NULL;
130089857Sobrien  bfd_size_type amt = sizeof (ieee_ar_data_type);
130133965Sjdp
1302218822Sdim  abfd->tdata.ieee_ar_data = bfd_alloc (abfd, amt);
130333965Sjdp  if (!abfd->tdata.ieee_ar_data)
1304104834Sobrien    goto error_ret_restore;
130533965Sjdp  ieee = IEEE_AR_DATA (abfd);
130633965Sjdp
130789857Sobrien  /* Ignore the return value here.  It doesn't matter if we don't read
130889857Sobrien     the entire buffer.  We might have a very small ieee file.  */
1309218822Sdim  bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
131033965Sjdp
131133965Sjdp  ieee->h.first_byte = buffer;
131233965Sjdp  ieee->h.input_p = buffer;
131333965Sjdp
131433965Sjdp  ieee->h.abfd = abfd;
131533965Sjdp
131633965Sjdp  if (this_byte (&(ieee->h)) != Module_Beginning)
131777298Sobrien    goto got_wrong_format_error;
131833965Sjdp
131933965Sjdp  next_byte (&(ieee->h));
132033965Sjdp  library = read_id (&(ieee->h));
132133965Sjdp  if (strcmp (library, "LIBRARY") != 0)
132277298Sobrien    goto got_wrong_format_error;
132377298Sobrien
132477298Sobrien  /* Throw away the filename.  */
132533965Sjdp  read_id (&(ieee->h));
132633965Sjdp
132733965Sjdp  ieee->element_count = 0;
132833965Sjdp  ieee->element_index = 0;
132933965Sjdp
133077298Sobrien  next_byte (&(ieee->h));	/* Drop the ad part.  */
133177298Sobrien  must_parse_int (&(ieee->h));	/* And the two dummy numbers.  */
133233965Sjdp  must_parse_int (&(ieee->h));
133333965Sjdp
133433965Sjdp  alc_elts = 10;
1335218822Sdim  elts = bfd_malloc (alc_elts * sizeof *elts);
133633965Sjdp  if (elts == NULL)
133733965Sjdp    goto error_return;
133833965Sjdp
133977298Sobrien  /* Read the index of the BB table.  */
134033965Sjdp  while (1)
134133965Sjdp    {
134233965Sjdp      int rec;
134333965Sjdp      ieee_ar_obstack_type *t;
134433965Sjdp
134533965Sjdp      rec = read_2bytes (&(ieee->h));
134633965Sjdp      if (rec != (int) ieee_assign_value_to_variable_enum)
134733965Sjdp	break;
134833965Sjdp
134933965Sjdp      if (ieee->element_count >= alc_elts)
135033965Sjdp	{
135133965Sjdp	  ieee_ar_obstack_type *n;
135233965Sjdp
135333965Sjdp	  alc_elts *= 2;
1354218822Sdim	  n = bfd_realloc (elts, alc_elts * sizeof (* elts));
135533965Sjdp	  if (n == NULL)
135633965Sjdp	    goto error_return;
135733965Sjdp	  elts = n;
135833965Sjdp	}
135933965Sjdp
136033965Sjdp      t = &elts[ieee->element_count];
136133965Sjdp      ieee->element_count++;
136233965Sjdp
136333965Sjdp      must_parse_int (&(ieee->h));
136433965Sjdp      t->file_offset = must_parse_int (&(ieee->h));
136533965Sjdp      t->abfd = (bfd *) NULL;
136633965Sjdp
136777298Sobrien      /* Make sure that we don't go over the end of the buffer.  */
136889857Sobrien      if ((size_t) ieee_pos (IEEE_DATA (abfd)) > sizeof (buffer) / 2)
136933965Sjdp	{
137077298Sobrien	  /* Past half way, reseek and reprime.  */
137189857Sobrien	  buffer_offset += ieee_pos (IEEE_DATA (abfd));
137233965Sjdp	  if (bfd_seek (abfd, buffer_offset, SEEK_SET) != 0)
137333965Sjdp	    goto error_return;
137477298Sobrien
137589857Sobrien	  /* Again ignore return value of bfd_bread.  */
1376218822Sdim	  bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
137733965Sjdp	  ieee->h.first_byte = buffer;
137833965Sjdp	  ieee->h.input_p = buffer;
137933965Sjdp	}
138033965Sjdp    }
138133965Sjdp
138289857Sobrien  amt = ieee->element_count;
138389857Sobrien  amt *= sizeof *ieee->elements;
1384218822Sdim  ieee->elements = bfd_alloc (abfd, amt);
138533965Sjdp  if (ieee->elements == NULL)
138633965Sjdp    goto error_return;
138777298Sobrien
138889857Sobrien  memcpy (ieee->elements, elts, (size_t) amt);
138933965Sjdp  free (elts);
139033965Sjdp  elts = NULL;
139133965Sjdp
139277298Sobrien  /* Now scan the area again, and replace BB offsets with file offsets.  */
139333965Sjdp  for (i = 2; i < ieee->element_count; i++)
139433965Sjdp    {
139533965Sjdp      if (bfd_seek (abfd, ieee->elements[i].file_offset, SEEK_SET) != 0)
139633965Sjdp	goto error_return;
139777298Sobrien
139889857Sobrien      /* Again ignore return value of bfd_bread.  */
1399218822Sdim      bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
140033965Sjdp      ieee->h.first_byte = buffer;
140133965Sjdp      ieee->h.input_p = buffer;
140233965Sjdp
140377298Sobrien      next_byte (&(ieee->h));		/* Drop F8.  */
140477298Sobrien      next_byte (&(ieee->h));		/* Drop 14.  */
140577298Sobrien      must_parse_int (&(ieee->h));	/* Drop size of block.  */
140689857Sobrien
140733965Sjdp      if (must_parse_int (&(ieee->h)) != 0)
140877298Sobrien	/* This object has been deleted.  */
140977298Sobrien	ieee->elements[i].file_offset = 0;
141033965Sjdp      else
141177298Sobrien	ieee->elements[i].file_offset = must_parse_int (&(ieee->h));
141233965Sjdp    }
141333965Sjdp
141433965Sjdp  /*  abfd->has_armap = ;*/
141533965Sjdp
141633965Sjdp  return abfd->xvec;
141733965Sjdp
141860484Sobrien got_wrong_format_error:
141960484Sobrien  bfd_set_error (bfd_error_wrong_format);
142033965Sjdp error_return:
142133965Sjdp  if (elts != NULL)
142233965Sjdp    free (elts);
1423104834Sobrien  bfd_release (abfd, ieee);
1424104834Sobrien error_ret_restore:
1425104834Sobrien  abfd->tdata.ieee_ar_data = save;
142677298Sobrien
142733965Sjdp  return NULL;
142833965Sjdp}
142933965Sjdp
1430218822Sdimstatic bfd_boolean
1431218822Sdimieee_mkobject (bfd *abfd)
143233965Sjdp{
143389857Sobrien  bfd_size_type amt;
143433965Sjdp
1435218822Sdim  output_ptr_start = NULL;
1436218822Sdim  output_ptr = NULL;
1437218822Sdim  output_ptr_end = NULL;
1438218822Sdim  input_ptr_start = NULL;
1439218822Sdim  input_ptr = NULL;
1440218822Sdim  input_ptr_end = NULL;
1441218822Sdim  input_bfd = NULL;
1442218822Sdim  output_bfd = NULL;
1443218822Sdim  output_buffer = 0;
1444218822Sdim  amt = sizeof (ieee_data_type);
1445218822Sdim  abfd->tdata.ieee_data = bfd_zalloc (abfd, amt);
1446218822Sdim  return abfd->tdata.ieee_data != NULL;
144733965Sjdp}
144833965Sjdp
1449130561Sobrienstatic bfd_boolean
1450218822Sdimdo_one (ieee_data_type *ieee,
1451218822Sdim	ieee_per_section_type *current_map,
1452218822Sdim	unsigned char *location_ptr,
1453218822Sdim	asection *s,
1454218822Sdim	int iterations)
145533965Sjdp{
145633965Sjdp  switch (this_byte (&(ieee->h)))
145733965Sjdp    {
145833965Sjdp    case ieee_load_constant_bytes_enum:
145933965Sjdp      {
146033965Sjdp	unsigned int number_of_maus;
146133965Sjdp	unsigned int i;
1462130561Sobrien
146333965Sjdp	next_byte (&(ieee->h));
146433965Sjdp	number_of_maus = must_parse_int (&(ieee->h));
146533965Sjdp
146633965Sjdp	for (i = 0; i < number_of_maus; i++)
146733965Sjdp	  {
146833965Sjdp	    location_ptr[current_map->pc++] = this_byte (&(ieee->h));
146933965Sjdp	    next_byte (&(ieee->h));
147033965Sjdp	  }
147133965Sjdp      }
147233965Sjdp      break;
147333965Sjdp
147433965Sjdp    case ieee_load_with_relocation_enum:
147533965Sjdp      {
1476130561Sobrien	bfd_boolean loop = TRUE;
1477130561Sobrien
147833965Sjdp	next_byte (&(ieee->h));
147933965Sjdp	while (loop)
148033965Sjdp	  {
148133965Sjdp	    switch (this_byte (&(ieee->h)))
148233965Sjdp	      {
148333965Sjdp	      case ieee_variable_R_enum:
148433965Sjdp
148533965Sjdp	      case ieee_function_signed_open_b_enum:
148633965Sjdp	      case ieee_function_unsigned_open_b_enum:
148733965Sjdp	      case ieee_function_either_open_b_enum:
148833965Sjdp		{
148933965Sjdp		  unsigned int extra = 4;
1490130561Sobrien		  bfd_boolean pcrel = FALSE;
149133965Sjdp		  asection *section;
149289857Sobrien		  ieee_reloc_type *r;
149389857Sobrien
1494218822Sdim		  r = bfd_alloc (ieee->h.abfd, sizeof (* r));
149533965Sjdp		  if (!r)
1496130561Sobrien		    return FALSE;
149733965Sjdp
149833965Sjdp		  *(current_map->reloc_tail_ptr) = r;
149933965Sjdp		  current_map->reloc_tail_ptr = &r->next;
150033965Sjdp		  r->next = (ieee_reloc_type *) NULL;
150133965Sjdp		  next_byte (&(ieee->h));
150233965Sjdp/*			    abort();*/
150333965Sjdp		  r->relent.sym_ptr_ptr = 0;
150433965Sjdp		  parse_expression (ieee,
150533965Sjdp				    &r->relent.addend,
150633965Sjdp				    &r->symbol,
150733965Sjdp				    &pcrel, &extra, &section);
150833965Sjdp		  r->relent.address = current_map->pc;
150933965Sjdp		  s->flags |= SEC_RELOC;
151033965Sjdp		  s->owner->flags |= HAS_RELOC;
151133965Sjdp		  s->reloc_count++;
151238889Sjdp		  if (r->relent.sym_ptr_ptr == NULL && section != NULL)
151338889Sjdp		    r->relent.sym_ptr_ptr = section->symbol_ptr_ptr;
151433965Sjdp
151533965Sjdp		  if (this_byte (&(ieee->h)) == (int) ieee_comma)
151633965Sjdp		    {
151733965Sjdp		      next_byte (&(ieee->h));
1518130561Sobrien		      /* Fetch number of bytes to pad.  */
151933965Sjdp		      extra = must_parse_int (&(ieee->h));
152033965Sjdp		    };
152133965Sjdp
152233965Sjdp		  switch (this_byte (&(ieee->h)))
152333965Sjdp		    {
152433965Sjdp		    case ieee_function_signed_close_b_enum:
152533965Sjdp		      next_byte (&(ieee->h));
152633965Sjdp		      break;
152733965Sjdp		    case ieee_function_unsigned_close_b_enum:
152833965Sjdp		      next_byte (&(ieee->h));
152933965Sjdp		      break;
153033965Sjdp		    case ieee_function_either_close_b_enum:
153133965Sjdp		      next_byte (&(ieee->h));
153233965Sjdp		      break;
153333965Sjdp		    default:
153433965Sjdp		      break;
153533965Sjdp		    }
1536130561Sobrien		  /* Build a relocation entry for this type.  */
153733965Sjdp		  /* If pc rel then stick -ve pc into instruction
153833965Sjdp		     and take out of reloc ..
153933965Sjdp
154033965Sjdp		     I've changed this. It's all too complicated. I
154133965Sjdp		     keep 0 in the instruction now.  */
154233965Sjdp
154333965Sjdp		  switch (extra)
154433965Sjdp		    {
154533965Sjdp		    case 0:
154633965Sjdp		    case 4:
154733965Sjdp
1548104834Sobrien		      if (pcrel)
154933965Sjdp			{
155033965Sjdp#if KEEPMINUSPCININST
155189857Sobrien			  bfd_put_32 (ieee->h.abfd, -current_map->pc,
155289857Sobrien				      location_ptr + current_map->pc);
155333965Sjdp			  r->relent.howto = &rel32_howto;
155489857Sobrien			  r->relent.addend -= current_map->pc;
155533965Sjdp#else
155689857Sobrien			  bfd_put_32 (ieee->h.abfd, (bfd_vma) 0, location_ptr +
155733965Sjdp				      current_map->pc);
155833965Sjdp			  r->relent.howto = &rel32_howto;
155933965Sjdp#endif
156033965Sjdp			}
156133965Sjdp		      else
156233965Sjdp			{
156389857Sobrien			  bfd_put_32 (ieee->h.abfd, (bfd_vma) 0,
156489857Sobrien				      location_ptr + current_map->pc);
156533965Sjdp			  r->relent.howto = &abs32_howto;
156633965Sjdp			}
156733965Sjdp		      current_map->pc += 4;
156833965Sjdp		      break;
156933965Sjdp		    case 2:
1570104834Sobrien		      if (pcrel)
157133965Sjdp			{
157233965Sjdp#if KEEPMINUSPCININST
157389857Sobrien			  bfd_put_16 (ieee->h.abfd, (bfd_vma) -current_map->pc,
157489857Sobrien				      location_ptr + current_map->pc);
157533965Sjdp			  r->relent.addend -= current_map->pc;
157633965Sjdp			  r->relent.howto = &rel16_howto;
157733965Sjdp#else
157833965Sjdp
157989857Sobrien			  bfd_put_16 (ieee->h.abfd, (bfd_vma) 0,
158089857Sobrien				      location_ptr + current_map->pc);
158133965Sjdp			  r->relent.howto = &rel16_howto;
158233965Sjdp#endif
158333965Sjdp			}
158433965Sjdp
158533965Sjdp		      else
158633965Sjdp			{
158789857Sobrien			  bfd_put_16 (ieee->h.abfd, (bfd_vma) 0,
158889857Sobrien				      location_ptr + current_map->pc);
158933965Sjdp			  r->relent.howto = &abs16_howto;
159033965Sjdp			}
159133965Sjdp		      current_map->pc += 2;
159233965Sjdp		      break;
159333965Sjdp		    case 1:
1594104834Sobrien		      if (pcrel)
159533965Sjdp			{
159633965Sjdp#if KEEPMINUSPCININST
159733965Sjdp			  bfd_put_8 (ieee->h.abfd, (int) (-current_map->pc), location_ptr + current_map->pc);
159833965Sjdp			  r->relent.addend -= current_map->pc;
159933965Sjdp			  r->relent.howto = &rel8_howto;
160033965Sjdp#else
160133965Sjdp			  bfd_put_8 (ieee->h.abfd, 0, location_ptr + current_map->pc);
160233965Sjdp			  r->relent.howto = &rel8_howto;
160333965Sjdp#endif
160433965Sjdp			}
160533965Sjdp		      else
160633965Sjdp			{
160733965Sjdp			  bfd_put_8 (ieee->h.abfd, 0, location_ptr + current_map->pc);
160833965Sjdp			  r->relent.howto = &abs8_howto;
160933965Sjdp			}
161033965Sjdp		      current_map->pc += 1;
161133965Sjdp		      break;
161233965Sjdp
161333965Sjdp		    default:
161433965Sjdp		      BFD_FAIL ();
1615130561Sobrien		      return FALSE;
161633965Sjdp		    }
161733965Sjdp		}
161833965Sjdp		break;
161933965Sjdp	      default:
162033965Sjdp		{
162133965Sjdp		  bfd_vma this_size;
1622218822Sdim
1623104834Sobrien		  if (parse_int (&(ieee->h), &this_size))
162433965Sjdp		    {
162533965Sjdp		      unsigned int i;
1626218822Sdim
162733965Sjdp		      for (i = 0; i < this_size; i++)
162833965Sjdp			{
162933965Sjdp			  location_ptr[current_map->pc++] = this_byte (&(ieee->h));
163033965Sjdp			  next_byte (&(ieee->h));
163133965Sjdp			}
163233965Sjdp		    }
163333965Sjdp		  else
1634218822Sdim		    loop = FALSE;
163533965Sjdp		}
163633965Sjdp	      }
163733965Sjdp
163833965Sjdp	    /* Prevent more than the first load-item of an LR record
1639218822Sdim	       from being repeated (MRI convention).  */
164033965Sjdp	    if (iterations != 1)
1641130561Sobrien	      loop = FALSE;
164233965Sjdp	  }
164333965Sjdp      }
164433965Sjdp    }
1645130561Sobrien  return TRUE;
164633965Sjdp}
164733965Sjdp
1648130561Sobrien/* Read in all the section data and relocation stuff too.  */
1649130561Sobrien
1650130561Sobrienstatic bfd_boolean
1651218822Sdimieee_slurp_section_data (bfd *abfd)
165233965Sjdp{
165333965Sjdp  bfd_byte *location_ptr = (bfd_byte *) NULL;
165433965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
165533965Sjdp  unsigned int section_number;
1656218822Sdim  ieee_per_section_type *current_map = NULL;
165733965Sjdp  asection *s;
1658218822Sdim
1659130561Sobrien  /* Seek to the start of the data area.  */
1660104834Sobrien  if (ieee->read_data)
1661130561Sobrien    return TRUE;
1662130561Sobrien  ieee->read_data = TRUE;
166389857Sobrien  ieee_seek (ieee, ieee->w.r.data_part);
166433965Sjdp
1665130561Sobrien  /* Allocate enough space for all the section contents.  */
166633965Sjdp  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
166733965Sjdp    {
1668130561Sobrien      ieee_per_section_type *per = ieee_per_section (s);
1669218822Sdim      arelent **relpp;
1670218822Sdim
167133965Sjdp      if ((s->flags & SEC_DEBUGGING) != 0)
167233965Sjdp	continue;
1673218822Sdim      per->data = bfd_alloc (ieee->h.abfd, s->size);
167433965Sjdp      if (!per->data)
1675130561Sobrien	return FALSE;
1676218822Sdim      relpp = &s->relocation;
1677218822Sdim      per->reloc_tail_ptr = (ieee_reloc_type **) relpp;
167833965Sjdp    }
167933965Sjdp
1680130561Sobrien  while (TRUE)
168133965Sjdp    {
168233965Sjdp      switch (this_byte (&(ieee->h)))
168333965Sjdp	{
1684130561Sobrien	  /* IF we see anything strange then quit.  */
168533965Sjdp	default:
1686130561Sobrien	  return TRUE;
168733965Sjdp
168833965Sjdp	case ieee_set_current_section_enum:
168933965Sjdp	  next_byte (&(ieee->h));
169033965Sjdp	  section_number = must_parse_int (&(ieee->h));
169133965Sjdp	  s = ieee->section_table[section_number];
169233965Sjdp	  s->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
1693130561Sobrien	  current_map = ieee_per_section (s);
169433965Sjdp	  location_ptr = current_map->data - s->vma;
1695130561Sobrien	  /* The document I have says that Microtec's compilers reset
1696130561Sobrien	     this after a sec section, even though the standard says not
1697130561Sobrien	     to, SO...  */
169833965Sjdp	  current_map->pc = s->vma;
169933965Sjdp	  break;
170033965Sjdp
170133965Sjdp	case ieee_e2_first_byte_enum:
170233965Sjdp	  next_byte (&(ieee->h));
170333965Sjdp	  switch (this_byte (&(ieee->h)))
170433965Sjdp	    {
170533965Sjdp	    case ieee_set_current_pc_enum & 0xff:
170633965Sjdp	      {
170733965Sjdp		bfd_vma value;
170833965Sjdp		ieee_symbol_index_type symbol;
170933965Sjdp		unsigned int extra;
1710130561Sobrien		bfd_boolean pcrel;
1711130561Sobrien
171233965Sjdp		next_byte (&(ieee->h));
1713130561Sobrien		must_parse_int (&(ieee->h));	/* Throw away section #.  */
171433965Sjdp		parse_expression (ieee, &value,
171533965Sjdp				  &symbol,
171633965Sjdp				  &pcrel, &extra,
171733965Sjdp				  0);
171833965Sjdp		current_map->pc = value;
1719218822Sdim		BFD_ASSERT ((unsigned) (value - s->vma) <= s->size);
172033965Sjdp	      }
172133965Sjdp	      break;
172233965Sjdp
172333965Sjdp	    case ieee_value_starting_address_enum & 0xff:
172433965Sjdp	      next_byte (&(ieee->h));
172533965Sjdp	      if (this_byte (&(ieee->h)) == ieee_function_either_open_b_enum)
172633965Sjdp		next_byte (&(ieee->h));
172733965Sjdp	      abfd->start_address = must_parse_int (&(ieee->h));
1728130561Sobrien	      /* We've got to the end of the data now -  */
1729130561Sobrien	      return TRUE;
173033965Sjdp	    default:
173133965Sjdp	      BFD_FAIL ();
1732130561Sobrien	      return FALSE;
173333965Sjdp	    }
173433965Sjdp	  break;
173533965Sjdp	case ieee_repeat_data_enum:
173633965Sjdp	  {
173733965Sjdp	    /* Repeat the following LD or LR n times - we do this by
1738130561Sobrien	       remembering the stream pointer before running it and
1739130561Sobrien	       resetting it and running it n times. We special case
1740130561Sobrien	       the repetition of a repeat_data/load_constant.  */
174133965Sjdp	    unsigned int iterations;
174233965Sjdp	    unsigned char *start;
1743130561Sobrien
174433965Sjdp	    next_byte (&(ieee->h));
174533965Sjdp	    iterations = must_parse_int (&(ieee->h));
174633965Sjdp	    start = ieee->h.input_p;
1747130561Sobrien	    if (start[0] == (int) ieee_load_constant_bytes_enum
1748130561Sobrien		&& start[1] == 1)
174933965Sjdp	      {
175033965Sjdp		while (iterations != 0)
175133965Sjdp		  {
175233965Sjdp		    location_ptr[current_map->pc++] = start[2];
175333965Sjdp		    iterations--;
175433965Sjdp		  }
175533965Sjdp		next_byte (&(ieee->h));
175633965Sjdp		next_byte (&(ieee->h));
175733965Sjdp		next_byte (&(ieee->h));
175833965Sjdp	      }
175933965Sjdp	    else
176033965Sjdp	      {
176133965Sjdp		while (iterations != 0)
176233965Sjdp		  {
176333965Sjdp		    ieee->h.input_p = start;
176433965Sjdp		    if (!do_one (ieee, current_map, location_ptr, s,
176589857Sobrien				 (int) iterations))
1766130561Sobrien		      return FALSE;
176733965Sjdp		    iterations--;
176833965Sjdp		  }
176933965Sjdp	      }
177033965Sjdp	  }
177133965Sjdp	  break;
177233965Sjdp	case ieee_load_constant_bytes_enum:
177333965Sjdp	case ieee_load_with_relocation_enum:
1774130561Sobrien	  if (!do_one (ieee, current_map, location_ptr, s, 1))
1775130561Sobrien	    return FALSE;
177633965Sjdp	}
177733965Sjdp    }
177833965Sjdp}
177933965Sjdp
1780218822Sdimstatic const bfd_target *
1781218822Sdimieee_object_p (bfd *abfd)
1782218822Sdim{
1783218822Sdim  char *processor;
1784218822Sdim  unsigned int part;
1785218822Sdim  ieee_data_type *ieee;
1786218822Sdim  unsigned char buffer[300];
1787218822Sdim  ieee_data_type *save = IEEE_DATA (abfd);
1788218822Sdim  bfd_size_type amt;
1789218822Sdim
1790218822Sdim  abfd->tdata.ieee_data = 0;
1791218822Sdim  ieee_mkobject (abfd);
1792218822Sdim
1793218822Sdim  ieee = IEEE_DATA (abfd);
1794218822Sdim  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
1795218822Sdim    goto fail;
1796218822Sdim  /* Read the first few bytes in to see if it makes sense.  Ignore
1797218822Sdim     bfd_bread return value;  The file might be very small.  */
1798218822Sdim  bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
1799218822Sdim
1800218822Sdim  ieee->h.input_p = buffer;
1801218822Sdim  if (this_byte_and_next (&(ieee->h)) != Module_Beginning)
1802218822Sdim    goto got_wrong_format;
1803218822Sdim
1804218822Sdim  ieee->read_symbols = FALSE;
1805218822Sdim  ieee->read_data = FALSE;
1806218822Sdim  ieee->section_count = 0;
1807218822Sdim  ieee->external_symbol_max_index = 0;
1808218822Sdim  ieee->external_symbol_min_index = IEEE_PUBLIC_BASE;
1809218822Sdim  ieee->external_reference_min_index = IEEE_REFERENCE_BASE;
1810218822Sdim  ieee->external_reference_max_index = 0;
1811218822Sdim  ieee->h.abfd = abfd;
1812218822Sdim  ieee->section_table = NULL;
1813218822Sdim  ieee->section_table_size = 0;
1814218822Sdim
1815218822Sdim  processor = ieee->mb.processor = read_id (&(ieee->h));
1816218822Sdim  if (strcmp (processor, "LIBRARY") == 0)
1817218822Sdim    goto got_wrong_format;
1818218822Sdim  ieee->mb.module_name = read_id (&(ieee->h));
1819218822Sdim  if (abfd->filename == (const char *) NULL)
1820218822Sdim    abfd->filename = ieee->mb.module_name;
1821218822Sdim
1822218822Sdim  /* Determine the architecture and machine type of the object file.  */
1823218822Sdim  {
1824218822Sdim    const bfd_arch_info_type *arch;
1825218822Sdim    char family[10];
1826218822Sdim
1827218822Sdim    /* IEEE does not specify the format of the processor identification
1828218822Sdim       string, so the compiler is free to put in it whatever it wants.
1829218822Sdim       We try here to recognize different processors belonging to the
1830218822Sdim       m68k family.  Code for other processors can be added here.  */
1831218822Sdim    if ((processor[0] == '6') && (processor[1] == '8'))
1832218822Sdim      {
1833218822Sdim	if (processor[2] == '3')	    /* 683xx integrated processors.  */
1834218822Sdim	  {
1835218822Sdim	    switch (processor[3])
1836218822Sdim	      {
1837218822Sdim	      case '0':			    /* 68302, 68306, 68307 */
1838218822Sdim	      case '2':			    /* 68322, 68328 */
1839218822Sdim	      case '5':			    /* 68356 */
1840218822Sdim		strcpy (family, "68000");   /* MC68000-based controllers.  */
1841218822Sdim		break;
1842218822Sdim
1843218822Sdim	      case '3':			    /* 68330, 68331, 68332, 68333,
1844218822Sdim					       68334, 68335, 68336, 68338 */
1845218822Sdim	      case '6':			    /* 68360 */
1846218822Sdim	      case '7':			    /* 68376 */
1847218822Sdim		strcpy (family, "68332");   /* CPU32 and CPU32+ */
1848218822Sdim		break;
1849218822Sdim
1850218822Sdim	      case '4':
1851218822Sdim		if (processor[4] == '9')    /* 68349 */
1852218822Sdim		  strcpy (family, "68030"); /* CPU030 */
1853218822Sdim		else		            /* 68340, 68341 */
1854218822Sdim		  strcpy (family, "68332"); /* CPU32 and CPU32+ */
1855218822Sdim		break;
1856218822Sdim
1857218822Sdim	      default:			    /* Does not exist yet.  */
1858218822Sdim		strcpy (family, "68332");   /* Guess it will be CPU32 */
1859218822Sdim	      }
1860218822Sdim	  }
1861218822Sdim	else if (TOUPPER (processor[3]) == 'F')  /* 68F333 */
1862218822Sdim	  strcpy (family, "68332");	           /* CPU32 */
1863218822Sdim	else if ((TOUPPER (processor[3]) == 'C') /* Embedded controllers.  */
1864218822Sdim		 && ((TOUPPER (processor[2]) == 'E')
1865218822Sdim		     || (TOUPPER (processor[2]) == 'H')
1866218822Sdim		     || (TOUPPER (processor[2]) == 'L')))
1867218822Sdim	  {
1868218822Sdim	    strcpy (family, "68");
1869218822Sdim	    strncat (family, processor + 4, 7);
1870218822Sdim	    family[9] = '\0';
1871218822Sdim	  }
1872218822Sdim	else				 /* "Regular" processors.  */
1873218822Sdim	  {
1874218822Sdim	    strncpy (family, processor, 9);
1875218822Sdim	    family[9] = '\0';
1876218822Sdim	  }
1877218822Sdim      }
1878218822Sdim    else if ((CONST_STRNEQ (processor, "cpu32")) /* CPU32 and CPU32+  */
1879218822Sdim	     || (CONST_STRNEQ (processor, "CPU32")))
1880218822Sdim      strcpy (family, "68332");
1881218822Sdim    else
1882218822Sdim      {
1883218822Sdim	strncpy (family, processor, 9);
1884218822Sdim	family[9] = '\0';
1885218822Sdim      }
1886218822Sdim
1887218822Sdim    arch = bfd_scan_arch (family);
1888218822Sdim    if (arch == 0)
1889218822Sdim      goto got_wrong_format;
1890218822Sdim    abfd->arch_info = arch;
1891218822Sdim  }
1892218822Sdim
1893218822Sdim  if (this_byte (&(ieee->h)) != (int) ieee_address_descriptor_enum)
1894218822Sdim    goto fail;
1895218822Sdim
1896218822Sdim  next_byte (&(ieee->h));
1897218822Sdim
1898218822Sdim  if (! parse_int (&(ieee->h), &ieee->ad.number_of_bits_mau))
1899218822Sdim    goto fail;
1900218822Sdim
1901218822Sdim  if (! parse_int (&(ieee->h), &ieee->ad.number_of_maus_in_address))
1902218822Sdim    goto fail;
1903218822Sdim
1904218822Sdim  /* If there is a byte order info, take it.  */
1905218822Sdim  if (this_byte (&(ieee->h)) == (int) ieee_variable_L_enum
1906218822Sdim      || this_byte (&(ieee->h)) == (int) ieee_variable_M_enum)
1907218822Sdim    next_byte (&(ieee->h));
1908218822Sdim
1909218822Sdim  for (part = 0; part < N_W_VARIABLES; part++)
1910218822Sdim    {
1911218822Sdim      bfd_boolean ok;
1912218822Sdim
1913218822Sdim      if (read_2bytes (&(ieee->h)) != (int) ieee_assign_value_to_variable_enum)
1914218822Sdim	goto fail;
1915218822Sdim
1916218822Sdim      if (this_byte_and_next (&(ieee->h)) != part)
1917218822Sdim	goto fail;
1918218822Sdim
1919218822Sdim      ieee->w.offset[part] = parse_i (&(ieee->h), &ok);
1920218822Sdim      if (! ok)
1921218822Sdim	goto fail;
1922218822Sdim    }
1923218822Sdim
1924218822Sdim  if (ieee->w.r.external_part != 0)
1925218822Sdim    abfd->flags = HAS_SYMS;
1926218822Sdim
1927218822Sdim  /* By now we know that this is a real IEEE file, we're going to read
1928218822Sdim     the whole thing into memory so that we can run up and down it
1929218822Sdim     quickly.  We can work out how big the file is from the trailer
1930218822Sdim     record.  */
1931218822Sdim
1932218822Sdim  amt = ieee->w.r.me_record + 1;
1933218822Sdim  IEEE_DATA (abfd)->h.first_byte = bfd_alloc (ieee->h.abfd, amt);
1934218822Sdim  if (!IEEE_DATA (abfd)->h.first_byte)
1935218822Sdim    goto fail;
1936218822Sdim  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
1937218822Sdim    goto fail;
1938218822Sdim  /* FIXME: Check return value.  I'm not sure whether it needs to read
1939218822Sdim     the entire buffer or not.  */
1940218822Sdim  bfd_bread ((void *) (IEEE_DATA (abfd)->h.first_byte),
1941218822Sdim	    (bfd_size_type) ieee->w.r.me_record + 1, abfd);
1942218822Sdim
1943218822Sdim  ieee_slurp_sections (abfd);
1944218822Sdim
1945218822Sdim  if (! ieee_slurp_debug (abfd))
1946218822Sdim    goto fail;
1947218822Sdim
1948218822Sdim  /* Parse section data to activate file and section flags implied by
1949218822Sdim     section contents.  */
1950218822Sdim  if (! ieee_slurp_section_data (abfd))
1951218822Sdim    goto fail;
1952218822Sdim
1953218822Sdim  return abfd->xvec;
1954218822Sdimgot_wrong_format:
1955218822Sdim  bfd_set_error (bfd_error_wrong_format);
1956218822Sdimfail:
1957218822Sdim  bfd_release (abfd, ieee);
1958218822Sdim  abfd->tdata.ieee_data = save;
1959218822Sdim  return (const bfd_target *) NULL;
1960218822Sdim}
1961218822Sdim
1962218822Sdimstatic void
1963218822Sdimieee_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1964218822Sdim		      asymbol *symbol,
1965218822Sdim		      symbol_info *ret)
1966218822Sdim{
1967218822Sdim  bfd_symbol_info (symbol, ret);
1968218822Sdim  if (symbol->name[0] == ' ')
1969218822Sdim    ret->name = "* empty table entry ";
1970218822Sdim  if (!symbol->section)
1971218822Sdim    ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
1972218822Sdim}
1973218822Sdim
1974218822Sdimstatic void
1975218822Sdimieee_print_symbol (bfd *abfd,
1976218822Sdim		   void * afile,
1977218822Sdim		   asymbol *symbol,
1978218822Sdim		   bfd_print_symbol_type how)
1979218822Sdim{
1980218822Sdim  FILE *file = (FILE *) afile;
1981218822Sdim
1982218822Sdim  switch (how)
1983218822Sdim    {
1984218822Sdim    case bfd_print_symbol_name:
1985218822Sdim      fprintf (file, "%s", symbol->name);
1986218822Sdim      break;
1987218822Sdim    case bfd_print_symbol_more:
1988218822Sdim      BFD_FAIL ();
1989218822Sdim      break;
1990218822Sdim    case bfd_print_symbol_all:
1991218822Sdim      {
1992218822Sdim	const char *section_name =
1993218822Sdim	  (symbol->section == (asection *) NULL
1994218822Sdim	   ? "*abs"
1995218822Sdim	   : symbol->section->name);
1996218822Sdim
1997218822Sdim	if (symbol->name[0] == ' ')
1998218822Sdim	  fprintf (file, "* empty table entry ");
1999218822Sdim	else
2000218822Sdim	  {
2001218822Sdim	    bfd_print_symbol_vandf (abfd, (void *) file, symbol);
2002218822Sdim
2003218822Sdim	    fprintf (file, " %-5s %04x %02x %s",
2004218822Sdim		     section_name,
2005218822Sdim		     (unsigned) ieee_symbol (symbol)->index,
2006218822Sdim		     (unsigned) 0,
2007218822Sdim		     symbol->name);
2008218822Sdim	  }
2009218822Sdim      }
2010218822Sdim      break;
2011218822Sdim    }
2012218822Sdim}
2013218822Sdim
2014130561Sobrienstatic bfd_boolean
2015218822Sdimieee_new_section_hook (bfd *abfd, asection *newsect)
201633965Sjdp{
201733965Sjdp  if (!newsect->used_by_bfd)
2018218822Sdim    {
2019218822Sdim      newsect->used_by_bfd = bfd_alloc (abfd, sizeof (ieee_per_section_type));
2020218822Sdim      if (!newsect->used_by_bfd)
2021218822Sdim	return FALSE;
2022218822Sdim    }
2023218822Sdim  ieee_per_section (newsect)->data = NULL;
202433965Sjdp  ieee_per_section (newsect)->section = newsect;
2025218822Sdim  return _bfd_generic_new_section_hook (abfd, newsect);
202633965Sjdp}
202733965Sjdp
202889857Sobrienstatic long
2029218822Sdimieee_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
203033965Sjdp{
203133965Sjdp  if ((asect->flags & SEC_DEBUGGING) != 0)
203233965Sjdp    return 0;
203333965Sjdp  if (! ieee_slurp_section_data (abfd))
203433965Sjdp    return -1;
203533965Sjdp  return (asect->reloc_count + 1) * sizeof (arelent *);
203633965Sjdp}
203733965Sjdp
2038130561Sobrienstatic bfd_boolean
2039218822Sdimieee_get_section_contents (bfd *abfd,
2040218822Sdim			   sec_ptr section,
2041218822Sdim			   void * location,
2042218822Sdim			   file_ptr offset,
2043218822Sdim			   bfd_size_type count)
204433965Sjdp{
2045130561Sobrien  ieee_per_section_type *p = ieee_per_section (section);
204633965Sjdp  if ((section->flags & SEC_DEBUGGING) != 0)
204733965Sjdp    return _bfd_generic_get_section_contents (abfd, section, location,
204833965Sjdp					      offset, count);
204933965Sjdp  ieee_slurp_section_data (abfd);
2050218822Sdim  (void) memcpy ((void *) location, (void *) (p->data + offset), (unsigned) count);
2051130561Sobrien  return TRUE;
205233965Sjdp}
205333965Sjdp
205489857Sobrienstatic long
2055218822Sdimieee_canonicalize_reloc (bfd *abfd,
2056218822Sdim			 sec_ptr section,
2057218822Sdim			 arelent **relptr,
2058218822Sdim			 asymbol **symbols)
205933965Sjdp{
206033965Sjdp  ieee_reloc_type *src = (ieee_reloc_type *) (section->relocation);
206133965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
206233965Sjdp
206333965Sjdp  if ((section->flags & SEC_DEBUGGING) != 0)
206433965Sjdp    return 0;
206533965Sjdp
206633965Sjdp  while (src != (ieee_reloc_type *) NULL)
206733965Sjdp    {
2068130561Sobrien      /* Work out which symbol to attach it this reloc to.  */
206933965Sjdp      switch (src->symbol.letter)
207033965Sjdp	{
207133965Sjdp	case 'I':
207233965Sjdp	  src->relent.sym_ptr_ptr =
207333965Sjdp	    symbols + src->symbol.index + ieee->external_symbol_base_offset;
207433965Sjdp	  break;
207533965Sjdp	case 'X':
207633965Sjdp	  src->relent.sym_ptr_ptr =
207733965Sjdp	    symbols + src->symbol.index + ieee->external_reference_base_offset;
207833965Sjdp	  break;
207933965Sjdp	case 0:
208038889Sjdp	  if (src->relent.sym_ptr_ptr != NULL)
208138889Sjdp	    src->relent.sym_ptr_ptr =
208238889Sjdp	      src->relent.sym_ptr_ptr[0]->section->symbol_ptr_ptr;
208333965Sjdp	  break;
208433965Sjdp	default:
208533965Sjdp
208633965Sjdp	  BFD_FAIL ();
208733965Sjdp	}
208833965Sjdp      *relptr++ = &src->relent;
208933965Sjdp      src = src->next;
209033965Sjdp    }
2091218822Sdim  *relptr = NULL;
209233965Sjdp  return section->reloc_count;
209333965Sjdp}
209433965Sjdp
209533965Sjdpstatic int
2096218822Sdimcomp (const void * ap, const void * bp)
209733965Sjdp{
209833965Sjdp  arelent *a = *((arelent **) ap);
209933965Sjdp  arelent *b = *((arelent **) bp);
210033965Sjdp  return a->address - b->address;
210133965Sjdp}
210233965Sjdp
210333965Sjdp/* Write the section headers.  */
210433965Sjdp
2105130561Sobrienstatic bfd_boolean
2106218822Sdimieee_write_section_part (bfd *abfd)
210733965Sjdp{
210833965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
210933965Sjdp  asection *s;
2110218822Sdim
211133965Sjdp  ieee->w.r.section_part = bfd_tell (abfd);
211233965Sjdp  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
211333965Sjdp    {
211433965Sjdp      if (! bfd_is_abs_section (s)
211533965Sjdp	  && (s->flags & SEC_DEBUGGING) == 0)
211633965Sjdp	{
211733965Sjdp	  if (! ieee_write_byte (abfd, ieee_section_type_enum)
211833965Sjdp	      || ! ieee_write_byte (abfd,
211933965Sjdp				    (bfd_byte) (s->index
212033965Sjdp						+ IEEE_SECTION_NUMBER_BASE)))
2121130561Sobrien	    return FALSE;
212233965Sjdp
212333965Sjdp	  if (abfd->flags & EXEC_P)
212433965Sjdp	    {
2125130561Sobrien	      /* This image is executable, so output absolute sections.  */
212633965Sjdp	      if (! ieee_write_byte (abfd, ieee_variable_A_enum)
212733965Sjdp		  || ! ieee_write_byte (abfd, ieee_variable_S_enum))
2128130561Sobrien		return FALSE;
212933965Sjdp	    }
213033965Sjdp	  else
213133965Sjdp	    {
213233965Sjdp	      if (! ieee_write_byte (abfd, ieee_variable_C_enum))
2133130561Sobrien		return FALSE;
213433965Sjdp	    }
213533965Sjdp
213633965Sjdp	  switch (s->flags & (SEC_CODE | SEC_DATA | SEC_ROM))
213733965Sjdp	    {
213833965Sjdp	    case SEC_CODE | SEC_LOAD:
213933965Sjdp	    case SEC_CODE:
214033965Sjdp	      if (! ieee_write_byte (abfd, ieee_variable_P_enum))
2141130561Sobrien		return FALSE;
214233965Sjdp	      break;
214333965Sjdp	    case SEC_DATA:
214433965Sjdp	    default:
214533965Sjdp	      if (! ieee_write_byte (abfd, ieee_variable_D_enum))
2146130561Sobrien		return FALSE;
214733965Sjdp	      break;
214833965Sjdp	    case SEC_ROM:
214933965Sjdp	    case SEC_ROM | SEC_DATA:
215033965Sjdp	    case SEC_ROM | SEC_LOAD:
215133965Sjdp	    case SEC_ROM | SEC_DATA | SEC_LOAD:
215233965Sjdp	      if (! ieee_write_byte (abfd, ieee_variable_R_enum))
2153130561Sobrien		return FALSE;
215433965Sjdp	    }
215533965Sjdp
215633965Sjdp
215733965Sjdp	  if (! ieee_write_id (abfd, s->name))
2158130561Sobrien	    return FALSE;
2159130561Sobrien	  /* Alignment.  */
216033965Sjdp	  if (! ieee_write_byte (abfd, ieee_section_alignment_enum)
216133965Sjdp	      || ! ieee_write_byte (abfd,
216233965Sjdp				    (bfd_byte) (s->index
216333965Sjdp						+ IEEE_SECTION_NUMBER_BASE))
216489857Sobrien	      || ! ieee_write_int (abfd, (bfd_vma) 1 << s->alignment_power))
2165130561Sobrien	    return FALSE;
216633965Sjdp
2167130561Sobrien	  /* Size.  */
216833965Sjdp	  if (! ieee_write_2bytes (abfd, ieee_section_size_enum)
216933965Sjdp	      || ! ieee_write_byte (abfd,
217033965Sjdp				    (bfd_byte) (s->index
217133965Sjdp						+ IEEE_SECTION_NUMBER_BASE))
2172218822Sdim	      || ! ieee_write_int (abfd, s->size))
2173130561Sobrien	    return FALSE;
217433965Sjdp	  if (abfd->flags & EXEC_P)
217533965Sjdp	    {
2176130561Sobrien	      /* Relocateable sections don't have asl records.  */
2177130561Sobrien	      /* Vma.  */
217833965Sjdp	      if (! ieee_write_2bytes (abfd, ieee_section_base_address_enum)
217933965Sjdp		  || ! ieee_write_byte (abfd,
218033965Sjdp					((bfd_byte)
218133965Sjdp					 (s->index
218233965Sjdp					  + IEEE_SECTION_NUMBER_BASE)))
218333965Sjdp		  || ! ieee_write_int (abfd, s->lma))
2184130561Sobrien		return FALSE;
218533965Sjdp	    }
218633965Sjdp	}
218733965Sjdp    }
218833965Sjdp
2189130561Sobrien  return TRUE;
219033965Sjdp}
219133965Sjdp
2192130561Sobrienstatic bfd_boolean
2193218822Sdimdo_with_relocs (bfd *abfd, asection *s)
219433965Sjdp{
219533965Sjdp  unsigned int number_of_maus_in_address =
219633965Sjdp    bfd_arch_bits_per_address (abfd) / bfd_arch_bits_per_byte (abfd);
219733965Sjdp  unsigned int relocs_to_go = s->reloc_count;
219833965Sjdp  bfd_byte *stream = ieee_per_section (s)->data;
219933965Sjdp  arelent **p = s->orelocation;
220033965Sjdp  bfd_size_type current_byte_index = 0;
220133965Sjdp
220233965Sjdp  qsort (s->orelocation,
220333965Sjdp	 relocs_to_go,
220433965Sjdp	 sizeof (arelent **),
220533965Sjdp	 comp);
220633965Sjdp
2207130561Sobrien  /* Output the section preheader.  */
220833965Sjdp  if (! ieee_write_byte (abfd, ieee_set_current_section_enum)
220933965Sjdp      || ! ieee_write_byte (abfd,
221033965Sjdp			    (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE))
221133965Sjdp      || ! ieee_write_2bytes (abfd, ieee_set_current_pc_enum)
221233965Sjdp      || ! ieee_write_byte (abfd,
221333965Sjdp			    (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE)))
2214130561Sobrien    return FALSE;
221589857Sobrien
221633965Sjdp  if ((abfd->flags & EXEC_P) != 0 && relocs_to_go == 0)
221733965Sjdp    {
221833965Sjdp      if (! ieee_write_int (abfd, s->lma))
2219130561Sobrien	return FALSE;
222033965Sjdp    }
222133965Sjdp  else
222233965Sjdp    {
222389857Sobrien      if (! ieee_write_expression (abfd, (bfd_vma) 0, s->symbol, 0, 0))
2224130561Sobrien	return FALSE;
222533965Sjdp    }
222633965Sjdp
222733965Sjdp  if (relocs_to_go == 0)
222833965Sjdp    {
222933965Sjdp      /* If there aren't any relocations then output the load constant
2230130561Sobrien	 byte opcode rather than the load with relocation opcode.  */
2231218822Sdim      while (current_byte_index < s->size)
223233965Sjdp	{
223333965Sjdp	  bfd_size_type run;
223433965Sjdp	  unsigned int MAXRUN = 127;
2235130561Sobrien
223633965Sjdp	  run = MAXRUN;
2237218822Sdim	  if (run > s->size - current_byte_index)
2238218822Sdim	    run = s->size - current_byte_index;
223933965Sjdp
224033965Sjdp	  if (run != 0)
224133965Sjdp	    {
224233965Sjdp	      if (! ieee_write_byte (abfd, ieee_load_constant_bytes_enum))
2243130561Sobrien		return FALSE;
2244130561Sobrien	      /* Output a stream of bytes.  */
224533965Sjdp	      if (! ieee_write_int (abfd, run))
2246130561Sobrien		return FALSE;
2247218822Sdim	      if (bfd_bwrite ((void *) (stream + current_byte_index), run, abfd)
224833965Sjdp		  != run)
2249130561Sobrien		return FALSE;
225033965Sjdp	      current_byte_index += run;
225133965Sjdp	    }
225233965Sjdp	}
225333965Sjdp    }
225433965Sjdp  else
225533965Sjdp    {
225633965Sjdp      if (! ieee_write_byte (abfd, ieee_load_with_relocation_enum))
2257130561Sobrien	return FALSE;
225833965Sjdp
225933965Sjdp      /* Output the data stream as the longest sequence of bytes
226033965Sjdp	 possible, allowing for the a reasonable packet size and
226133965Sjdp	 relocation stuffs.  */
2262218822Sdim      if (stream == NULL)
226333965Sjdp	{
2264130561Sobrien	  /* Outputting a section without data, fill it up.  */
2265218822Sdim	  stream = bfd_zalloc (abfd, s->size);
226633965Sjdp	  if (!stream)
2267130561Sobrien	    return FALSE;
226833965Sjdp	}
2269218822Sdim      while (current_byte_index < s->size)
227033965Sjdp	{
227133965Sjdp	  bfd_size_type run;
227233965Sjdp	  unsigned int MAXRUN = 127;
2273130561Sobrien
227433965Sjdp	  if (relocs_to_go)
227533965Sjdp	    {
227633965Sjdp	      run = (*p)->address - current_byte_index;
227733965Sjdp	      if (run > MAXRUN)
227833965Sjdp		run = MAXRUN;
227933965Sjdp	    }
228033965Sjdp	  else
2281130561Sobrien	    run = MAXRUN;
2282130561Sobrien
2283218822Sdim	  if (run > s->size - current_byte_index)
2284218822Sdim	    run = s->size - current_byte_index;
228533965Sjdp
228633965Sjdp	  if (run != 0)
228733965Sjdp	    {
2288130561Sobrien	      /* Output a stream of bytes.  */
228933965Sjdp	      if (! ieee_write_int (abfd, run))
2290130561Sobrien		return FALSE;
2291218822Sdim	      if (bfd_bwrite ((void *) (stream + current_byte_index), run, abfd)
229233965Sjdp		  != run)
2293130561Sobrien		return FALSE;
229433965Sjdp	      current_byte_index += run;
229533965Sjdp	    }
2296130561Sobrien
2297130561Sobrien	  /* Output any relocations here.  */
229833965Sjdp	  if (relocs_to_go && (*p) && (*p)->address == current_byte_index)
229933965Sjdp	    {
230033965Sjdp	      while (relocs_to_go
230133965Sjdp		     && (*p) && (*p)->address == current_byte_index)
230233965Sjdp		{
230333965Sjdp		  arelent *r = *p;
230433965Sjdp		  bfd_signed_vma ov;
230533965Sjdp		  switch (r->howto->size)
230633965Sjdp		    {
230733965Sjdp		    case 2:
230833965Sjdp		      ov = bfd_get_signed_32 (abfd,
230933965Sjdp					      stream + current_byte_index);
231033965Sjdp		      current_byte_index += 4;
231133965Sjdp		      break;
231233965Sjdp		    case 1:
231333965Sjdp		      ov = bfd_get_signed_16 (abfd,
231433965Sjdp					      stream + current_byte_index);
231533965Sjdp		      current_byte_index += 2;
231633965Sjdp		      break;
231733965Sjdp		    case 0:
231833965Sjdp		      ov = bfd_get_signed_8 (abfd,
231933965Sjdp					     stream + current_byte_index);
232033965Sjdp		      current_byte_index++;
232133965Sjdp		      break;
232233965Sjdp		    default:
232333965Sjdp		      ov = 0;
232433965Sjdp		      BFD_FAIL ();
2325130561Sobrien		      return FALSE;
232633965Sjdp		    }
232733965Sjdp
232833965Sjdp		  ov &= r->howto->src_mask;
232933965Sjdp
233033965Sjdp		  if (r->howto->pc_relative
233133965Sjdp		      && ! r->howto->pcrel_offset)
233233965Sjdp		    ov += r->address;
233333965Sjdp
233433965Sjdp		  if (! ieee_write_byte (abfd,
233533965Sjdp					 ieee_function_either_open_b_enum))
2336130561Sobrien		    return FALSE;
233733965Sjdp
233833965Sjdp		  if (r->sym_ptr_ptr != (asymbol **) NULL)
233933965Sjdp		    {
234033965Sjdp		      if (! ieee_write_expression (abfd, r->addend + ov,
234133965Sjdp						   *(r->sym_ptr_ptr),
234233965Sjdp						   r->howto->pc_relative,
234389857Sobrien						   (unsigned) s->index))
2344130561Sobrien			return FALSE;
234533965Sjdp		    }
234633965Sjdp		  else
234733965Sjdp		    {
234833965Sjdp		      if (! ieee_write_expression (abfd, r->addend + ov,
234933965Sjdp						   (asymbol *) NULL,
235033965Sjdp						   r->howto->pc_relative,
235189857Sobrien						   (unsigned) s->index))
2352130561Sobrien			return FALSE;
235333965Sjdp		    }
235433965Sjdp
235533965Sjdp		  if (number_of_maus_in_address
235633965Sjdp		      != bfd_get_reloc_size (r->howto))
235733965Sjdp		    {
235889857Sobrien		      bfd_vma rsize = bfd_get_reloc_size (r->howto);
235989857Sobrien		      if (! ieee_write_int (abfd, rsize))
2360130561Sobrien			return FALSE;
236133965Sjdp		    }
236233965Sjdp		  if (! ieee_write_byte (abfd,
236333965Sjdp					 ieee_function_either_close_b_enum))
2364130561Sobrien		    return FALSE;
236533965Sjdp
236633965Sjdp		  relocs_to_go--;
236733965Sjdp		  p++;
236833965Sjdp		}
236933965Sjdp
237033965Sjdp	    }
237133965Sjdp	}
237233965Sjdp    }
237333965Sjdp
2374130561Sobrien  return TRUE;
237533965Sjdp}
237633965Sjdp
237733965Sjdp/* If there are no relocations in the output section then we can be
237833965Sjdp   clever about how we write.  We block items up into a max of 127
237933965Sjdp   bytes.  */
238033965Sjdp
2381130561Sobrienstatic bfd_boolean
2382218822Sdimdo_as_repeat (bfd *abfd, asection *s)
238333965Sjdp{
2384218822Sdim  if (s->size)
238533965Sjdp    {
238633965Sjdp      if (! ieee_write_byte (abfd, ieee_set_current_section_enum)
238733965Sjdp	  || ! ieee_write_byte (abfd,
238833965Sjdp				(bfd_byte) (s->index
238933965Sjdp					    + IEEE_SECTION_NUMBER_BASE))
239033965Sjdp	  || ! ieee_write_byte (abfd, ieee_set_current_pc_enum >> 8)
239133965Sjdp	  || ! ieee_write_byte (abfd, ieee_set_current_pc_enum & 0xff)
239233965Sjdp	  || ! ieee_write_byte (abfd,
239333965Sjdp				(bfd_byte) (s->index
239489857Sobrien					    + IEEE_SECTION_NUMBER_BASE)))
2395130561Sobrien	return FALSE;
239689857Sobrien
239789857Sobrien      if ((abfd->flags & EXEC_P) != 0)
239889857Sobrien	{
239989857Sobrien	  if (! ieee_write_int (abfd, s->lma))
2400130561Sobrien	    return FALSE;
240189857Sobrien	}
240289857Sobrien      else
240389857Sobrien	{
240489857Sobrien	  if (! ieee_write_expression (abfd, (bfd_vma) 0, s->symbol, 0, 0))
2405130561Sobrien	    return FALSE;
240689857Sobrien	}
240789857Sobrien
240889857Sobrien      if (! ieee_write_byte (abfd, ieee_repeat_data_enum)
2409218822Sdim	  || ! ieee_write_int (abfd, s->size)
241033965Sjdp	  || ! ieee_write_byte (abfd, ieee_load_constant_bytes_enum)
241133965Sjdp	  || ! ieee_write_byte (abfd, 1)
241233965Sjdp	  || ! ieee_write_byte (abfd, 0))
2413130561Sobrien	return FALSE;
241433965Sjdp    }
241533965Sjdp
2416130561Sobrien  return TRUE;
241733965Sjdp}
241833965Sjdp
2419130561Sobrienstatic bfd_boolean
2420218822Sdimdo_without_relocs (bfd *abfd, asection *s)
242133965Sjdp{
242233965Sjdp  bfd_byte *stream = ieee_per_section (s)->data;
242333965Sjdp
242433965Sjdp  if (stream == 0 || ((s->flags & SEC_LOAD) == 0))
242533965Sjdp    {
242633965Sjdp      if (! do_as_repeat (abfd, s))
2427130561Sobrien	return FALSE;
242833965Sjdp    }
242933965Sjdp  else
243033965Sjdp    {
243133965Sjdp      unsigned int i;
2432130561Sobrien
2433218822Sdim      for (i = 0; i < s->size; i++)
243433965Sjdp	{
243533965Sjdp	  if (stream[i] != 0)
243633965Sjdp	    {
243733965Sjdp	      if (! do_with_relocs (abfd, s))
2438130561Sobrien		return FALSE;
2439130561Sobrien	      return TRUE;
244033965Sjdp	    }
244133965Sjdp	}
244233965Sjdp      if (! do_as_repeat (abfd, s))
2443130561Sobrien	return FALSE;
244433965Sjdp    }
244533965Sjdp
2446130561Sobrien  return TRUE;
244733965Sjdp}
244833965Sjdp
244933965Sjdpstatic void
2450218822Sdimfill (void)
245133965Sjdp{
245289857Sobrien  bfd_size_type amt = input_ptr_end - input_ptr_start;
245333965Sjdp  /* FIXME: Check return value.  I'm not sure whether it needs to read
245433965Sjdp     the entire buffer or not.  */
2455218822Sdim  bfd_bread ((void *) input_ptr_start, amt, input_bfd);
245633965Sjdp  input_ptr = input_ptr_start;
245733965Sjdp}
245889857Sobrien
245933965Sjdpstatic void
2460218822Sdimflush (void)
246133965Sjdp{
246289857Sobrien  bfd_size_type amt = output_ptr - output_ptr_start;
2463130561Sobrien
2464218822Sdim  if (bfd_bwrite ((void *) (output_ptr_start), amt, output_bfd) != amt)
246533965Sjdp    abort ();
246633965Sjdp  output_ptr = output_ptr_start;
246733965Sjdp  output_buffer++;
246833965Sjdp}
246933965Sjdp
247033965Sjdp#define THIS() ( *input_ptr )
2471218822Sdim#define NEXT() { input_ptr++; if (input_ptr == input_ptr_end) fill (); }
2472218822Sdim#define OUT(x) { *output_ptr++ = (x); if (output_ptr == output_ptr_end)  flush (); }
247333965Sjdp
247433965Sjdpstatic void
2475218822Sdimwrite_int (int value)
247633965Sjdp{
247733965Sjdp  if (value >= 0 && value <= 127)
247833965Sjdp    {
247933965Sjdp      OUT (value);
248033965Sjdp    }
248133965Sjdp  else
248233965Sjdp    {
248333965Sjdp      unsigned int length;
2484218822Sdim
2485130561Sobrien      /* How many significant bytes ?  */
2486130561Sobrien      /* FIXME FOR LONGER INTS.  */
248733965Sjdp      if (value & 0xff000000)
2488130561Sobrien	length = 4;
248933965Sjdp      else if (value & 0x00ff0000)
2490130561Sobrien	length = 3;
249133965Sjdp      else if (value & 0x0000ff00)
2492130561Sobrien	length = 2;
249333965Sjdp      else
249433965Sjdp	length = 1;
249533965Sjdp
249633965Sjdp      OUT ((int) ieee_number_repeat_start_enum + length);
249733965Sjdp      switch (length)
249833965Sjdp	{
249933965Sjdp	case 4:
250033965Sjdp	  OUT (value >> 24);
250133965Sjdp	case 3:
250233965Sjdp	  OUT (value >> 16);
250333965Sjdp	case 2:
250433965Sjdp	  OUT (value >> 8);
250533965Sjdp	case 1:
250633965Sjdp	  OUT (value);
250733965Sjdp	}
250833965Sjdp    }
250933965Sjdp}
251033965Sjdp
251133965Sjdpstatic void
2512218822Sdimcopy_id (void)
251333965Sjdp{
251433965Sjdp  int length = THIS ();
251533965Sjdp  char ch;
2516130561Sobrien
251733965Sjdp  OUT (length);
251833965Sjdp  NEXT ();
251933965Sjdp  while (length--)
252033965Sjdp    {
252133965Sjdp      ch = THIS ();
252233965Sjdp      OUT (ch);
252333965Sjdp      NEXT ();
252433965Sjdp    }
252533965Sjdp}
252633965Sjdp
252733965Sjdp#define VAR(x) ((x | 0x80))
252833965Sjdpstatic void
2529218822Sdimcopy_expression (void)
253033965Sjdp{
253133965Sjdp  int stack[10];
253233965Sjdp  int *tos = stack;
253389857Sobrien  int value;
2534130561Sobrien
253533965Sjdp  while (1)
253633965Sjdp    {
253733965Sjdp      switch (THIS ())
253833965Sjdp	{
253933965Sjdp	case 0x84:
254033965Sjdp	  NEXT ();
254133965Sjdp	  value = THIS ();
254233965Sjdp	  NEXT ();
254333965Sjdp	  value = (value << 8) | THIS ();
254433965Sjdp	  NEXT ();
254533965Sjdp	  value = (value << 8) | THIS ();
254633965Sjdp	  NEXT ();
254733965Sjdp	  value = (value << 8) | THIS ();
254833965Sjdp	  NEXT ();
254933965Sjdp	  *tos++ = value;
255033965Sjdp	  break;
255133965Sjdp	case 0x83:
255233965Sjdp	  NEXT ();
255333965Sjdp	  value = THIS ();
255433965Sjdp	  NEXT ();
255533965Sjdp	  value = (value << 8) | THIS ();
255633965Sjdp	  NEXT ();
255733965Sjdp	  value = (value << 8) | THIS ();
255833965Sjdp	  NEXT ();
255933965Sjdp	  *tos++ = value;
256033965Sjdp	  break;
256133965Sjdp	case 0x82:
256233965Sjdp	  NEXT ();
256333965Sjdp	  value = THIS ();
256433965Sjdp	  NEXT ();
256533965Sjdp	  value = (value << 8) | THIS ();
256633965Sjdp	  NEXT ();
256733965Sjdp	  *tos++ = value;
256833965Sjdp	  break;
256933965Sjdp	case 0x81:
257033965Sjdp	  NEXT ();
257133965Sjdp	  value = THIS ();
257233965Sjdp	  NEXT ();
257333965Sjdp	  *tos++ = value;
257433965Sjdp	  break;
257533965Sjdp	case 0x80:
257633965Sjdp	  NEXT ();
257733965Sjdp	  *tos++ = 0;
257833965Sjdp	  break;
257933965Sjdp	default:
258033965Sjdp	  if (THIS () > 0x84)
258133965Sjdp	    {
2582130561Sobrien	      /* Not a number, just bug out with the answer.  */
258333965Sjdp	      write_int (*(--tos));
258433965Sjdp	      return;
258533965Sjdp	    }
258633965Sjdp	  *tos++ = THIS ();
258733965Sjdp	  NEXT ();
258833965Sjdp	  break;
258933965Sjdp	case 0xa5:
2590130561Sobrien	  /* PLUS anything.  */
259189857Sobrien	  value = *(--tos);
259289857Sobrien	  value += *(--tos);
259389857Sobrien	  *tos++ = value;
259489857Sobrien	  NEXT ();
259533965Sjdp	  break;
259633965Sjdp	case VAR ('R'):
259733965Sjdp	  {
259833965Sjdp	    int section_number;
259933965Sjdp	    ieee_data_type *ieee;
260033965Sjdp	    asection *s;
2601130561Sobrien
260233965Sjdp	    NEXT ();
260333965Sjdp	    section_number = THIS ();
260433965Sjdp
260533965Sjdp	    NEXT ();
260633965Sjdp	    ieee = IEEE_DATA (input_bfd);
260733965Sjdp	    s = ieee->section_table[section_number];
260889857Sobrien	    value = 0;
260933965Sjdp	    if (s->output_section)
261089857Sobrien	      value = s->output_section->lma;
261133965Sjdp	    value += s->output_offset;
261233965Sjdp	    *tos++ = value;
261333965Sjdp	  }
261433965Sjdp	  break;
261533965Sjdp	case 0x90:
261633965Sjdp	  {
261733965Sjdp	    NEXT ();
261833965Sjdp	    write_int (*(--tos));
261933965Sjdp	    OUT (0x90);
262033965Sjdp	    return;
262133965Sjdp	  }
262233965Sjdp	}
262333965Sjdp    }
262433965Sjdp}
262533965Sjdp
262633965Sjdp/* Drop the int in the buffer, and copy a null into the gap, which we
2627218822Sdim   will overwrite later.  */
262833965Sjdp
262933965Sjdpstatic void
2630218822Sdimfill_int (struct output_buffer_struct *buf)
263133965Sjdp{
263233965Sjdp  if (buf->buffer == output_buffer)
263333965Sjdp    {
2634130561Sobrien      /* Still a chance to output the size.  */
263533965Sjdp      int value = output_ptr - buf->ptrp + 3;
263633965Sjdp      buf->ptrp[0] = value >> 24;
263733965Sjdp      buf->ptrp[1] = value >> 16;
263833965Sjdp      buf->ptrp[2] = value >> 8;
263933965Sjdp      buf->ptrp[3] = value >> 0;
264033965Sjdp    }
264133965Sjdp}
264233965Sjdp
264333965Sjdpstatic void
2644218822Sdimdrop_int (struct output_buffer_struct *buf)
264533965Sjdp{
264633965Sjdp  int type = THIS ();
264733965Sjdp  int ch;
2648130561Sobrien
264933965Sjdp  if (type <= 0x84)
265033965Sjdp    {
265133965Sjdp      NEXT ();
265233965Sjdp      switch (type)
265333965Sjdp	{
265433965Sjdp	case 0x84:
265533965Sjdp	  ch = THIS ();
265633965Sjdp	  NEXT ();
265733965Sjdp	case 0x83:
265833965Sjdp	  ch = THIS ();
265933965Sjdp	  NEXT ();
266033965Sjdp	case 0x82:
266133965Sjdp	  ch = THIS ();
266233965Sjdp	  NEXT ();
266333965Sjdp	case 0x81:
266433965Sjdp	  ch = THIS ();
266533965Sjdp	  NEXT ();
266633965Sjdp	case 0x80:
266733965Sjdp	  break;
266833965Sjdp	}
266933965Sjdp    }
267033965Sjdp  OUT (0x84);
267133965Sjdp  buf->ptrp = output_ptr;
267233965Sjdp  buf->buffer = output_buffer;
267333965Sjdp  OUT (0);
267433965Sjdp  OUT (0);
267533965Sjdp  OUT (0);
267633965Sjdp  OUT (0);
267733965Sjdp}
267833965Sjdp
267933965Sjdpstatic void
2680218822Sdimcopy_int (void)
268133965Sjdp{
268233965Sjdp  int type = THIS ();
268333965Sjdp  int ch;
268433965Sjdp  if (type <= 0x84)
268533965Sjdp    {
268633965Sjdp      OUT (type);
268733965Sjdp      NEXT ();
268833965Sjdp      switch (type)
268933965Sjdp	{
269033965Sjdp	case 0x84:
269133965Sjdp	  ch = THIS ();
269233965Sjdp	  NEXT ();
269333965Sjdp	  OUT (ch);
269433965Sjdp	case 0x83:
269533965Sjdp	  ch = THIS ();
269633965Sjdp	  NEXT ();
269733965Sjdp	  OUT (ch);
269833965Sjdp	case 0x82:
269933965Sjdp	  ch = THIS ();
270033965Sjdp	  NEXT ();
270133965Sjdp	  OUT (ch);
270233965Sjdp	case 0x81:
270333965Sjdp	  ch = THIS ();
270433965Sjdp	  NEXT ();
270533965Sjdp	  OUT (ch);
270633965Sjdp	case 0x80:
270733965Sjdp	  break;
270833965Sjdp	}
270933965Sjdp    }
271033965Sjdp}
271133965Sjdp
2712218822Sdim#define ID      copy_id ()
2713218822Sdim#define INT     copy_int ()
2714218822Sdim#define EXP     copy_expression ()
2715218822Sdim#define INTn(q) copy_int ()
2716218822Sdim#define EXPn(q) copy_expression ()
271733965Sjdp
271833965Sjdpstatic void
2719218822Sdimcopy_till_end (void)
272033965Sjdp{
2721218822Sdim  int ch = THIS ();
2722218822Sdim
2723218822Sdim  while (1)
2724218822Sdim    {
2725218822Sdim      while (ch <= 0x80)
2726218822Sdim	{
2727218822Sdim	  OUT (ch);
2728218822Sdim	  NEXT ();
2729218822Sdim	  ch = THIS ();
2730218822Sdim	}
2731218822Sdim      switch (ch)
2732218822Sdim	{
2733218822Sdim	case 0x84:
2734218822Sdim	  OUT (THIS ());
2735218822Sdim	  NEXT ();
2736218822Sdim	case 0x83:
2737218822Sdim	  OUT (THIS ());
2738218822Sdim	  NEXT ();
2739218822Sdim	case 0x82:
2740218822Sdim	  OUT (THIS ());
2741218822Sdim	  NEXT ();
2742218822Sdim	case 0x81:
2743218822Sdim	  OUT (THIS ());
2744218822Sdim	  NEXT ();
2745218822Sdim	  OUT (THIS ());
2746218822Sdim	  NEXT ();
2747218822Sdim
2748218822Sdim	  ch = THIS ();
2749218822Sdim	  break;
2750218822Sdim	default:
2751218822Sdim	  return;
2752218822Sdim	}
2753218822Sdim    }
2754218822Sdim
2755218822Sdim}
2756218822Sdim
2757218822Sdimstatic void
2758218822Sdimf1_record (void)
2759218822Sdim{
276033965Sjdp  int ch;
2761130561Sobrien
2762130561Sobrien  /* ATN record.  */
276333965Sjdp  NEXT ();
276433965Sjdp  ch = THIS ();
276533965Sjdp  switch (ch)
276633965Sjdp    {
276733965Sjdp    default:
276833965Sjdp      OUT (0xf1);
276933965Sjdp      OUT (ch);
277033965Sjdp      break;
277133965Sjdp    case 0xc9:
277233965Sjdp      NEXT ();
277333965Sjdp      OUT (0xf1);
277433965Sjdp      OUT (0xc9);
277533965Sjdp      INT;
277633965Sjdp      INT;
277733965Sjdp      ch = THIS ();
277833965Sjdp      switch (ch)
277933965Sjdp	{
278033965Sjdp	case 0x16:
278133965Sjdp	  NEXT ();
278233965Sjdp	  break;
278333965Sjdp	case 0x01:
278433965Sjdp	  NEXT ();
278533965Sjdp	  break;
278633965Sjdp	case 0x00:
278733965Sjdp	  NEXT ();
278833965Sjdp	  INT;
278933965Sjdp	  break;
279033965Sjdp	case 0x03:
279133965Sjdp	  NEXT ();
279233965Sjdp	  INT;
279333965Sjdp	  break;
279433965Sjdp	case 0x13:
279533965Sjdp	  EXPn (instruction address);
279633965Sjdp	  break;
279733965Sjdp	default:
279833965Sjdp	  break;
279933965Sjdp	}
280033965Sjdp      break;
280133965Sjdp    case 0xd8:
2802130561Sobrien      /* EXternal ref.  */
280333965Sjdp      NEXT ();
280433965Sjdp      OUT (0xf1);
280533965Sjdp      OUT (0xd8);
280633965Sjdp      EXP;
280733965Sjdp      EXP;
280833965Sjdp      EXP;
280933965Sjdp      EXP;
281033965Sjdp      break;
281133965Sjdp    case 0xce:
281233965Sjdp      NEXT ();
281333965Sjdp      OUT (0xf1);
281433965Sjdp      OUT (0xce);
281533965Sjdp      INT;
281633965Sjdp      INT;
281733965Sjdp      ch = THIS ();
281833965Sjdp      INT;
281933965Sjdp      switch (ch)
282033965Sjdp	{
282133965Sjdp	case 0x01:
282233965Sjdp	  INT;
282333965Sjdp	  INT;
282433965Sjdp	  break;
282533965Sjdp	case 0x02:
282633965Sjdp	  INT;
282733965Sjdp	  break;
282833965Sjdp	case 0x04:
282933965Sjdp	  EXPn (external function);
283033965Sjdp	  break;
283133965Sjdp	case 0x05:
283233965Sjdp	  break;
283333965Sjdp	case 0x07:
283433965Sjdp	  INTn (line number);
283533965Sjdp	  INT;
283633965Sjdp	case 0x08:
283733965Sjdp	  break;
283833965Sjdp	case 0x0a:
283933965Sjdp	  INTn (locked register);
284033965Sjdp	  INT;
284133965Sjdp	  break;
284233965Sjdp	case 0x3f:
284333965Sjdp	  copy_till_end ();
284433965Sjdp	  break;
284533965Sjdp	case 0x3e:
284633965Sjdp	  copy_till_end ();
284733965Sjdp	  break;
284833965Sjdp	case 0x40:
284933965Sjdp	  copy_till_end ();
285033965Sjdp	  break;
285133965Sjdp	case 0x41:
285233965Sjdp	  ID;
285333965Sjdp	  break;
285433965Sjdp	}
285533965Sjdp    }
285633965Sjdp}
285733965Sjdp
285833965Sjdpstatic void
2859218822Sdimf0_record (void)
286033965Sjdp{
2861130561Sobrien  /* Attribute record.  */
286233965Sjdp  NEXT ();
286333965Sjdp  OUT (0xf0);
286433965Sjdp  INTn (Symbol name);
286533965Sjdp  ID;
286633965Sjdp}
286733965Sjdp
286833965Sjdpstatic void
2869218822Sdimf2_record (void)
287033965Sjdp{
287133965Sjdp  NEXT ();
287233965Sjdp  OUT (0xf2);
287333965Sjdp  INT;
287433965Sjdp  NEXT ();
287533965Sjdp  OUT (0xce);
287633965Sjdp  INT;
287733965Sjdp  copy_till_end ();
287833965Sjdp}
287933965Sjdp
288033965Sjdpstatic void
2881218822Sdimf8_record (void)
288233965Sjdp{
288333965Sjdp  int ch;
288433965Sjdp  NEXT ();
288533965Sjdp  ch = THIS ();
288633965Sjdp  switch (ch)
288733965Sjdp    {
288833965Sjdp    case 0x01:
288933965Sjdp    case 0x02:
289033965Sjdp    case 0x03:
2891130561Sobrien      /* Unique typedefs for module.  */
2892130561Sobrien      /* GLobal typedefs.   */
2893130561Sobrien      /* High level module scope beginning.  */
289433965Sjdp      {
289533965Sjdp	struct output_buffer_struct ob;
2896130561Sobrien
289733965Sjdp	NEXT ();
289833965Sjdp	OUT (0xf8);
289933965Sjdp	OUT (ch);
290033965Sjdp	drop_int (&ob);
290133965Sjdp	ID;
290233965Sjdp
290333965Sjdp	block ();
290433965Sjdp
290533965Sjdp	NEXT ();
290633965Sjdp	fill_int (&ob);
290733965Sjdp	OUT (0xf9);
290833965Sjdp      }
290933965Sjdp      break;
291033965Sjdp    case 0x04:
2911130561Sobrien      /* Global function.  */
291233965Sjdp      {
291333965Sjdp	struct output_buffer_struct ob;
2914130561Sobrien
291533965Sjdp	NEXT ();
291633965Sjdp	OUT (0xf8);
291733965Sjdp	OUT (0x04);
291833965Sjdp	drop_int (&ob);
291933965Sjdp	ID;
292033965Sjdp	INTn (stack size);
292133965Sjdp	INTn (ret val);
292233965Sjdp	EXPn (offset);
292333965Sjdp
292433965Sjdp	block ();
292533965Sjdp
292633965Sjdp	NEXT ();
292733965Sjdp	OUT (0xf9);
292833965Sjdp	EXPn (size of block);
292933965Sjdp	fill_int (&ob);
293033965Sjdp      }
293133965Sjdp      break;
293233965Sjdp
293333965Sjdp    case 0x05:
2934130561Sobrien      /* File name for source line numbers.  */
293533965Sjdp      {
293633965Sjdp	struct output_buffer_struct ob;
2937130561Sobrien
293833965Sjdp	NEXT ();
293933965Sjdp	OUT (0xf8);
294033965Sjdp	OUT (0x05);
294133965Sjdp	drop_int (&ob);
294233965Sjdp	ID;
294333965Sjdp	INTn (year);
294433965Sjdp	INTn (month);
294533965Sjdp	INTn (day);
294633965Sjdp	INTn (hour);
294733965Sjdp	INTn (monute);
294833965Sjdp	INTn (second);
294933965Sjdp	block ();
295033965Sjdp	NEXT ();
295133965Sjdp	OUT (0xf9);
295233965Sjdp	fill_int (&ob);
295333965Sjdp      }
295433965Sjdp      break;
295533965Sjdp
295633965Sjdp    case 0x06:
2957130561Sobrien      /* Local function.  */
295833965Sjdp      {
295933965Sjdp	struct output_buffer_struct ob;
2960130561Sobrien
296133965Sjdp	NEXT ();
296233965Sjdp	OUT (0xf8);
296333965Sjdp	OUT (0x06);
296433965Sjdp	drop_int (&ob);
296533965Sjdp	ID;
296633965Sjdp	INTn (stack size);
296733965Sjdp	INTn (type return);
296833965Sjdp	EXPn (offset);
296933965Sjdp	block ();
297033965Sjdp	NEXT ();
297133965Sjdp	OUT (0xf9);
297233965Sjdp	EXPn (size);
297333965Sjdp	fill_int (&ob);
297433965Sjdp      }
297533965Sjdp      break;
297633965Sjdp
297733965Sjdp    case 0x0a:
2978130561Sobrien      /* Assembler module scope beginning -  */
297933965Sjdp      {
298033965Sjdp	struct output_buffer_struct ob;
298133965Sjdp
298233965Sjdp	NEXT ();
298333965Sjdp	OUT (0xf8);
298433965Sjdp	OUT (0x0a);
298533965Sjdp	drop_int (&ob);
298633965Sjdp	ID;
298733965Sjdp	ID;
298833965Sjdp	INT;
298933965Sjdp	ID;
299033965Sjdp	INT;
299133965Sjdp	INT;
299233965Sjdp	INT;
299333965Sjdp	INT;
299433965Sjdp	INT;
299533965Sjdp	INT;
299633965Sjdp
299733965Sjdp	block ();
299833965Sjdp
299933965Sjdp	NEXT ();
300033965Sjdp	OUT (0xf9);
300133965Sjdp	fill_int (&ob);
300233965Sjdp      }
300333965Sjdp      break;
300433965Sjdp    case 0x0b:
300533965Sjdp      {
300633965Sjdp	struct output_buffer_struct ob;
3007130561Sobrien
300833965Sjdp	NEXT ();
300933965Sjdp	OUT (0xf8);
301033965Sjdp	OUT (0x0b);
301133965Sjdp	drop_int (&ob);
301233965Sjdp	ID;
301333965Sjdp	INT;
301433965Sjdp	INTn (section index);
301533965Sjdp	EXPn (offset);
301633965Sjdp	INTn (stuff);
301733965Sjdp
301833965Sjdp	block ();
301933965Sjdp
302033965Sjdp	OUT (0xf9);
302133965Sjdp	NEXT ();
302233965Sjdp	EXPn (Size in Maus);
302333965Sjdp	fill_int (&ob);
302433965Sjdp      }
302533965Sjdp      break;
302633965Sjdp    }
302733965Sjdp}
302833965Sjdp
302933965Sjdpstatic void
3030218822Sdime2_record (void)
303133965Sjdp{
303233965Sjdp  OUT (0xe2);
303333965Sjdp  NEXT ();
303433965Sjdp  OUT (0xce);
303533965Sjdp  NEXT ();
303633965Sjdp  INT;
303733965Sjdp  EXP;
303833965Sjdp}
303933965Sjdp
304033965Sjdpstatic void
3041218822Sdimblock (void)
304233965Sjdp{
304333965Sjdp  int ch;
3044130561Sobrien
304533965Sjdp  while (1)
304633965Sjdp    {
304733965Sjdp      ch = THIS ();
304833965Sjdp      switch (ch)
304933965Sjdp	{
305033965Sjdp	case 0xe1:
305133965Sjdp	case 0xe5:
305233965Sjdp	  return;
305333965Sjdp	case 0xf9:
305433965Sjdp	  return;
305533965Sjdp	case 0xf0:
305633965Sjdp	  f0_record ();
305733965Sjdp	  break;
305833965Sjdp	case 0xf1:
305933965Sjdp	  f1_record ();
306033965Sjdp	  break;
306133965Sjdp	case 0xf2:
306233965Sjdp	  f2_record ();
306333965Sjdp	  break;
306433965Sjdp	case 0xf8:
306533965Sjdp	  f8_record ();
306633965Sjdp	  break;
306733965Sjdp	case 0xe2:
306833965Sjdp	  e2_record ();
306933965Sjdp	  break;
307033965Sjdp
307133965Sjdp	}
307233965Sjdp    }
307333965Sjdp}
307433965Sjdp
3075130561Sobrien/* Moves all the debug information from the source bfd to the output
3076130561Sobrien   bfd, and relocates any expressions it finds.  */
307733965Sjdp
307833965Sjdpstatic void
3079218822Sdimrelocate_debug (bfd *output ATTRIBUTE_UNUSED,
3080218822Sdim		bfd *input)
308133965Sjdp{
308233965Sjdp#define IBS 400
308333965Sjdp#define OBS 400
308433965Sjdp  unsigned char input_buffer[IBS];
308533965Sjdp
308633965Sjdp  input_ptr_start = input_ptr = input_buffer;
308733965Sjdp  input_ptr_end = input_buffer + IBS;
308833965Sjdp  input_bfd = input;
308933965Sjdp  /* FIXME: Check return value.  I'm not sure whether it needs to read
309033965Sjdp     the entire buffer or not.  */
3091218822Sdim  bfd_bread ((void *) input_ptr_start, (bfd_size_type) IBS, input);
309233965Sjdp  block ();
309333965Sjdp}
309433965Sjdp
309577298Sobrien/* Gather together all the debug information from each input BFD into
309677298Sobrien   one place, relocating it and emitting it as we go.  */
309733965Sjdp
3098130561Sobrienstatic bfd_boolean
3099218822Sdimieee_write_debug_part (bfd *abfd)
310033965Sjdp{
310133965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
310233965Sjdp  bfd_chain_type *chain = ieee->chain_root;
310389857Sobrien  unsigned char obuff[OBS];
3104130561Sobrien  bfd_boolean some_debug = FALSE;
310533965Sjdp  file_ptr here = bfd_tell (abfd);
310633965Sjdp
310789857Sobrien  output_ptr_start = output_ptr = obuff;
310889857Sobrien  output_ptr_end = obuff + OBS;
310989857Sobrien  output_ptr = obuff;
311033965Sjdp  output_bfd = abfd;
311133965Sjdp
311233965Sjdp  if (chain == (bfd_chain_type *) NULL)
311333965Sjdp    {
311433965Sjdp      asection *s;
311533965Sjdp
311633965Sjdp      for (s = abfd->sections; s != NULL; s = s->next)
311733965Sjdp	if ((s->flags & SEC_DEBUGGING) != 0)
311833965Sjdp	  break;
311933965Sjdp      if (s == NULL)
312033965Sjdp	{
312133965Sjdp	  ieee->w.r.debug_information_part = 0;
3122130561Sobrien	  return TRUE;
312333965Sjdp	}
312433965Sjdp
312533965Sjdp      ieee->w.r.debug_information_part = here;
3126218822Sdim      if (bfd_bwrite (s->contents, s->size, abfd) != s->size)
3127130561Sobrien	return FALSE;
312833965Sjdp    }
312933965Sjdp  else
313033965Sjdp    {
313133965Sjdp      while (chain != (bfd_chain_type *) NULL)
313233965Sjdp	{
313333965Sjdp	  bfd *entry = chain->this;
313433965Sjdp	  ieee_data_type *entry_ieee = IEEE_DATA (entry);
3135130561Sobrien
313633965Sjdp	  if (entry_ieee->w.r.debug_information_part)
313733965Sjdp	    {
313833965Sjdp	      if (bfd_seek (entry, entry_ieee->w.r.debug_information_part,
313989857Sobrien			    SEEK_SET) != 0)
3140130561Sobrien		return FALSE;
314133965Sjdp	      relocate_debug (abfd, entry);
314233965Sjdp	    }
314333965Sjdp
314433965Sjdp	  chain = chain->next;
314533965Sjdp	}
3146130561Sobrien
314733965Sjdp      if (some_debug)
3148130561Sobrien	ieee->w.r.debug_information_part = here;
314933965Sjdp      else
3150130561Sobrien	ieee->w.r.debug_information_part = 0;
315133965Sjdp
315233965Sjdp      flush ();
315333965Sjdp    }
315433965Sjdp
3155130561Sobrien  return TRUE;
315633965Sjdp}
315733965Sjdp
315833965Sjdp/* Write the data in an ieee way.  */
315933965Sjdp
3160130561Sobrienstatic bfd_boolean
3161218822Sdimieee_write_data_part (bfd *abfd)
316233965Sjdp{
316333965Sjdp  asection *s;
3164130561Sobrien
316533965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
316633965Sjdp  ieee->w.r.data_part = bfd_tell (abfd);
3167130561Sobrien
316833965Sjdp  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
316933965Sjdp    {
317033965Sjdp      /* Skip sections that have no loadable contents (.bss,
317133965Sjdp         debugging, etc.)  */
317233965Sjdp      if ((s->flags & SEC_LOAD) == 0)
317333965Sjdp	continue;
317433965Sjdp
317533965Sjdp      /* Sort the reloc records so we can insert them in the correct
3176218822Sdim	 places.  */
317733965Sjdp      if (s->reloc_count != 0)
317833965Sjdp	{
317933965Sjdp	  if (! do_with_relocs (abfd, s))
3180130561Sobrien	    return FALSE;
318133965Sjdp	}
318233965Sjdp      else
318333965Sjdp	{
318433965Sjdp	  if (! do_without_relocs (abfd, s))
3185130561Sobrien	    return FALSE;
318633965Sjdp	}
318733965Sjdp    }
318833965Sjdp
3189130561Sobrien  return TRUE;
319033965Sjdp}
319133965Sjdp
3192130561Sobrienstatic bfd_boolean
3193218822Sdiminit_for_output (bfd *abfd)
319433965Sjdp{
319533965Sjdp  asection *s;
3196130561Sobrien
319733965Sjdp  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
319833965Sjdp    {
319933965Sjdp      if ((s->flags & SEC_DEBUGGING) != 0)
320033965Sjdp	continue;
3201218822Sdim      if (s->size != 0)
320233965Sjdp	{
3203218822Sdim	  bfd_size_type size = s->size;
3204218822Sdim	  ieee_per_section (s)->data = bfd_alloc (abfd, size);
320533965Sjdp	  if (!ieee_per_section (s)->data)
3206130561Sobrien	    return FALSE;
320733965Sjdp	}
320833965Sjdp    }
3209130561Sobrien  return TRUE;
321033965Sjdp}
321133965Sjdp
3212130561Sobrien/* Exec and core file sections.  */
321333965Sjdp
3214130561Sobrien/* Set section contents is complicated with IEEE since the format is
3215130561Sobrien   not a byte image, but a record stream.  */
3216130561Sobrien
3217130561Sobrienstatic bfd_boolean
3218218822Sdimieee_set_section_contents (bfd *abfd,
3219218822Sdim			   sec_ptr section,
3220218822Sdim			   const void * location,
3221218822Sdim			   file_ptr offset,
3222218822Sdim			   bfd_size_type count)
322333965Sjdp{
322433965Sjdp  if ((section->flags & SEC_DEBUGGING) != 0)
322533965Sjdp    {
322633965Sjdp      if (section->contents == NULL)
322733965Sjdp	{
3228218822Sdim	  bfd_size_type size = section->size;
3229218822Sdim	  section->contents = bfd_alloc (abfd, size);
323033965Sjdp	  if (section->contents == NULL)
3231130561Sobrien	    return FALSE;
323233965Sjdp	}
323333965Sjdp      /* bfd_set_section_contents has already checked that everything
323433965Sjdp         is within range.  */
323589857Sobrien      memcpy (section->contents + offset, location, (size_t) count);
3236130561Sobrien      return TRUE;
323733965Sjdp    }
323833965Sjdp
323933965Sjdp  if (ieee_per_section (section)->data == (bfd_byte *) NULL)
324033965Sjdp    {
324133965Sjdp      if (!init_for_output (abfd))
3242130561Sobrien	return FALSE;
324333965Sjdp    }
3244218822Sdim  memcpy ((void *) (ieee_per_section (section)->data + offset),
3245218822Sdim	  (void *) location,
324633965Sjdp	  (unsigned int) count);
3247130561Sobrien  return TRUE;
324833965Sjdp}
324933965Sjdp
325033965Sjdp/* Write the external symbols of a file.  IEEE considers two sorts of
325133965Sjdp   external symbols, public, and referenced.  It uses to internal
325233965Sjdp   forms to index them as well.  When we write them out we turn their
325333965Sjdp   symbol values into indexes from the right base.  */
325433965Sjdp
3255130561Sobrienstatic bfd_boolean
3256218822Sdimieee_write_external_part (bfd *abfd)
325733965Sjdp{
325833965Sjdp  asymbol **q;
325933965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
326033965Sjdp  unsigned int reference_index = IEEE_REFERENCE_BASE;
326133965Sjdp  unsigned int public_index = IEEE_PUBLIC_BASE + 2;
326233965Sjdp  file_ptr here = bfd_tell (abfd);
3263130561Sobrien  bfd_boolean hadone = FALSE;
3264130561Sobrien
326533965Sjdp  if (abfd->outsymbols != (asymbol **) NULL)
326633965Sjdp    {
326733965Sjdp
326833965Sjdp      for (q = abfd->outsymbols; *q != (asymbol *) NULL; q++)
326933965Sjdp	{
327033965Sjdp	  asymbol *p = *q;
3271130561Sobrien
327233965Sjdp	  if (bfd_is_und_section (p->section))
327333965Sjdp	    {
3274130561Sobrien	      /* This must be a symbol reference.  */
327533965Sjdp	      if (! ieee_write_byte (abfd, ieee_external_reference_enum)
327689857Sobrien		  || ! ieee_write_int (abfd, (bfd_vma) reference_index)
327733965Sjdp		  || ! ieee_write_id (abfd, p->name))
3278130561Sobrien		return FALSE;
327933965Sjdp	      p->value = reference_index;
328033965Sjdp	      reference_index++;
3281130561Sobrien	      hadone = TRUE;
328233965Sjdp	    }
328333965Sjdp	  else if (bfd_is_com_section (p->section))
328433965Sjdp	    {
3285130561Sobrien	      /* This is a weak reference.  */
328633965Sjdp	      if (! ieee_write_byte (abfd, ieee_external_reference_enum)
328789857Sobrien		  || ! ieee_write_int (abfd, (bfd_vma) reference_index)
328833965Sjdp		  || ! ieee_write_id (abfd, p->name)
328933965Sjdp		  || ! ieee_write_byte (abfd,
329033965Sjdp					ieee_weak_external_reference_enum)
329189857Sobrien		  || ! ieee_write_int (abfd, (bfd_vma) reference_index)
329233965Sjdp		  || ! ieee_write_int (abfd, p->value))
3293130561Sobrien		return FALSE;
329433965Sjdp	      p->value = reference_index;
329533965Sjdp	      reference_index++;
3296130561Sobrien	      hadone = TRUE;
329733965Sjdp	    }
329833965Sjdp	  else if (p->flags & BSF_GLOBAL)
329933965Sjdp	    {
3300130561Sobrien	      /* This must be a symbol definition.  */
330133965Sjdp	      if (! ieee_write_byte (abfd, ieee_external_symbol_enum)
330289857Sobrien		  || ! ieee_write_int (abfd, (bfd_vma) public_index)
330333965Sjdp		  || ! ieee_write_id (abfd, p->name)
330433965Sjdp		  || ! ieee_write_2bytes (abfd, ieee_attribute_record_enum)
330589857Sobrien		  || ! ieee_write_int (abfd, (bfd_vma) public_index)
3306218822Sdim		  || ! ieee_write_byte (abfd, 15) /* Instruction address.  */
3307218822Sdim		  || ! ieee_write_byte (abfd, 19) /* Static symbol.  */
3308218822Sdim		  || ! ieee_write_byte (abfd, 1)) /* One of them.  */
3309130561Sobrien		return FALSE;
331033965Sjdp
3311130561Sobrien	      /* Write out the value.  */
331233965Sjdp	      if (! ieee_write_2bytes (abfd, ieee_value_record_enum)
331389857Sobrien		  || ! ieee_write_int (abfd, (bfd_vma) public_index))
3314130561Sobrien		return FALSE;
331533965Sjdp	      if (! bfd_is_abs_section (p->section))
331633965Sjdp		{
331733965Sjdp		  if (abfd->flags & EXEC_P)
331833965Sjdp		    {
331933965Sjdp		      /* If fully linked, then output all symbols
3320130561Sobrien			 relocated.  */
332133965Sjdp		      if (! (ieee_write_int
332233965Sjdp			     (abfd,
332333965Sjdp			      (p->value
332433965Sjdp			       + p->section->output_offset
332533965Sjdp			       + p->section->output_section->vma))))
3326130561Sobrien			return FALSE;
332733965Sjdp		    }
332833965Sjdp		  else
332933965Sjdp		    {
333033965Sjdp		      if (! (ieee_write_expression
333133965Sjdp			     (abfd,
333233965Sjdp			      p->value + p->section->output_offset,
333333965Sjdp			      p->section->output_section->symbol,
3334130561Sobrien			      FALSE, 0)))
3335130561Sobrien			return FALSE;
333633965Sjdp		    }
333733965Sjdp		}
333833965Sjdp	      else
333933965Sjdp		{
334033965Sjdp		  if (! ieee_write_expression (abfd,
334133965Sjdp					       p->value,
334233965Sjdp					       bfd_abs_section_ptr->symbol,
3343130561Sobrien					       FALSE, 0))
3344130561Sobrien		    return FALSE;
334533965Sjdp		}
334633965Sjdp	      p->value = public_index;
334733965Sjdp	      public_index++;
3348130561Sobrien	      hadone = TRUE;
334933965Sjdp	    }
335033965Sjdp	  else
335133965Sjdp	    {
3352130561Sobrien	      /* This can happen - when there are gaps in the symbols read
3353130561Sobrien	         from an input ieee file.  */
335433965Sjdp	    }
335533965Sjdp	}
335633965Sjdp    }
335733965Sjdp  if (hadone)
335833965Sjdp    ieee->w.r.external_part = here;
335933965Sjdp
3360130561Sobrien  return TRUE;
336133965Sjdp}
336233965Sjdp
336333965Sjdp
336489857Sobrienstatic const unsigned char exten[] =
336533965Sjdp{
336633965Sjdp  0xf0, 0x20, 0x00,
3367130561Sobrien  0xf1, 0xce, 0x20, 0x00, 37, 3, 3,	/* Set version 3 rev 3.  */
3368130561Sobrien  0xf1, 0xce, 0x20, 0x00, 39, 2,	/* Keep symbol in  original case.  */
3369130561Sobrien  0xf1, 0xce, 0x20, 0x00, 38		/* Set object type relocatable to x.  */
337033965Sjdp};
337133965Sjdp
337289857Sobrienstatic const unsigned char envi[] =
337333965Sjdp{
337433965Sjdp  0xf0, 0x21, 0x00,
337533965Sjdp
337633965Sjdp/*    0xf1, 0xce, 0x21, 00, 50, 0x82, 0x07, 0xc7, 0x09, 0x11, 0x11,
337733965Sjdp    0x19, 0x2c,
337833965Sjdp*/
3379218822Sdim  0xf1, 0xce, 0x21, 00, 52, 0x00,	/* exec ok.  */
338033965Sjdp
3381218822Sdim  0xf1, 0xce, 0x21, 0, 53, 0x03,/* host unix.  */
338233965Sjdp/*    0xf1, 0xce, 0x21, 0, 54, 2,1,1	tool & version # */
338333965Sjdp};
338433965Sjdp
3385130561Sobrienstatic bfd_boolean
3386218822Sdimieee_write_me_part (bfd *abfd)
338733965Sjdp{
338833965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
338933965Sjdp  ieee->w.r.trailer_part = bfd_tell (abfd);
339033965Sjdp  if (abfd->start_address)
339133965Sjdp    {
339233965Sjdp      if (! ieee_write_2bytes (abfd, ieee_value_starting_address_enum)
339333965Sjdp	  || ! ieee_write_byte (abfd, ieee_function_either_open_b_enum)
339433965Sjdp	  || ! ieee_write_int (abfd, abfd->start_address)
339533965Sjdp	  || ! ieee_write_byte (abfd, ieee_function_either_close_b_enum))
3396130561Sobrien	return FALSE;
339733965Sjdp    }
339833965Sjdp  ieee->w.r.me_record = bfd_tell (abfd);
339933965Sjdp  if (! ieee_write_byte (abfd, ieee_module_end_enum))
3400130561Sobrien    return FALSE;
3401130561Sobrien  return TRUE;
340233965Sjdp}
340333965Sjdp
340433965Sjdp/* Write out the IEEE processor ID.  */
340533965Sjdp
3406130561Sobrienstatic bfd_boolean
3407218822Sdimieee_write_processor (bfd *abfd)
340833965Sjdp{
340933965Sjdp  const bfd_arch_info_type *arch;
341033965Sjdp
341133965Sjdp  arch = bfd_get_arch_info (abfd);
341233965Sjdp  switch (arch->arch)
341333965Sjdp    {
341433965Sjdp    default:
341533965Sjdp      if (! ieee_write_id (abfd, bfd_printable_name (abfd)))
3416130561Sobrien	return FALSE;
341733965Sjdp      break;
341833965Sjdp
341933965Sjdp    case bfd_arch_h8300:
342033965Sjdp      if (! ieee_write_id (abfd, "H8/300"))
3421130561Sobrien	return FALSE;
342233965Sjdp      break;
342333965Sjdp
342433965Sjdp    case bfd_arch_h8500:
342533965Sjdp      if (! ieee_write_id (abfd, "H8/500"))
3426130561Sobrien	return FALSE;
342733965Sjdp      break;
342833965Sjdp
342933965Sjdp    case bfd_arch_i960:
343033965Sjdp      switch (arch->mach)
343133965Sjdp	{
343233965Sjdp	default:
343333965Sjdp	case bfd_mach_i960_core:
343433965Sjdp	case bfd_mach_i960_ka_sa:
343533965Sjdp	  if (! ieee_write_id (abfd, "80960KA"))
3436130561Sobrien	    return FALSE;
343733965Sjdp	  break;
343833965Sjdp
343933965Sjdp	case bfd_mach_i960_kb_sb:
344033965Sjdp	  if (! ieee_write_id (abfd, "80960KB"))
3441130561Sobrien	    return FALSE;
344233965Sjdp	  break;
344333965Sjdp
344433965Sjdp	case bfd_mach_i960_ca:
344533965Sjdp	  if (! ieee_write_id (abfd, "80960CA"))
3446130561Sobrien	    return FALSE;
344733965Sjdp	  break;
344833965Sjdp
344933965Sjdp	case bfd_mach_i960_mc:
345033965Sjdp	case bfd_mach_i960_xa:
345133965Sjdp	  if (! ieee_write_id (abfd, "80960MC"))
3452130561Sobrien	    return FALSE;
345333965Sjdp	  break;
345433965Sjdp	}
345533965Sjdp      break;
345633965Sjdp
345733965Sjdp    case bfd_arch_m68k:
345833965Sjdp      {
345960484Sobrien	const char *id;
346033965Sjdp
346160484Sobrien	switch (arch->mach)
346260484Sobrien	  {
346360484Sobrien	  default:		id = "68020"; break;
346460484Sobrien	  case bfd_mach_m68000: id = "68000"; break;
346560484Sobrien	  case bfd_mach_m68008: id = "68008"; break;
346660484Sobrien	  case bfd_mach_m68010: id = "68010"; break;
346760484Sobrien	  case bfd_mach_m68020: id = "68020"; break;
346860484Sobrien	  case bfd_mach_m68030: id = "68030"; break;
346960484Sobrien	  case bfd_mach_m68040: id = "68040"; break;
347060484Sobrien	  case bfd_mach_m68060: id = "68060"; break;
347160484Sobrien	  case bfd_mach_cpu32:  id = "cpu32"; break;
3472218822Sdim	  case bfd_mach_mcf_isa_a_nodiv: id = "isa-a:nodiv"; break;
3473218822Sdim	  case bfd_mach_mcf_isa_a: id = "isa-a"; break;
3474218822Sdim	  case bfd_mach_mcf_isa_a_mac: id = "isa-a:mac"; break;
3475218822Sdim	  case bfd_mach_mcf_isa_a_emac: id = "isa-a:emac"; break;
3476218822Sdim	  case bfd_mach_mcf_isa_aplus: id = "isa-aplus"; break;
3477218822Sdim	  case bfd_mach_mcf_isa_aplus_mac: id = "isa-aplus:mac"; break;
3478218822Sdim	  case bfd_mach_mcf_isa_aplus_emac: id = "isa-aplus:mac"; break;
3479218822Sdim	  case bfd_mach_mcf_isa_b_nousp: id = "isa-b:nousp"; break;
3480218822Sdim	  case bfd_mach_mcf_isa_b_nousp_mac: id = "isa-b:nousp:mac"; break;
3481218822Sdim	  case bfd_mach_mcf_isa_b_nousp_emac: id = "isa-b:nousp:emac"; break;
3482218822Sdim	  case bfd_mach_mcf_isa_b: id = "isa-b"; break;
3483218822Sdim	  case bfd_mach_mcf_isa_b_mac: id = "isa-b:mac"; break;
3484218822Sdim	  case bfd_mach_mcf_isa_b_emac: id = "isa-b:emac"; break;
3485218822Sdim	  case bfd_mach_mcf_isa_b_float: id = "isa-b:float"; break;
3486218822Sdim	  case bfd_mach_mcf_isa_b_float_mac: id = "isa-b:float:mac"; break;
3487218822Sdim	  case bfd_mach_mcf_isa_b_float_emac: id = "isa-b:float:emac"; break;
348860484Sobrien	  }
348960484Sobrien
349060484Sobrien	if (! ieee_write_id (abfd, id))
3491130561Sobrien	  return FALSE;
349233965Sjdp      }
349333965Sjdp      break;
349433965Sjdp    }
349533965Sjdp
3496130561Sobrien  return TRUE;
349733965Sjdp}
349833965Sjdp
3499130561Sobrienstatic bfd_boolean
3500218822Sdimieee_write_object_contents (bfd *abfd)
350133965Sjdp{
350233965Sjdp  ieee_data_type *ieee = IEEE_DATA (abfd);
350333965Sjdp  unsigned int i;
350433965Sjdp  file_ptr old;
350533965Sjdp
3506130561Sobrien  /* Fast forward over the header area.  */
350733965Sjdp  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
3508130561Sobrien    return FALSE;
350933965Sjdp
351033965Sjdp  if (! ieee_write_byte (abfd, ieee_module_beginning_enum)
351133965Sjdp      || ! ieee_write_processor (abfd)
351233965Sjdp      || ! ieee_write_id (abfd, abfd->filename))
3513130561Sobrien    return FALSE;
351433965Sjdp
3515130561Sobrien  /* Fast forward over the variable bits.  */
351633965Sjdp  if (! ieee_write_byte (abfd, ieee_address_descriptor_enum))
3517130561Sobrien    return FALSE;
351833965Sjdp
3519130561Sobrien  /* Bits per MAU.  */
352033965Sjdp  if (! ieee_write_byte (abfd, (bfd_byte) (bfd_arch_bits_per_byte (abfd))))
3521130561Sobrien    return FALSE;
3522130561Sobrien  /* MAU's per address.  */
352333965Sjdp  if (! ieee_write_byte (abfd,
352433965Sjdp			 (bfd_byte) (bfd_arch_bits_per_address (abfd)
352533965Sjdp				     / bfd_arch_bits_per_byte (abfd))))
3526130561Sobrien    return FALSE;
352733965Sjdp
352833965Sjdp  old = bfd_tell (abfd);
352933965Sjdp  if (bfd_seek (abfd, (file_ptr) (8 * N_W_VARIABLES), SEEK_CUR) != 0)
3530130561Sobrien    return FALSE;
353133965Sjdp
353233965Sjdp  ieee->w.r.extension_record = bfd_tell (abfd);
353389857Sobrien  if (bfd_bwrite ((char *) exten, (bfd_size_type) sizeof (exten), abfd)
353489857Sobrien      != sizeof (exten))
3535130561Sobrien    return FALSE;
353633965Sjdp  if (abfd->flags & EXEC_P)
353733965Sjdp    {
3538218822Sdim      if (! ieee_write_byte (abfd, 0x1)) /* Absolute.  */
3539130561Sobrien	return FALSE;
354033965Sjdp    }
354133965Sjdp  else
354233965Sjdp    {
3543218822Sdim      if (! ieee_write_byte (abfd, 0x2)) /* Relocateable.  */
3544130561Sobrien	return FALSE;
354533965Sjdp    }
354633965Sjdp
354733965Sjdp  ieee->w.r.environmental_record = bfd_tell (abfd);
354889857Sobrien  if (bfd_bwrite ((char *) envi, (bfd_size_type) sizeof (envi), abfd)
354989857Sobrien      != sizeof (envi))
3550130561Sobrien    return FALSE;
355133965Sjdp
355233965Sjdp  /* The HP emulator database requires a timestamp in the file.  */
355333965Sjdp  {
355433965Sjdp    time_t now;
355533965Sjdp    const struct tm *t;
355633965Sjdp
355733965Sjdp    time (&now);
355833965Sjdp    t = (struct tm *) localtime (&now);
355933965Sjdp    if (! ieee_write_2bytes (abfd, (int) ieee_atn_record_enum)
356033965Sjdp	|| ! ieee_write_byte (abfd, 0x21)
356133965Sjdp	|| ! ieee_write_byte (abfd, 0)
356233965Sjdp	|| ! ieee_write_byte (abfd, 50)
356389857Sobrien	|| ! ieee_write_int (abfd, (bfd_vma) (t->tm_year + 1900))
356489857Sobrien	|| ! ieee_write_int (abfd, (bfd_vma) (t->tm_mon + 1))
356589857Sobrien	|| ! ieee_write_int (abfd, (bfd_vma) t->tm_mday)
356689857Sobrien	|| ! ieee_write_int (abfd, (bfd_vma) t->tm_hour)
356789857Sobrien	|| ! ieee_write_int (abfd, (bfd_vma) t->tm_min)
356889857Sobrien	|| ! ieee_write_int (abfd, (bfd_vma) t->tm_sec))
3569130561Sobrien      return FALSE;
357033965Sjdp  }
357133965Sjdp
357233965Sjdp  output_bfd = abfd;
357333965Sjdp
357433965Sjdp  flush ();
357533965Sjdp
357633965Sjdp  if (! ieee_write_section_part (abfd))
3577130561Sobrien    return FALSE;
357833965Sjdp  /* First write the symbols.  This changes their values into table
357933965Sjdp    indeces so we cant use it after this point.  */
358033965Sjdp  if (! ieee_write_external_part (abfd))
3581130561Sobrien    return FALSE;
358233965Sjdp
358333965Sjdp  /* Write any debugs we have been told about.  */
358433965Sjdp  if (! ieee_write_debug_part (abfd))
3585130561Sobrien    return FALSE;
358633965Sjdp
358733965Sjdp  /* Can only write the data once the symbols have been written, since
358833965Sjdp     the data contains relocation information which points to the
358933965Sjdp     symbols.  */
359033965Sjdp  if (! ieee_write_data_part (abfd))
3591130561Sobrien    return FALSE;
359233965Sjdp
359333965Sjdp  /* At the end we put the end!  */
359433965Sjdp  if (! ieee_write_me_part (abfd))
3595130561Sobrien    return FALSE;
359633965Sjdp
3597130561Sobrien  /* Generate the header.  */
359833965Sjdp  if (bfd_seek (abfd, old, SEEK_SET) != 0)
3599130561Sobrien    return FALSE;
360033965Sjdp
360133965Sjdp  for (i = 0; i < N_W_VARIABLES; i++)
360233965Sjdp    {
360333965Sjdp      if (! ieee_write_2bytes (abfd, ieee_assign_value_to_variable_enum)
360433965Sjdp	  || ! ieee_write_byte (abfd, (bfd_byte) i)
360589857Sobrien	  || ! ieee_write_int5_out (abfd, (bfd_vma) ieee->w.offset[i]))
3606130561Sobrien	return FALSE;
360733965Sjdp    }
360833965Sjdp
3609130561Sobrien  return TRUE;
361033965Sjdp}
361133965Sjdp
3612218822Sdim/* Native-level interface to symbols.  */
361333965Sjdp
361433965Sjdp/* We read the symbols into a buffer, which is discarded when this
361533965Sjdp   function exits.  We read the strings into a buffer large enough to
3616130561Sobrien   hold them all plus all the cached symbol entries.  */
361733965Sjdp
361889857Sobrienstatic asymbol *
3619218822Sdimieee_make_empty_symbol (bfd *abfd)
362033965Sjdp{
362189857Sobrien  bfd_size_type amt = sizeof (ieee_symbol_type);
3622218822Sdim  ieee_symbol_type *new = bfd_zalloc (abfd, amt);
3623130561Sobrien
362433965Sjdp  if (!new)
362533965Sjdp    return NULL;
362633965Sjdp  new->symbol.the_bfd = abfd;
362733965Sjdp  return &new->symbol;
362833965Sjdp}
362933965Sjdp
363033965Sjdpstatic bfd *
3631218822Sdimieee_openr_next_archived_file (bfd *arch, bfd *prev)
363233965Sjdp{
363333965Sjdp  ieee_ar_data_type *ar = IEEE_AR_DATA (arch);
3634130561Sobrien
3635130561Sobrien  /* Take the next one from the arch state, or reset.  */
363633965Sjdp  if (prev == (bfd *) NULL)
3637130561Sobrien    /* Reset the index - the first two entries are bogus.  */
3638130561Sobrien    ar->element_index = 2;
3639130561Sobrien
3640130561Sobrien  while (TRUE)
364133965Sjdp    {
364233965Sjdp      ieee_ar_obstack_type *p = ar->elements + ar->element_index;
3643130561Sobrien
364433965Sjdp      ar->element_index++;
364533965Sjdp      if (ar->element_index <= ar->element_count)
364633965Sjdp	{
364733965Sjdp	  if (p->file_offset != (file_ptr) 0)
364833965Sjdp	    {
364933965Sjdp	      if (p->abfd == (bfd *) NULL)
365033965Sjdp		{
365133965Sjdp		  p->abfd = _bfd_create_empty_archive_element_shell (arch);
365233965Sjdp		  p->abfd->origin = p->file_offset;
365333965Sjdp		}
365433965Sjdp	      return p->abfd;
365533965Sjdp	    }
365633965Sjdp	}
365733965Sjdp      else
365833965Sjdp	{
365933965Sjdp	  bfd_set_error (bfd_error_no_more_archived_files);
3660218822Sdim	  return NULL;
366133965Sjdp	}
366233965Sjdp    }
366333965Sjdp}
366433965Sjdp
3665130561Sobrienstatic bfd_boolean
3666218822Sdimieee_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
3667218822Sdim			asection *section ATTRIBUTE_UNUSED,
3668218822Sdim			asymbol **symbols ATTRIBUTE_UNUSED,
3669218822Sdim			bfd_vma offset ATTRIBUTE_UNUSED,
3670218822Sdim			const char **filename_ptr ATTRIBUTE_UNUSED,
3671218822Sdim			const char **functionname_ptr ATTRIBUTE_UNUSED,
3672218822Sdim			unsigned int *line_ptr ATTRIBUTE_UNUSED)
367333965Sjdp{
3674130561Sobrien  return FALSE;
367533965Sjdp}
367633965Sjdp
3677218822Sdimstatic bfd_boolean
3678218822Sdimieee_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
3679218822Sdim			const char **filename_ptr ATTRIBUTE_UNUSED,
3680218822Sdim			const char **functionname_ptr ATTRIBUTE_UNUSED,
3681218822Sdim			unsigned int *line_ptr ATTRIBUTE_UNUSED)
3682218822Sdim{
3683218822Sdim  return FALSE;
3684218822Sdim}
3685218822Sdim
368633965Sjdpstatic int
3687218822Sdimieee_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
368833965Sjdp{
368938889Sjdp  ieee_ar_data_type *ar = (ieee_ar_data_type *) NULL;
369033965Sjdp  ieee_data_type *ieee;
369133965Sjdp
369238889Sjdp  if (abfd->my_archive != NULL)
369338889Sjdp    ar = abfd->my_archive->tdata.ieee_ar_data;
369433965Sjdp  if (ar == (ieee_ar_data_type *) NULL)
369533965Sjdp    {
369633965Sjdp      bfd_set_error (bfd_error_invalid_operation);
369733965Sjdp      return -1;
369833965Sjdp    }
369933965Sjdp
370033965Sjdp  if (IEEE_DATA (abfd) == NULL)
370133965Sjdp    {
370233965Sjdp      if (ieee_object_p (abfd) == NULL)
370333965Sjdp	{
370433965Sjdp	  bfd_set_error (bfd_error_wrong_format);
370533965Sjdp	  return -1;
370633965Sjdp	}
370733965Sjdp    }
370833965Sjdp
370933965Sjdp  ieee = IEEE_DATA (abfd);
371033965Sjdp
371133965Sjdp  buf->st_size = ieee->w.r.me_record + 1;
371233965Sjdp  buf->st_mode = 0644;
371333965Sjdp  return 0;
371433965Sjdp}
371533965Sjdp
371633965Sjdpstatic int
3717218822Sdimieee_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
3718218822Sdim		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
371933965Sjdp{
372033965Sjdp  return 0;
372133965Sjdp}
372233965Sjdp
372333965Sjdp#define	ieee_close_and_cleanup _bfd_generic_close_and_cleanup
372433965Sjdp#define ieee_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
372533965Sjdp
372633965Sjdp#define ieee_slurp_armap bfd_true
372733965Sjdp#define ieee_slurp_extended_name_table bfd_true
372833965Sjdp#define ieee_construct_extended_name_table \
3729130561Sobrien  ((bfd_boolean (*) \
3730218822Sdim    (bfd *, char **, bfd_size_type *, const char **)) \
373133965Sjdp   bfd_true)
373233965Sjdp#define ieee_truncate_arname bfd_dont_truncate_arname
373333965Sjdp#define ieee_write_armap \
3734130561Sobrien  ((bfd_boolean (*) \
3735218822Sdim    (bfd *, unsigned int, struct orl *, unsigned int, int)) \
373633965Sjdp   bfd_true)
373733965Sjdp#define ieee_read_ar_hdr bfd_nullvoidptr
373833965Sjdp#define ieee_update_armap_timestamp bfd_true
373933965Sjdp#define ieee_get_elt_at_index _bfd_generic_get_elt_at_index
374033965Sjdp
3741218822Sdim#define ieee_bfd_is_target_special_symbol  \
3742218822Sdim  ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
374333965Sjdp#define ieee_bfd_is_local_label_name bfd_generic_is_local_label_name
374433965Sjdp#define ieee_get_lineno _bfd_nosymbols_get_lineno
374533965Sjdp#define ieee_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
374633965Sjdp#define ieee_read_minisymbols _bfd_generic_read_minisymbols
374733965Sjdp#define ieee_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
374833965Sjdp
374933965Sjdp#define ieee_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
3750218822Sdim#define ieee_bfd_reloc_name_lookup _bfd_norelocs_bfd_reloc_name_lookup
375133965Sjdp
375233965Sjdp#define ieee_set_arch_mach _bfd_generic_set_arch_mach
375333965Sjdp
375433965Sjdp#define ieee_get_section_contents_in_window \
375533965Sjdp  _bfd_generic_get_section_contents_in_window
375633965Sjdp#define ieee_bfd_get_relocated_section_contents \
375733965Sjdp  bfd_generic_get_relocated_section_contents
375833965Sjdp#define ieee_bfd_relax_section bfd_generic_relax_section
375960484Sobrien#define ieee_bfd_gc_sections bfd_generic_gc_sections
376089857Sobrien#define ieee_bfd_merge_sections bfd_generic_merge_sections
3761218822Sdim#define ieee_bfd_is_group_section bfd_generic_is_group_section
3762104834Sobrien#define ieee_bfd_discard_group bfd_generic_discard_group
3763218822Sdim#define ieee_section_already_linked \
3764218822Sdim  _bfd_generic_section_already_linked
376533965Sjdp#define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
3766104834Sobrien#define ieee_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
376733965Sjdp#define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
3768104834Sobrien#define ieee_bfd_link_just_syms _bfd_generic_link_just_syms
376933965Sjdp#define ieee_bfd_final_link _bfd_generic_final_link
377033965Sjdp#define ieee_bfd_link_split_section  _bfd_generic_link_split_section
377133965Sjdp
377233965Sjdpconst bfd_target ieee_vec =
377333965Sjdp{
3774218822Sdim  "ieee",			/* Name.  */
377533965Sjdp  bfd_target_ieee_flavour,
3776218822Sdim  BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
3777218822Sdim  BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
3778218822Sdim  (HAS_RELOC | EXEC_P |		/* Object flags.  */
377933965Sjdp   HAS_LINENO | HAS_DEBUG |
378033965Sjdp   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
378133965Sjdp  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
3782218822Sdim   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
3783218822Sdim  '_',				/* Leading underscore.  */
3784218822Sdim  ' ',				/* AR_pad_char.  */
3785218822Sdim  16,				/* AR_max_namelen.  */
378633965Sjdp  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
378733965Sjdp  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3788218822Sdim  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
378933965Sjdp  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
379033965Sjdp  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3791218822Sdim  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
379233965Sjdp
379333965Sjdp  {_bfd_dummy_target,
3794218822Sdim   ieee_object_p,		/* bfd_check_format.  */
379533965Sjdp   ieee_archive_p,
379633965Sjdp   _bfd_dummy_target,
379733965Sjdp  },
379833965Sjdp  {
379933965Sjdp    bfd_false,
380033965Sjdp    ieee_mkobject,
380133965Sjdp    _bfd_generic_mkarchive,
380233965Sjdp    bfd_false
380333965Sjdp  },
380433965Sjdp  {
380533965Sjdp    bfd_false,
380633965Sjdp    ieee_write_object_contents,
380733965Sjdp    _bfd_write_archive_contents,
380833965Sjdp    bfd_false,
380933965Sjdp  },
381033965Sjdp
381189857Sobrien  /* ieee_close_and_cleanup, ieee_bfd_free_cached_info, ieee_new_section_hook,
3812218822Sdim     ieee_get_section_contents, ieee_get_section_contents_in_window.  */
381333965Sjdp  BFD_JUMP_TABLE_GENERIC (ieee),
381489857Sobrien
381533965Sjdp  BFD_JUMP_TABLE_COPY (_bfd_generic),
381633965Sjdp  BFD_JUMP_TABLE_CORE (_bfd_nocore),
381789857Sobrien
381889857Sobrien  /* ieee_slurp_armap, ieee_slurp_extended_name_table,
381989857Sobrien     ieee_construct_extended_name_table, ieee_truncate_arname,
382089857Sobrien     ieee_write_armap, ieee_read_ar_hdr, ieee_openr_next_archived_file,
382189857Sobrien     ieee_get_elt_at_index, ieee_generic_stat_arch_elt,
3822218822Sdim     ieee_update_armap_timestamp.  */
382333965Sjdp  BFD_JUMP_TABLE_ARCHIVE (ieee),
382489857Sobrien
3825130561Sobrien  /* ieee_get_symtab_upper_bound, ieee_canonicalize_symtab,
3826130561Sobrien     ieee_make_empty_symbol, ieee_print_symbol, ieee_get_symbol_info,
3827130561Sobrien     ieee_bfd_is_local_label_name, ieee_get_lineno,
3828130561Sobrien     ieee_find_nearest_line, ieee_bfd_make_debug_symbol,
3829218822Sdim     ieee_read_minisymbols, ieee_minisymbol_to_symbol.  */
383033965Sjdp  BFD_JUMP_TABLE_SYMBOLS (ieee),
383189857Sobrien
383289857Sobrien  /* ieee_get_reloc_upper_bound, ieee_canonicalize_reloc,
3833218822Sdim     ieee_bfd_reloc_type_lookup.   */
383433965Sjdp  BFD_JUMP_TABLE_RELOCS (ieee),
383589857Sobrien
3836218822Sdim  /* ieee_set_arch_mach, ieee_set_section_contents.  */
383733965Sjdp  BFD_JUMP_TABLE_WRITE (ieee),
383889857Sobrien
383989857Sobrien  /* ieee_sizeof_headers, ieee_bfd_get_relocated_section_contents,
384089857Sobrien     ieee_bfd_relax_section, ieee_bfd_link_hash_table_create,
3841104834Sobrien     _bfd_generic_link_hash_table_free,
384289857Sobrien     ieee_bfd_link_add_symbols, ieee_bfd_final_link,
384389857Sobrien     ieee_bfd_link_split_section, ieee_bfd_gc_sections,
3844218822Sdim     ieee_bfd_merge_sections.  */
384533965Sjdp  BFD_JUMP_TABLE_LINK (ieee),
384689857Sobrien
384733965Sjdp  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
384833965Sjdp
384960484Sobrien  NULL,
385089857Sobrien
3851218822Sdim  NULL
385233965Sjdp};
3853