133965Sjdp/* Generic ECOFF (Extended-COFF) routines.
2130561Sobrien   Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
3218822Sdim   2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
433965Sjdp   Original version by Per Bothner.
533965Sjdp   Full support added by Ian Lance Taylor, ian@cygnus.com.
633965Sjdp
7104834Sobrien   This file is part of BFD, the Binary File Descriptor library.
833965Sjdp
9104834Sobrien   This program is free software; you can redistribute it and/or modify
10104834Sobrien   it under the terms of the GNU General Public License as published by
11104834Sobrien   the Free Software Foundation; either version 2 of the License, or
12104834Sobrien   (at your option) any later version.
1333965Sjdp
14104834Sobrien   This program is distributed in the hope that it will be useful,
15104834Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
16104834Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17104834Sobrien   GNU General Public License for more details.
1833965Sjdp
19104834Sobrien   You should have received a copy of the GNU General Public License
20104834Sobrien   along with this program; if not, write to the Free Software
21218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2233965Sjdp
23218822Sdim#include "sysdep.h"
2433965Sjdp#include "bfd.h"
2533965Sjdp#include "bfdlink.h"
2633965Sjdp#include "libbfd.h"
2733965Sjdp#include "aout/ar.h"
2833965Sjdp#include "aout/ranlib.h"
2933965Sjdp#include "aout/stab_gnu.h"
3033965Sjdp
3133965Sjdp/* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
3233965Sjdp   some other stuff which we don't want and which conflicts with stuff
3333965Sjdp   we do want.  */
3433965Sjdp#include "libaout.h"
3533965Sjdp#include "aout/aout64.h"
3633965Sjdp#undef N_ABS
3733965Sjdp#undef exec_hdr
3833965Sjdp#undef obj_sym_filepos
3933965Sjdp
4033965Sjdp#include "coff/internal.h"
4133965Sjdp#include "coff/sym.h"
4233965Sjdp#include "coff/symconst.h"
4333965Sjdp#include "coff/ecoff.h"
4433965Sjdp#include "libcoff.h"
4533965Sjdp#include "libecoff.h"
46218822Sdim#include "libiberty.h"
4733965Sjdp
48218822Sdim#define streq(a, b)	(strcmp ((a), (b)) == 0)
49218822Sdim#define strneq(a, b, n)	(strncmp ((a), (b), (n)) == 0)
50218822Sdim
5133965Sjdp
5233965Sjdp/* This stuff is somewhat copied from coffcode.h.  */
5360484Sobrienstatic asection bfd_debug_section =
5460484Sobrien{
55218822Sdim  /* name,      id,  index, next, prev, flags, user_set_vma,       */
56218822Sdim     "*DEBUG*", 0,   0,     NULL, NULL, 0,     0,
57218822Sdim  /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      */
58218822Sdim     0,           0,                1,       0,
59218822Sdim  /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       */
60218822Sdim     0,            0,             0,          0,
61218822Sdim  /* has_gp_reloc, need_finalize_relax, reloc_done,                */
62218822Sdim     0,            0,                   0,
63218822Sdim  /* vma, lma, size, rawsize,                                      */
64218822Sdim     0,   0,   0,    0,
6578828Sobrien  /* output_offset, output_section, alignment_power,               */
6678828Sobrien     0,             NULL,           0,
6778828Sobrien  /* relocation, orelocation, reloc_count, filepos, rel_filepos,   */
6878828Sobrien     NULL,       NULL,        0,           0,       0,
6978828Sobrien  /* line_filepos, userdata, contents, lineno, lineno_count,       */
7078828Sobrien     0,            NULL,     NULL,     NULL,   0,
71218822Sdim  /* entsize, kept_section, moving_line_filepos,                   */
72218822Sdim     0,       NULL,         0,
7378828Sobrien  /* target_index, used_by_bfd, constructor_chain, owner,          */
7478828Sobrien     0,            NULL,        NULL,              NULL,
7578828Sobrien  /* symbol,                                                       */
76218822Sdim     NULL,
7778828Sobrien  /* symbol_ptr_ptr,                                               */
78218822Sdim     NULL,
79218822Sdim  /* map_head, map_tail                                            */
80218822Sdim     { NULL }, { NULL }
8160484Sobrien};
8233965Sjdp
8333965Sjdp/* Create an ECOFF object.  */
8433965Sjdp
85130561Sobrienbfd_boolean
86218822Sdim_bfd_ecoff_mkobject (bfd *abfd)
8733965Sjdp{
8889857Sobrien  bfd_size_type amt = sizeof (ecoff_data_type);
89104834Sobrien
90218822Sdim  abfd->tdata.ecoff_obj_data = bfd_zalloc (abfd, amt);
9133965Sjdp  if (abfd->tdata.ecoff_obj_data == NULL)
92130561Sobrien    return FALSE;
9333965Sjdp
94130561Sobrien  return TRUE;
9533965Sjdp}
9633965Sjdp
9733965Sjdp/* This is a hook called by coff_real_object_p to create any backend
9833965Sjdp   specific information.  */
9933965Sjdp
100218822Sdimvoid *
101218822Sdim_bfd_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr)
10233965Sjdp{
10333965Sjdp  struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
10433965Sjdp  struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
10533965Sjdp  ecoff_data_type *ecoff;
10633965Sjdp
107104834Sobrien  if (! _bfd_ecoff_mkobject (abfd))
10833965Sjdp    return NULL;
10933965Sjdp
11033965Sjdp  ecoff = ecoff_data (abfd);
11133965Sjdp  ecoff->gp_size = 8;
11233965Sjdp  ecoff->sym_filepos = internal_f->f_symptr;
11333965Sjdp
114218822Sdim  if (internal_a != NULL)
11533965Sjdp    {
11633965Sjdp      int i;
11733965Sjdp
11833965Sjdp      ecoff->text_start = internal_a->text_start;
11933965Sjdp      ecoff->text_end = internal_a->text_start + internal_a->tsize;
12033965Sjdp      ecoff->gp = internal_a->gp_value;
12133965Sjdp      ecoff->gprmask = internal_a->gprmask;
12233965Sjdp      for (i = 0; i < 4; i++)
12333965Sjdp	ecoff->cprmask[i] = internal_a->cprmask[i];
12433965Sjdp      ecoff->fprmask = internal_a->fprmask;
12533965Sjdp      if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
12633965Sjdp	abfd->flags |= D_PAGED;
12733965Sjdp      else
12833965Sjdp	abfd->flags &=~ D_PAGED;
12933965Sjdp    }
13033965Sjdp
13133965Sjdp  /* It turns out that no special action is required by the MIPS or
13233965Sjdp     Alpha ECOFF backends.  They have different information in the
13333965Sjdp     a.out header, but we just copy it all (e.g., gprmask, cprmask and
13433965Sjdp     fprmask) and let the swapping routines ensure that only relevant
13533965Sjdp     information is written out.  */
13633965Sjdp
137218822Sdim  return (void *) ecoff;
13833965Sjdp}
13933965Sjdp
14033965Sjdp/* Initialize a new section.  */
14133965Sjdp
142130561Sobrienbfd_boolean
143218822Sdim_bfd_ecoff_new_section_hook (bfd *abfd, asection *section)
14433965Sjdp{
145218822Sdim  unsigned int i;
146218822Sdim  static struct
147218822Sdim  {
148218822Sdim    const char * name;
149218822Sdim    flagword flags;
150218822Sdim  }
151218822Sdim  section_flags [] =
152218822Sdim  {
153218822Sdim    { _TEXT,   SEC_ALLOC | SEC_CODE | SEC_LOAD },
154218822Sdim    { _INIT,   SEC_ALLOC | SEC_CODE | SEC_LOAD },
155218822Sdim    { _FINI,   SEC_ALLOC | SEC_CODE | SEC_LOAD },
156218822Sdim    { _DATA,   SEC_ALLOC | SEC_DATA | SEC_LOAD },
157218822Sdim    { _SDATA,  SEC_ALLOC | SEC_DATA | SEC_LOAD },
158218822Sdim    { _RDATA,  SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
159218822Sdim    { _LIT8,   SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
160218822Sdim    { _LIT4,   SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
161218822Sdim    { _RCONST, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
162218822Sdim    { _PDATA,  SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
163218822Sdim    { _BSS,    SEC_ALLOC},
164218822Sdim    { _SBSS,   SEC_ALLOC},
165218822Sdim    /* An Irix 4 shared libary.  */
166218822Sdim    { _LIB,    SEC_COFF_SHARED_LIBRARY}
167218822Sdim  };
168218822Sdim
16933965Sjdp  section->alignment_power = 4;
17033965Sjdp
171218822Sdim  for (i = 0; i < ARRAY_SIZE (section_flags); i++)
172218822Sdim    if (streq (section->name, section_flags[i].name))
173218822Sdim      {
174218822Sdim	section->flags |= section_flags[i].flags;
175218822Sdim	break;
176218822Sdim      }
17733965Sjdp
178218822Sdim
17933965Sjdp  /* Probably any other section name is SEC_NEVER_LOAD, but I'm
18033965Sjdp     uncertain about .init on some systems and I don't know how shared
18133965Sjdp     libraries work.  */
18233965Sjdp
183218822Sdim  return _bfd_generic_new_section_hook (abfd, section);
18433965Sjdp}
18533965Sjdp
18633965Sjdp/* Determine the machine architecture and type.  This is called from
18733965Sjdp   the generic COFF routines.  It is the inverse of ecoff_get_magic,
18833965Sjdp   below.  This could be an ECOFF backend routine, with one version
18933965Sjdp   for each target, but there aren't all that many ECOFF targets.  */
19033965Sjdp
191130561Sobrienbfd_boolean
192218822Sdim_bfd_ecoff_set_arch_mach_hook (bfd *abfd, void * filehdr)
19333965Sjdp{
194218822Sdim  struct internal_filehdr *internal_f = filehdr;
19533965Sjdp  enum bfd_architecture arch;
19633965Sjdp  unsigned long mach;
19733965Sjdp
19833965Sjdp  switch (internal_f->f_magic)
19933965Sjdp    {
20033965Sjdp    case MIPS_MAGIC_1:
20133965Sjdp    case MIPS_MAGIC_LITTLE:
20233965Sjdp    case MIPS_MAGIC_BIG:
20333965Sjdp      arch = bfd_arch_mips;
204130561Sobrien      mach = bfd_mach_mips3000;
20533965Sjdp      break;
20633965Sjdp
20733965Sjdp    case MIPS_MAGIC_LITTLE2:
20833965Sjdp    case MIPS_MAGIC_BIG2:
209104834Sobrien      /* MIPS ISA level 2: the r6000.  */
21033965Sjdp      arch = bfd_arch_mips;
211130561Sobrien      mach = bfd_mach_mips6000;
21233965Sjdp      break;
21333965Sjdp
21433965Sjdp    case MIPS_MAGIC_LITTLE3:
21533965Sjdp    case MIPS_MAGIC_BIG3:
216104834Sobrien      /* MIPS ISA level 3: the r4000.  */
21733965Sjdp      arch = bfd_arch_mips;
218130561Sobrien      mach = bfd_mach_mips4000;
21933965Sjdp      break;
22033965Sjdp
22133965Sjdp    case ALPHA_MAGIC:
22233965Sjdp      arch = bfd_arch_alpha;
22333965Sjdp      mach = 0;
22433965Sjdp      break;
22533965Sjdp
22633965Sjdp    default:
22733965Sjdp      arch = bfd_arch_obscure;
22833965Sjdp      mach = 0;
22933965Sjdp      break;
23033965Sjdp    }
23133965Sjdp
23233965Sjdp  return bfd_default_set_arch_mach (abfd, arch, mach);
23333965Sjdp}
23433965Sjdp
23533965Sjdp/* Get the magic number to use based on the architecture and machine.
23633965Sjdp   This is the inverse of _bfd_ecoff_set_arch_mach_hook, above.  */
23733965Sjdp
23833965Sjdpstatic int
239218822Sdimecoff_get_magic (bfd *abfd)
24033965Sjdp{
24133965Sjdp  int big, little;
24233965Sjdp
24333965Sjdp  switch (bfd_get_arch (abfd))
24433965Sjdp    {
24533965Sjdp    case bfd_arch_mips:
24633965Sjdp      switch (bfd_get_mach (abfd))
24733965Sjdp	{
24833965Sjdp	default:
24933965Sjdp	case 0:
250130561Sobrien	case bfd_mach_mips3000:
25133965Sjdp	  big = MIPS_MAGIC_BIG;
25233965Sjdp	  little = MIPS_MAGIC_LITTLE;
25333965Sjdp	  break;
25433965Sjdp
255130561Sobrien	case bfd_mach_mips6000:
25633965Sjdp	  big = MIPS_MAGIC_BIG2;
25733965Sjdp	  little = MIPS_MAGIC_LITTLE2;
25833965Sjdp	  break;
25933965Sjdp
260130561Sobrien	case bfd_mach_mips4000:
26133965Sjdp	  big = MIPS_MAGIC_BIG3;
26233965Sjdp	  little = MIPS_MAGIC_LITTLE3;
26333965Sjdp	  break;
26433965Sjdp	}
26533965Sjdp
26633965Sjdp      return bfd_big_endian (abfd) ? big : little;
26733965Sjdp
26833965Sjdp    case bfd_arch_alpha:
26933965Sjdp      return ALPHA_MAGIC;
27033965Sjdp
27133965Sjdp    default:
27233965Sjdp      abort ();
27333965Sjdp      return 0;
27433965Sjdp    }
27533965Sjdp}
27633965Sjdp
27733965Sjdp/* Get the section s_flags to use for a section.  */
27833965Sjdp
27933965Sjdpstatic long
280218822Sdimecoff_sec_to_styp_flags (const char *name, flagword flags)
28133965Sjdp{
282218822Sdim  unsigned int i;
283218822Sdim  static struct
284218822Sdim  {
285218822Sdim    const char * name;
286218822Sdim    long flags;
287218822Sdim  }
288218822Sdim  styp_flags [] =
289218822Sdim  {
290218822Sdim    { _TEXT,    STYP_TEXT       },
291218822Sdim    { _DATA,    STYP_DATA       },
292218822Sdim    { _SDATA,   STYP_SDATA      },
293218822Sdim    { _RDATA,   STYP_RDATA      },
294218822Sdim    { _LITA,    STYP_LITA       },
295218822Sdim    { _LIT8,    STYP_LIT8       },
296218822Sdim    { _LIT4,    STYP_LIT4       },
297218822Sdim    { _BSS,     STYP_BSS        },
298218822Sdim    { _SBSS,    STYP_SBSS       },
299218822Sdim    { _INIT,    STYP_ECOFF_INIT },
300218822Sdim    { _FINI,    STYP_ECOFF_FINI },
301218822Sdim    { _PDATA,   STYP_PDATA      },
302218822Sdim    { _XDATA,   STYP_XDATA      },
303218822Sdim    { _LIB,     STYP_ECOFF_LIB  },
304218822Sdim    { _GOT,     STYP_GOT        },
305218822Sdim    { _HASH,    STYP_HASH       },
306218822Sdim    { _DYNAMIC, STYP_DYNAMIC    },
307218822Sdim    { _LIBLIST, STYP_LIBLIST    },
308218822Sdim    { _RELDYN,  STYP_RELDYN     },
309218822Sdim    { _CONFLIC, STYP_CONFLIC    },
310218822Sdim    { _DYNSTR,  STYP_DYNSTR     },
311218822Sdim    { _DYNSYM,  STYP_DYNSYM     },
312218822Sdim    { _RCONST,  STYP_RCONST     }
313218822Sdim  };
314218822Sdim  long styp = 0;
31533965Sjdp
316218822Sdim  for (i = 0; i < ARRAY_SIZE (styp_flags); i++)
317218822Sdim    if (streq (name, styp_flags[i].name))
318218822Sdim      {
319218822Sdim	styp = styp_flags[i].flags;
320218822Sdim	break;
321218822Sdim      }
32233965Sjdp
323218822Sdim  if (styp == 0)
32433965Sjdp    {
325218822Sdim      if (streq (name, _COMMENT))
326218822Sdim	{
327218822Sdim	  styp = STYP_COMMENT;
328218822Sdim	  flags &=~ SEC_NEVER_LOAD;
329218822Sdim	}
330218822Sdim      else if (flags & SEC_CODE)
331218822Sdim	styp = STYP_TEXT;
332218822Sdim      else if (flags & SEC_DATA)
333218822Sdim	styp = STYP_DATA;
334218822Sdim      else if (flags & SEC_READONLY)
335218822Sdim	styp = STYP_RDATA;
336218822Sdim      else if (flags & SEC_LOAD)
337218822Sdim	styp = STYP_REG;
338218822Sdim      else
339218822Sdim	styp = STYP_BSS;
34033965Sjdp    }
34133965Sjdp
34233965Sjdp  if (flags & SEC_NEVER_LOAD)
34333965Sjdp    styp |= STYP_NOLOAD;
34433965Sjdp
34533965Sjdp  return styp;
34633965Sjdp}
34733965Sjdp
34833965Sjdp/* Get the BFD flags to use for a section.  */
34933965Sjdp
350130561Sobrienbfd_boolean
351218822Sdim_bfd_ecoff_styp_to_sec_flags (bfd *abfd ATTRIBUTE_UNUSED,
352218822Sdim			      void * hdr,
353218822Sdim			      const char *name ATTRIBUTE_UNUSED,
354218822Sdim			      asection *section ATTRIBUTE_UNUSED,
355218822Sdim			      flagword * flags_ptr)
35633965Sjdp{
357218822Sdim  struct internal_scnhdr *internal_s = hdr;
35833965Sjdp  long styp_flags = internal_s->s_flags;
35989857Sobrien  flagword sec_flags = 0;
36033965Sjdp
36133965Sjdp  if (styp_flags & STYP_NOLOAD)
36233965Sjdp    sec_flags |= SEC_NEVER_LOAD;
36333965Sjdp
36433965Sjdp  /* For 386 COFF, at least, an unloadable text or data section is
36533965Sjdp     actually a shared library section.  */
36633965Sjdp  if ((styp_flags & STYP_TEXT)
36733965Sjdp      || (styp_flags & STYP_ECOFF_INIT)
36833965Sjdp      || (styp_flags & STYP_ECOFF_FINI)
36933965Sjdp      || (styp_flags & STYP_DYNAMIC)
37033965Sjdp      || (styp_flags & STYP_LIBLIST)
37133965Sjdp      || (styp_flags & STYP_RELDYN)
37233965Sjdp      || styp_flags == STYP_CONFLIC
37333965Sjdp      || (styp_flags & STYP_DYNSTR)
37433965Sjdp      || (styp_flags & STYP_DYNSYM)
37533965Sjdp      || (styp_flags & STYP_HASH))
37633965Sjdp    {
37733965Sjdp      if (sec_flags & SEC_NEVER_LOAD)
37833965Sjdp	sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY;
37933965Sjdp      else
38033965Sjdp	sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
38133965Sjdp    }
38233965Sjdp  else if ((styp_flags & STYP_DATA)
38333965Sjdp	   || (styp_flags & STYP_RDATA)
38433965Sjdp	   || (styp_flags & STYP_SDATA)
38533965Sjdp	   || styp_flags == STYP_PDATA
38633965Sjdp	   || styp_flags == STYP_XDATA
38733965Sjdp	   || (styp_flags & STYP_GOT)
38833965Sjdp	   || styp_flags == STYP_RCONST)
38933965Sjdp    {
39033965Sjdp      if (sec_flags & SEC_NEVER_LOAD)
39133965Sjdp	sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
39233965Sjdp      else
39333965Sjdp	sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
39433965Sjdp      if ((styp_flags & STYP_RDATA)
39533965Sjdp	  || styp_flags == STYP_PDATA
39633965Sjdp	  || styp_flags == STYP_RCONST)
39733965Sjdp	sec_flags |= SEC_READONLY;
39833965Sjdp    }
39933965Sjdp  else if ((styp_flags & STYP_BSS)
40033965Sjdp	   || (styp_flags & STYP_SBSS))
40189857Sobrien    sec_flags |= SEC_ALLOC;
40233965Sjdp  else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT)
40389857Sobrien    sec_flags |= SEC_NEVER_LOAD;
40433965Sjdp  else if ((styp_flags & STYP_LITA)
40533965Sjdp	   || (styp_flags & STYP_LIT8)
40633965Sjdp	   || (styp_flags & STYP_LIT4))
40789857Sobrien    sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
40833965Sjdp  else if (styp_flags & STYP_ECOFF_LIB)
40989857Sobrien    sec_flags |= SEC_COFF_SHARED_LIBRARY;
41033965Sjdp  else
41189857Sobrien    sec_flags |= SEC_ALLOC | SEC_LOAD;
41233965Sjdp
41389857Sobrien  * flags_ptr = sec_flags;
414130561Sobrien  return TRUE;
41533965Sjdp}
41633965Sjdp
41733965Sjdp/* Read in the symbolic header for an ECOFF object file.  */
41833965Sjdp
419130561Sobrienstatic bfd_boolean
420218822Sdimecoff_slurp_symbolic_header (bfd *abfd)
42133965Sjdp{
42233965Sjdp  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
42333965Sjdp  bfd_size_type external_hdr_size;
424218822Sdim  void * raw = NULL;
42533965Sjdp  HDRR *internal_symhdr;
42633965Sjdp
42733965Sjdp  /* See if we've already read it in.  */
42877298Sobrien  if (ecoff_data (abfd)->debug_info.symbolic_header.magic ==
42933965Sjdp      backend->debug_swap.sym_magic)
430130561Sobrien    return TRUE;
43133965Sjdp
43233965Sjdp  /* See whether there is a symbolic header.  */
43333965Sjdp  if (ecoff_data (abfd)->sym_filepos == 0)
43433965Sjdp    {
43533965Sjdp      bfd_get_symcount (abfd) = 0;
436130561Sobrien      return TRUE;
43733965Sjdp    }
43833965Sjdp
43933965Sjdp  /* At this point bfd_get_symcount (abfd) holds the number of symbols
44033965Sjdp     as read from the file header, but on ECOFF this is always the
44133965Sjdp     size of the symbolic information header.  It would be cleaner to
44233965Sjdp     handle this when we first read the file in coffgen.c.  */
44333965Sjdp  external_hdr_size = backend->debug_swap.external_hdr_size;
44433965Sjdp  if (bfd_get_symcount (abfd) != external_hdr_size)
44533965Sjdp    {
44633965Sjdp      bfd_set_error (bfd_error_bad_value);
447130561Sobrien      return FALSE;
44833965Sjdp    }
44933965Sjdp
45033965Sjdp  /* Read the symbolic information header.  */
451218822Sdim  raw = bfd_malloc (external_hdr_size);
45233965Sjdp  if (raw == NULL)
45333965Sjdp    goto error_return;
45433965Sjdp
45589857Sobrien  if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) != 0
45689857Sobrien      || bfd_bread (raw, external_hdr_size, abfd) != external_hdr_size)
45733965Sjdp    goto error_return;
45833965Sjdp  internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
45933965Sjdp  (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr);
46033965Sjdp
46133965Sjdp  if (internal_symhdr->magic != backend->debug_swap.sym_magic)
46233965Sjdp    {
46333965Sjdp      bfd_set_error (bfd_error_bad_value);
46433965Sjdp      goto error_return;
46533965Sjdp    }
46633965Sjdp
46733965Sjdp  /* Now we can get the correct number of symbols.  */
46833965Sjdp  bfd_get_symcount (abfd) = (internal_symhdr->isymMax
46933965Sjdp			     + internal_symhdr->iextMax);
47033965Sjdp
47133965Sjdp  if (raw != NULL)
47233965Sjdp    free (raw);
473130561Sobrien  return TRUE;
47433965Sjdp error_return:
47533965Sjdp  if (raw != NULL)
47633965Sjdp    free (raw);
477130561Sobrien  return FALSE;
47833965Sjdp}
47933965Sjdp
48033965Sjdp/* Read in and swap the important symbolic information for an ECOFF
48133965Sjdp   object file.  This is called by gdb via the read_debug_info entry
48233965Sjdp   point in the backend structure.  */
48333965Sjdp
484130561Sobrienbfd_boolean
485218822Sdim_bfd_ecoff_slurp_symbolic_info (bfd *abfd,
486218822Sdim				asection *ignore ATTRIBUTE_UNUSED,
487218822Sdim				struct ecoff_debug_info *debug)
48833965Sjdp{
48933965Sjdp  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
49033965Sjdp  HDRR *internal_symhdr;
49133965Sjdp  bfd_size_type raw_base;
49233965Sjdp  bfd_size_type raw_size;
493218822Sdim  void * raw;
49433965Sjdp  bfd_size_type external_fdr_size;
49533965Sjdp  char *fraw_src;
49633965Sjdp  char *fraw_end;
49733965Sjdp  struct fdr *fdr_ptr;
49833965Sjdp  bfd_size_type raw_end;
49933965Sjdp  bfd_size_type cb_end;
50089857Sobrien  bfd_size_type amt;
50189857Sobrien  file_ptr pos;
50233965Sjdp
50333965Sjdp  BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info);
50433965Sjdp
50533965Sjdp  /* Check whether we've already gotten it, and whether there's any to
50633965Sjdp     get.  */
507218822Sdim  if (ecoff_data (abfd)->raw_syments != NULL)
508130561Sobrien    return TRUE;
50933965Sjdp  if (ecoff_data (abfd)->sym_filepos == 0)
51033965Sjdp    {
51133965Sjdp      bfd_get_symcount (abfd) = 0;
512130561Sobrien      return TRUE;
51333965Sjdp    }
51433965Sjdp
51533965Sjdp  if (! ecoff_slurp_symbolic_header (abfd))
516130561Sobrien    return FALSE;
51733965Sjdp
51833965Sjdp  internal_symhdr = &debug->symbolic_header;
51933965Sjdp
52033965Sjdp  /* Read all the symbolic information at once.  */
52133965Sjdp  raw_base = (ecoff_data (abfd)->sym_filepos
52233965Sjdp	      + backend->debug_swap.external_hdr_size);
52333965Sjdp
52433965Sjdp  /* Alpha ecoff makes the determination of raw_size difficult. It has
52533965Sjdp     an undocumented debug data section between the symhdr and the first
52633965Sjdp     documented section. And the ordering of the sections varies between
52733965Sjdp     statically and dynamically linked executables.
52833965Sjdp     If bfd supports SEEK_END someday, this code could be simplified.  */
52933965Sjdp  raw_end = 0;
53033965Sjdp
53133965Sjdp#define UPDATE_RAW_END(start, count, size) \
53233965Sjdp  cb_end = internal_symhdr->start + internal_symhdr->count * (size); \
53333965Sjdp  if (cb_end > raw_end) \
53433965Sjdp    raw_end = cb_end
53533965Sjdp
53633965Sjdp  UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char));
53733965Sjdp  UPDATE_RAW_END (cbDnOffset, idnMax, backend->debug_swap.external_dnr_size);
53833965Sjdp  UPDATE_RAW_END (cbPdOffset, ipdMax, backend->debug_swap.external_pdr_size);
53933965Sjdp  UPDATE_RAW_END (cbSymOffset, isymMax, backend->debug_swap.external_sym_size);
540104834Sobrien  /* eraxxon@alumni.rice.edu: ioptMax refers to the size of the
541218822Sdim     optimization symtab, not the number of entries.  */
542104834Sobrien  UPDATE_RAW_END (cbOptOffset, ioptMax, sizeof (char));
54333965Sjdp  UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext));
54433965Sjdp  UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char));
54533965Sjdp  UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char));
54633965Sjdp  UPDATE_RAW_END (cbFdOffset, ifdMax, backend->debug_swap.external_fdr_size);
54733965Sjdp  UPDATE_RAW_END (cbRfdOffset, crfd, backend->debug_swap.external_rfd_size);
54833965Sjdp  UPDATE_RAW_END (cbExtOffset, iextMax, backend->debug_swap.external_ext_size);
54933965Sjdp
55033965Sjdp#undef UPDATE_RAW_END
55133965Sjdp
55233965Sjdp  raw_size = raw_end - raw_base;
55333965Sjdp  if (raw_size == 0)
55433965Sjdp    {
55533965Sjdp      ecoff_data (abfd)->sym_filepos = 0;
556130561Sobrien      return TRUE;
55733965Sjdp    }
558218822Sdim  raw = bfd_alloc (abfd, raw_size);
55933965Sjdp  if (raw == NULL)
560130561Sobrien    return FALSE;
56189857Sobrien
56289857Sobrien  pos = ecoff_data (abfd)->sym_filepos;
56389857Sobrien  pos += backend->debug_swap.external_hdr_size;
56489857Sobrien  if (bfd_seek (abfd, pos, SEEK_SET) != 0
56589857Sobrien      || bfd_bread (raw, raw_size, abfd) != raw_size)
56633965Sjdp    {
56733965Sjdp      bfd_release (abfd, raw);
568130561Sobrien      return FALSE;
56933965Sjdp    }
57033965Sjdp
57133965Sjdp  ecoff_data (abfd)->raw_syments = raw;
57233965Sjdp
57333965Sjdp  /* Get pointers for the numeric offsets in the HDRR structure.  */
574218822Sdim#define FIX(off1, off2, type)				\
575218822Sdim  if (internal_symhdr->off1 == 0)			\
576218822Sdim    debug->off2 = NULL;					\
577218822Sdim  else							\
578218822Sdim    debug->off2 = (type) ((char *) raw			\
579218822Sdim			  + (internal_symhdr->off1	\
58033965Sjdp			     - raw_base))
581104834Sobrien
58233965Sjdp  FIX (cbLineOffset, line, unsigned char *);
583218822Sdim  FIX (cbDnOffset, external_dnr, void *);
584218822Sdim  FIX (cbPdOffset, external_pdr, void *);
585218822Sdim  FIX (cbSymOffset, external_sym, void *);
586218822Sdim  FIX (cbOptOffset, external_opt, void *);
58733965Sjdp  FIX (cbAuxOffset, external_aux, union aux_ext *);
58833965Sjdp  FIX (cbSsOffset, ss, char *);
58933965Sjdp  FIX (cbSsExtOffset, ssext, char *);
590218822Sdim  FIX (cbFdOffset, external_fdr, void *);
591218822Sdim  FIX (cbRfdOffset, external_rfd, void *);
592218822Sdim  FIX (cbExtOffset, external_ext, void *);
59333965Sjdp#undef FIX
59433965Sjdp
59533965Sjdp  /* I don't want to always swap all the data, because it will just
59633965Sjdp     waste time and most programs will never look at it.  The only
59733965Sjdp     time the linker needs most of the debugging information swapped
59833965Sjdp     is when linking big-endian and little-endian MIPS object files
59933965Sjdp     together, which is not a common occurrence.
60033965Sjdp
60133965Sjdp     We need to look at the fdr to deal with a lot of information in
60233965Sjdp     the symbols, so we swap them here.  */
60389857Sobrien  amt = internal_symhdr->ifdMax;
60489857Sobrien  amt *= sizeof (struct fdr);
605218822Sdim  debug->fdr = bfd_alloc (abfd, amt);
60633965Sjdp  if (debug->fdr == NULL)
607130561Sobrien    return FALSE;
60833965Sjdp  external_fdr_size = backend->debug_swap.external_fdr_size;
60933965Sjdp  fdr_ptr = debug->fdr;
61033965Sjdp  fraw_src = (char *) debug->external_fdr;
61133965Sjdp  fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size;
61233965Sjdp  for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
613218822Sdim    (*backend->debug_swap.swap_fdr_in) (abfd, (void *) fraw_src, fdr_ptr);
61433965Sjdp
615130561Sobrien  return TRUE;
61633965Sjdp}
61733965Sjdp
61833965Sjdp/* ECOFF symbol table routines.  The ECOFF symbol table is described
61933965Sjdp   in gcc/mips-tfile.c.  */
62033965Sjdp
62133965Sjdp/* ECOFF uses two common sections.  One is the usual one, and the
62233965Sjdp   other is for small objects.  All the small objects are kept
62333965Sjdp   together, and then referenced via the gp pointer, which yields
62433965Sjdp   faster assembler code.  This is what we use for the small common
62533965Sjdp   section.  */
62633965Sjdpstatic asection ecoff_scom_section;
62733965Sjdpstatic asymbol ecoff_scom_symbol;
62833965Sjdpstatic asymbol *ecoff_scom_symbol_ptr;
62933965Sjdp
63033965Sjdp/* Create an empty symbol.  */
63133965Sjdp
63233965Sjdpasymbol *
633218822Sdim_bfd_ecoff_make_empty_symbol (bfd *abfd)
63433965Sjdp{
63533965Sjdp  ecoff_symbol_type *new;
63689857Sobrien  bfd_size_type amt = sizeof (ecoff_symbol_type);
63733965Sjdp
638218822Sdim  new = bfd_zalloc (abfd, amt);
639218822Sdim  if (new == NULL)
640218822Sdim    return NULL;
641218822Sdim  new->symbol.section = NULL;
642218822Sdim  new->fdr = NULL;
643130561Sobrien  new->local = FALSE;
64433965Sjdp  new->native = NULL;
64533965Sjdp  new->symbol.the_bfd = abfd;
64633965Sjdp  return &new->symbol;
64733965Sjdp}
64833965Sjdp
64933965Sjdp/* Set the BFD flags and section for an ECOFF symbol.  */
65033965Sjdp
651130561Sobrienstatic bfd_boolean
652218822Sdimecoff_set_symbol_info (bfd *abfd,
653218822Sdim		       SYMR *ecoff_sym,
654218822Sdim		       asymbol *asym,
655218822Sdim		       int ext,
656218822Sdim		       int weak)
65733965Sjdp{
65833965Sjdp  asym->the_bfd = abfd;
65933965Sjdp  asym->value = ecoff_sym->value;
66033965Sjdp  asym->section = &bfd_debug_section;
66133965Sjdp  asym->udata.i = 0;
66233965Sjdp
66333965Sjdp  /* Most symbol types are just for debugging.  */
66433965Sjdp  switch (ecoff_sym->st)
66533965Sjdp    {
66633965Sjdp    case stGlobal:
66733965Sjdp    case stStatic:
66833965Sjdp    case stLabel:
66933965Sjdp    case stProc:
67033965Sjdp    case stStaticProc:
67133965Sjdp      break;
67233965Sjdp    case stNil:
67333965Sjdp      if (ECOFF_IS_STAB (ecoff_sym))
67433965Sjdp	{
67533965Sjdp	  asym->flags = BSF_DEBUGGING;
676130561Sobrien	  return TRUE;
67733965Sjdp	}
67833965Sjdp      break;
67933965Sjdp    default:
68033965Sjdp      asym->flags = BSF_DEBUGGING;
681130561Sobrien      return TRUE;
68233965Sjdp    }
68333965Sjdp
68433965Sjdp  if (weak)
68533965Sjdp    asym->flags = BSF_EXPORT | BSF_WEAK;
68633965Sjdp  else if (ext)
68733965Sjdp    asym->flags = BSF_EXPORT | BSF_GLOBAL;
68833965Sjdp  else
68933965Sjdp    {
69033965Sjdp      asym->flags = BSF_LOCAL;
69133965Sjdp      /* Normally, a local stProc symbol will have a corresponding
69233965Sjdp         external symbol.  We mark the local symbol as a debugging
69333965Sjdp         symbol, in order to prevent nm from printing both out.
69433965Sjdp         Similarly, we mark stLabel and stabs symbols as debugging
69533965Sjdp         symbols.  In both cases, we do want to set the value
69633965Sjdp         correctly based on the symbol class.  */
69733965Sjdp      if (ecoff_sym->st == stProc
69833965Sjdp	  || ecoff_sym->st == stLabel
69933965Sjdp	  || ECOFF_IS_STAB (ecoff_sym))
70033965Sjdp	asym->flags |= BSF_DEBUGGING;
70133965Sjdp    }
702104834Sobrien
703104834Sobrien  if (ecoff_sym->st == stProc || ecoff_sym->st == stStaticProc)
704104834Sobrien    asym->flags |= BSF_FUNCTION;
705104834Sobrien
70633965Sjdp  switch (ecoff_sym->sc)
70733965Sjdp    {
70833965Sjdp    case scNil:
70933965Sjdp      /* Used for compiler generated labels.  Leave them in the
71033965Sjdp	 debugging section, and mark them as local.  If BSF_DEBUGGING
71133965Sjdp	 is set, then nm does not display them for some reason.  If no
71233965Sjdp	 flags are set then the linker whines about them.  */
71333965Sjdp      asym->flags = BSF_LOCAL;
71433965Sjdp      break;
71533965Sjdp    case scText:
716218822Sdim      asym->section = bfd_make_section_old_way (abfd, _TEXT);
71733965Sjdp      asym->value -= asym->section->vma;
71833965Sjdp      break;
71933965Sjdp    case scData:
720218822Sdim      asym->section = bfd_make_section_old_way (abfd, _DATA);
72133965Sjdp      asym->value -= asym->section->vma;
72233965Sjdp      break;
72333965Sjdp    case scBss:
724218822Sdim      asym->section = bfd_make_section_old_way (abfd, _BSS);
72533965Sjdp      asym->value -= asym->section->vma;
72633965Sjdp      break;
72733965Sjdp    case scRegister:
72833965Sjdp      asym->flags = BSF_DEBUGGING;
72933965Sjdp      break;
73033965Sjdp    case scAbs:
73133965Sjdp      asym->section = bfd_abs_section_ptr;
73233965Sjdp      break;
73333965Sjdp    case scUndefined:
73433965Sjdp      asym->section = bfd_und_section_ptr;
73533965Sjdp      asym->flags = 0;
73633965Sjdp      asym->value = 0;
73733965Sjdp      break;
73833965Sjdp    case scCdbLocal:
73933965Sjdp    case scBits:
74033965Sjdp    case scCdbSystem:
74133965Sjdp    case scRegImage:
74233965Sjdp    case scInfo:
74333965Sjdp    case scUserStruct:
74433965Sjdp      asym->flags = BSF_DEBUGGING;
74533965Sjdp      break;
74633965Sjdp    case scSData:
74733965Sjdp      asym->section = bfd_make_section_old_way (abfd, ".sdata");
74833965Sjdp      asym->value -= asym->section->vma;
74933965Sjdp      break;
75033965Sjdp    case scSBss:
75133965Sjdp      asym->section = bfd_make_section_old_way (abfd, ".sbss");
75233965Sjdp      asym->value -= asym->section->vma;
75333965Sjdp      break;
75433965Sjdp    case scRData:
75533965Sjdp      asym->section = bfd_make_section_old_way (abfd, ".rdata");
75633965Sjdp      asym->value -= asym->section->vma;
75733965Sjdp      break;
75833965Sjdp    case scVar:
75933965Sjdp      asym->flags = BSF_DEBUGGING;
76033965Sjdp      break;
76133965Sjdp    case scCommon:
76233965Sjdp      if (asym->value > ecoff_data (abfd)->gp_size)
76333965Sjdp	{
76433965Sjdp	  asym->section = bfd_com_section_ptr;
76533965Sjdp	  asym->flags = 0;
76633965Sjdp	  break;
76733965Sjdp	}
76833965Sjdp      /* Fall through.  */
76933965Sjdp    case scSCommon:
77033965Sjdp      if (ecoff_scom_section.name == NULL)
77133965Sjdp	{
77233965Sjdp	  /* Initialize the small common section.  */
77333965Sjdp	  ecoff_scom_section.name = SCOMMON;
77433965Sjdp	  ecoff_scom_section.flags = SEC_IS_COMMON;
77533965Sjdp	  ecoff_scom_section.output_section = &ecoff_scom_section;
77633965Sjdp	  ecoff_scom_section.symbol = &ecoff_scom_symbol;
77733965Sjdp	  ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr;
77833965Sjdp	  ecoff_scom_symbol.name = SCOMMON;
77933965Sjdp	  ecoff_scom_symbol.flags = BSF_SECTION_SYM;
78033965Sjdp	  ecoff_scom_symbol.section = &ecoff_scom_section;
78133965Sjdp	  ecoff_scom_symbol_ptr = &ecoff_scom_symbol;
78233965Sjdp	}
78333965Sjdp      asym->section = &ecoff_scom_section;
78433965Sjdp      asym->flags = 0;
78533965Sjdp      break;
78633965Sjdp    case scVarRegister:
78733965Sjdp    case scVariant:
78833965Sjdp      asym->flags = BSF_DEBUGGING;
78933965Sjdp      break;
79033965Sjdp    case scSUndefined:
79133965Sjdp      asym->section = bfd_und_section_ptr;
79233965Sjdp      asym->flags = 0;
79333965Sjdp      asym->value = 0;
79433965Sjdp      break;
79533965Sjdp    case scInit:
79633965Sjdp      asym->section = bfd_make_section_old_way (abfd, ".init");
79733965Sjdp      asym->value -= asym->section->vma;
79833965Sjdp      break;
79933965Sjdp    case scBasedVar:
80033965Sjdp    case scXData:
80133965Sjdp    case scPData:
80233965Sjdp      asym->flags = BSF_DEBUGGING;
80333965Sjdp      break;
80433965Sjdp    case scFini:
80533965Sjdp      asym->section = bfd_make_section_old_way (abfd, ".fini");
80633965Sjdp      asym->value -= asym->section->vma;
80733965Sjdp      break;
80833965Sjdp    case scRConst:
80933965Sjdp      asym->section = bfd_make_section_old_way (abfd, ".rconst");
81033965Sjdp      asym->value -= asym->section->vma;
81133965Sjdp      break;
81233965Sjdp    default:
81333965Sjdp      break;
81433965Sjdp    }
81533965Sjdp
81633965Sjdp  /* Look for special constructors symbols and make relocation entries
81733965Sjdp     in a special construction section.  These are produced by the
81833965Sjdp     -fgnu-linker argument to g++.  */
81933965Sjdp  if (ECOFF_IS_STAB (ecoff_sym))
82033965Sjdp    {
82133965Sjdp      switch (ECOFF_UNMARK_STAB (ecoff_sym->index))
82233965Sjdp	{
82333965Sjdp	default:
82433965Sjdp	  break;
82533965Sjdp
82633965Sjdp	case N_SETA:
82733965Sjdp	case N_SETT:
82833965Sjdp	case N_SETD:
82933965Sjdp	case N_SETB:
830218822Sdim	  /* Mark the symbol as a constructor.  */
831218822Sdim	  asym->flags |= BSF_CONSTRUCTOR;
83233965Sjdp	  break;
83333965Sjdp	}
83433965Sjdp    }
835130561Sobrien  return TRUE;
83633965Sjdp}
83733965Sjdp
83833965Sjdp/* Read an ECOFF symbol table.  */
83933965Sjdp
840130561Sobrienbfd_boolean
841218822Sdim_bfd_ecoff_slurp_symbol_table (bfd *abfd)
84233965Sjdp{
84333965Sjdp  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
84433965Sjdp  const bfd_size_type external_ext_size
84533965Sjdp    = backend->debug_swap.external_ext_size;
84633965Sjdp  const bfd_size_type external_sym_size
84733965Sjdp    = backend->debug_swap.external_sym_size;
848218822Sdim  void (* const swap_ext_in) (bfd *, void *, EXTR *)
84933965Sjdp    = backend->debug_swap.swap_ext_in;
850218822Sdim  void (* const swap_sym_in) (bfd *, void *, SYMR *)
85133965Sjdp    = backend->debug_swap.swap_sym_in;
85233965Sjdp  bfd_size_type internal_size;
85333965Sjdp  ecoff_symbol_type *internal;
85433965Sjdp  ecoff_symbol_type *internal_ptr;
85533965Sjdp  char *eraw_src;
85633965Sjdp  char *eraw_end;
85733965Sjdp  FDR *fdr_ptr;
85833965Sjdp  FDR *fdr_end;
85933965Sjdp
86033965Sjdp  /* If we've already read in the symbol table, do nothing.  */
86133965Sjdp  if (ecoff_data (abfd)->canonical_symbols != NULL)
862130561Sobrien    return TRUE;
86333965Sjdp
86433965Sjdp  /* Get the symbolic information.  */
865218822Sdim  if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL,
86633965Sjdp					&ecoff_data (abfd)->debug_info))
867130561Sobrien    return FALSE;
86833965Sjdp  if (bfd_get_symcount (abfd) == 0)
869130561Sobrien    return TRUE;
87033965Sjdp
87189857Sobrien  internal_size = bfd_get_symcount (abfd);
87289857Sobrien  internal_size *= sizeof (ecoff_symbol_type);
873218822Sdim  internal = bfd_alloc (abfd, internal_size);
87433965Sjdp  if (internal == NULL)
875130561Sobrien    return FALSE;
87633965Sjdp
87733965Sjdp  internal_ptr = internal;
87833965Sjdp  eraw_src = (char *) ecoff_data (abfd)->debug_info.external_ext;
87933965Sjdp  eraw_end = (eraw_src
88033965Sjdp	      + (ecoff_data (abfd)->debug_info.symbolic_header.iextMax
88133965Sjdp		 * external_ext_size));
88233965Sjdp  for (; eraw_src < eraw_end; eraw_src += external_ext_size, internal_ptr++)
88333965Sjdp    {
88433965Sjdp      EXTR internal_esym;
88533965Sjdp
886218822Sdim      (*swap_ext_in) (abfd, (void *) eraw_src, &internal_esym);
88733965Sjdp      internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext
88833965Sjdp				   + internal_esym.asym.iss);
88933965Sjdp      if (!ecoff_set_symbol_info (abfd, &internal_esym.asym,
89033965Sjdp				  &internal_ptr->symbol, 1,
89133965Sjdp				  internal_esym.weakext))
892130561Sobrien	return FALSE;
89333965Sjdp      /* The alpha uses a negative ifd field for section symbols.  */
89433965Sjdp      if (internal_esym.ifd >= 0)
89533965Sjdp	internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr
89633965Sjdp			     + internal_esym.ifd);
89733965Sjdp      else
89833965Sjdp	internal_ptr->fdr = NULL;
899130561Sobrien      internal_ptr->local = FALSE;
900218822Sdim      internal_ptr->native = (void *) eraw_src;
90133965Sjdp    }
90233965Sjdp
90333965Sjdp  /* The local symbols must be accessed via the fdr's, because the
90433965Sjdp     string and aux indices are relative to the fdr information.  */
90533965Sjdp  fdr_ptr = ecoff_data (abfd)->debug_info.fdr;
90633965Sjdp  fdr_end = fdr_ptr + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax;
90733965Sjdp  for (; fdr_ptr < fdr_end; fdr_ptr++)
90833965Sjdp    {
90933965Sjdp      char *lraw_src;
91033965Sjdp      char *lraw_end;
91133965Sjdp
91233965Sjdp      lraw_src = ((char *) ecoff_data (abfd)->debug_info.external_sym
91333965Sjdp		  + fdr_ptr->isymBase * external_sym_size);
91433965Sjdp      lraw_end = lraw_src + fdr_ptr->csym * external_sym_size;
91533965Sjdp      for (;
91633965Sjdp	   lraw_src < lraw_end;
91733965Sjdp	   lraw_src += external_sym_size, internal_ptr++)
91833965Sjdp	{
91933965Sjdp	  SYMR internal_sym;
92033965Sjdp
921218822Sdim	  (*swap_sym_in) (abfd, (void *) lraw_src, &internal_sym);
92233965Sjdp	  internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss
92333965Sjdp				       + fdr_ptr->issBase
92433965Sjdp				       + internal_sym.iss);
92533965Sjdp	  if (!ecoff_set_symbol_info (abfd, &internal_sym,
92633965Sjdp				      &internal_ptr->symbol, 0, 0))
927130561Sobrien	    return FALSE;
92833965Sjdp	  internal_ptr->fdr = fdr_ptr;
929130561Sobrien	  internal_ptr->local = TRUE;
930218822Sdim	  internal_ptr->native = (void *) lraw_src;
93133965Sjdp	}
93233965Sjdp    }
93333965Sjdp
93433965Sjdp  ecoff_data (abfd)->canonical_symbols = internal;
93533965Sjdp
936130561Sobrien  return TRUE;
93733965Sjdp}
93833965Sjdp
93933965Sjdp/* Return the amount of space needed for the canonical symbols.  */
94033965Sjdp
94133965Sjdplong
942218822Sdim_bfd_ecoff_get_symtab_upper_bound (bfd *abfd)
94333965Sjdp{
944218822Sdim  if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL,
94533965Sjdp					&ecoff_data (abfd)->debug_info))
94633965Sjdp    return -1;
94733965Sjdp
94833965Sjdp  if (bfd_get_symcount (abfd) == 0)
94933965Sjdp    return 0;
95033965Sjdp
95133965Sjdp  return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *));
95233965Sjdp}
95333965Sjdp
95433965Sjdp/* Get the canonical symbols.  */
95533965Sjdp
95633965Sjdplong
957218822Sdim_bfd_ecoff_canonicalize_symtab (bfd *abfd, asymbol **alocation)
95833965Sjdp{
95933965Sjdp  unsigned int counter = 0;
96033965Sjdp  ecoff_symbol_type *symbase;
96133965Sjdp  ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
96233965Sjdp
963104834Sobrien  if (! _bfd_ecoff_slurp_symbol_table (abfd))
96433965Sjdp    return -1;
96533965Sjdp  if (bfd_get_symcount (abfd) == 0)
96633965Sjdp    return 0;
96733965Sjdp
96833965Sjdp  symbase = ecoff_data (abfd)->canonical_symbols;
96933965Sjdp  while (counter < bfd_get_symcount (abfd))
97033965Sjdp    {
97133965Sjdp      *(location++) = symbase++;
97233965Sjdp      counter++;
97333965Sjdp    }
974218822Sdim  *location++ = NULL;
97533965Sjdp  return bfd_get_symcount (abfd);
97633965Sjdp}
97733965Sjdp
97833965Sjdp/* Turn ECOFF type information into a printable string.
97933965Sjdp   ecoff_emit_aggregate and ecoff_type_to_string are from
98033965Sjdp   gcc/mips-tdump.c, with swapping added and used_ptr removed.  */
98133965Sjdp
98233965Sjdp/* Write aggregate information to a string.  */
98333965Sjdp
98433965Sjdpstatic void
985218822Sdimecoff_emit_aggregate (bfd *abfd,
986218822Sdim		      FDR *fdr,
987218822Sdim		      char *string,
988218822Sdim		      RNDXR *rndx,
989218822Sdim		      long isym,
990218822Sdim		      const char *which)
99133965Sjdp{
99233965Sjdp  const struct ecoff_debug_swap * const debug_swap =
99333965Sjdp    &ecoff_backend (abfd)->debug_swap;
99433965Sjdp  struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
99533965Sjdp  unsigned int ifd = rndx->rfd;
99633965Sjdp  unsigned int indx = rndx->index;
99733965Sjdp  const char *name;
99877298Sobrien
99933965Sjdp  if (ifd == 0xfff)
100033965Sjdp    ifd = isym;
100133965Sjdp
100233965Sjdp  /* An ifd of -1 is an opaque type.  An escaped index of 0 is a
100333965Sjdp     struct return type of a procedure compiled without -g.  */
100433965Sjdp  if (ifd == 0xffffffff
100533965Sjdp      || (rndx->rfd == 0xfff && indx == 0))
100633965Sjdp    name = "<undefined>";
100733965Sjdp  else if (indx == indexNil)
100833965Sjdp    name = "<no name>";
100933965Sjdp  else
101033965Sjdp    {
101133965Sjdp      SYMR sym;
101233965Sjdp
101333965Sjdp      if (debug_info->external_rfd == NULL)
101433965Sjdp	fdr = debug_info->fdr + ifd;
101533965Sjdp      else
101633965Sjdp	{
101733965Sjdp	  RFDT rfd;
101833965Sjdp
101933965Sjdp	  (*debug_swap->swap_rfd_in) (abfd,
102033965Sjdp				      ((char *) debug_info->external_rfd
102133965Sjdp				       + ((fdr->rfdBase + ifd)
102233965Sjdp					  * debug_swap->external_rfd_size)),
102333965Sjdp				      &rfd);
102433965Sjdp	  fdr = debug_info->fdr + rfd;
102533965Sjdp	}
102633965Sjdp
102733965Sjdp      indx += fdr->isymBase;
102833965Sjdp
102933965Sjdp      (*debug_swap->swap_sym_in) (abfd,
103033965Sjdp				  ((char *) debug_info->external_sym
103133965Sjdp				   + indx * debug_swap->external_sym_size),
103233965Sjdp				  &sym);
103333965Sjdp
103433965Sjdp      name = debug_info->ss + fdr->issBase + sym.iss;
103533965Sjdp    }
103633965Sjdp
103733965Sjdp  sprintf (string,
103833965Sjdp	   "%s %s { ifd = %u, index = %lu }",
103933965Sjdp	   which, name, ifd,
104033965Sjdp	   ((long) indx
104133965Sjdp	    + debug_info->symbolic_header.iextMax));
104233965Sjdp}
104333965Sjdp
104433965Sjdp/* Convert the type information to string format.  */
104533965Sjdp
104633965Sjdpstatic char *
1047218822Sdimecoff_type_to_string (bfd *abfd, FDR *fdr, unsigned int indx)
104833965Sjdp{
104933965Sjdp  union aux_ext *aux_ptr;
105033965Sjdp  int bigendian;
105133965Sjdp  AUXU u;
1052218822Sdim  struct qual
1053218822Sdim  {
105433965Sjdp    unsigned int  type;
105533965Sjdp    int  low_bound;
105633965Sjdp    int  high_bound;
105733965Sjdp    int  stride;
105833965Sjdp  } qualifiers[7];
105933965Sjdp  unsigned int basic_type;
106033965Sjdp  int i;
106133965Sjdp  char buffer1[1024];
106233965Sjdp  static char buffer2[1024];
106333965Sjdp  char *p1 = buffer1;
106433965Sjdp  char *p2 = buffer2;
106533965Sjdp  RNDXR rndx;
106633965Sjdp
106733965Sjdp  aux_ptr = ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase;
106833965Sjdp  bigendian = fdr->fBigendian;
106933965Sjdp
107033965Sjdp  for (i = 0; i < 7; i++)
107133965Sjdp    {
107233965Sjdp      qualifiers[i].low_bound = 0;
107333965Sjdp      qualifiers[i].high_bound = 0;
107433965Sjdp      qualifiers[i].stride = 0;
107533965Sjdp    }
107633965Sjdp
107733965Sjdp  if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == (bfd_vma) -1)
107833965Sjdp    return "-1 (no type)";
107933965Sjdp  _bfd_ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
108033965Sjdp
108133965Sjdp  basic_type = u.ti.bt;
108233965Sjdp  qualifiers[0].type = u.ti.tq0;
108333965Sjdp  qualifiers[1].type = u.ti.tq1;
108433965Sjdp  qualifiers[2].type = u.ti.tq2;
108533965Sjdp  qualifiers[3].type = u.ti.tq3;
108633965Sjdp  qualifiers[4].type = u.ti.tq4;
108733965Sjdp  qualifiers[5].type = u.ti.tq5;
108833965Sjdp  qualifiers[6].type = tqNil;
108933965Sjdp
1090104834Sobrien  /* Go get the basic type.  */
109133965Sjdp  switch (basic_type)
109233965Sjdp    {
1093104834Sobrien    case btNil:			/* Undefined.  */
109433965Sjdp      strcpy (p1, "nil");
109533965Sjdp      break;
109633965Sjdp
1097104834Sobrien    case btAdr:			/* Address - integer same size as pointer.  */
109833965Sjdp      strcpy (p1, "address");
109933965Sjdp      break;
110033965Sjdp
1101104834Sobrien    case btChar:		/* Character.  */
110233965Sjdp      strcpy (p1, "char");
110333965Sjdp      break;
110433965Sjdp
1105104834Sobrien    case btUChar:		/* Unsigned character.  */
110633965Sjdp      strcpy (p1, "unsigned char");
110733965Sjdp      break;
110833965Sjdp
1109104834Sobrien    case btShort:		/* Short.  */
111033965Sjdp      strcpy (p1, "short");
111133965Sjdp      break;
111233965Sjdp
1113104834Sobrien    case btUShort:		/* Unsigned short.  */
111433965Sjdp      strcpy (p1, "unsigned short");
111533965Sjdp      break;
111633965Sjdp
1117104834Sobrien    case btInt:			/* Int.  */
111833965Sjdp      strcpy (p1, "int");
111933965Sjdp      break;
112033965Sjdp
1121104834Sobrien    case btUInt:		/* Unsigned int.  */
112233965Sjdp      strcpy (p1, "unsigned int");
112333965Sjdp      break;
112433965Sjdp
1125104834Sobrien    case btLong:		/* Long.  */
112633965Sjdp      strcpy (p1, "long");
112733965Sjdp      break;
112833965Sjdp
1129104834Sobrien    case btULong:		/* Unsigned long.  */
113033965Sjdp      strcpy (p1, "unsigned long");
113133965Sjdp      break;
113233965Sjdp
1133104834Sobrien    case btFloat:		/* Float (real).  */
113433965Sjdp      strcpy (p1, "float");
113533965Sjdp      break;
113633965Sjdp
1137104834Sobrien    case btDouble:		/* Double (real).  */
113833965Sjdp      strcpy (p1, "double");
113933965Sjdp      break;
114033965Sjdp
114133965Sjdp      /* Structures add 1-2 aux words:
114233965Sjdp	 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
114333965Sjdp	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
114433965Sjdp
1145104834Sobrien    case btStruct:		/* Structure (Record).  */
114633965Sjdp      _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
114733965Sjdp      ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
114833965Sjdp			    (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
114933965Sjdp			    "struct");
1150104834Sobrien      indx++;			/* Skip aux words.  */
115133965Sjdp      break;
115233965Sjdp
115333965Sjdp      /* Unions add 1-2 aux words:
115433965Sjdp	 1st word is [ST_RFDESCAPE, offset] pointer to union def;
115533965Sjdp	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
115633965Sjdp
1157104834Sobrien    case btUnion:		/* Union.  */
115833965Sjdp      _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
115933965Sjdp      ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
116033965Sjdp			    (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
116133965Sjdp			    "union");
1162104834Sobrien      indx++;			/* Skip aux words.  */
116333965Sjdp      break;
116433965Sjdp
116533965Sjdp      /* Enumerations add 1-2 aux words:
116633965Sjdp	 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
116733965Sjdp	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
116833965Sjdp
1169104834Sobrien    case btEnum:		/* Enumeration.  */
117033965Sjdp      _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
117133965Sjdp      ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
117233965Sjdp			    (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
117333965Sjdp			    "enum");
1174104834Sobrien      indx++;			/* Skip aux words.  */
117533965Sjdp      break;
117633965Sjdp
1177104834Sobrien    case btTypedef:		/* Defined via a typedef, isymRef points.  */
117833965Sjdp      strcpy (p1, "typedef");
117933965Sjdp      break;
118033965Sjdp
1181104834Sobrien    case btRange:		/* Subrange of int.  */
118233965Sjdp      strcpy (p1, "subrange");
118333965Sjdp      break;
118433965Sjdp
1185104834Sobrien    case btSet:			/* Pascal sets.  */
118633965Sjdp      strcpy (p1, "set");
118733965Sjdp      break;
118833965Sjdp
1189104834Sobrien    case btComplex:		/* Fortran complex.  */
119033965Sjdp      strcpy (p1, "complex");
119133965Sjdp      break;
119233965Sjdp
1193104834Sobrien    case btDComplex:		/* Fortran double complex.  */
119433965Sjdp      strcpy (p1, "double complex");
119533965Sjdp      break;
119633965Sjdp
1197104834Sobrien    case btIndirect:		/* Forward or unnamed typedef.  */
119833965Sjdp      strcpy (p1, "forward/unamed typedef");
119933965Sjdp      break;
120033965Sjdp
1201104834Sobrien    case btFixedDec:		/* Fixed Decimal.  */
120233965Sjdp      strcpy (p1, "fixed decimal");
120333965Sjdp      break;
120433965Sjdp
1205104834Sobrien    case btFloatDec:		/* Float Decimal.  */
120633965Sjdp      strcpy (p1, "float decimal");
120733965Sjdp      break;
120833965Sjdp
1209104834Sobrien    case btString:		/* Varying Length Character String.  */
121033965Sjdp      strcpy (p1, "string");
121133965Sjdp      break;
121233965Sjdp
1213104834Sobrien    case btBit:			/* Aligned Bit String.  */
121433965Sjdp      strcpy (p1, "bit");
121533965Sjdp      break;
121633965Sjdp
1217104834Sobrien    case btPicture:		/* Picture.  */
121833965Sjdp      strcpy (p1, "picture");
121933965Sjdp      break;
122033965Sjdp
1221104834Sobrien    case btVoid:		/* Void.  */
122233965Sjdp      strcpy (p1, "void");
122333965Sjdp      break;
122433965Sjdp
122533965Sjdp    default:
122660484Sobrien      sprintf (p1, _("Unknown basic type %d"), (int) basic_type);
122733965Sjdp      break;
122833965Sjdp    }
122933965Sjdp
123033965Sjdp  p1 += strlen (buffer1);
123133965Sjdp
1232104834Sobrien  /* If this is a bitfield, get the bitsize.  */
123333965Sjdp  if (u.ti.fBitfield)
123433965Sjdp    {
123533965Sjdp      int bitsize;
123633965Sjdp
123733965Sjdp      bitsize = AUX_GET_WIDTH (bigendian, &aux_ptr[indx++]);
123833965Sjdp      sprintf (p1, " : %d", bitsize);
123933965Sjdp      p1 += strlen (buffer1);
124033965Sjdp    }
124133965Sjdp
1242104834Sobrien  /* Deal with any qualifiers.  */
124333965Sjdp  if (qualifiers[0].type != tqNil)
124433965Sjdp    {
1245104834Sobrien      /* Snarf up any array bounds in the correct order.  Arrays
1246104834Sobrien         store 5 successive words in the aux. table:
1247104834Sobrien        	word 0	RNDXR to type of the bounds (ie, int)
1248104834Sobrien        	word 1	Current file descriptor index
1249104834Sobrien        	word 2	low bound
1250104834Sobrien        	word 3	high bound (or -1 if [])
1251104834Sobrien        	word 4	stride size in bits.  */
125233965Sjdp      for (i = 0; i < 7; i++)
125333965Sjdp	{
125433965Sjdp	  if (qualifiers[i].type == tqArray)
125533965Sjdp	    {
125633965Sjdp	      qualifiers[i].low_bound =
125733965Sjdp		AUX_GET_DNLOW (bigendian, &aux_ptr[indx+2]);
125833965Sjdp	      qualifiers[i].high_bound =
125933965Sjdp		AUX_GET_DNHIGH (bigendian, &aux_ptr[indx+3]);
126033965Sjdp	      qualifiers[i].stride =
126133965Sjdp		AUX_GET_WIDTH (bigendian, &aux_ptr[indx+4]);
126233965Sjdp	      indx += 5;
126333965Sjdp	    }
126433965Sjdp	}
126533965Sjdp
1266104834Sobrien      /* Now print out the qualifiers.  */
126733965Sjdp      for (i = 0; i < 6; i++)
126833965Sjdp	{
126933965Sjdp	  switch (qualifiers[i].type)
127033965Sjdp	    {
127133965Sjdp	    case tqNil:
127233965Sjdp	    case tqMax:
127333965Sjdp	      break;
127433965Sjdp
127533965Sjdp	    case tqPtr:
127633965Sjdp	      strcpy (p2, "ptr to ");
127733965Sjdp	      p2 += sizeof ("ptr to ")-1;
127833965Sjdp	      break;
127933965Sjdp
128033965Sjdp	    case tqVol:
128133965Sjdp	      strcpy (p2, "volatile ");
128233965Sjdp	      p2 += sizeof ("volatile ")-1;
128333965Sjdp	      break;
128433965Sjdp
128533965Sjdp	    case tqFar:
128633965Sjdp	      strcpy (p2, "far ");
128733965Sjdp	      p2 += sizeof ("far ")-1;
128833965Sjdp	      break;
128933965Sjdp
129033965Sjdp	    case tqProc:
129133965Sjdp	      strcpy (p2, "func. ret. ");
129233965Sjdp	      p2 += sizeof ("func. ret. ");
129333965Sjdp	      break;
129433965Sjdp
129533965Sjdp	    case tqArray:
129633965Sjdp	      {
129733965Sjdp		int first_array = i;
129833965Sjdp		int j;
129933965Sjdp
130033965Sjdp		/* Print array bounds reversed (ie, in the order the C
130177298Sobrien		   programmer writes them).  C is such a fun language....  */
130233965Sjdp		while (i < 5 && qualifiers[i+1].type == tqArray)
130333965Sjdp		  i++;
130433965Sjdp
130533965Sjdp		for (j = i; j >= first_array; j--)
130633965Sjdp		  {
130733965Sjdp		    strcpy (p2, "array [");
130833965Sjdp		    p2 += sizeof ("array [")-1;
130933965Sjdp		    if (qualifiers[j].low_bound != 0)
131033965Sjdp		      sprintf (p2,
131133965Sjdp			       "%ld:%ld {%ld bits}",
131233965Sjdp			       (long) qualifiers[j].low_bound,
131333965Sjdp			       (long) qualifiers[j].high_bound,
131433965Sjdp			       (long) qualifiers[j].stride);
131533965Sjdp
131633965Sjdp		    else if (qualifiers[j].high_bound != -1)
131733965Sjdp		      sprintf (p2,
131833965Sjdp			       "%ld {%ld bits}",
131933965Sjdp			       (long) (qualifiers[j].high_bound + 1),
132033965Sjdp			       (long) (qualifiers[j].stride));
132133965Sjdp
132233965Sjdp		    else
132333965Sjdp		      sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
132433965Sjdp
132533965Sjdp		    p2 += strlen (p2);
132633965Sjdp		    strcpy (p2, "] of ");
132733965Sjdp		    p2 += sizeof ("] of ")-1;
132833965Sjdp		  }
132933965Sjdp	      }
133033965Sjdp	      break;
133133965Sjdp	    }
133233965Sjdp	}
133333965Sjdp    }
133433965Sjdp
133533965Sjdp  strcpy (p2, buffer1);
133633965Sjdp  return buffer2;
133733965Sjdp}
133833965Sjdp
133933965Sjdp/* Return information about ECOFF symbol SYMBOL in RET.  */
134033965Sjdp
134133965Sjdpvoid
1342218822Sdim_bfd_ecoff_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
1343218822Sdim			    asymbol *symbol,
1344218822Sdim			    symbol_info *ret)
134533965Sjdp{
134633965Sjdp  bfd_symbol_info (symbol, ret);
134733965Sjdp}
134833965Sjdp
134933965Sjdp/* Return whether this is a local label.  */
135033965Sjdp
1351130561Sobrienbfd_boolean
1352218822Sdim_bfd_ecoff_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
1353218822Sdim				    const char *name)
135433965Sjdp{
135533965Sjdp  return name[0] == '$';
135633965Sjdp}
135733965Sjdp
135833965Sjdp/* Print information about an ECOFF symbol.  */
135933965Sjdp
136033965Sjdpvoid
1361218822Sdim_bfd_ecoff_print_symbol (bfd *abfd,
1362218822Sdim			 void * filep,
1363218822Sdim			 asymbol *symbol,
1364218822Sdim			 bfd_print_symbol_type how)
136533965Sjdp{
136633965Sjdp  const struct ecoff_debug_swap * const debug_swap
136733965Sjdp    = &ecoff_backend (abfd)->debug_swap;
136833965Sjdp  FILE *file = (FILE *)filep;
136933965Sjdp
137033965Sjdp  switch (how)
137133965Sjdp    {
137233965Sjdp    case bfd_print_symbol_name:
137333965Sjdp      fprintf (file, "%s", symbol->name);
137433965Sjdp      break;
137533965Sjdp    case bfd_print_symbol_more:
137633965Sjdp      if (ecoffsymbol (symbol)->local)
137733965Sjdp	{
137833965Sjdp	  SYMR ecoff_sym;
137977298Sobrien
138033965Sjdp	  (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native,
138133965Sjdp				      &ecoff_sym);
138233965Sjdp	  fprintf (file, "ecoff local ");
138333965Sjdp	  fprintf_vma (file, (bfd_vma) ecoff_sym.value);
138433965Sjdp	  fprintf (file, " %x %x", (unsigned) ecoff_sym.st,
138533965Sjdp		   (unsigned) ecoff_sym.sc);
138633965Sjdp	}
138733965Sjdp      else
138833965Sjdp	{
138933965Sjdp	  EXTR ecoff_ext;
139033965Sjdp
139133965Sjdp	  (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native,
139233965Sjdp				      &ecoff_ext);
139333965Sjdp	  fprintf (file, "ecoff extern ");
139433965Sjdp	  fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value);
139533965Sjdp	  fprintf (file, " %x %x", (unsigned) ecoff_ext.asym.st,
139633965Sjdp		   (unsigned) ecoff_ext.asym.sc);
139733965Sjdp	}
139833965Sjdp      break;
139933965Sjdp    case bfd_print_symbol_all:
1400104834Sobrien      /* Print out the symbols in a reasonable way.  */
140133965Sjdp      {
140233965Sjdp	char type;
140333965Sjdp	int pos;
140433965Sjdp	EXTR ecoff_ext;
140533965Sjdp	char jmptbl;
140633965Sjdp	char cobol_main;
140733965Sjdp	char weakext;
140833965Sjdp
140933965Sjdp	if (ecoffsymbol (symbol)->local)
141033965Sjdp	  {
141133965Sjdp	    (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native,
141233965Sjdp					&ecoff_ext.asym);
141333965Sjdp	    type = 'l';
141433965Sjdp	    pos = ((((char *) ecoffsymbol (symbol)->native
141533965Sjdp		     - (char *) ecoff_data (abfd)->debug_info.external_sym)
141633965Sjdp		    / debug_swap->external_sym_size)
141733965Sjdp		   + ecoff_data (abfd)->debug_info.symbolic_header.iextMax);
141833965Sjdp	    jmptbl = ' ';
141933965Sjdp	    cobol_main = ' ';
142033965Sjdp	    weakext = ' ';
142133965Sjdp	  }
142233965Sjdp	else
142333965Sjdp	  {
142433965Sjdp	    (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native,
142533965Sjdp					&ecoff_ext);
142633965Sjdp	    type = 'e';
142733965Sjdp	    pos = (((char *) ecoffsymbol (symbol)->native
142833965Sjdp		    - (char *) ecoff_data (abfd)->debug_info.external_ext)
142933965Sjdp		   / debug_swap->external_ext_size);
143033965Sjdp	    jmptbl = ecoff_ext.jmptbl ? 'j' : ' ';
143133965Sjdp	    cobol_main = ecoff_ext.cobol_main ? 'c' : ' ';
143233965Sjdp	    weakext = ecoff_ext.weakext ? 'w' : ' ';
143333965Sjdp	  }
143433965Sjdp
143533965Sjdp	fprintf (file, "[%3d] %c ",
143633965Sjdp		 pos, type);
143733965Sjdp	fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value);
143833965Sjdp	fprintf (file, " st %x sc %x indx %x %c%c%c %s",
143933965Sjdp		 (unsigned) ecoff_ext.asym.st,
144033965Sjdp		 (unsigned) ecoff_ext.asym.sc,
144133965Sjdp		 (unsigned) ecoff_ext.asym.index,
144233965Sjdp		 jmptbl, cobol_main, weakext,
144333965Sjdp		 symbol->name);
144433965Sjdp
144533965Sjdp	if (ecoffsymbol (symbol)->fdr != NULL
144633965Sjdp	    && ecoff_ext.asym.index != indexNil)
144733965Sjdp	  {
144833965Sjdp	    FDR *fdr;
144933965Sjdp	    unsigned int indx;
145033965Sjdp	    int bigendian;
145133965Sjdp	    bfd_size_type sym_base;
145233965Sjdp	    union aux_ext *aux_base;
145333965Sjdp
145433965Sjdp	    fdr = ecoffsymbol (symbol)->fdr;
145533965Sjdp	    indx = ecoff_ext.asym.index;
145633965Sjdp
145733965Sjdp	    /* sym_base is used to map the fdr relative indices which
145833965Sjdp	       appear in the file to the position number which we are
145933965Sjdp	       using.  */
146033965Sjdp	    sym_base = fdr->isymBase;
146133965Sjdp	    if (ecoffsymbol (symbol)->local)
146233965Sjdp	      sym_base +=
146333965Sjdp		ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
146433965Sjdp
146533965Sjdp	    /* aux_base is the start of the aux entries for this file;
146633965Sjdp	       asym.index is an offset from this.  */
146733965Sjdp	    aux_base = (ecoff_data (abfd)->debug_info.external_aux
146833965Sjdp			+ fdr->iauxBase);
146933965Sjdp
147033965Sjdp	    /* The aux entries are stored in host byte order; the
147133965Sjdp	       order is indicated by a bit in the fdr.  */
147233965Sjdp	    bigendian = fdr->fBigendian;
147333965Sjdp
1474104834Sobrien	    /* This switch is basically from gcc/mips-tdump.c.  */
147533965Sjdp	    switch (ecoff_ext.asym.st)
147633965Sjdp	      {
147733965Sjdp	      case stNil:
147833965Sjdp	      case stLabel:
147933965Sjdp		break;
148033965Sjdp
148133965Sjdp	      case stFile:
148233965Sjdp	      case stBlock:
148360484Sobrien		fprintf (file, _("\n      End+1 symbol: %ld"),
148433965Sjdp			 (long) (indx + sym_base));
148533965Sjdp		break;
148633965Sjdp
148733965Sjdp	      case stEnd:
148833965Sjdp		if (ecoff_ext.asym.sc == scText
148933965Sjdp		    || ecoff_ext.asym.sc == scInfo)
149060484Sobrien		  fprintf (file, _("\n      First symbol: %ld"),
149133965Sjdp			   (long) (indx + sym_base));
149233965Sjdp		else
149377298Sobrien		  fprintf (file, _("\n      First symbol: %ld"),
149433965Sjdp			   ((long)
149533965Sjdp			    (AUX_GET_ISYM (bigendian,
149633965Sjdp					   &aux_base[ecoff_ext.asym.index])
149733965Sjdp			     + sym_base)));
149833965Sjdp		break;
149933965Sjdp
150033965Sjdp	      case stProc:
150133965Sjdp	      case stStaticProc:
150233965Sjdp		if (ECOFF_IS_STAB (&ecoff_ext.asym))
150333965Sjdp		  ;
150433965Sjdp		else if (ecoffsymbol (symbol)->local)
150560484Sobrien		  fprintf (file, _("\n      End+1 symbol: %-7ld   Type:  %s"),
150633965Sjdp			   ((long)
150733965Sjdp			    (AUX_GET_ISYM (bigendian,
150833965Sjdp					   &aux_base[ecoff_ext.asym.index])
150933965Sjdp			     + sym_base)),
151033965Sjdp			   ecoff_type_to_string (abfd, fdr, indx + 1));
151133965Sjdp		else
151260484Sobrien		  fprintf (file, _("\n      Local symbol: %ld"),
151333965Sjdp			   ((long) indx
151433965Sjdp			    + (long) sym_base
151533965Sjdp			    + (ecoff_data (abfd)
151633965Sjdp			       ->debug_info.symbolic_header.iextMax)));
151733965Sjdp		break;
151833965Sjdp
151933965Sjdp	      case stStruct:
152060484Sobrien		fprintf (file, _("\n      struct; End+1 symbol: %ld"),
152133965Sjdp			 (long) (indx + sym_base));
152233965Sjdp		break;
152333965Sjdp
152433965Sjdp	      case stUnion:
152560484Sobrien		fprintf (file, _("\n      union; End+1 symbol: %ld"),
152633965Sjdp			 (long) (indx + sym_base));
152733965Sjdp		break;
152833965Sjdp
152933965Sjdp	      case stEnum:
153060484Sobrien		fprintf (file, _("\n      enum; End+1 symbol: %ld"),
153133965Sjdp			 (long) (indx + sym_base));
153233965Sjdp		break;
153333965Sjdp
153433965Sjdp	      default:
153533965Sjdp		if (! ECOFF_IS_STAB (&ecoff_ext.asym))
153660484Sobrien		  fprintf (file, _("\n      Type: %s"),
153733965Sjdp			   ecoff_type_to_string (abfd, fdr, indx));
153833965Sjdp		break;
153933965Sjdp	      }
154033965Sjdp	  }
154133965Sjdp      }
154233965Sjdp      break;
154333965Sjdp    }
154433965Sjdp}
154533965Sjdp
154633965Sjdp/* Read in the relocs for a section.  */
154733965Sjdp
1548130561Sobrienstatic bfd_boolean
1549218822Sdimecoff_slurp_reloc_table (bfd *abfd,
1550218822Sdim			 asection *section,
1551218822Sdim			 asymbol **symbols)
155233965Sjdp{
155333965Sjdp  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
155433965Sjdp  arelent *internal_relocs;
155533965Sjdp  bfd_size_type external_reloc_size;
155689857Sobrien  bfd_size_type amt;
155733965Sjdp  char *external_relocs;
155833965Sjdp  arelent *rptr;
155933965Sjdp  unsigned int i;
156033965Sjdp
1561218822Sdim  if (section->relocation != NULL
156233965Sjdp      || section->reloc_count == 0
156333965Sjdp      || (section->flags & SEC_CONSTRUCTOR) != 0)
1564130561Sobrien    return TRUE;
156533965Sjdp
1566104834Sobrien  if (! _bfd_ecoff_slurp_symbol_table (abfd))
1567130561Sobrien    return FALSE;
156877298Sobrien
156989857Sobrien  amt = section->reloc_count;
157089857Sobrien  amt *= sizeof (arelent);
1571218822Sdim  internal_relocs = bfd_alloc (abfd, amt);
157289857Sobrien
157333965Sjdp  external_reloc_size = backend->external_reloc_size;
157489857Sobrien  amt = external_reloc_size * section->reloc_count;
1575218822Sdim  external_relocs = bfd_alloc (abfd, amt);
1576218822Sdim  if (internal_relocs == NULL || external_relocs == NULL)
1577130561Sobrien    return FALSE;
157833965Sjdp  if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0)
1579130561Sobrien    return FALSE;
158089857Sobrien  if (bfd_bread (external_relocs, amt, abfd) != amt)
1581130561Sobrien    return FALSE;
158233965Sjdp
158333965Sjdp  for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++)
158433965Sjdp    {
158533965Sjdp      struct internal_reloc intern;
158633965Sjdp
158733965Sjdp      (*backend->swap_reloc_in) (abfd,
158833965Sjdp				 external_relocs + i * external_reloc_size,
158933965Sjdp				 &intern);
159033965Sjdp
159133965Sjdp      if (intern.r_extern)
159233965Sjdp	{
159333965Sjdp	  /* r_symndx is an index into the external symbols.  */
159433965Sjdp	  BFD_ASSERT (intern.r_symndx >= 0
159533965Sjdp		      && (intern.r_symndx
159633965Sjdp			  < (ecoff_data (abfd)
159733965Sjdp			     ->debug_info.symbolic_header.iextMax)));
159833965Sjdp	  rptr->sym_ptr_ptr = symbols + intern.r_symndx;
159933965Sjdp	  rptr->addend = 0;
160033965Sjdp	}
160133965Sjdp      else if (intern.r_symndx == RELOC_SECTION_NONE
160233965Sjdp	       || intern.r_symndx == RELOC_SECTION_ABS)
160333965Sjdp	{
160433965Sjdp	  rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
160533965Sjdp	  rptr->addend = 0;
160633965Sjdp	}
160733965Sjdp      else
160833965Sjdp	{
160989857Sobrien	  const char *sec_name;
161033965Sjdp	  asection *sec;
161133965Sjdp
161233965Sjdp	  /* r_symndx is a section key.  */
161333965Sjdp	  switch (intern.r_symndx)
161433965Sjdp	    {
1615218822Sdim	    case RELOC_SECTION_TEXT:  sec_name = _TEXT;  break;
1616218822Sdim	    case RELOC_SECTION_RDATA: sec_name = _RDATA; break;
1617218822Sdim	    case RELOC_SECTION_DATA:  sec_name = _DATA;  break;
1618218822Sdim	    case RELOC_SECTION_SDATA: sec_name = _SDATA; break;
1619218822Sdim	    case RELOC_SECTION_SBSS:  sec_name = _SBSS;  break;
1620218822Sdim	    case RELOC_SECTION_BSS:   sec_name = _BSS;   break;
1621218822Sdim	    case RELOC_SECTION_INIT:  sec_name = _INIT;  break;
1622218822Sdim	    case RELOC_SECTION_LIT8:  sec_name = _LIT8;  break;
1623218822Sdim	    case RELOC_SECTION_LIT4:  sec_name = _LIT4;  break;
1624218822Sdim	    case RELOC_SECTION_XDATA: sec_name = _XDATA; break;
1625218822Sdim	    case RELOC_SECTION_PDATA: sec_name = _PDATA; break;
1626218822Sdim	    case RELOC_SECTION_FINI:  sec_name = _FINI;  break;
1627218822Sdim	    case RELOC_SECTION_LITA:  sec_name = _LITA;  break;
1628218822Sdim	    case RELOC_SECTION_RCONST: sec_name = _RCONST; break;
162933965Sjdp	    default: abort ();
163033965Sjdp	    }
163133965Sjdp
163233965Sjdp	  sec = bfd_get_section_by_name (abfd, sec_name);
1633218822Sdim	  if (sec == NULL)
163433965Sjdp	    abort ();
163533965Sjdp	  rptr->sym_ptr_ptr = sec->symbol_ptr_ptr;
163633965Sjdp
163733965Sjdp	  rptr->addend = - bfd_get_section_vma (abfd, sec);
163833965Sjdp	}
163933965Sjdp
164033965Sjdp      rptr->address = intern.r_vaddr - bfd_get_section_vma (abfd, section);
164133965Sjdp
164233965Sjdp      /* Let the backend select the howto field and do any other
164333965Sjdp	 required processing.  */
164433965Sjdp      (*backend->adjust_reloc_in) (abfd, &intern, rptr);
164533965Sjdp    }
164633965Sjdp
164733965Sjdp  bfd_release (abfd, external_relocs);
164833965Sjdp
164933965Sjdp  section->relocation = internal_relocs;
165033965Sjdp
1651130561Sobrien  return TRUE;
165233965Sjdp}
165333965Sjdp
165433965Sjdp/* Get a canonical list of relocs.  */
165533965Sjdp
165633965Sjdplong
1657218822Sdim_bfd_ecoff_canonicalize_reloc (bfd *abfd,
1658218822Sdim			       asection *section,
1659218822Sdim			       arelent **relptr,
1660218822Sdim			       asymbol **symbols)
166133965Sjdp{
166233965Sjdp  unsigned int count;
166333965Sjdp
166477298Sobrien  if (section->flags & SEC_CONSTRUCTOR)
166533965Sjdp    {
166633965Sjdp      arelent_chain *chain;
166733965Sjdp
166833965Sjdp      /* This section has relocs made up by us, not the file, so take
166933965Sjdp	 them out of their chain and place them into the data area
167033965Sjdp	 provided.  */
167133965Sjdp      for (count = 0, chain = section->constructor_chain;
167233965Sjdp	   count < section->reloc_count;
167333965Sjdp	   count++, chain = chain->next)
167433965Sjdp	*relptr++ = &chain->relent;
167533965Sjdp    }
167633965Sjdp  else
167777298Sobrien    {
167833965Sjdp      arelent *tblptr;
167933965Sjdp
1680104834Sobrien      if (! ecoff_slurp_reloc_table (abfd, section, symbols))
168133965Sjdp	return -1;
168233965Sjdp
168333965Sjdp      tblptr = section->relocation;
168433965Sjdp
168533965Sjdp      for (count = 0; count < section->reloc_count; count++)
168633965Sjdp	*relptr++ = tblptr++;
168733965Sjdp    }
168833965Sjdp
1689218822Sdim  *relptr = NULL;
169033965Sjdp
169133965Sjdp  return section->reloc_count;
169233965Sjdp}
169333965Sjdp
169433965Sjdp/* Provided a BFD, a section and an offset into the section, calculate
169533965Sjdp   and return the name of the source file and the line nearest to the
169633965Sjdp   wanted location.  */
169733965Sjdp
1698130561Sobrienbfd_boolean
1699218822Sdim_bfd_ecoff_find_nearest_line (bfd *abfd,
1700218822Sdim			      asection *section,
1701218822Sdim			      asymbol **ignore_symbols ATTRIBUTE_UNUSED,
1702218822Sdim			      bfd_vma offset,
1703218822Sdim			      const char **filename_ptr,
1704218822Sdim			      const char **functionname_ptr,
1705218822Sdim			      unsigned int *retline_ptr)
170633965Sjdp{
170733965Sjdp  const struct ecoff_debug_swap * const debug_swap
170833965Sjdp    = &ecoff_backend (abfd)->debug_swap;
170933965Sjdp  struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
171033965Sjdp  struct ecoff_find_line *line_info;
171133965Sjdp
171233965Sjdp  /* Make sure we have the FDR's.  */
1713218822Sdim  if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, debug_info)
171433965Sjdp      || bfd_get_symcount (abfd) == 0)
1715130561Sobrien    return FALSE;
171633965Sjdp
171733965Sjdp  if (ecoff_data (abfd)->find_line_info == NULL)
171833965Sjdp    {
171989857Sobrien      bfd_size_type amt = sizeof (struct ecoff_find_line);
1720218822Sdim
1721218822Sdim      ecoff_data (abfd)->find_line_info = bfd_zalloc (abfd, amt);
172233965Sjdp      if (ecoff_data (abfd)->find_line_info == NULL)
1723130561Sobrien	return FALSE;
172433965Sjdp    }
172533965Sjdp  line_info = ecoff_data (abfd)->find_line_info;
172633965Sjdp
172733965Sjdp  return _bfd_ecoff_locate_line (abfd, section, offset, debug_info,
172833965Sjdp				 debug_swap, line_info, filename_ptr,
172933965Sjdp				 functionname_ptr, retline_ptr);
173033965Sjdp}
173133965Sjdp
173233965Sjdp/* Copy private BFD data.  This is called by objcopy and strip.  We
173333965Sjdp   use it to copy the ECOFF debugging information from one BFD to the
173433965Sjdp   other.  It would be theoretically possible to represent the ECOFF
173533965Sjdp   debugging information in the symbol table.  However, it would be a
173633965Sjdp   lot of work, and there would be little gain (gas, gdb, and ld
173733965Sjdp   already access the ECOFF debugging information via the
173833965Sjdp   ecoff_debug_info structure, and that structure would have to be
173933965Sjdp   retained in order to support ECOFF debugging in MIPS ELF).
174033965Sjdp
174133965Sjdp   The debugging information for the ECOFF external symbols comes from
174233965Sjdp   the symbol table, so this function only handles the other debugging
174333965Sjdp   information.  */
174433965Sjdp
1745130561Sobrienbfd_boolean
1746218822Sdim_bfd_ecoff_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
174733965Sjdp{
174833965Sjdp  struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info;
174933965Sjdp  struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info;
1750218822Sdim  int i;
175133965Sjdp  asymbol **sym_ptr_ptr;
175233965Sjdp  size_t c;
1753130561Sobrien  bfd_boolean local;
175433965Sjdp
175533965Sjdp  /* We only want to copy information over if both BFD's use ECOFF
175633965Sjdp     format.  */
175733965Sjdp  if (bfd_get_flavour (ibfd) != bfd_target_ecoff_flavour
175833965Sjdp      || bfd_get_flavour (obfd) != bfd_target_ecoff_flavour)
1759130561Sobrien    return TRUE;
176033965Sjdp
176133965Sjdp  /* Copy the GP value and the register masks.  */
176233965Sjdp  ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp;
176333965Sjdp  ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask;
176433965Sjdp  ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask;
176533965Sjdp  for (i = 0; i < 3; i++)
176633965Sjdp    ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i];
176733965Sjdp
176833965Sjdp  /* Copy the version stamp.  */
176933965Sjdp  oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp;
177033965Sjdp
177133965Sjdp  /* If there are no symbols, don't copy any debugging information.  */
177233965Sjdp  c = bfd_get_symcount (obfd);
177333965Sjdp  sym_ptr_ptr = bfd_get_outsymbols (obfd);
1774218822Sdim  if (c == 0 || sym_ptr_ptr == NULL)
1775130561Sobrien    return TRUE;
177633965Sjdp
177733965Sjdp  /* See if there are any local symbols.  */
1778130561Sobrien  local = FALSE;
177933965Sjdp  for (; c > 0; c--, sym_ptr_ptr++)
178033965Sjdp    {
178133965Sjdp      if (ecoffsymbol (*sym_ptr_ptr)->local)
178233965Sjdp	{
1783130561Sobrien	  local = TRUE;
178433965Sjdp	  break;
178533965Sjdp	}
178633965Sjdp    }
178733965Sjdp
178833965Sjdp  if (local)
178933965Sjdp    {
179033965Sjdp      /* There are some local symbols.  We just bring over all the
179133965Sjdp	 debugging information.  FIXME: This is not quite the right
179233965Sjdp	 thing to do.  If the user has asked us to discard all
179333965Sjdp	 debugging information, then we are probably going to wind up
179433965Sjdp	 keeping it because there will probably be some local symbol
179533965Sjdp	 which objcopy did not discard.  We should actually break
179633965Sjdp	 apart the debugging information and only keep that which
179733965Sjdp	 applies to the symbols we want to keep.  */
179833965Sjdp      oinfo->symbolic_header.ilineMax = iinfo->symbolic_header.ilineMax;
179933965Sjdp      oinfo->symbolic_header.cbLine = iinfo->symbolic_header.cbLine;
180033965Sjdp      oinfo->line = iinfo->line;
180133965Sjdp
180233965Sjdp      oinfo->symbolic_header.idnMax = iinfo->symbolic_header.idnMax;
180333965Sjdp      oinfo->external_dnr = iinfo->external_dnr;
180433965Sjdp
180533965Sjdp      oinfo->symbolic_header.ipdMax = iinfo->symbolic_header.ipdMax;
180633965Sjdp      oinfo->external_pdr = iinfo->external_pdr;
180733965Sjdp
180833965Sjdp      oinfo->symbolic_header.isymMax = iinfo->symbolic_header.isymMax;
180933965Sjdp      oinfo->external_sym = iinfo->external_sym;
181033965Sjdp
181133965Sjdp      oinfo->symbolic_header.ioptMax = iinfo->symbolic_header.ioptMax;
181233965Sjdp      oinfo->external_opt = iinfo->external_opt;
181333965Sjdp
181433965Sjdp      oinfo->symbolic_header.iauxMax = iinfo->symbolic_header.iauxMax;
181533965Sjdp      oinfo->external_aux = iinfo->external_aux;
181633965Sjdp
181733965Sjdp      oinfo->symbolic_header.issMax = iinfo->symbolic_header.issMax;
181833965Sjdp      oinfo->ss = iinfo->ss;
181933965Sjdp
182033965Sjdp      oinfo->symbolic_header.ifdMax = iinfo->symbolic_header.ifdMax;
182133965Sjdp      oinfo->external_fdr = iinfo->external_fdr;
182233965Sjdp
182333965Sjdp      oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd;
182433965Sjdp      oinfo->external_rfd = iinfo->external_rfd;
182533965Sjdp    }
182633965Sjdp  else
182733965Sjdp    {
182833965Sjdp      /* We are discarding all the local symbol information.  Look
182933965Sjdp	 through the external symbols and remove all references to FDR
183033965Sjdp	 or aux information.  */
183133965Sjdp      c = bfd_get_symcount (obfd);
183233965Sjdp      sym_ptr_ptr = bfd_get_outsymbols (obfd);
183333965Sjdp      for (; c > 0; c--, sym_ptr_ptr++)
183433965Sjdp	{
183533965Sjdp	  EXTR esym;
183633965Sjdp
183733965Sjdp	  (*(ecoff_backend (obfd)->debug_swap.swap_ext_in))
183833965Sjdp	    (obfd, ecoffsymbol (*sym_ptr_ptr)->native, &esym);
183933965Sjdp	  esym.ifd = ifdNil;
184033965Sjdp	  esym.asym.index = indexNil;
184133965Sjdp	  (*(ecoff_backend (obfd)->debug_swap.swap_ext_out))
184233965Sjdp	    (obfd, &esym, ecoffsymbol (*sym_ptr_ptr)->native);
184333965Sjdp	}
184433965Sjdp    }
184533965Sjdp
1846130561Sobrien  return TRUE;
184733965Sjdp}
184833965Sjdp
184933965Sjdp/* Set the architecture.  The supported architecture is stored in the
185033965Sjdp   backend pointer.  We always set the architecture anyhow, since many
185133965Sjdp   callers ignore the return value.  */
185233965Sjdp
1853130561Sobrienbfd_boolean
1854218822Sdim_bfd_ecoff_set_arch_mach (bfd *abfd,
1855218822Sdim			  enum bfd_architecture arch,
1856218822Sdim			  unsigned long machine)
185733965Sjdp{
185833965Sjdp  bfd_default_set_arch_mach (abfd, arch, machine);
185933965Sjdp  return arch == ecoff_backend (abfd)->arch;
186033965Sjdp}
186133965Sjdp
186233965Sjdp/* Get the size of the section headers.  */
186333965Sjdp
186433965Sjdpint
1865218822Sdim_bfd_ecoff_sizeof_headers (bfd *abfd,
1866218822Sdim			   struct bfd_link_info *info ATTRIBUTE_UNUSED)
186733965Sjdp{
186833965Sjdp  asection *current;
186933965Sjdp  int c;
187033965Sjdp  int ret;
187133965Sjdp
187233965Sjdp  c = 0;
187333965Sjdp  for (current = abfd->sections;
1874218822Sdim       current != NULL;
187577298Sobrien       current = current->next)
187633965Sjdp    ++c;
187733965Sjdp
187833965Sjdp  ret = (bfd_coff_filhsz (abfd)
187933965Sjdp	 + bfd_coff_aoutsz (abfd)
188033965Sjdp	 + c * bfd_coff_scnhsz (abfd));
188133965Sjdp  return BFD_ALIGN (ret, 16);
188233965Sjdp}
188333965Sjdp
188433965Sjdp/* Get the contents of a section.  */
188533965Sjdp
1886130561Sobrienbfd_boolean
1887218822Sdim_bfd_ecoff_get_section_contents (bfd *abfd,
1888218822Sdim				 asection *section,
1889218822Sdim				 void * location,
1890218822Sdim				 file_ptr offset,
1891218822Sdim				 bfd_size_type count)
189233965Sjdp{
189333965Sjdp  return _bfd_generic_get_section_contents (abfd, section, location,
189433965Sjdp					    offset, count);
189533965Sjdp}
189633965Sjdp
189733965Sjdp/* Sort sections by VMA, but put SEC_ALLOC sections first.  This is
189833965Sjdp   called via qsort.  */
189933965Sjdp
190033965Sjdpstatic int
1901218822Sdimecoff_sort_hdrs (const void * arg1, const void * arg2)
190233965Sjdp{
190333965Sjdp  const asection *hdr1 = *(const asection **) arg1;
190433965Sjdp  const asection *hdr2 = *(const asection **) arg2;
190533965Sjdp
190633965Sjdp  if ((hdr1->flags & SEC_ALLOC) != 0)
190733965Sjdp    {
190833965Sjdp      if ((hdr2->flags & SEC_ALLOC) == 0)
190933965Sjdp	return -1;
191033965Sjdp    }
191133965Sjdp  else
191233965Sjdp    {
191333965Sjdp      if ((hdr2->flags & SEC_ALLOC) != 0)
191433965Sjdp	return 1;
191533965Sjdp    }
191633965Sjdp  if (hdr1->vma < hdr2->vma)
191733965Sjdp    return -1;
191833965Sjdp  else if (hdr1->vma > hdr2->vma)
191933965Sjdp    return 1;
192033965Sjdp  else
192133965Sjdp    return 0;
192233965Sjdp}
192333965Sjdp
192433965Sjdp/* Calculate the file position for each section, and set
192533965Sjdp   reloc_filepos.  */
192633965Sjdp
1927130561Sobrienstatic bfd_boolean
1928218822Sdimecoff_compute_section_file_positions (bfd *abfd)
192933965Sjdp{
193033965Sjdp  file_ptr sofar, file_sofar;
193133965Sjdp  asection **sorted_hdrs;
193233965Sjdp  asection *current;
193333965Sjdp  unsigned int i;
193433965Sjdp  file_ptr old_sofar;
1935130561Sobrien  bfd_boolean rdata_in_text;
1936130561Sobrien  bfd_boolean first_data, first_nonalloc;
193733965Sjdp  const bfd_vma round = ecoff_backend (abfd)->round;
193889857Sobrien  bfd_size_type amt;
193933965Sjdp
1940218822Sdim  sofar = _bfd_ecoff_sizeof_headers (abfd, NULL);
194133965Sjdp  file_sofar = sofar;
194233965Sjdp
194333965Sjdp  /* Sort the sections by VMA.  */
194489857Sobrien  amt = abfd->section_count;
194589857Sobrien  amt *= sizeof (asection *);
1946218822Sdim  sorted_hdrs = bfd_malloc (amt);
194733965Sjdp  if (sorted_hdrs == NULL)
1948130561Sobrien    return FALSE;
194933965Sjdp  for (current = abfd->sections, i = 0;
195033965Sjdp       current != NULL;
195133965Sjdp       current = current->next, i++)
195233965Sjdp    sorted_hdrs[i] = current;
195333965Sjdp  BFD_ASSERT (i == abfd->section_count);
195433965Sjdp
195533965Sjdp  qsort (sorted_hdrs, abfd->section_count, sizeof (asection *),
195633965Sjdp	 ecoff_sort_hdrs);
195733965Sjdp
195833965Sjdp  /* Some versions of the OSF linker put the .rdata section in the
195933965Sjdp     text segment, and some do not.  */
196033965Sjdp  rdata_in_text = ecoff_backend (abfd)->rdata_in_text;
196133965Sjdp  if (rdata_in_text)
196233965Sjdp    {
196333965Sjdp      for (i = 0; i < abfd->section_count; i++)
196433965Sjdp	{
196533965Sjdp	  current = sorted_hdrs[i];
1966218822Sdim	  if (streq (current->name, _RDATA))
196733965Sjdp	    break;
196833965Sjdp	  if ((current->flags & SEC_CODE) == 0
1969218822Sdim	      && ! streq (current->name, _PDATA)
1970218822Sdim	      && ! streq (current->name, _RCONST))
197133965Sjdp	    {
1972130561Sobrien	      rdata_in_text = FALSE;
197333965Sjdp	      break;
197433965Sjdp	    }
197533965Sjdp	}
197633965Sjdp    }
197733965Sjdp  ecoff_data (abfd)->rdata_in_text = rdata_in_text;
197833965Sjdp
1979130561Sobrien  first_data = TRUE;
1980130561Sobrien  first_nonalloc = TRUE;
198133965Sjdp  for (i = 0; i < abfd->section_count; i++)
198233965Sjdp    {
198333965Sjdp      unsigned int alignment_power;
198433965Sjdp
198533965Sjdp      current = sorted_hdrs[i];
198633965Sjdp
198733965Sjdp      /* For the Alpha ECOFF .pdata section the lnnoptr field is
198833965Sjdp	 supposed to indicate the number of .pdata entries that are
198933965Sjdp	 really in the section.  Each entry is 8 bytes.  We store this
199033965Sjdp	 away in line_filepos before increasing the section size.  */
1991218822Sdim      if (streq (current->name, _PDATA))
1992218822Sdim	current->line_filepos = current->size / 8;
199333965Sjdp
199433965Sjdp      alignment_power = current->alignment_power;
199533965Sjdp
199633965Sjdp      /* On Ultrix, the data sections in an executable file must be
199733965Sjdp	 aligned to a page boundary within the file.  This does not
199833965Sjdp	 affect the section size, though.  FIXME: Does this work for
199933965Sjdp	 other platforms?  It requires some modification for the
200033965Sjdp	 Alpha, because .rdata on the Alpha goes with the text, not
200133965Sjdp	 the data.  */
200233965Sjdp      if ((abfd->flags & EXEC_P) != 0
200333965Sjdp	  && (abfd->flags & D_PAGED) != 0
200433965Sjdp	  && ! first_data
200533965Sjdp	  && (current->flags & SEC_CODE) == 0
200633965Sjdp	  && (! rdata_in_text
2007218822Sdim	      || ! streq (current->name, _RDATA))
2008218822Sdim	  && ! streq (current->name, _PDATA)
2009218822Sdim	  && ! streq (current->name, _RCONST))
201033965Sjdp	{
201133965Sjdp	  sofar = (sofar + round - 1) &~ (round - 1);
201233965Sjdp	  file_sofar = (file_sofar + round - 1) &~ (round - 1);
2013130561Sobrien	  first_data = FALSE;
201433965Sjdp	}
2015218822Sdim      else if (streq (current->name, _LIB))
201633965Sjdp	{
201733965Sjdp	  /* On Irix 4, the location of contents of the .lib section
201833965Sjdp	     from a shared library section is also rounded up to a
201933965Sjdp	     page boundary.  */
202033965Sjdp
202133965Sjdp	  sofar = (sofar + round - 1) &~ (round - 1);
202233965Sjdp	  file_sofar = (file_sofar + round - 1) &~ (round - 1);
202333965Sjdp	}
202433965Sjdp      else if (first_nonalloc
202533965Sjdp	       && (current->flags & SEC_ALLOC) == 0
202633965Sjdp	       && (abfd->flags & D_PAGED) != 0)
202733965Sjdp	{
202833965Sjdp	  /* Skip up to the next page for an unallocated section, such
202933965Sjdp             as the .comment section on the Alpha.  This leaves room
203033965Sjdp             for the .bss section.  */
2031130561Sobrien	  first_nonalloc = FALSE;
203233965Sjdp	  sofar = (sofar + round - 1) &~ (round - 1);
203333965Sjdp	  file_sofar = (file_sofar + round - 1) &~ (round - 1);
203433965Sjdp	}
203533965Sjdp
203633965Sjdp      /* Align the sections in the file to the same boundary on
203733965Sjdp	 which they are aligned in virtual memory.  */
203833965Sjdp      sofar = BFD_ALIGN (sofar, 1 << alignment_power);
203933965Sjdp      if ((current->flags & SEC_HAS_CONTENTS) != 0)
204033965Sjdp	file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power);
204133965Sjdp
204233965Sjdp      if ((abfd->flags & D_PAGED) != 0
204333965Sjdp	  && (current->flags & SEC_ALLOC) != 0)
204433965Sjdp	{
204533965Sjdp	  sofar += (current->vma - sofar) % round;
204633965Sjdp	  if ((current->flags & SEC_HAS_CONTENTS) != 0)
204733965Sjdp	    file_sofar += (current->vma - file_sofar) % round;
204833965Sjdp	}
204933965Sjdp
205033965Sjdp      if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) != 0)
205133965Sjdp	current->filepos = file_sofar;
205233965Sjdp
2053218822Sdim      sofar += current->size;
205433965Sjdp      if ((current->flags & SEC_HAS_CONTENTS) != 0)
2055218822Sdim	file_sofar += current->size;
205633965Sjdp
2057104834Sobrien      /* Make sure that this section is of the right size too.  */
205833965Sjdp      old_sofar = sofar;
205933965Sjdp      sofar = BFD_ALIGN (sofar, 1 << alignment_power);
206033965Sjdp      if ((current->flags & SEC_HAS_CONTENTS) != 0)
206133965Sjdp	file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power);
2062218822Sdim      current->size += sofar - old_sofar;
206333965Sjdp    }
206433965Sjdp
206533965Sjdp  free (sorted_hdrs);
206633965Sjdp  sorted_hdrs = NULL;
206733965Sjdp
206833965Sjdp  ecoff_data (abfd)->reloc_filepos = file_sofar;
206933965Sjdp
2070130561Sobrien  return TRUE;
207133965Sjdp}
207233965Sjdp
207333965Sjdp/* Determine the location of the relocs for all the sections in the
207433965Sjdp   output file, as well as the location of the symbolic debugging
207533965Sjdp   information.  */
207633965Sjdp
207733965Sjdpstatic bfd_size_type
2078218822Sdimecoff_compute_reloc_file_positions (bfd *abfd)
207933965Sjdp{
208033965Sjdp  const bfd_size_type external_reloc_size =
208133965Sjdp    ecoff_backend (abfd)->external_reloc_size;
208233965Sjdp  file_ptr reloc_base;
208333965Sjdp  bfd_size_type reloc_size;
208433965Sjdp  asection *current;
208533965Sjdp  file_ptr sym_base;
208633965Sjdp
208733965Sjdp  if (! abfd->output_has_begun)
208833965Sjdp    {
208933965Sjdp      if (! ecoff_compute_section_file_positions (abfd))
209033965Sjdp	abort ();
2091130561Sobrien      abfd->output_has_begun = TRUE;
209233965Sjdp    }
209377298Sobrien
209433965Sjdp  reloc_base = ecoff_data (abfd)->reloc_filepos;
209533965Sjdp
209633965Sjdp  reloc_size = 0;
209733965Sjdp  for (current = abfd->sections;
2098218822Sdim       current != NULL;
209977298Sobrien       current = current->next)
210033965Sjdp    {
210133965Sjdp      if (current->reloc_count == 0)
210233965Sjdp	current->rel_filepos = 0;
210333965Sjdp      else
210433965Sjdp	{
210533965Sjdp	  bfd_size_type relsize;
210633965Sjdp
210733965Sjdp	  current->rel_filepos = reloc_base;
210833965Sjdp	  relsize = current->reloc_count * external_reloc_size;
210933965Sjdp	  reloc_size += relsize;
211033965Sjdp	  reloc_base += relsize;
211133965Sjdp	}
211233965Sjdp    }
211333965Sjdp
211433965Sjdp  sym_base = ecoff_data (abfd)->reloc_filepos + reloc_size;
211533965Sjdp
211633965Sjdp  /* At least on Ultrix, the symbol table of an executable file must
211733965Sjdp     be aligned to a page boundary.  FIXME: Is this true on other
211833965Sjdp     platforms?  */
211933965Sjdp  if ((abfd->flags & EXEC_P) != 0
212033965Sjdp      && (abfd->flags & D_PAGED) != 0)
212133965Sjdp    sym_base = ((sym_base + ecoff_backend (abfd)->round - 1)
212233965Sjdp		&~ (ecoff_backend (abfd)->round - 1));
212333965Sjdp
212433965Sjdp  ecoff_data (abfd)->sym_filepos = sym_base;
212533965Sjdp
212633965Sjdp  return reloc_size;
212733965Sjdp}
212833965Sjdp
212933965Sjdp/* Set the contents of a section.  */
213033965Sjdp
2131130561Sobrienbfd_boolean
2132218822Sdim_bfd_ecoff_set_section_contents (bfd *abfd,
2133218822Sdim				 asection *section,
2134218822Sdim				 const void * location,
2135218822Sdim				 file_ptr offset,
2136218822Sdim				 bfd_size_type count)
213733965Sjdp{
213889857Sobrien  file_ptr pos;
213989857Sobrien
214033965Sjdp  /* This must be done first, because bfd_set_section_contents is
2141130561Sobrien     going to set output_has_begun to TRUE.  */
2142218822Sdim  if (! abfd->output_has_begun
2143218822Sdim      && ! ecoff_compute_section_file_positions (abfd))
2144218822Sdim    return FALSE;
214533965Sjdp
214633965Sjdp  /* Handle the .lib section specially so that Irix 4 shared libraries
214733965Sjdp     work out.  See coff_set_section_contents in coffcode.h.  */
2148218822Sdim  if (streq (section->name, _LIB))
214933965Sjdp    {
215033965Sjdp      bfd_byte *rec, *recend;
215133965Sjdp
215233965Sjdp      rec = (bfd_byte *) location;
215333965Sjdp      recend = rec + count;
215433965Sjdp      while (rec < recend)
215533965Sjdp	{
215633965Sjdp	  ++section->lma;
215733965Sjdp	  rec += bfd_get_32 (abfd, rec) * 4;
215833965Sjdp	}
215933965Sjdp
216033965Sjdp      BFD_ASSERT (rec == recend);
216133965Sjdp    }
216233965Sjdp
216333965Sjdp  if (count == 0)
2164130561Sobrien    return TRUE;
216533965Sjdp
216689857Sobrien  pos = section->filepos + offset;
216789857Sobrien  if (bfd_seek (abfd, pos, SEEK_SET) != 0
216889857Sobrien      || bfd_bwrite (location, count, abfd) != count)
2169130561Sobrien    return FALSE;
217033965Sjdp
2171130561Sobrien  return TRUE;
217233965Sjdp}
217333965Sjdp
217433965Sjdp/* Get the GP value for an ECOFF file.  This is a hook used by
217533965Sjdp   nlmconv.  */
217633965Sjdp
217733965Sjdpbfd_vma
2178218822Sdimbfd_ecoff_get_gp_value (bfd *abfd)
217933965Sjdp{
218033965Sjdp  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
218133965Sjdp      || bfd_get_format (abfd) != bfd_object)
218233965Sjdp    {
218333965Sjdp      bfd_set_error (bfd_error_invalid_operation);
218433965Sjdp      return 0;
218533965Sjdp    }
218677298Sobrien
218733965Sjdp  return ecoff_data (abfd)->gp;
218833965Sjdp}
218933965Sjdp
219033965Sjdp/* Set the GP value for an ECOFF file.  This is a hook used by the
219133965Sjdp   assembler.  */
219233965Sjdp
2193130561Sobrienbfd_boolean
2194218822Sdimbfd_ecoff_set_gp_value (bfd *abfd, bfd_vma gp_value)
219533965Sjdp{
219633965Sjdp  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
219733965Sjdp      || bfd_get_format (abfd) != bfd_object)
219833965Sjdp    {
219933965Sjdp      bfd_set_error (bfd_error_invalid_operation);
2200130561Sobrien      return FALSE;
220133965Sjdp    }
220233965Sjdp
220333965Sjdp  ecoff_data (abfd)->gp = gp_value;
220433965Sjdp
2205130561Sobrien  return TRUE;
220633965Sjdp}
220733965Sjdp
220833965Sjdp/* Set the register masks for an ECOFF file.  This is a hook used by
220933965Sjdp   the assembler.  */
221033965Sjdp
2211130561Sobrienbfd_boolean
2212218822Sdimbfd_ecoff_set_regmasks (bfd *abfd,
2213218822Sdim			unsigned long gprmask,
2214218822Sdim			unsigned long fprmask,
2215218822Sdim			unsigned long *cprmask)
221633965Sjdp{
221733965Sjdp  ecoff_data_type *tdata;
221833965Sjdp
221933965Sjdp  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
222033965Sjdp      || bfd_get_format (abfd) != bfd_object)
222133965Sjdp    {
222233965Sjdp      bfd_set_error (bfd_error_invalid_operation);
2223130561Sobrien      return FALSE;
222433965Sjdp    }
222533965Sjdp
222633965Sjdp  tdata = ecoff_data (abfd);
222733965Sjdp  tdata->gprmask = gprmask;
222833965Sjdp  tdata->fprmask = fprmask;
2229218822Sdim  if (cprmask != NULL)
223033965Sjdp    {
2231104834Sobrien      int i;
223233965Sjdp
223333965Sjdp      for (i = 0; i < 3; i++)
223433965Sjdp	tdata->cprmask[i] = cprmask[i];
223533965Sjdp    }
223633965Sjdp
2237130561Sobrien  return TRUE;
223833965Sjdp}
223933965Sjdp
224033965Sjdp/* Get ECOFF EXTR information for an external symbol.  This function
224133965Sjdp   is passed to bfd_ecoff_debug_externals.  */
224233965Sjdp
2243130561Sobrienstatic bfd_boolean
2244218822Sdimecoff_get_extr (asymbol *sym, EXTR *esym)
224533965Sjdp{
224633965Sjdp  ecoff_symbol_type *ecoff_sym_ptr;
224733965Sjdp  bfd *input_bfd;
224833965Sjdp
224933965Sjdp  if (bfd_asymbol_flavour (sym) != bfd_target_ecoff_flavour
225033965Sjdp      || ecoffsymbol (sym)->native == NULL)
225133965Sjdp    {
225233965Sjdp      /* Don't include debugging, local, or section symbols.  */
225333965Sjdp      if ((sym->flags & BSF_DEBUGGING) != 0
225433965Sjdp	  || (sym->flags & BSF_LOCAL) != 0
225533965Sjdp	  || (sym->flags & BSF_SECTION_SYM) != 0)
2256130561Sobrien	return FALSE;
225733965Sjdp
225833965Sjdp      esym->jmptbl = 0;
225933965Sjdp      esym->cobol_main = 0;
226033965Sjdp      esym->weakext = (sym->flags & BSF_WEAK) != 0;
226133965Sjdp      esym->reserved = 0;
226233965Sjdp      esym->ifd = ifdNil;
226333965Sjdp      /* FIXME: we can do better than this for st and sc.  */
226433965Sjdp      esym->asym.st = stGlobal;
226533965Sjdp      esym->asym.sc = scAbs;
226633965Sjdp      esym->asym.reserved = 0;
226733965Sjdp      esym->asym.index = indexNil;
2268130561Sobrien      return TRUE;
226933965Sjdp    }
227033965Sjdp
227133965Sjdp  ecoff_sym_ptr = ecoffsymbol (sym);
227233965Sjdp
227333965Sjdp  if (ecoff_sym_ptr->local)
2274130561Sobrien    return FALSE;
227533965Sjdp
227633965Sjdp  input_bfd = bfd_asymbol_bfd (sym);
227733965Sjdp  (*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in))
227833965Sjdp    (input_bfd, ecoff_sym_ptr->native, esym);
227933965Sjdp
228033965Sjdp  /* If the symbol was defined by the linker, then esym will be
228133965Sjdp     undefined but sym will not be.  Get a better class for such a
228233965Sjdp     symbol.  */
228333965Sjdp  if ((esym->asym.sc == scUndefined
228433965Sjdp       || esym->asym.sc == scSUndefined)
228533965Sjdp      && ! bfd_is_und_section (bfd_get_section (sym)))
228633965Sjdp    esym->asym.sc = scAbs;
228733965Sjdp
228833965Sjdp  /* Adjust the FDR index for the symbol by that used for the input
228933965Sjdp     BFD.  */
229033965Sjdp  if (esym->ifd != -1)
229133965Sjdp    {
229233965Sjdp      struct ecoff_debug_info *input_debug;
229333965Sjdp
229433965Sjdp      input_debug = &ecoff_data (input_bfd)->debug_info;
229533965Sjdp      BFD_ASSERT (esym->ifd < input_debug->symbolic_header.ifdMax);
2296218822Sdim      if (input_debug->ifdmap != NULL)
229733965Sjdp	esym->ifd = input_debug->ifdmap[esym->ifd];
229833965Sjdp    }
229933965Sjdp
2300130561Sobrien  return TRUE;
230133965Sjdp}
230233965Sjdp
230333965Sjdp/* Set the external symbol index.  This routine is passed to
230433965Sjdp   bfd_ecoff_debug_externals.  */
230533965Sjdp
230633965Sjdpstatic void
2307218822Sdimecoff_set_index (asymbol *sym, bfd_size_type indx)
230833965Sjdp{
230933965Sjdp  ecoff_set_sym_index (sym, indx);
231033965Sjdp}
231133965Sjdp
231233965Sjdp/* Write out an ECOFF file.  */
231333965Sjdp
2314130561Sobrienbfd_boolean
2315218822Sdim_bfd_ecoff_write_object_contents (bfd *abfd)
231633965Sjdp{
231733965Sjdp  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
231833965Sjdp  const bfd_vma round = backend->round;
231933965Sjdp  const bfd_size_type filhsz = bfd_coff_filhsz (abfd);
232033965Sjdp  const bfd_size_type aoutsz = bfd_coff_aoutsz (abfd);
232133965Sjdp  const bfd_size_type scnhsz = bfd_coff_scnhsz (abfd);
232233965Sjdp  const bfd_size_type external_hdr_size
232333965Sjdp    = backend->debug_swap.external_hdr_size;
232433965Sjdp  const bfd_size_type external_reloc_size = backend->external_reloc_size;
2325218822Sdim  void (* const adjust_reloc_out) (bfd *, const arelent *, struct internal_reloc *)
232633965Sjdp    = backend->adjust_reloc_out;
2327218822Sdim  void (* const swap_reloc_out) (bfd *, const struct internal_reloc *, void *)
232833965Sjdp    = backend->swap_reloc_out;
232933965Sjdp  struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info;
233033965Sjdp  HDRR * const symhdr = &debug->symbolic_header;
233133965Sjdp  asection *current;
233233965Sjdp  unsigned int count;
233333965Sjdp  bfd_size_type reloc_size;
233433965Sjdp  bfd_size_type text_size;
233533965Sjdp  bfd_vma text_start;
2336130561Sobrien  bfd_boolean set_text_start;
233733965Sjdp  bfd_size_type data_size;
233833965Sjdp  bfd_vma data_start;
2339130561Sobrien  bfd_boolean set_data_start;
234033965Sjdp  bfd_size_type bss_size;
2341218822Sdim  void * buff = NULL;
2342218822Sdim  void * reloc_buff = NULL;
234333965Sjdp  struct internal_filehdr internal_f;
234433965Sjdp  struct internal_aouthdr internal_a;
234533965Sjdp  int i;
234633965Sjdp
234733965Sjdp  /* Determine where the sections and relocs will go in the output
234833965Sjdp     file.  */
234933965Sjdp  reloc_size = ecoff_compute_reloc_file_positions (abfd);
235033965Sjdp
235133965Sjdp  count = 1;
235233965Sjdp  for (current = abfd->sections;
2353218822Sdim       current != NULL;
235477298Sobrien       current = current->next)
235533965Sjdp    {
235633965Sjdp      current->target_index = count;
235733965Sjdp      ++count;
235833965Sjdp    }
235933965Sjdp
236033965Sjdp  if ((abfd->flags & D_PAGED) != 0)
2361218822Sdim    text_size = _bfd_ecoff_sizeof_headers (abfd, NULL);
236233965Sjdp  else
236333965Sjdp    text_size = 0;
236433965Sjdp  text_start = 0;
2365130561Sobrien  set_text_start = FALSE;
236633965Sjdp  data_size = 0;
236733965Sjdp  data_start = 0;
2368130561Sobrien  set_data_start = FALSE;
236933965Sjdp  bss_size = 0;
237033965Sjdp
237133965Sjdp  /* Write section headers to the file.  */
237233965Sjdp
237333965Sjdp  /* Allocate buff big enough to hold a section header,
237433965Sjdp     file header, or a.out header.  */
237533965Sjdp  {
237633965Sjdp    bfd_size_type siz;
2377218822Sdim
237833965Sjdp    siz = scnhsz;
237933965Sjdp    if (siz < filhsz)
238033965Sjdp      siz = filhsz;
238133965Sjdp    if (siz < aoutsz)
238233965Sjdp      siz = aoutsz;
2383218822Sdim    buff = bfd_malloc (siz);
238433965Sjdp    if (buff == NULL)
238533965Sjdp      goto error_return;
238633965Sjdp  }
238733965Sjdp
238833965Sjdp  internal_f.f_nscns = 0;
238933965Sjdp  if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0)
239033965Sjdp    goto error_return;
2391218822Sdim
239233965Sjdp  for (current = abfd->sections;
2393218822Sdim       current != NULL;
239433965Sjdp       current = current->next)
239533965Sjdp    {
239633965Sjdp      struct internal_scnhdr section;
239733965Sjdp      bfd_vma vma;
239833965Sjdp
239933965Sjdp      ++internal_f.f_nscns;
240033965Sjdp
240133965Sjdp      strncpy (section.s_name, current->name, sizeof section.s_name);
240233965Sjdp
240333965Sjdp      /* This seems to be correct for Irix 4 shared libraries.  */
240433965Sjdp      vma = bfd_get_section_vma (abfd, current);
2405218822Sdim      if (streq (current->name, _LIB))
240633965Sjdp	section.s_vaddr = 0;
240733965Sjdp      else
240833965Sjdp	section.s_vaddr = vma;
240933965Sjdp
241033965Sjdp      section.s_paddr = current->lma;
2411218822Sdim      section.s_size = current->size;
241233965Sjdp
241333965Sjdp      /* If this section is unloadable then the scnptr will be 0.  */
241433965Sjdp      if ((current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
241533965Sjdp	section.s_scnptr = 0;
241633965Sjdp      else
241733965Sjdp	section.s_scnptr = current->filepos;
241833965Sjdp      section.s_relptr = current->rel_filepos;
241933965Sjdp
242033965Sjdp      /* FIXME: the lnnoptr of the .sbss or .sdata section of an
242133965Sjdp	 object file produced by the assembler is supposed to point to
242233965Sjdp	 information about how much room is required by objects of
242333965Sjdp	 various different sizes.  I think this only matters if we
242433965Sjdp	 want the linker to compute the best size to use, or
242533965Sjdp	 something.  I don't know what happens if the information is
242633965Sjdp	 not present.  */
2427218822Sdim      if (! streq (current->name, _PDATA))
242833965Sjdp	section.s_lnnoptr = 0;
242933965Sjdp      else
243033965Sjdp	{
243133965Sjdp	  /* The Alpha ECOFF .pdata section uses the lnnoptr field to
243233965Sjdp	     hold the number of entries in the section (each entry is
243333965Sjdp	     8 bytes).  We stored this in the line_filepos field in
243433965Sjdp	     ecoff_compute_section_file_positions.  */
243533965Sjdp	  section.s_lnnoptr = current->line_filepos;
243633965Sjdp	}
243733965Sjdp
243833965Sjdp      section.s_nreloc = current->reloc_count;
243933965Sjdp      section.s_nlnno = 0;
244033965Sjdp      section.s_flags = ecoff_sec_to_styp_flags (current->name,
244133965Sjdp						 current->flags);
244233965Sjdp
2443218822Sdim      if (bfd_coff_swap_scnhdr_out (abfd, (void *) &section, buff) == 0
244489857Sobrien	  || bfd_bwrite (buff, scnhsz, abfd) != scnhsz)
244533965Sjdp	goto error_return;
244633965Sjdp
244733965Sjdp      if ((section.s_flags & STYP_TEXT) != 0
244833965Sjdp	  || ((section.s_flags & STYP_RDATA) != 0
244933965Sjdp	      && ecoff_data (abfd)->rdata_in_text)
245033965Sjdp	  || section.s_flags == STYP_PDATA
245133965Sjdp	  || (section.s_flags & STYP_DYNAMIC) != 0
245233965Sjdp	  || (section.s_flags & STYP_LIBLIST) != 0
245333965Sjdp	  || (section.s_flags & STYP_RELDYN) != 0
245433965Sjdp	  || section.s_flags == STYP_CONFLIC
245533965Sjdp	  || (section.s_flags & STYP_DYNSTR) != 0
245633965Sjdp	  || (section.s_flags & STYP_DYNSYM) != 0
245733965Sjdp	  || (section.s_flags & STYP_HASH) != 0
245833965Sjdp	  || (section.s_flags & STYP_ECOFF_INIT) != 0
245933965Sjdp	  || (section.s_flags & STYP_ECOFF_FINI) != 0
246033965Sjdp	  || section.s_flags == STYP_RCONST)
246133965Sjdp	{
2462218822Sdim	  text_size += current->size;
246333965Sjdp	  if (! set_text_start || text_start > vma)
246433965Sjdp	    {
246533965Sjdp	      text_start = vma;
2466130561Sobrien	      set_text_start = TRUE;
246733965Sjdp	    }
246833965Sjdp	}
246933965Sjdp      else if ((section.s_flags & STYP_RDATA) != 0
247033965Sjdp	       || (section.s_flags & STYP_DATA) != 0
247133965Sjdp	       || (section.s_flags & STYP_LITA) != 0
247233965Sjdp	       || (section.s_flags & STYP_LIT8) != 0
247333965Sjdp	       || (section.s_flags & STYP_LIT4) != 0
247433965Sjdp	       || (section.s_flags & STYP_SDATA) != 0
247533965Sjdp	       || section.s_flags == STYP_XDATA
247633965Sjdp	       || (section.s_flags & STYP_GOT) != 0)
247733965Sjdp	{
2478218822Sdim	  data_size += current->size;
247933965Sjdp	  if (! set_data_start || data_start > vma)
248033965Sjdp	    {
248133965Sjdp	      data_start = vma;
2482130561Sobrien	      set_data_start = TRUE;
248333965Sjdp	    }
248433965Sjdp	}
248533965Sjdp      else if ((section.s_flags & STYP_BSS) != 0
248633965Sjdp	       || (section.s_flags & STYP_SBSS) != 0)
2487218822Sdim	bss_size += current->size;
248833965Sjdp      else if (section.s_flags == 0
248933965Sjdp	       || (section.s_flags & STYP_ECOFF_LIB) != 0
249033965Sjdp	       || section.s_flags == STYP_COMMENT)
2491104834Sobrien	/* Do nothing.  */ ;
249233965Sjdp      else
249333965Sjdp	abort ();
249477298Sobrien    }
249533965Sjdp
249633965Sjdp  /* Set up the file header.  */
249733965Sjdp  internal_f.f_magic = ecoff_get_magic (abfd);
249833965Sjdp
249933965Sjdp  /* We will NOT put a fucking timestamp in the header here. Every
250033965Sjdp     time you put it back, I will come in and take it out again.  I'm
250133965Sjdp     sorry.  This field does not belong here.  We fill it with a 0 so
250233965Sjdp     it compares the same but is not a reasonable time. --
250333965Sjdp     gnu@cygnus.com.  */
250433965Sjdp  internal_f.f_timdat = 0;
250533965Sjdp
250633965Sjdp  if (bfd_get_symcount (abfd) != 0)
250733965Sjdp    {
250833965Sjdp      /* The ECOFF f_nsyms field is not actually the number of
250933965Sjdp	 symbols, it's the size of symbolic information header.  */
251033965Sjdp      internal_f.f_nsyms = external_hdr_size;
251133965Sjdp      internal_f.f_symptr = ecoff_data (abfd)->sym_filepos;
251233965Sjdp    }
251333965Sjdp  else
251433965Sjdp    {
251533965Sjdp      internal_f.f_nsyms = 0;
251633965Sjdp      internal_f.f_symptr = 0;
251733965Sjdp    }
251833965Sjdp
251933965Sjdp  internal_f.f_opthdr = aoutsz;
252033965Sjdp
252133965Sjdp  internal_f.f_flags = F_LNNO;
252233965Sjdp  if (reloc_size == 0)
252333965Sjdp    internal_f.f_flags |= F_RELFLG;
252433965Sjdp  if (bfd_get_symcount (abfd) == 0)
252533965Sjdp    internal_f.f_flags |= F_LSYMS;
252633965Sjdp  if (abfd->flags & EXEC_P)
252733965Sjdp    internal_f.f_flags |= F_EXEC;
252833965Sjdp
252933965Sjdp  if (bfd_little_endian (abfd))
253033965Sjdp    internal_f.f_flags |= F_AR32WR;
253133965Sjdp  else
253233965Sjdp    internal_f.f_flags |= F_AR32W;
253333965Sjdp
253433965Sjdp  /* Set up the ``optional'' header.  */
253533965Sjdp  if ((abfd->flags & D_PAGED) != 0)
253633965Sjdp    internal_a.magic = ECOFF_AOUT_ZMAGIC;
253733965Sjdp  else
253833965Sjdp    internal_a.magic = ECOFF_AOUT_OMAGIC;
253933965Sjdp
254033965Sjdp  /* FIXME: Is this really correct?  */
254133965Sjdp  internal_a.vstamp = symhdr->vstamp;
254233965Sjdp
254333965Sjdp  /* At least on Ultrix, these have to be rounded to page boundaries.
254433965Sjdp     FIXME: Is this true on other platforms?  */
254533965Sjdp  if ((abfd->flags & D_PAGED) != 0)
254633965Sjdp    {
254733965Sjdp      internal_a.tsize = (text_size + round - 1) &~ (round - 1);
254833965Sjdp      internal_a.text_start = text_start &~ (round - 1);
254933965Sjdp      internal_a.dsize = (data_size + round - 1) &~ (round - 1);
255033965Sjdp      internal_a.data_start = data_start &~ (round - 1);
255133965Sjdp    }
255233965Sjdp  else
255333965Sjdp    {
255433965Sjdp      internal_a.tsize = text_size;
255533965Sjdp      internal_a.text_start = text_start;
255633965Sjdp      internal_a.dsize = data_size;
255733965Sjdp      internal_a.data_start = data_start;
255833965Sjdp    }
255933965Sjdp
256033965Sjdp  /* On Ultrix, the initial portions of the .sbss and .bss segments
256133965Sjdp     are at the end of the data section.  The bsize field in the
256233965Sjdp     optional header records how many bss bytes are required beyond
256333965Sjdp     those in the data section.  The value is not rounded to a page
256433965Sjdp     boundary.  */
256533965Sjdp  if (bss_size < internal_a.dsize - data_size)
256633965Sjdp    bss_size = 0;
256733965Sjdp  else
256833965Sjdp    bss_size -= internal_a.dsize - data_size;
256933965Sjdp  internal_a.bsize = bss_size;
257033965Sjdp  internal_a.bss_start = internal_a.data_start + internal_a.dsize;
257133965Sjdp
257233965Sjdp  internal_a.entry = bfd_get_start_address (abfd);
257333965Sjdp
257433965Sjdp  internal_a.gp_value = ecoff_data (abfd)->gp;
257533965Sjdp
257633965Sjdp  internal_a.gprmask = ecoff_data (abfd)->gprmask;
257733965Sjdp  internal_a.fprmask = ecoff_data (abfd)->fprmask;
257833965Sjdp  for (i = 0; i < 4; i++)
257933965Sjdp    internal_a.cprmask[i] = ecoff_data (abfd)->cprmask[i];
258033965Sjdp
258133965Sjdp  /* Let the backend adjust the headers if necessary.  */
258233965Sjdp  if (backend->adjust_headers)
258333965Sjdp    {
258433965Sjdp      if (! (*backend->adjust_headers) (abfd, &internal_f, &internal_a))
258533965Sjdp	goto error_return;
258633965Sjdp    }
258733965Sjdp
258833965Sjdp  /* Write out the file header and the optional header.  */
258933965Sjdp  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
259033965Sjdp    goto error_return;
259133965Sjdp
2592218822Sdim  bfd_coff_swap_filehdr_out (abfd, (void *) &internal_f, buff);
259389857Sobrien  if (bfd_bwrite (buff, filhsz, abfd) != filhsz)
259433965Sjdp    goto error_return;
259533965Sjdp
2596218822Sdim  bfd_coff_swap_aouthdr_out (abfd, (void *) &internal_a, buff);
259789857Sobrien  if (bfd_bwrite (buff, aoutsz, abfd) != aoutsz)
259833965Sjdp    goto error_return;
259933965Sjdp
260033965Sjdp  /* Build the external symbol information.  This must be done before
260133965Sjdp     writing out the relocs so that we know the symbol indices.  We
260233965Sjdp     don't do this if this BFD was created by the backend linker,
260333965Sjdp     since it will have already handled the symbols and relocs.  */
260433965Sjdp  if (! ecoff_data (abfd)->linker)
260533965Sjdp    {
260633965Sjdp      symhdr->iextMax = 0;
260733965Sjdp      symhdr->issExtMax = 0;
260833965Sjdp      debug->external_ext = debug->external_ext_end = NULL;
260933965Sjdp      debug->ssext = debug->ssext_end = NULL;
2610104834Sobrien      if (! bfd_ecoff_debug_externals (abfd, debug, &backend->debug_swap,
2611104834Sobrien				       (abfd->flags & EXEC_P) == 0,
2612104834Sobrien				       ecoff_get_extr, ecoff_set_index))
261333965Sjdp	goto error_return;
261433965Sjdp
261533965Sjdp      /* Write out the relocs.  */
261633965Sjdp      for (current = abfd->sections;
2617218822Sdim	   current != NULL;
261833965Sjdp	   current = current->next)
261933965Sjdp	{
262033965Sjdp	  arelent **reloc_ptr_ptr;
262133965Sjdp	  arelent **reloc_end;
262233965Sjdp	  char *out_ptr;
262389857Sobrien	  bfd_size_type amt;
262433965Sjdp
262533965Sjdp	  if (current->reloc_count == 0)
262633965Sjdp	    continue;
262733965Sjdp
262889857Sobrien	  amt = current->reloc_count * external_reloc_size;
262989857Sobrien	  reloc_buff = bfd_alloc (abfd, amt);
263033965Sjdp	  if (reloc_buff == NULL)
263133965Sjdp	    goto error_return;
263233965Sjdp
263333965Sjdp	  reloc_ptr_ptr = current->orelocation;
263433965Sjdp	  reloc_end = reloc_ptr_ptr + current->reloc_count;
263533965Sjdp	  out_ptr = (char *) reloc_buff;
2636218822Sdim
263733965Sjdp	  for (;
263833965Sjdp	       reloc_ptr_ptr < reloc_end;
263933965Sjdp	       reloc_ptr_ptr++, out_ptr += external_reloc_size)
264033965Sjdp	    {
264133965Sjdp	      arelent *reloc;
264233965Sjdp	      asymbol *sym;
264333965Sjdp	      struct internal_reloc in;
264477298Sobrien
2645218822Sdim	      memset ((void *) &in, 0, sizeof in);
264633965Sjdp
264733965Sjdp	      reloc = *reloc_ptr_ptr;
264833965Sjdp	      sym = *reloc->sym_ptr_ptr;
264933965Sjdp
2650218822Sdim	      /* If the howto field has not been initialised then skip this reloc.
2651218822Sdim		 This assumes that an error message has been issued elsewhere.  */
2652218822Sdim	      if (reloc->howto == NULL)
2653218822Sdim		continue;
2654218822Sdim
265533965Sjdp	      in.r_vaddr = (reloc->address
265633965Sjdp			    + bfd_get_section_vma (abfd, current));
265733965Sjdp	      in.r_type = reloc->howto->type;
265833965Sjdp
265933965Sjdp	      if ((sym->flags & BSF_SECTION_SYM) == 0)
266033965Sjdp		{
266133965Sjdp		  in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr);
266233965Sjdp		  in.r_extern = 1;
266333965Sjdp		}
266433965Sjdp	      else
266533965Sjdp		{
266689857Sobrien		  const char *name;
2667218822Sdim		  unsigned int i;
2668218822Sdim		  static struct
2669218822Sdim		  {
2670218822Sdim		    const char * name;
2671218822Sdim		    long r_symndx;
2672218822Sdim		  }
2673218822Sdim		  section_symndx [] =
2674218822Sdim		  {
2675218822Sdim		    { _TEXT,   RELOC_SECTION_TEXT   },
2676218822Sdim		    { _RDATA,  RELOC_SECTION_RDATA  },
2677218822Sdim		    { _DATA,   RELOC_SECTION_DATA   },
2678218822Sdim		    { _SDATA,  RELOC_SECTION_SDATA  },
2679218822Sdim		    { _SBSS,   RELOC_SECTION_SBSS   },
2680218822Sdim		    { _BSS,    RELOC_SECTION_BSS    },
2681218822Sdim		    { _INIT,   RELOC_SECTION_INIT   },
2682218822Sdim		    { _LIT8,   RELOC_SECTION_LIT8   },
2683218822Sdim		    { _LIT4,   RELOC_SECTION_LIT4   },
2684218822Sdim		    { _XDATA,  RELOC_SECTION_XDATA  },
2685218822Sdim		    { _PDATA,  RELOC_SECTION_PDATA  },
2686218822Sdim		    { _FINI,   RELOC_SECTION_FINI   },
2687218822Sdim		    { _LITA,   RELOC_SECTION_LITA   },
2688218822Sdim		    { "*ABS*", RELOC_SECTION_ABS    },
2689218822Sdim		    { _RCONST, RELOC_SECTION_RCONST }
2690218822Sdim		  };
269133965Sjdp
269233965Sjdp		  name = bfd_get_section_name (abfd, bfd_get_section (sym));
2693218822Sdim
2694218822Sdim		  for (i = 0; i < ARRAY_SIZE (section_symndx); i++)
2695218822Sdim		    if (streq (name, section_symndx[i].name))
2696218822Sdim		      {
2697218822Sdim			in.r_symndx = section_symndx[i].r_symndx;
2698218822Sdim			break;
2699218822Sdim		      }
2700218822Sdim
2701218822Sdim		  if (i == ARRAY_SIZE (section_symndx))
270233965Sjdp		    abort ();
270333965Sjdp		  in.r_extern = 0;
270433965Sjdp		}
270533965Sjdp
270633965Sjdp	      (*adjust_reloc_out) (abfd, reloc, &in);
270733965Sjdp
2708218822Sdim	      (*swap_reloc_out) (abfd, &in, (void *) out_ptr);
270933965Sjdp	    }
271033965Sjdp
271133965Sjdp	  if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0)
271233965Sjdp	    goto error_return;
271389857Sobrien	  amt = current->reloc_count * external_reloc_size;
271489857Sobrien	  if (bfd_bwrite (reloc_buff, amt, abfd) != amt)
271533965Sjdp	    goto error_return;
271633965Sjdp	  bfd_release (abfd, reloc_buff);
271733965Sjdp	  reloc_buff = NULL;
271833965Sjdp	}
271933965Sjdp
272033965Sjdp      /* Write out the symbolic debugging information.  */
272133965Sjdp      if (bfd_get_symcount (abfd) > 0)
272233965Sjdp	{
272333965Sjdp	  /* Write out the debugging information.  */
2724104834Sobrien	  if (! bfd_ecoff_write_debug (abfd, debug, &backend->debug_swap,
2725104834Sobrien				       ecoff_data (abfd)->sym_filepos))
272633965Sjdp	    goto error_return;
272733965Sjdp	}
272833965Sjdp    }
272933965Sjdp
273033965Sjdp  /* The .bss section of a demand paged executable must receive an
273133965Sjdp     entire page.  If there are symbols, the symbols will start on the
273233965Sjdp     next page.  If there are no symbols, we must fill out the page by
273333965Sjdp     hand.  */
273433965Sjdp  if (bfd_get_symcount (abfd) == 0
273533965Sjdp      && (abfd->flags & EXEC_P) != 0
273633965Sjdp      && (abfd->flags & D_PAGED) != 0)
273733965Sjdp    {
273833965Sjdp      char c;
273933965Sjdp
274033965Sjdp      if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
274133965Sjdp		    SEEK_SET) != 0)
274233965Sjdp	goto error_return;
274389857Sobrien      if (bfd_bread (&c, (bfd_size_type) 1, abfd) == 0)
274433965Sjdp	c = 0;
274533965Sjdp      if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
274633965Sjdp		    SEEK_SET) != 0)
274733965Sjdp	goto error_return;
274889857Sobrien      if (bfd_bwrite (&c, (bfd_size_type) 1, abfd) != 1)
274933965Sjdp	goto error_return;
275033965Sjdp    }
275133965Sjdp
275233965Sjdp  if (reloc_buff != NULL)
275333965Sjdp    bfd_release (abfd, reloc_buff);
275433965Sjdp  if (buff != NULL)
275533965Sjdp    free (buff);
2756130561Sobrien  return TRUE;
275733965Sjdp error_return:
275833965Sjdp  if (reloc_buff != NULL)
275933965Sjdp    bfd_release (abfd, reloc_buff);
276033965Sjdp  if (buff != NULL)
276133965Sjdp    free (buff);
2762130561Sobrien  return FALSE;
276333965Sjdp}
276433965Sjdp
276533965Sjdp/* Archive handling.  ECOFF uses what appears to be a unique type of
276633965Sjdp   archive header (armap).  The byte ordering of the armap and the
276733965Sjdp   contents are encoded in the name of the armap itself.  At least for
276833965Sjdp   now, we only support archives with the same byte ordering in the
276933965Sjdp   armap and the contents.
277033965Sjdp
277133965Sjdp   The first four bytes in the armap are the number of symbol
277233965Sjdp   definitions.  This is always a power of two.
277333965Sjdp
277433965Sjdp   This is followed by the symbol definitions.  Each symbol definition
277533965Sjdp   occupies 8 bytes.  The first four bytes are the offset from the
277633965Sjdp   start of the armap strings to the null-terminated string naming
277733965Sjdp   this symbol.  The second four bytes are the file offset to the
277833965Sjdp   archive member which defines this symbol.  If the second four bytes
277933965Sjdp   are 0, then this is not actually a symbol definition, and it should
278033965Sjdp   be ignored.
278133965Sjdp
278233965Sjdp   The symbols are hashed into the armap with a closed hashing scheme.
278333965Sjdp   See the functions below for the details of the algorithm.
278433965Sjdp
278533965Sjdp   After the symbol definitions comes four bytes holding the size of
278633965Sjdp   the string table, followed by the string table itself.  */
278733965Sjdp
278833965Sjdp/* The name of an archive headers looks like this:
278933965Sjdp   __________E[BL]E[BL]_ (with a trailing space).
279033965Sjdp   The trailing space is changed to an X if the archive is changed to
279133965Sjdp   indicate that the armap is out of date.
279233965Sjdp
279333965Sjdp   The Alpha seems to use ________64E[BL]E[BL]_.  */
279433965Sjdp
2795218822Sdim#define ARMAP_BIG_ENDIAN 		'B'
2796218822Sdim#define ARMAP_LITTLE_ENDIAN 		'L'
2797218822Sdim#define ARMAP_MARKER 			'E'
2798218822Sdim#define ARMAP_START_LENGTH 		10
2799218822Sdim#define ARMAP_HEADER_MARKER_INDEX	10
2800218822Sdim#define ARMAP_HEADER_ENDIAN_INDEX 	11
2801218822Sdim#define ARMAP_OBJECT_MARKER_INDEX 	12
2802218822Sdim#define ARMAP_OBJECT_ENDIAN_INDEX 	13
2803218822Sdim#define ARMAP_END_INDEX 		14
2804218822Sdim#define ARMAP_END 			"_ "
280533965Sjdp
280633965Sjdp/* This is a magic number used in the hashing algorithm.  */
2807218822Sdim#define ARMAP_HASH_MAGIC 		0x9dd68ab5
280833965Sjdp
280933965Sjdp/* This returns the hash value to use for a string.  It also sets
281033965Sjdp   *REHASH to the rehash adjustment if the first slot is taken.  SIZE
281133965Sjdp   is the number of entries in the hash table, and HLOG is the log
281233965Sjdp   base 2 of SIZE.  */
281333965Sjdp
281433965Sjdpstatic unsigned int
2815218822Sdimecoff_armap_hash (const char *s,
2816218822Sdim		  unsigned int *rehash,
2817218822Sdim		  unsigned int size,
2818218822Sdim		  unsigned int hlog)
281933965Sjdp{
282033965Sjdp  unsigned int hash;
282133965Sjdp
282233965Sjdp  if (hlog == 0)
282333965Sjdp    return 0;
282433965Sjdp  hash = *s++;
282533965Sjdp  while (*s != '\0')
282633965Sjdp    hash = ((hash >> 27) | (hash << 5)) + *s++;
282733965Sjdp  hash *= ARMAP_HASH_MAGIC;
282833965Sjdp  *rehash = (hash & (size - 1)) | 1;
282933965Sjdp  return hash >> (32 - hlog);
283033965Sjdp}
283133965Sjdp
283233965Sjdp/* Read in the armap.  */
283333965Sjdp
2834130561Sobrienbfd_boolean
2835218822Sdim_bfd_ecoff_slurp_armap (bfd *abfd)
283633965Sjdp{
283733965Sjdp  char nextname[17];
283833965Sjdp  unsigned int i;
283933965Sjdp  struct areltdata *mapdata;
284033965Sjdp  bfd_size_type parsed_size;
284133965Sjdp  char *raw_armap;
284233965Sjdp  struct artdata *ardata;
284333965Sjdp  unsigned int count;
284433965Sjdp  char *raw_ptr;
284533965Sjdp  struct symdef *symdef_ptr;
284633965Sjdp  char *stringbase;
284789857Sobrien  bfd_size_type amt;
284877298Sobrien
284933965Sjdp  /* Get the name of the first element.  */
2850218822Sdim  i = bfd_bread ((void *) nextname, (bfd_size_type) 16, abfd);
285133965Sjdp  if (i == 0)
2852130561Sobrien      return TRUE;
285333965Sjdp  if (i != 16)
2854130561Sobrien      return FALSE;
285533965Sjdp
285633965Sjdp  if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
2857130561Sobrien    return FALSE;
285833965Sjdp
285933965Sjdp  /* Irix 4.0.5F apparently can use either an ECOFF armap or a
286033965Sjdp     standard COFF armap.  We could move the ECOFF armap stuff into
286133965Sjdp     bfd_slurp_armap, but that seems inappropriate since no other
286233965Sjdp     target uses this format.  Instead, we check directly for a COFF
286333965Sjdp     armap.  */
2864218822Sdim  if (CONST_STRNEQ (nextname, "/               "))
286533965Sjdp    return bfd_slurp_armap (abfd);
286633965Sjdp
286733965Sjdp  /* See if the first element is an armap.  */
2868218822Sdim  if (! strneq (nextname, ecoff_backend (abfd)->armap_start, ARMAP_START_LENGTH)
286933965Sjdp      || nextname[ARMAP_HEADER_MARKER_INDEX] != ARMAP_MARKER
287033965Sjdp      || (nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
287133965Sjdp	  && nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
287233965Sjdp      || nextname[ARMAP_OBJECT_MARKER_INDEX] != ARMAP_MARKER
287333965Sjdp      || (nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
287433965Sjdp	  && nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
2875218822Sdim      || ! strneq (nextname + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1))
287633965Sjdp    {
2877130561Sobrien      bfd_has_map (abfd) = FALSE;
2878130561Sobrien      return TRUE;
287933965Sjdp    }
288033965Sjdp
288133965Sjdp  /* Make sure we have the right byte ordering.  */
288233965Sjdp  if (((nextname[ARMAP_HEADER_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
288333965Sjdp       ^ (bfd_header_big_endian (abfd)))
288433965Sjdp      || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
288533965Sjdp	  ^ (bfd_big_endian (abfd))))
288633965Sjdp    {
288733965Sjdp      bfd_set_error (bfd_error_wrong_format);
2888130561Sobrien      return FALSE;
288933965Sjdp    }
289033965Sjdp
289133965Sjdp  /* Read in the armap.  */
289233965Sjdp  ardata = bfd_ardata (abfd);
289333965Sjdp  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
2894218822Sdim  if (mapdata == NULL)
2895130561Sobrien    return FALSE;
289633965Sjdp  parsed_size = mapdata->parsed_size;
2897218822Sdim  bfd_release (abfd, (void *) mapdata);
289877298Sobrien
2899218822Sdim  raw_armap = bfd_alloc (abfd, parsed_size);
2900218822Sdim  if (raw_armap == NULL)
2901130561Sobrien    return FALSE;
290277298Sobrien
2903218822Sdim  if (bfd_bread ((void *) raw_armap, parsed_size, abfd) != parsed_size)
290433965Sjdp    {
290533965Sjdp      if (bfd_get_error () != bfd_error_system_call)
290633965Sjdp	bfd_set_error (bfd_error_malformed_archive);
2907218822Sdim      bfd_release (abfd, (void *) raw_armap);
2908130561Sobrien      return FALSE;
290933965Sjdp    }
291077298Sobrien
2911218822Sdim  ardata->tdata = (void *) raw_armap;
291233965Sjdp
291389857Sobrien  count = H_GET_32 (abfd, raw_armap);
291433965Sjdp
291533965Sjdp  ardata->symdef_count = 0;
2916218822Sdim  ardata->cache = NULL;
291733965Sjdp
291833965Sjdp  /* This code used to overlay the symdefs over the raw archive data,
291933965Sjdp     but that doesn't work on a 64 bit host.  */
292033965Sjdp  stringbase = raw_armap + count * 8 + 8;
292133965Sjdp
292233965Sjdp#ifdef CHECK_ARMAP_HASH
292333965Sjdp  {
292433965Sjdp    unsigned int hlog;
292533965Sjdp
292633965Sjdp    /* Double check that I have the hashing algorithm right by making
292733965Sjdp       sure that every symbol can be looked up successfully.  */
292833965Sjdp    hlog = 0;
292933965Sjdp    for (i = 1; i < count; i <<= 1)
293033965Sjdp      hlog++;
293133965Sjdp    BFD_ASSERT (i == count);
293233965Sjdp
293333965Sjdp    raw_ptr = raw_armap + 4;
293433965Sjdp    for (i = 0; i < count; i++, raw_ptr += 8)
293533965Sjdp      {
293633965Sjdp	unsigned int name_offset, file_offset;
293733965Sjdp	unsigned int hash, rehash, srch;
293877298Sobrien
293989857Sobrien	name_offset = H_GET_32 (abfd, raw_ptr);
294089857Sobrien	file_offset = H_GET_32 (abfd, (raw_ptr + 4));
294133965Sjdp	if (file_offset == 0)
294233965Sjdp	  continue;
294333965Sjdp	hash = ecoff_armap_hash (stringbase + name_offset, &rehash, count,
294433965Sjdp				 hlog);
294533965Sjdp	if (hash == i)
294633965Sjdp	  continue;
294733965Sjdp
294833965Sjdp	/* See if we can rehash to this location.  */
294933965Sjdp	for (srch = (hash + rehash) & (count - 1);
295033965Sjdp	     srch != hash && srch != i;
295133965Sjdp	     srch = (srch + rehash) & (count - 1))
295289857Sobrien	  BFD_ASSERT (H_GET_32 (abfd, (raw_armap + 8 + srch * 8)) != 0);
295333965Sjdp	BFD_ASSERT (srch == i);
295433965Sjdp      }
295533965Sjdp  }
295633965Sjdp
295733965Sjdp#endif /* CHECK_ARMAP_HASH */
295833965Sjdp
295933965Sjdp  raw_ptr = raw_armap + 4;
296033965Sjdp  for (i = 0; i < count; i++, raw_ptr += 8)
296189857Sobrien    if (H_GET_32 (abfd, (raw_ptr + 4)) != 0)
296233965Sjdp      ++ardata->symdef_count;
296333965Sjdp
296489857Sobrien  amt = ardata->symdef_count;
296589857Sobrien  amt *= sizeof (struct symdef);
2966218822Sdim  symdef_ptr = bfd_alloc (abfd, amt);
296733965Sjdp  if (!symdef_ptr)
2968130561Sobrien    return FALSE;
296933965Sjdp
297033965Sjdp  ardata->symdefs = (carsym *) symdef_ptr;
297133965Sjdp
297233965Sjdp  raw_ptr = raw_armap + 4;
297333965Sjdp  for (i = 0; i < count; i++, raw_ptr += 8)
297433965Sjdp    {
297533965Sjdp      unsigned int name_offset, file_offset;
297633965Sjdp
297789857Sobrien      file_offset = H_GET_32 (abfd, (raw_ptr + 4));
297833965Sjdp      if (file_offset == 0)
297933965Sjdp	continue;
298089857Sobrien      name_offset = H_GET_32 (abfd, raw_ptr);
298133965Sjdp      symdef_ptr->s.name = stringbase + name_offset;
298233965Sjdp      symdef_ptr->file_offset = file_offset;
298333965Sjdp      ++symdef_ptr;
298433965Sjdp    }
298533965Sjdp
298633965Sjdp  ardata->first_file_filepos = bfd_tell (abfd);
298733965Sjdp  /* Pad to an even boundary.  */
298833965Sjdp  ardata->first_file_filepos += ardata->first_file_filepos % 2;
298933965Sjdp
2990130561Sobrien  bfd_has_map (abfd) = TRUE;
299133965Sjdp
2992130561Sobrien  return TRUE;
299333965Sjdp}
299433965Sjdp
299533965Sjdp/* Write out an armap.  */
299633965Sjdp
2997130561Sobrienbfd_boolean
2998218822Sdim_bfd_ecoff_write_armap (bfd *abfd,
2999218822Sdim			unsigned int elength,
3000218822Sdim			struct orl *map,
3001218822Sdim			unsigned int orl_count,
3002218822Sdim			int stridx)
300333965Sjdp{
300433965Sjdp  unsigned int hashsize, hashlog;
300589857Sobrien  bfd_size_type symdefsize;
300633965Sjdp  int padit;
300733965Sjdp  unsigned int stringsize;
300833965Sjdp  unsigned int mapsize;
300933965Sjdp  file_ptr firstreal;
301033965Sjdp  struct ar_hdr hdr;
301133965Sjdp  struct stat statbuf;
301233965Sjdp  unsigned int i;
301333965Sjdp  bfd_byte temp[4];
301433965Sjdp  bfd_byte *hashtable;
301533965Sjdp  bfd *current;
301633965Sjdp  bfd *last_elt;
301733965Sjdp
301833965Sjdp  /* Ultrix appears to use as a hash table size the least power of two
301933965Sjdp     greater than twice the number of entries.  */
302038889Sjdp  for (hashlog = 0; ((unsigned int) 1 << hashlog) <= 2 * orl_count; hashlog++)
302133965Sjdp    ;
302233965Sjdp  hashsize = 1 << hashlog;
302333965Sjdp
302433965Sjdp  symdefsize = hashsize * 8;
302533965Sjdp  padit = stridx % 2;
302633965Sjdp  stringsize = stridx + padit;
302733965Sjdp
302877298Sobrien  /* Include 8 bytes to store symdefsize and stringsize in output.  */
302933965Sjdp  mapsize = symdefsize + stringsize + 8;
303033965Sjdp
303133965Sjdp  firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength;
303233965Sjdp
3033218822Sdim  memset ((void *) &hdr, 0, sizeof hdr);
303433965Sjdp
303533965Sjdp  /* Work out the ECOFF armap name.  */
303633965Sjdp  strcpy (hdr.ar_name, ecoff_backend (abfd)->armap_start);
303733965Sjdp  hdr.ar_name[ARMAP_HEADER_MARKER_INDEX] = ARMAP_MARKER;
303833965Sjdp  hdr.ar_name[ARMAP_HEADER_ENDIAN_INDEX] =
303933965Sjdp    (bfd_header_big_endian (abfd)
304033965Sjdp     ? ARMAP_BIG_ENDIAN
304133965Sjdp     : ARMAP_LITTLE_ENDIAN);
304233965Sjdp  hdr.ar_name[ARMAP_OBJECT_MARKER_INDEX] = ARMAP_MARKER;
304333965Sjdp  hdr.ar_name[ARMAP_OBJECT_ENDIAN_INDEX] =
304433965Sjdp    bfd_big_endian (abfd) ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN;
304533965Sjdp  memcpy (hdr.ar_name + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1);
304633965Sjdp
304733965Sjdp  /* Write the timestamp of the archive header to be just a little bit
304833965Sjdp     later than the timestamp of the file, otherwise the linker will
304933965Sjdp     complain that the index is out of date.  Actually, the Ultrix
305033965Sjdp     linker just checks the archive name; the GNU linker may check the
305133965Sjdp     date.  */
305233965Sjdp  stat (abfd->filename, &statbuf);
3053251227Spfg  sprintf (hdr.ar_date, "%ld", (long) (statbuf.st_mtime + 60));
305433965Sjdp
305533965Sjdp  /* The DECstation uses zeroes for the uid, gid and mode of the
305633965Sjdp     armap.  */
305733965Sjdp  hdr.ar_uid[0] = '0';
305833965Sjdp  hdr.ar_gid[0] = '0';
305977298Sobrien  /* Building gcc ends up extracting the armap as a file - twice.  */
306060484Sobrien  hdr.ar_mode[0] = '6';
306160484Sobrien  hdr.ar_mode[1] = '4';
306260484Sobrien  hdr.ar_mode[2] = '4';
306333965Sjdp
306433965Sjdp  sprintf (hdr.ar_size, "%-10d", (int) mapsize);
306533965Sjdp
306633965Sjdp  hdr.ar_fmag[0] = '`';
306733965Sjdp  hdr.ar_fmag[1] = '\012';
306833965Sjdp
306933965Sjdp  /* Turn all null bytes in the header into spaces.  */
307033965Sjdp  for (i = 0; i < sizeof (struct ar_hdr); i++)
307177298Sobrien   if (((char *) (&hdr))[i] == '\0')
307277298Sobrien     (((char *) (&hdr))[i]) = ' ';
307333965Sjdp
3074218822Sdim  if (bfd_bwrite ((void *) &hdr, (bfd_size_type) sizeof (struct ar_hdr), abfd)
307533965Sjdp      != sizeof (struct ar_hdr))
3076130561Sobrien    return FALSE;
307733965Sjdp
307889857Sobrien  H_PUT_32 (abfd, hashsize, temp);
3079218822Sdim  if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4)
3080130561Sobrien    return FALSE;
308177298Sobrien
3082218822Sdim  hashtable = bfd_zalloc (abfd, symdefsize);
308333965Sjdp  if (!hashtable)
3084130561Sobrien    return FALSE;
308533965Sjdp
308633965Sjdp  current = abfd->archive_head;
308733965Sjdp  last_elt = current;
308833965Sjdp  for (i = 0; i < orl_count; i++)
308933965Sjdp    {
3090218822Sdim      unsigned int hash, rehash = 0;
309133965Sjdp
309233965Sjdp      /* Advance firstreal to the file position of this archive
309333965Sjdp	 element.  */
309489857Sobrien      if (map[i].u.abfd != last_elt)
309533965Sjdp	{
309633965Sjdp	  do
309733965Sjdp	    {
309833965Sjdp	      firstreal += arelt_size (current) + sizeof (struct ar_hdr);
309933965Sjdp	      firstreal += firstreal % 2;
3100218822Sdim	      current = current->archive_next;
310133965Sjdp	    }
310289857Sobrien	  while (current != map[i].u.abfd);
310333965Sjdp	}
310433965Sjdp
310533965Sjdp      last_elt = current;
310633965Sjdp
310733965Sjdp      hash = ecoff_armap_hash (*map[i].name, &rehash, hashsize, hashlog);
310889857Sobrien      if (H_GET_32 (abfd, (hashtable + (hash * 8) + 4)) != 0)
310933965Sjdp	{
311033965Sjdp	  unsigned int srch;
311133965Sjdp
311233965Sjdp	  /* The desired slot is already taken.  */
311333965Sjdp	  for (srch = (hash + rehash) & (hashsize - 1);
311433965Sjdp	       srch != hash;
311533965Sjdp	       srch = (srch + rehash) & (hashsize - 1))
311689857Sobrien	    if (H_GET_32 (abfd, (hashtable + (srch * 8) + 4)) == 0)
311733965Sjdp	      break;
311833965Sjdp
311933965Sjdp	  BFD_ASSERT (srch != hash);
312033965Sjdp
312133965Sjdp	  hash = srch;
312233965Sjdp	}
312377298Sobrien
312489857Sobrien      H_PUT_32 (abfd, map[i].namidx, (hashtable + hash * 8));
312589857Sobrien      H_PUT_32 (abfd, firstreal, (hashtable + hash * 8 + 4));
312633965Sjdp    }
312733965Sjdp
3128218822Sdim  if (bfd_bwrite ((void *) hashtable, symdefsize, abfd) != symdefsize)
3129130561Sobrien    return FALSE;
313033965Sjdp
313133965Sjdp  bfd_release (abfd, hashtable);
313233965Sjdp
313333965Sjdp  /* Now write the strings.  */
313489857Sobrien  H_PUT_32 (abfd, stringsize, temp);
3135218822Sdim  if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4)
3136130561Sobrien    return FALSE;
313733965Sjdp  for (i = 0; i < orl_count; i++)
313833965Sjdp    {
313933965Sjdp      bfd_size_type len;
314033965Sjdp
314133965Sjdp      len = strlen (*map[i].name) + 1;
3142218822Sdim      if (bfd_bwrite ((void *) (*map[i].name), len, abfd) != len)
3143130561Sobrien	return FALSE;
314433965Sjdp    }
314533965Sjdp
314633965Sjdp  /* The spec sez this should be a newline.  But in order to be
314733965Sjdp     bug-compatible for DECstation ar we use a null.  */
314833965Sjdp  if (padit)
314933965Sjdp    {
315089857Sobrien      if (bfd_bwrite ("", (bfd_size_type) 1, abfd) != 1)
3151130561Sobrien	return FALSE;
315233965Sjdp    }
315333965Sjdp
3154130561Sobrien  return TRUE;
315533965Sjdp}
315633965Sjdp
315733965Sjdp/* See whether this BFD is an archive.  If it is, read in the armap
315833965Sjdp   and the extended name table.  */
315933965Sjdp
316033965Sjdpconst bfd_target *
3161218822Sdim_bfd_ecoff_archive_p (bfd *abfd)
316233965Sjdp{
316333965Sjdp  struct artdata *tdata_hold;
316433965Sjdp  char armag[SARMAG + 1];
316589857Sobrien  bfd_size_type amt;
316633965Sjdp
3167218822Sdim  if (bfd_bread ((void *) armag, (bfd_size_type) SARMAG, abfd) != SARMAG)
316833965Sjdp    {
316933965Sjdp      if (bfd_get_error () != bfd_error_system_call)
317033965Sjdp	bfd_set_error (bfd_error_wrong_format);
3171218822Sdim      return NULL;
317233965Sjdp    }
317333965Sjdp
3174218822Sdim  if (! strneq (armag, ARMAG, SARMAG))
317533965Sjdp    {
317633965Sjdp      bfd_set_error (bfd_error_wrong_format);
317733965Sjdp      return NULL;
317833965Sjdp    }
317933965Sjdp
3180104834Sobrien  tdata_hold = bfd_ardata (abfd);
3181104834Sobrien
318289857Sobrien  amt = sizeof (struct artdata);
3183218822Sdim  bfd_ardata (abfd) = bfd_zalloc (abfd, amt);
3184218822Sdim  if (bfd_ardata (abfd) == NULL)
318533965Sjdp    {
3186104834Sobrien      bfd_ardata (abfd) = tdata_hold;
3187218822Sdim      return NULL;
318833965Sjdp    }
318933965Sjdp
319033965Sjdp  bfd_ardata (abfd)->first_file_filepos = SARMAG;
3191218822Sdim  /* Already cleared by bfd_zalloc above.
3192218822Sdim     bfd_ardata (abfd)->cache = NULL;
3193218822Sdim     bfd_ardata (abfd)->archive_head = NULL;
3194218822Sdim     bfd_ardata (abfd)->symdefs = NULL;
3195218822Sdim     bfd_ardata (abfd)->extended_names = NULL;
3196218822Sdim     bfd_ardata (abfd)->extended_names_size = 0;
3197218822Sdim     bfd_ardata (abfd)->tdata = NULL;  */
319877298Sobrien
3199104834Sobrien  if (! _bfd_ecoff_slurp_armap (abfd)
3200104834Sobrien      || ! _bfd_ecoff_slurp_extended_name_table (abfd))
320133965Sjdp    {
320233965Sjdp      bfd_release (abfd, bfd_ardata (abfd));
3203104834Sobrien      bfd_ardata (abfd) = tdata_hold;
3204218822Sdim      return NULL;
320533965Sjdp    }
320677298Sobrien
320733965Sjdp  if (bfd_has_map (abfd))
320833965Sjdp    {
320933965Sjdp      bfd *first;
321033965Sjdp
321133965Sjdp      /* This archive has a map, so we may presume that the contents
321233965Sjdp	 are object files.  Make sure that if the first file in the
321333965Sjdp	 archive can be recognized as an object file, it is for this
321433965Sjdp	 target.  If not, assume that this is the wrong format.  If
321533965Sjdp	 the first file is not an object file, somebody is doing
321633965Sjdp	 something weird, and we permit it so that ar -t will work.  */
321733965Sjdp
3218218822Sdim      first = bfd_openr_next_archived_file (abfd, NULL);
321933965Sjdp      if (first != NULL)
322033965Sjdp	{
3221130561Sobrien	  first->target_defaulted = FALSE;
322233965Sjdp	  if (bfd_check_format (first, bfd_object)
322333965Sjdp	      && first->xvec != abfd->xvec)
322433965Sjdp	    {
3225104834Sobrien	      /* We ought to close `first' here, but we can't, because
3226104834Sobrien		 we have no way to remove it from the archive cache.
3227218822Sdim		 It's almost impossible to figure out when we can
3228104834Sobrien		 release bfd_ardata.  FIXME.  */
3229104834Sobrien	      bfd_set_error (bfd_error_wrong_object_format);
3230104834Sobrien	      bfd_ardata (abfd) = tdata_hold;
323133965Sjdp	      return NULL;
323233965Sjdp	    }
3233104834Sobrien	  /* And we ought to close `first' here too.  */
323433965Sjdp	}
323533965Sjdp    }
323633965Sjdp
323733965Sjdp  return abfd->xvec;
323833965Sjdp}
323933965Sjdp
324033965Sjdp/* ECOFF linker code.  */
324133965Sjdp
324233965Sjdp/* Routine to create an entry in an ECOFF link hash table.  */
324333965Sjdp
324433965Sjdpstatic struct bfd_hash_entry *
3245218822Sdimecoff_link_hash_newfunc (struct bfd_hash_entry *entry,
3246218822Sdim			 struct bfd_hash_table *table,
3247218822Sdim			 const char *string)
324833965Sjdp{
324933965Sjdp  struct ecoff_link_hash_entry *ret = (struct ecoff_link_hash_entry *) entry;
325033965Sjdp
325133965Sjdp  /* Allocate the structure if it has not already been allocated by a
325233965Sjdp     subclass.  */
3253218822Sdim  if (ret == NULL)
325433965Sjdp    ret = ((struct ecoff_link_hash_entry *)
325533965Sjdp	   bfd_hash_allocate (table, sizeof (struct ecoff_link_hash_entry)));
3256218822Sdim  if (ret == NULL)
325733965Sjdp    return NULL;
325833965Sjdp
325933965Sjdp  /* Call the allocation method of the superclass.  */
326033965Sjdp  ret = ((struct ecoff_link_hash_entry *)
326133965Sjdp	 _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
326233965Sjdp				 table, string));
326333965Sjdp
326433965Sjdp  if (ret)
326533965Sjdp    {
326633965Sjdp      /* Set local fields.  */
326733965Sjdp      ret->indx = -1;
326833965Sjdp      ret->abfd = NULL;
326933965Sjdp      ret->written = 0;
327033965Sjdp      ret->small = 0;
327133965Sjdp    }
3272218822Sdim  memset ((void *) &ret->esym, 0, sizeof ret->esym);
327333965Sjdp
327433965Sjdp  return (struct bfd_hash_entry *) ret;
327533965Sjdp}
327633965Sjdp
327733965Sjdp/* Create an ECOFF link hash table.  */
327833965Sjdp
327933965Sjdpstruct bfd_link_hash_table *
3280218822Sdim_bfd_ecoff_bfd_link_hash_table_create (bfd *abfd)
328133965Sjdp{
328233965Sjdp  struct ecoff_link_hash_table *ret;
328389857Sobrien  bfd_size_type amt = sizeof (struct ecoff_link_hash_table);
328433965Sjdp
3285218822Sdim  ret = bfd_malloc (amt);
328633965Sjdp  if (ret == NULL)
328733965Sjdp    return NULL;
3288218822Sdim  if (!_bfd_link_hash_table_init (&ret->root, abfd,
3289218822Sdim				  ecoff_link_hash_newfunc,
3290218822Sdim				  sizeof (struct ecoff_link_hash_entry)))
329133965Sjdp    {
329233965Sjdp      free (ret);
3293218822Sdim      return NULL;
329433965Sjdp    }
329533965Sjdp  return &ret->root;
329633965Sjdp}
329733965Sjdp
329833965Sjdp/* Look up an entry in an ECOFF link hash table.  */
329933965Sjdp
330033965Sjdp#define ecoff_link_hash_lookup(table, string, create, copy, follow) \
330133965Sjdp  ((struct ecoff_link_hash_entry *) \
330233965Sjdp   bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow)))
330333965Sjdp
330433965Sjdp/* Traverse an ECOFF link hash table.  */
330533965Sjdp
330633965Sjdp#define ecoff_link_hash_traverse(table, func, info)			\
330733965Sjdp  (bfd_link_hash_traverse						\
330833965Sjdp   (&(table)->root,							\
3309218822Sdim    (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func),	\
331033965Sjdp    (info)))
331133965Sjdp
331233965Sjdp/* Get the ECOFF link hash table from the info structure.  This is
331333965Sjdp   just a cast.  */
331433965Sjdp
331533965Sjdp#define ecoff_hash_table(p) ((struct ecoff_link_hash_table *) ((p)->hash))
331633965Sjdp
331733965Sjdp/* Add the external symbols of an object file to the global linker
331833965Sjdp   hash table.  The external symbols and strings we are passed are
331933965Sjdp   just allocated on the stack, and will be discarded.  We must
332033965Sjdp   explicitly save any information we may need later on in the link.
332133965Sjdp   We do not want to read the external symbol information again.  */
332233965Sjdp
3323130561Sobrienstatic bfd_boolean
3324218822Sdimecoff_link_add_externals (bfd *abfd,
3325218822Sdim			  struct bfd_link_info *info,
3326218822Sdim			  void * external_ext,
3327218822Sdim			  char *ssext)
332833965Sjdp{
332933965Sjdp  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
3330218822Sdim  void (* const swap_ext_in) (bfd *, void *, EXTR *)
333133965Sjdp    = backend->debug_swap.swap_ext_in;
333233965Sjdp  bfd_size_type external_ext_size = backend->debug_swap.external_ext_size;
333333965Sjdp  unsigned long ext_count;
3334107492Sobrien  struct bfd_link_hash_entry **sym_hash;
333533965Sjdp  char *ext_ptr;
333633965Sjdp  char *ext_end;
333789857Sobrien  bfd_size_type amt;
333833965Sjdp
333933965Sjdp  ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
334033965Sjdp
334189857Sobrien  amt = ext_count;
334289857Sobrien  amt *= sizeof (struct bfd_link_hash_entry *);
3343218822Sdim  sym_hash = bfd_alloc (abfd, amt);
334433965Sjdp  if (!sym_hash)
3345130561Sobrien    return FALSE;
3346107492Sobrien  ecoff_data (abfd)->sym_hashes = (struct ecoff_link_hash_entry **) sym_hash;
334733965Sjdp
334833965Sjdp  ext_ptr = (char *) external_ext;
334933965Sjdp  ext_end = ext_ptr + ext_count * external_ext_size;
335033965Sjdp  for (; ext_ptr < ext_end; ext_ptr += external_ext_size, sym_hash++)
335133965Sjdp    {
335233965Sjdp      EXTR esym;
3353130561Sobrien      bfd_boolean skip;
335433965Sjdp      bfd_vma value;
335533965Sjdp      asection *section;
335633965Sjdp      const char *name;
335733965Sjdp      struct ecoff_link_hash_entry *h;
335833965Sjdp
335933965Sjdp      *sym_hash = NULL;
336033965Sjdp
3361218822Sdim      (*swap_ext_in) (abfd, (void *) ext_ptr, &esym);
336233965Sjdp
336333965Sjdp      /* Skip debugging symbols.  */
3364130561Sobrien      skip = FALSE;
336533965Sjdp      switch (esym.asym.st)
336633965Sjdp	{
336733965Sjdp	case stGlobal:
336833965Sjdp	case stStatic:
336933965Sjdp	case stLabel:
337033965Sjdp	case stProc:
337133965Sjdp	case stStaticProc:
337233965Sjdp	  break;
337333965Sjdp	default:
3374130561Sobrien	  skip = TRUE;
337533965Sjdp	  break;
337633965Sjdp	}
337733965Sjdp
337833965Sjdp      if (skip)
337933965Sjdp	continue;
338033965Sjdp
338133965Sjdp      /* Get the information for this symbol.  */
338233965Sjdp      value = esym.asym.value;
338333965Sjdp      switch (esym.asym.sc)
338433965Sjdp	{
338533965Sjdp	default:
338633965Sjdp	case scNil:
338733965Sjdp	case scRegister:
338833965Sjdp	case scCdbLocal:
338933965Sjdp	case scBits:
339033965Sjdp	case scCdbSystem:
339133965Sjdp	case scRegImage:
339233965Sjdp	case scInfo:
339333965Sjdp	case scUserStruct:
339433965Sjdp	case scVar:
339533965Sjdp	case scVarRegister:
339633965Sjdp	case scVariant:
339733965Sjdp	case scBasedVar:
339833965Sjdp	case scXData:
339933965Sjdp	case scPData:
340033965Sjdp	  section = NULL;
340133965Sjdp	  break;
340233965Sjdp	case scText:
3403218822Sdim	  section = bfd_make_section_old_way (abfd, _TEXT);
340433965Sjdp	  value -= section->vma;
340533965Sjdp	  break;
340633965Sjdp	case scData:
3407218822Sdim	  section = bfd_make_section_old_way (abfd, _DATA);
340833965Sjdp	  value -= section->vma;
340933965Sjdp	  break;
341033965Sjdp	case scBss:
3411218822Sdim	  section = bfd_make_section_old_way (abfd, _BSS);
341233965Sjdp	  value -= section->vma;
341333965Sjdp	  break;
341433965Sjdp	case scAbs:
341533965Sjdp	  section = bfd_abs_section_ptr;
341633965Sjdp	  break;
341733965Sjdp	case scUndefined:
341833965Sjdp	  section = bfd_und_section_ptr;
341933965Sjdp	  break;
342033965Sjdp	case scSData:
3421218822Sdim	  section = bfd_make_section_old_way (abfd, _SDATA);
342233965Sjdp	  value -= section->vma;
342333965Sjdp	  break;
342433965Sjdp	case scSBss:
3425218822Sdim	  section = bfd_make_section_old_way (abfd, _SBSS);
342633965Sjdp	  value -= section->vma;
342733965Sjdp	  break;
342833965Sjdp	case scRData:
3429218822Sdim	  section = bfd_make_section_old_way (abfd, _RDATA);
343033965Sjdp	  value -= section->vma;
343133965Sjdp	  break;
343233965Sjdp	case scCommon:
343333965Sjdp	  if (value > ecoff_data (abfd)->gp_size)
343433965Sjdp	    {
343533965Sjdp	      section = bfd_com_section_ptr;
343633965Sjdp	      break;
343733965Sjdp	    }
343833965Sjdp	  /* Fall through.  */
343933965Sjdp	case scSCommon:
344033965Sjdp	  if (ecoff_scom_section.name == NULL)
344133965Sjdp	    {
344233965Sjdp	      /* Initialize the small common section.  */
344333965Sjdp	      ecoff_scom_section.name = SCOMMON;
344433965Sjdp	      ecoff_scom_section.flags = SEC_IS_COMMON;
344533965Sjdp	      ecoff_scom_section.output_section = &ecoff_scom_section;
344633965Sjdp	      ecoff_scom_section.symbol = &ecoff_scom_symbol;
344733965Sjdp	      ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr;
344833965Sjdp	      ecoff_scom_symbol.name = SCOMMON;
344933965Sjdp	      ecoff_scom_symbol.flags = BSF_SECTION_SYM;
345033965Sjdp	      ecoff_scom_symbol.section = &ecoff_scom_section;
345133965Sjdp	      ecoff_scom_symbol_ptr = &ecoff_scom_symbol;
345233965Sjdp	    }
345333965Sjdp	  section = &ecoff_scom_section;
345433965Sjdp	  break;
345533965Sjdp	case scSUndefined:
345633965Sjdp	  section = bfd_und_section_ptr;
345733965Sjdp	  break;
345833965Sjdp	case scInit:
3459218822Sdim	  section = bfd_make_section_old_way (abfd, _INIT);
346033965Sjdp	  value -= section->vma;
346133965Sjdp	  break;
346233965Sjdp	case scFini:
3463218822Sdim	  section = bfd_make_section_old_way (abfd, _FINI);
346433965Sjdp	  value -= section->vma;
346533965Sjdp	  break;
346633965Sjdp	case scRConst:
3467218822Sdim	  section = bfd_make_section_old_way (abfd, _RCONST);
346833965Sjdp	  value -= section->vma;
346933965Sjdp	  break;
347033965Sjdp	}
347133965Sjdp
3472218822Sdim      if (section == NULL)
347333965Sjdp	continue;
347433965Sjdp
347533965Sjdp      name = ssext + esym.asym.iss;
347633965Sjdp
347733965Sjdp      if (! (_bfd_generic_link_add_one_symbol
347833965Sjdp	     (info, abfd, name,
347989857Sobrien	      (flagword) (esym.weakext ? BSF_WEAK : BSF_GLOBAL),
3480218822Sdim	      section, value, NULL, TRUE, TRUE, sym_hash)))
3481130561Sobrien	return FALSE;
348233965Sjdp
3483107492Sobrien      h = (struct ecoff_link_hash_entry *) *sym_hash;
348433965Sjdp
348533965Sjdp      /* If we are building an ECOFF hash table, save the external
348633965Sjdp	 symbol information.  */
348733965Sjdp      if (info->hash->creator->flavour == bfd_get_flavour (abfd))
348833965Sjdp	{
3489218822Sdim	  if (h->abfd == NULL
349033965Sjdp	      || (! bfd_is_und_section (section)
349133965Sjdp		  && (! bfd_is_com_section (section)
349233965Sjdp		      || (h->root.type != bfd_link_hash_defined
349333965Sjdp			  && h->root.type != bfd_link_hash_defweak))))
349433965Sjdp	    {
349533965Sjdp	      h->abfd = abfd;
349633965Sjdp	      h->esym = esym;
349733965Sjdp	    }
349833965Sjdp
349933965Sjdp	  /* Remember whether this symbol was small undefined.  */
350033965Sjdp	  if (esym.asym.sc == scSUndefined)
350133965Sjdp	    h->small = 1;
350233965Sjdp
350333965Sjdp	  /* If this symbol was ever small undefined, it needs to wind
350433965Sjdp	     up in a GP relative section.  We can't control the
350533965Sjdp	     section of a defined symbol, but we can control the
350633965Sjdp	     section of a common symbol.  This case is actually needed
350733965Sjdp	     on Ultrix 4.2 to handle the symbol cred in -lckrb.  */
350833965Sjdp	  if (h->small
350933965Sjdp	      && h->root.type == bfd_link_hash_common
3510218822Sdim	      && streq (h->root.u.c.p->section->name, SCOMMON))
351133965Sjdp	    {
351233965Sjdp	      h->root.u.c.p->section = bfd_make_section_old_way (abfd,
351333965Sjdp								 SCOMMON);
351433965Sjdp	      h->root.u.c.p->section->flags = SEC_ALLOC;
351533965Sjdp	      if (h->esym.asym.sc == scCommon)
351633965Sjdp		h->esym.asym.sc = scSCommon;
351733965Sjdp	    }
351833965Sjdp	}
351933965Sjdp    }
352033965Sjdp
3521130561Sobrien  return TRUE;
352233965Sjdp}
352333965Sjdp
3524218822Sdim/* Add symbols from an ECOFF object file to the global linker hash
3525218822Sdim   table.  */
352633965Sjdp
3527218822Sdimstatic bfd_boolean
3528218822Sdimecoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
352933965Sjdp{
3530218822Sdim  HDRR *symhdr;
3531218822Sdim  bfd_size_type external_ext_size;
3532218822Sdim  void * external_ext = NULL;
3533218822Sdim  bfd_size_type esize;
3534218822Sdim  char *ssext = NULL;
3535218822Sdim  bfd_boolean result;
353633965Sjdp
3537218822Sdim  if (! ecoff_slurp_symbolic_header (abfd))
3538218822Sdim    return FALSE;
353933965Sjdp
3540218822Sdim  /* If there are no symbols, we don't want it.  */
3541218822Sdim  if (bfd_get_symcount (abfd) == 0)
3542218822Sdim    return TRUE;
3543218822Sdim
3544218822Sdim  symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
3545218822Sdim
3546218822Sdim  /* Read in the external symbols and external strings.  */
3547218822Sdim  external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size;
3548218822Sdim  esize = symhdr->iextMax * external_ext_size;
3549218822Sdim  external_ext = bfd_malloc (esize);
3550218822Sdim  if (external_ext == NULL && esize != 0)
3551218822Sdim    goto error_return;
3552218822Sdim
3553218822Sdim  if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0
3554218822Sdim      || bfd_bread (external_ext, esize, abfd) != esize)
3555218822Sdim    goto error_return;
3556218822Sdim
3557218822Sdim  ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax);
3558218822Sdim  if (ssext == NULL && symhdr->issExtMax != 0)
3559218822Sdim    goto error_return;
3560218822Sdim
3561218822Sdim  if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0
3562218822Sdim      || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd)
3563218822Sdim	  != (bfd_size_type) symhdr->issExtMax))
3564218822Sdim    goto error_return;
3565218822Sdim
3566218822Sdim  result = ecoff_link_add_externals (abfd, info, external_ext, ssext);
3567218822Sdim
3568218822Sdim  if (ssext != NULL)
3569218822Sdim    free (ssext);
3570218822Sdim  if (external_ext != NULL)
3571218822Sdim    free (external_ext);
3572218822Sdim  return result;
3573218822Sdim
3574218822Sdim error_return:
3575218822Sdim  if (ssext != NULL)
3576218822Sdim    free (ssext);
3577218822Sdim  if (external_ext != NULL)
3578218822Sdim    free (external_ext);
3579218822Sdim  return FALSE;
3580218822Sdim}
3581218822Sdim
3582218822Sdim/* This is called if we used _bfd_generic_link_add_archive_symbols
3583218822Sdim   because we were not dealing with an ECOFF archive.  */
3584218822Sdim
3585218822Sdimstatic bfd_boolean
3586218822Sdimecoff_link_check_archive_element (bfd *abfd,
3587218822Sdim				  struct bfd_link_info *info,
3588218822Sdim				  bfd_boolean *pneeded)
358933965Sjdp{
359033965Sjdp  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
3591218822Sdim  void (* const swap_ext_in) (bfd *, void *, EXTR *)
3592218822Sdim    = backend->debug_swap.swap_ext_in;
359333965Sjdp  HDRR *symhdr;
3594218822Sdim  bfd_size_type external_ext_size;
3595218822Sdim  void * external_ext = NULL;
3596218822Sdim  bfd_size_type esize;
3597218822Sdim  char *ssext = NULL;
3598218822Sdim  char *ext_ptr;
3599218822Sdim  char *ext_end;
360033965Sjdp
3601218822Sdim  *pneeded = FALSE;
360233965Sjdp
3603218822Sdim  if (! ecoff_slurp_symbolic_header (abfd))
3604218822Sdim    goto error_return;
360533965Sjdp
3606218822Sdim  /* If there are no symbols, we don't want it.  */
3607218822Sdim  if (bfd_get_symcount (abfd) == 0)
3608218822Sdim    goto successful_return;
360933965Sjdp
3610218822Sdim  symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
3611218822Sdim
3612218822Sdim  /* Read in the external symbols and external strings.  */
3613218822Sdim  external_ext_size = backend->debug_swap.external_ext_size;
3614218822Sdim  esize = symhdr->iextMax * external_ext_size;
3615218822Sdim  external_ext = bfd_malloc (esize);
3616218822Sdim  if (external_ext == NULL && esize != 0)
3617218822Sdim    goto error_return;
3618218822Sdim
3619218822Sdim  if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0
3620218822Sdim      || bfd_bread (external_ext, esize, abfd) != esize)
3621218822Sdim    goto error_return;
3622218822Sdim
3623218822Sdim  ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax);
3624218822Sdim  if (ssext == NULL && symhdr->issExtMax != 0)
3625218822Sdim    goto error_return;
3626218822Sdim
3627218822Sdim  if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0
3628218822Sdim      || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd)
3629218822Sdim	  != (bfd_size_type) symhdr->issExtMax))
3630218822Sdim    goto error_return;
3631218822Sdim
3632218822Sdim  /* Look through the external symbols to see if they define some
3633218822Sdim     symbol that is currently undefined.  */
3634218822Sdim  ext_ptr = (char *) external_ext;
3635218822Sdim  ext_end = ext_ptr + esize;
3636218822Sdim  for (; ext_ptr < ext_end; ext_ptr += external_ext_size)
363733965Sjdp    {
3638218822Sdim      EXTR esym;
3639218822Sdim      bfd_boolean def;
3640218822Sdim      const char *name;
3641218822Sdim      struct bfd_link_hash_entry *h;
364233965Sjdp
3643218822Sdim      (*swap_ext_in) (abfd, (void *) ext_ptr, &esym);
3644218822Sdim
3645218822Sdim      /* See if this symbol defines something.  */
3646218822Sdim      if (esym.asym.st != stGlobal
3647218822Sdim	  && esym.asym.st != stLabel
3648218822Sdim	  && esym.asym.st != stProc)
3649218822Sdim	continue;
3650218822Sdim
3651218822Sdim      switch (esym.asym.sc)
365233965Sjdp	{
3653218822Sdim	case scText:
3654218822Sdim	case scData:
3655218822Sdim	case scBss:
3656218822Sdim	case scAbs:
3657218822Sdim	case scSData:
3658218822Sdim	case scSBss:
3659218822Sdim	case scRData:
3660218822Sdim	case scCommon:
3661218822Sdim	case scSCommon:
3662218822Sdim	case scInit:
3663218822Sdim	case scFini:
3664218822Sdim	case scRConst:
3665218822Sdim	  def = TRUE;
3666218822Sdim	  break;
3667218822Sdim	default:
3668218822Sdim	  def = FALSE;
3669218822Sdim	  break;
367033965Sjdp	}
367133965Sjdp
3672218822Sdim      if (! def)
3673218822Sdim	continue;
367433965Sjdp
3675218822Sdim      name = ssext + esym.asym.iss;
3676218822Sdim      h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
367733965Sjdp
3678218822Sdim      /* Unlike the generic linker, we do not pull in elements because
3679218822Sdim	 of common symbols.  */
3680218822Sdim      if (h == NULL
3681218822Sdim	  || h->type != bfd_link_hash_undefined)
3682218822Sdim	continue;
3683218822Sdim
3684218822Sdim      /* Include this element.  */
3685218822Sdim      if (! (*info->callbacks->add_archive_element) (info, abfd, name))
3686218822Sdim	goto error_return;
3687218822Sdim      if (! ecoff_link_add_externals (abfd, info, external_ext, ssext))
3688218822Sdim	goto error_return;
3689218822Sdim
3690218822Sdim      *pneeded = TRUE;
3691218822Sdim      goto successful_return;
369233965Sjdp    }
369333965Sjdp
3694218822Sdim successful_return:
3695218822Sdim  if (external_ext != NULL)
3696218822Sdim    free (external_ext);
3697218822Sdim  if (ssext != NULL)
3698218822Sdim    free (ssext);
3699218822Sdim  return TRUE;
3700218822Sdim error_return:
3701218822Sdim  if (external_ext != NULL)
3702218822Sdim    free (external_ext);
3703218822Sdim  if (ssext != NULL)
3704218822Sdim    free (ssext);
3705218822Sdim  return FALSE;
3706218822Sdim}
370733965Sjdp
3708218822Sdim/* Add the symbols from an archive file to the global hash table.
3709218822Sdim   This looks through the undefined symbols, looks each one up in the
3710218822Sdim   archive hash table, and adds any associated object file.  We do not
3711218822Sdim   use _bfd_generic_link_add_archive_symbols because ECOFF archives
3712218822Sdim   already have a hash table, so there is no reason to construct
3713218822Sdim   another one.  */
371433965Sjdp
3715218822Sdimstatic bfd_boolean
3716218822Sdimecoff_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
3717218822Sdim{
3718218822Sdim  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
3719218822Sdim  const bfd_byte *raw_armap;
3720218822Sdim  struct bfd_link_hash_entry **pundef;
3721218822Sdim  unsigned int armap_count;
3722218822Sdim  unsigned int armap_log;
3723218822Sdim  unsigned int i;
3724218822Sdim  const bfd_byte *hashtable;
3725218822Sdim  const char *stringbase;
372633965Sjdp
3727218822Sdim  if (! bfd_has_map (abfd))
372833965Sjdp    {
3729218822Sdim      /* An empty archive is a special case.  */
3730218822Sdim      if (bfd_openr_next_archived_file (abfd, NULL) == NULL)
3731218822Sdim	return TRUE;
3732218822Sdim      bfd_set_error (bfd_error_no_armap);
3733218822Sdim      return FALSE;
373433965Sjdp    }
373533965Sjdp
3736218822Sdim  /* If we don't have any raw data for this archive, as can happen on
3737218822Sdim     Irix 4.0.5F, we call the generic routine.
3738218822Sdim     FIXME: We should be more clever about this, since someday tdata
3739218822Sdim     may get to something for a generic archive.  */
3740218822Sdim  raw_armap = (const bfd_byte *) bfd_ardata (abfd)->tdata;
3741218822Sdim  if (raw_armap == NULL)
3742218822Sdim    return (_bfd_generic_link_add_archive_symbols
3743218822Sdim	    (abfd, info, ecoff_link_check_archive_element));
3744218822Sdim
3745218822Sdim  armap_count = H_GET_32 (abfd, raw_armap);
3746218822Sdim
3747218822Sdim  armap_log = 0;
3748218822Sdim  for (i = 1; i < armap_count; i <<= 1)
3749218822Sdim    armap_log++;
3750218822Sdim  BFD_ASSERT (i == armap_count);
3751218822Sdim
3752218822Sdim  hashtable = raw_armap + 4;
3753218822Sdim  stringbase = (const char *) raw_armap + armap_count * 8 + 8;
3754218822Sdim
3755218822Sdim  /* Look through the list of undefined symbols.  */
3756218822Sdim  pundef = &info->hash->undefs;
3757218822Sdim  while (*pundef != NULL)
375833965Sjdp    {
375933965Sjdp      struct bfd_link_hash_entry *h;
3760218822Sdim      unsigned int hash, rehash = 0;
3761218822Sdim      unsigned int file_offset;
3762218822Sdim      const char *name;
3763218822Sdim      bfd *element;
376433965Sjdp
3765218822Sdim      h = *pundef;
3766218822Sdim
3767218822Sdim      /* When a symbol is defined, it is not necessarily removed from
3768218822Sdim	 the list.  */
3769218822Sdim      if (h->type != bfd_link_hash_undefined
3770218822Sdim	  && h->type != bfd_link_hash_common)
377133965Sjdp	{
3772218822Sdim	  /* Remove this entry from the list, for general cleanliness
3773218822Sdim	     and because we are going to look through the list again
3774218822Sdim	     if we search any more libraries.  We can't remove the
3775218822Sdim	     entry if it is the tail, because that would lose any
3776218822Sdim	     entries we add to the list later on.  */
3777218822Sdim	  if (*pundef != info->hash->undefs_tail)
3778218822Sdim	    *pundef = (*pundef)->u.undef.next;
3779218822Sdim	  else
3780218822Sdim	    pundef = &(*pundef)->u.undef.next;
3781218822Sdim	  continue;
3782218822Sdim	}
378333965Sjdp
3784218822Sdim      /* Native ECOFF linkers do not pull in archive elements merely
3785218822Sdim	 to satisfy common definitions, so neither do we.  We leave
3786218822Sdim	 them on the list, though, in case we are linking against some
3787218822Sdim	 other object format.  */
3788218822Sdim      if (h->type != bfd_link_hash_undefined)
3789218822Sdim	{
3790218822Sdim	  pundef = &(*pundef)->u.undef.next;
3791218822Sdim	  continue;
379233965Sjdp	}
3793218822Sdim
3794218822Sdim      /* Look for this symbol in the archive hash table.  */
3795218822Sdim      hash = ecoff_armap_hash (h->root.string, &rehash, armap_count,
3796218822Sdim			       armap_log);
3797218822Sdim
3798218822Sdim      file_offset = H_GET_32 (abfd, hashtable + (hash * 8) + 4);
3799218822Sdim      if (file_offset == 0)
380033965Sjdp	{
3801218822Sdim	  /* Nothing in this slot.  */
3802218822Sdim	  pundef = &(*pundef)->u.undef.next;
3803218822Sdim	  continue;
380433965Sjdp	}
380533965Sjdp
3806218822Sdim      name = stringbase + H_GET_32 (abfd, hashtable + (hash * 8));
3807218822Sdim      if (name[0] != h->root.string[0]
3808218822Sdim	  || ! streq (name, h->root.string))
380933965Sjdp	{
3810218822Sdim	  unsigned int srch;
3811218822Sdim	  bfd_boolean found;
3812218822Sdim
3813218822Sdim	  /* That was the wrong symbol.  Try rehashing.  */
3814218822Sdim	  found = FALSE;
3815218822Sdim	  for (srch = (hash + rehash) & (armap_count - 1);
3816218822Sdim	       srch != hash;
3817218822Sdim	       srch = (srch + rehash) & (armap_count - 1))
381833965Sjdp	    {
3819218822Sdim	      file_offset = H_GET_32 (abfd, hashtable + (srch * 8) + 4);
3820218822Sdim	      if (file_offset == 0)
3821218822Sdim		break;
3822218822Sdim	      name = stringbase + H_GET_32 (abfd, hashtable + (srch * 8));
3823218822Sdim	      if (name[0] == h->root.string[0]
3824218822Sdim		  && streq (name, h->root.string))
3825218822Sdim		{
3826218822Sdim		  found = TRUE;
3827218822Sdim		  break;
3828218822Sdim		}
382933965Sjdp	    }
3830218822Sdim
3831218822Sdim	  if (! found)
383233965Sjdp	    {
3833218822Sdim	      pundef = &(*pundef)->u.undef.next;
3834218822Sdim	      continue;
383533965Sjdp	    }
3836218822Sdim
3837218822Sdim	  hash = srch;
383833965Sjdp	}
383933965Sjdp
3840218822Sdim      element = (*backend->get_elt_at_filepos) (abfd, (file_ptr) file_offset);
3841218822Sdim      if (element == NULL)
3842218822Sdim	return FALSE;
384333965Sjdp
3844218822Sdim      if (! bfd_check_format (element, bfd_object))
3845218822Sdim	return FALSE;
384633965Sjdp
3847218822Sdim      /* Unlike the generic linker, we know that this element provides
3848218822Sdim	 a definition for an undefined symbol and we know that we want
3849218822Sdim	 to include it.  We don't need to check anything.  */
3850218822Sdim      if (! (*info->callbacks->add_archive_element) (info, element, name))
3851218822Sdim	return FALSE;
3852218822Sdim      if (! ecoff_link_add_object_symbols (element, info))
3853218822Sdim	return FALSE;
3854218822Sdim
3855218822Sdim      pundef = &(*pundef)->u.undef.next;
3856218822Sdim    }
3857218822Sdim
3858130561Sobrien  return TRUE;
385933965Sjdp}
386033965Sjdp
3861218822Sdim/* Given an ECOFF BFD, add symbols to the global hash table as
3862218822Sdim   appropriate.  */
3863218822Sdim
3864218822Sdimbfd_boolean
3865218822Sdim_bfd_ecoff_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
3866218822Sdim{
3867218822Sdim  switch (bfd_get_format (abfd))
3868218822Sdim    {
3869218822Sdim    case bfd_object:
3870218822Sdim      return ecoff_link_add_object_symbols (abfd, info);
3871218822Sdim    case bfd_archive:
3872218822Sdim      return ecoff_link_add_archive_symbols (abfd, info);
3873218822Sdim    default:
3874218822Sdim      bfd_set_error (bfd_error_wrong_format);
3875218822Sdim      return FALSE;
3876218822Sdim    }
3877218822Sdim}
3878218822Sdim
3879218822Sdim
3880218822Sdim/* ECOFF final link routines.  */
3881218822Sdim
3882218822Sdim/* Structure used to pass information to ecoff_link_write_external.  */
3883218822Sdim
3884218822Sdimstruct extsym_info
3885218822Sdim{
3886218822Sdim  bfd *abfd;
3887218822Sdim  struct bfd_link_info *info;
3888218822Sdim};
3889218822Sdim
389033965Sjdp/* Accumulate the debugging information for an input BFD into the
389133965Sjdp   output BFD.  This must read in the symbolic information of the
389233965Sjdp   input BFD.  */
389333965Sjdp
3894130561Sobrienstatic bfd_boolean
3895218822Sdimecoff_final_link_debug_accumulate (bfd *output_bfd,
3896218822Sdim				   bfd *input_bfd,
3897218822Sdim				   struct bfd_link_info *info,
3898218822Sdim				   void * handle)
389933965Sjdp{
390033965Sjdp  struct ecoff_debug_info * const debug = &ecoff_data (input_bfd)->debug_info;
390133965Sjdp  const struct ecoff_debug_swap * const swap =
390233965Sjdp    &ecoff_backend (input_bfd)->debug_swap;
390333965Sjdp  HDRR *symhdr = &debug->symbolic_header;
3904130561Sobrien  bfd_boolean ret;
390533965Sjdp
390689857Sobrien#define READ(ptr, offset, count, size, type)				 \
390789857Sobrien  if (symhdr->count == 0)						 \
390889857Sobrien    debug->ptr = NULL;							 \
390989857Sobrien  else									 \
391089857Sobrien    {									 \
391189857Sobrien      bfd_size_type amt = (bfd_size_type) size * symhdr->count;		 \
3912218822Sdim      debug->ptr = bfd_malloc (amt);					 \
391389857Sobrien      if (debug->ptr == NULL)						 \
391489857Sobrien	{								 \
3915130561Sobrien          ret = FALSE;							 \
391689857Sobrien          goto return_something;					 \
391789857Sobrien	}								 \
391889857Sobrien      if (bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
391989857Sobrien	  || bfd_bread (debug->ptr, amt, input_bfd) != amt)		 \
392089857Sobrien	{								 \
3921130561Sobrien          ret = FALSE;							 \
392289857Sobrien          goto return_something;					 \
392389857Sobrien	}								 \
392433965Sjdp    }
392533965Sjdp
392633965Sjdp  /* If raw_syments is not NULL, then the data was already by read by
392733965Sjdp     _bfd_ecoff_slurp_symbolic_info.  */
392833965Sjdp  if (ecoff_data (input_bfd)->raw_syments == NULL)
392933965Sjdp    {
393033965Sjdp      READ (line, cbLineOffset, cbLine, sizeof (unsigned char),
393133965Sjdp	    unsigned char *);
3932218822Sdim      READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
3933218822Sdim      READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
3934218822Sdim      READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
3935218822Sdim      READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
393633965Sjdp      READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
393733965Sjdp	    union aux_ext *);
393833965Sjdp      READ (ss, cbSsOffset, issMax, sizeof (char), char *);
3939218822Sdim      READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
3940218822Sdim      READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
394133965Sjdp    }
394233965Sjdp#undef READ
394333965Sjdp
394433965Sjdp  /* We do not read the external strings or the external symbols.  */
394533965Sjdp
394633965Sjdp  ret = (bfd_ecoff_debug_accumulate
394733965Sjdp	 (handle, output_bfd, &ecoff_data (output_bfd)->debug_info,
394833965Sjdp	  &ecoff_backend (output_bfd)->debug_swap,
394933965Sjdp	  input_bfd, debug, swap, info));
395033965Sjdp
395133965Sjdp return_something:
395233965Sjdp  if (ecoff_data (input_bfd)->raw_syments == NULL)
395333965Sjdp    {
395433965Sjdp      if (debug->line != NULL)
395533965Sjdp	free (debug->line);
395633965Sjdp      if (debug->external_dnr != NULL)
395733965Sjdp	free (debug->external_dnr);
395833965Sjdp      if (debug->external_pdr != NULL)
395933965Sjdp	free (debug->external_pdr);
396033965Sjdp      if (debug->external_sym != NULL)
396133965Sjdp	free (debug->external_sym);
396233965Sjdp      if (debug->external_opt != NULL)
396333965Sjdp	free (debug->external_opt);
396433965Sjdp      if (debug->external_aux != NULL)
396533965Sjdp	free (debug->external_aux);
396633965Sjdp      if (debug->ss != NULL)
396733965Sjdp	free (debug->ss);
396833965Sjdp      if (debug->external_fdr != NULL)
396933965Sjdp	free (debug->external_fdr);
397033965Sjdp      if (debug->external_rfd != NULL)
397133965Sjdp	free (debug->external_rfd);
397233965Sjdp
397333965Sjdp      /* Make sure we don't accidentally follow one of these pointers
397433965Sjdp	 into freed memory.  */
397533965Sjdp      debug->line = NULL;
397633965Sjdp      debug->external_dnr = NULL;
397733965Sjdp      debug->external_pdr = NULL;
397833965Sjdp      debug->external_sym = NULL;
397933965Sjdp      debug->external_opt = NULL;
398033965Sjdp      debug->external_aux = NULL;
398133965Sjdp      debug->ss = NULL;
398233965Sjdp      debug->external_fdr = NULL;
398333965Sjdp      debug->external_rfd = NULL;
398433965Sjdp    }
398533965Sjdp
398633965Sjdp  return ret;
398733965Sjdp}
398833965Sjdp
398933965Sjdp/* Relocate and write an ECOFF section into an ECOFF output file.  */
399033965Sjdp
3991130561Sobrienstatic bfd_boolean
3992218822Sdimecoff_indirect_link_order (bfd *output_bfd,
3993218822Sdim			   struct bfd_link_info *info,
3994218822Sdim			   asection *output_section,
3995218822Sdim			   struct bfd_link_order *link_order)
399633965Sjdp{
399733965Sjdp  asection *input_section;
399833965Sjdp  bfd *input_bfd;
399933965Sjdp  bfd_byte *contents = NULL;
400033965Sjdp  bfd_size_type external_reloc_size;
400133965Sjdp  bfd_size_type external_relocs_size;
4002218822Sdim  void * external_relocs = NULL;
400333965Sjdp
400433965Sjdp  BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
400533965Sjdp
400633965Sjdp  input_section = link_order->u.indirect.section;
400733965Sjdp  input_bfd = input_section->owner;
4008218822Sdim  if (input_section->size == 0)
4009218822Sdim    return TRUE;
401033965Sjdp
401133965Sjdp  BFD_ASSERT (input_section->output_section == output_section);
401233965Sjdp  BFD_ASSERT (input_section->output_offset == link_order->offset);
4013218822Sdim  BFD_ASSERT (input_section->size == link_order->size);
401433965Sjdp
4015218822Sdim  /* Get the section contents.  */
4016218822Sdim  if (!bfd_malloc_and_get_section (input_bfd, input_section, &contents))
401733965Sjdp    goto error_return;
401833965Sjdp
401933965Sjdp  /* Get the relocs.  If we are relaxing MIPS code, they will already
402033965Sjdp     have been read in.  Otherwise, we read them in now.  */
402133965Sjdp  external_reloc_size = ecoff_backend (input_bfd)->external_reloc_size;
402233965Sjdp  external_relocs_size = external_reloc_size * input_section->reloc_count;
402333965Sjdp
4024218822Sdim  external_relocs = bfd_malloc (external_relocs_size);
4025218822Sdim  if (external_relocs == NULL && external_relocs_size != 0)
4026218822Sdim    goto error_return;
402733965Sjdp
4028218822Sdim  if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
4029218822Sdim      || (bfd_bread (external_relocs, external_relocs_size, input_bfd)
4030218822Sdim	  != external_relocs_size))
4031218822Sdim    goto error_return;
403233965Sjdp
403333965Sjdp  /* Relocate the section contents.  */
403433965Sjdp  if (! ((*ecoff_backend (input_bfd)->relocate_section)
403533965Sjdp	 (output_bfd, info, input_bfd, input_section, contents,
403633965Sjdp	  external_relocs)))
403733965Sjdp    goto error_return;
403833965Sjdp
403933965Sjdp  /* Write out the relocated section.  */
404033965Sjdp  if (! bfd_set_section_contents (output_bfd,
404133965Sjdp				  output_section,
4042218822Sdim				  contents,
4043218822Sdim				  input_section->output_offset,
4044218822Sdim				  input_section->size))
404533965Sjdp    goto error_return;
404633965Sjdp
4047130561Sobrien  /* If we are producing relocatable output, the relocs were
404833965Sjdp     modified, and we write them out now.  We use the reloc_count
404933965Sjdp     field of output_section to keep track of the number of relocs we
405033965Sjdp     have output so far.  */
4051130561Sobrien  if (info->relocatable)
405233965Sjdp    {
405389857Sobrien      file_ptr pos = (output_section->rel_filepos
405489857Sobrien		      + output_section->reloc_count * external_reloc_size);
405589857Sobrien      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
405689857Sobrien	  || (bfd_bwrite (external_relocs, external_relocs_size, output_bfd)
405733965Sjdp	      != external_relocs_size))
405833965Sjdp	goto error_return;
405933965Sjdp      output_section->reloc_count += input_section->reloc_count;
406033965Sjdp    }
406133965Sjdp
406233965Sjdp  if (contents != NULL)
406333965Sjdp    free (contents);
4064218822Sdim  if (external_relocs != NULL)
406533965Sjdp    free (external_relocs);
4066130561Sobrien  return TRUE;
406733965Sjdp
406833965Sjdp error_return:
406933965Sjdp  if (contents != NULL)
407033965Sjdp    free (contents);
4071218822Sdim  if (external_relocs != NULL)
407233965Sjdp    free (external_relocs);
4073130561Sobrien  return FALSE;
407433965Sjdp}
407533965Sjdp
407633965Sjdp/* Generate a reloc when linking an ECOFF file.  This is a reloc
407733965Sjdp   requested by the linker, and does come from any input file.  This
407833965Sjdp   is used to build constructor and destructor tables when linking
407933965Sjdp   with -Ur.  */
408033965Sjdp
4081130561Sobrienstatic bfd_boolean
4082218822Sdimecoff_reloc_link_order (bfd *output_bfd,
4083218822Sdim			struct bfd_link_info *info,
4084218822Sdim			asection *output_section,
4085218822Sdim			struct bfd_link_order *link_order)
408633965Sjdp{
408733965Sjdp  enum bfd_link_order_type type;
408833965Sjdp  asection *section;
408933965Sjdp  bfd_vma addend;
409033965Sjdp  arelent rel;
409133965Sjdp  struct internal_reloc in;
409233965Sjdp  bfd_size_type external_reloc_size;
409333965Sjdp  bfd_byte *rbuf;
4094130561Sobrien  bfd_boolean ok;
409589857Sobrien  file_ptr pos;
409633965Sjdp
409733965Sjdp  type = link_order->type;
409833965Sjdp  section = NULL;
409933965Sjdp  addend = link_order->u.reloc.p->addend;
410033965Sjdp
410133965Sjdp  /* We set up an arelent to pass to the backend adjust_reloc_out
410233965Sjdp     routine.  */
410333965Sjdp  rel.address = link_order->offset;
410433965Sjdp
410533965Sjdp  rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
410633965Sjdp  if (rel.howto == 0)
410733965Sjdp    {
410833965Sjdp      bfd_set_error (bfd_error_bad_value);
4109130561Sobrien      return FALSE;
411033965Sjdp    }
411133965Sjdp
411233965Sjdp  if (type == bfd_section_reloc_link_order)
411333965Sjdp    {
411433965Sjdp      section = link_order->u.reloc.p->u.section;
411533965Sjdp      rel.sym_ptr_ptr = section->symbol_ptr_ptr;
411633965Sjdp    }
411733965Sjdp  else
411833965Sjdp    {
411933965Sjdp      struct bfd_link_hash_entry *h;
412033965Sjdp
412133965Sjdp      /* Treat a reloc against a defined symbol as though it were
412233965Sjdp         actually against the section.  */
412333965Sjdp      h = bfd_wrapped_link_hash_lookup (output_bfd, info,
412433965Sjdp					link_order->u.reloc.p->u.name,
4125130561Sobrien					FALSE, FALSE, FALSE);
412633965Sjdp      if (h != NULL
412733965Sjdp	  && (h->type == bfd_link_hash_defined
412833965Sjdp	      || h->type == bfd_link_hash_defweak))
412933965Sjdp	{
413033965Sjdp	  type = bfd_section_reloc_link_order;
413133965Sjdp	  section = h->u.def.section->output_section;
413233965Sjdp	  /* It seems that we ought to add the symbol value to the
413333965Sjdp             addend here, but in practice it has already been added
413433965Sjdp             because it was passed to constructor_callback.  */
413533965Sjdp	  addend += section->vma + h->u.def.section->output_offset;
413633965Sjdp	}
413733965Sjdp      else
413833965Sjdp	{
413933965Sjdp	  /* We can't set up a reloc against a symbol correctly,
414033965Sjdp	     because we have no asymbol structure.  Currently no
414133965Sjdp	     adjust_reloc_out routine cares.  */
4142218822Sdim	  rel.sym_ptr_ptr = NULL;
414333965Sjdp	}
414433965Sjdp    }
414533965Sjdp
414633965Sjdp  /* All ECOFF relocs are in-place.  Put the addend into the object
414733965Sjdp     file.  */
414833965Sjdp
414933965Sjdp  BFD_ASSERT (rel.howto->partial_inplace);
415033965Sjdp  if (addend != 0)
415133965Sjdp    {
415233965Sjdp      bfd_size_type size;
415333965Sjdp      bfd_reloc_status_type rstat;
415433965Sjdp      bfd_byte *buf;
415533965Sjdp
415633965Sjdp      size = bfd_get_reloc_size (rel.howto);
4157218822Sdim      buf = bfd_zmalloc (size);
4158218822Sdim      if (buf == NULL)
4159130561Sobrien	return FALSE;
416089857Sobrien      rstat = _bfd_relocate_contents (rel.howto, output_bfd,
416189857Sobrien				      (bfd_vma) addend, buf);
416233965Sjdp      switch (rstat)
416333965Sjdp	{
416433965Sjdp	case bfd_reloc_ok:
416533965Sjdp	  break;
416633965Sjdp	default:
416733965Sjdp	case bfd_reloc_outofrange:
416833965Sjdp	  abort ();
416933965Sjdp	case bfd_reloc_overflow:
417033965Sjdp	  if (! ((*info->callbacks->reloc_overflow)
4171218822Sdim		 (info, NULL,
417233965Sjdp		  (link_order->type == bfd_section_reloc_link_order
417333965Sjdp		   ? bfd_section_name (output_bfd, section)
417433965Sjdp		   : link_order->u.reloc.p->u.name),
4175218822Sdim		  rel.howto->name, addend, NULL,
4176218822Sdim		  NULL, (bfd_vma) 0)))
417733965Sjdp	    {
417833965Sjdp	      free (buf);
4179130561Sobrien	      return FALSE;
418033965Sjdp	    }
418133965Sjdp	  break;
418233965Sjdp	}
4183218822Sdim      ok = bfd_set_section_contents (output_bfd, output_section, (void *) buf,
418433965Sjdp				     (file_ptr) link_order->offset, size);
418533965Sjdp      free (buf);
418633965Sjdp      if (! ok)
4187130561Sobrien	return FALSE;
418833965Sjdp    }
418933965Sjdp
419033965Sjdp  rel.addend = 0;
419133965Sjdp
419289857Sobrien  /* Move the information into an internal_reloc structure.  */
419333965Sjdp  in.r_vaddr = (rel.address
419433965Sjdp		+ bfd_get_section_vma (output_bfd, output_section));
419533965Sjdp  in.r_type = rel.howto->type;
419633965Sjdp
419733965Sjdp  if (type == bfd_symbol_reloc_link_order)
419833965Sjdp    {
419933965Sjdp      struct ecoff_link_hash_entry *h;
420033965Sjdp
420133965Sjdp      h = ((struct ecoff_link_hash_entry *)
420233965Sjdp	   bfd_wrapped_link_hash_lookup (output_bfd, info,
420333965Sjdp					 link_order->u.reloc.p->u.name,
4204130561Sobrien					 FALSE, FALSE, TRUE));
4205218822Sdim      if (h != NULL
420633965Sjdp	  && h->indx != -1)
420733965Sjdp	in.r_symndx = h->indx;
420833965Sjdp      else
420933965Sjdp	{
421033965Sjdp	  if (! ((*info->callbacks->unattached_reloc)
4211218822Sdim		 (info, link_order->u.reloc.p->u.name, NULL,
4212218822Sdim		  NULL, (bfd_vma) 0)))
4213130561Sobrien	    return FALSE;
421433965Sjdp	  in.r_symndx = 0;
421533965Sjdp	}
421633965Sjdp      in.r_extern = 1;
421733965Sjdp    }
421833965Sjdp  else
421933965Sjdp    {
422089857Sobrien      const char *name;
4221218822Sdim      unsigned int i;
4222218822Sdim      static struct
4223218822Sdim      {
4224218822Sdim	const char * name;
4225218822Sdim	long r_symndx;
4226218822Sdim      }
4227218822Sdim      section_symndx [] =
4228218822Sdim      {
4229218822Sdim	{ _TEXT,   RELOC_SECTION_TEXT   },
4230218822Sdim	{ _RDATA,  RELOC_SECTION_RDATA  },
4231218822Sdim	{ _DATA,   RELOC_SECTION_DATA   },
4232218822Sdim	{ _SDATA,  RELOC_SECTION_SDATA  },
4233218822Sdim	{ _SBSS,   RELOC_SECTION_SBSS   },
4234218822Sdim	{ _BSS,    RELOC_SECTION_BSS    },
4235218822Sdim	{ _INIT,   RELOC_SECTION_INIT   },
4236218822Sdim	{ _LIT8,   RELOC_SECTION_LIT8   },
4237218822Sdim	{ _LIT4,   RELOC_SECTION_LIT4   },
4238218822Sdim	{ _XDATA,  RELOC_SECTION_XDATA  },
4239218822Sdim	{ _PDATA,  RELOC_SECTION_PDATA  },
4240218822Sdim	{ _FINI,   RELOC_SECTION_FINI   },
4241218822Sdim	{ _LITA,   RELOC_SECTION_LITA   },
4242218822Sdim	{ "*ABS*", RELOC_SECTION_ABS    },
4243218822Sdim	{ _RCONST, RELOC_SECTION_RCONST }
4244218822Sdim      };
424533965Sjdp
424633965Sjdp      name = bfd_get_section_name (output_bfd, section);
4247218822Sdim
4248218822Sdim      for (i = 0; i < ARRAY_SIZE (section_symndx); i++)
4249218822Sdim	if (streq (name, section_symndx[i].name))
4250218822Sdim	  {
4251218822Sdim	    in.r_symndx = section_symndx[i].r_symndx;
4252218822Sdim	    break;
4253218822Sdim	  }
4254218822Sdim
4255218822Sdim      if (i == ARRAY_SIZE (section_symndx))
425633965Sjdp	abort ();
4257218822Sdim
425833965Sjdp      in.r_extern = 0;
425933965Sjdp    }
426033965Sjdp
426133965Sjdp  /* Let the BFD backend adjust the reloc.  */
426233965Sjdp  (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in);
426333965Sjdp
426433965Sjdp  /* Get some memory and swap out the reloc.  */
426533965Sjdp  external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size;
4266218822Sdim  rbuf = bfd_malloc (external_reloc_size);
4267218822Sdim  if (rbuf == NULL)
4268130561Sobrien    return FALSE;
426933965Sjdp
4270218822Sdim  (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (void *) rbuf);
427133965Sjdp
427289857Sobrien  pos = (output_section->rel_filepos
427389857Sobrien	 + output_section->reloc_count * external_reloc_size);
427489857Sobrien  ok = (bfd_seek (output_bfd, pos, SEEK_SET) == 0
4275218822Sdim	&& (bfd_bwrite ((void *) rbuf, external_reloc_size, output_bfd)
427633965Sjdp	    == external_reloc_size));
427733965Sjdp
427833965Sjdp  if (ok)
427933965Sjdp    ++output_section->reloc_count;
428033965Sjdp
428133965Sjdp  free (rbuf);
428233965Sjdp
428333965Sjdp  return ok;
428433965Sjdp}
4285218822Sdim
4286218822Sdim/* Put out information for an external symbol.  These come only from
4287218822Sdim   the hash table.  */
4288218822Sdim
4289218822Sdimstatic bfd_boolean
4290218822Sdimecoff_link_write_external (struct ecoff_link_hash_entry *h, void * data)
4291218822Sdim{
4292218822Sdim  struct extsym_info *einfo = (struct extsym_info *) data;
4293218822Sdim  bfd *output_bfd = einfo->abfd;
4294218822Sdim  bfd_boolean strip;
4295218822Sdim
4296218822Sdim  if (h->root.type == bfd_link_hash_warning)
4297218822Sdim    {
4298218822Sdim      h = (struct ecoff_link_hash_entry *) h->root.u.i.link;
4299218822Sdim      if (h->root.type == bfd_link_hash_new)
4300218822Sdim	return TRUE;
4301218822Sdim    }
4302218822Sdim
4303218822Sdim  /* We need to check if this symbol is being stripped.  */
4304218822Sdim  if (h->root.type == bfd_link_hash_undefined
4305218822Sdim      || h->root.type == bfd_link_hash_undefweak)
4306218822Sdim    strip = FALSE;
4307218822Sdim  else if (einfo->info->strip == strip_all
4308218822Sdim	   || (einfo->info->strip == strip_some
4309218822Sdim	       && bfd_hash_lookup (einfo->info->keep_hash,
4310218822Sdim				   h->root.root.string,
4311218822Sdim				   FALSE, FALSE) == NULL))
4312218822Sdim    strip = TRUE;
4313218822Sdim  else
4314218822Sdim    strip = FALSE;
4315218822Sdim
4316218822Sdim  if (strip || h->written)
4317218822Sdim    return TRUE;
4318218822Sdim
4319218822Sdim  if (h->abfd == NULL)
4320218822Sdim    {
4321218822Sdim      h->esym.jmptbl = 0;
4322218822Sdim      h->esym.cobol_main = 0;
4323218822Sdim      h->esym.weakext = 0;
4324218822Sdim      h->esym.reserved = 0;
4325218822Sdim      h->esym.ifd = ifdNil;
4326218822Sdim      h->esym.asym.value = 0;
4327218822Sdim      h->esym.asym.st = stGlobal;
4328218822Sdim
4329218822Sdim      if (h->root.type != bfd_link_hash_defined
4330218822Sdim	  && h->root.type != bfd_link_hash_defweak)
4331218822Sdim	h->esym.asym.sc = scAbs;
4332218822Sdim      else
4333218822Sdim	{
4334218822Sdim	  asection *output_section;
4335218822Sdim	  const char *name;
4336218822Sdim	  unsigned int i;
4337218822Sdim	  static struct
4338218822Sdim	  {
4339218822Sdim	    const char * name;
4340218822Sdim	    int sc;
4341218822Sdim	  }
4342218822Sdim	  section_storage_classes [] =
4343218822Sdim	  {
4344218822Sdim	    { _TEXT,   scText   },
4345218822Sdim	    { _DATA,   scData   },
4346218822Sdim	    { _SDATA,  scSData  },
4347218822Sdim	    { _RDATA,  scRData  },
4348218822Sdim	    { _BSS,    scBss    },
4349218822Sdim	    { _SBSS,   scSBss   },
4350218822Sdim	    { _INIT,   scInit   },
4351218822Sdim	    { _FINI,   scFini   },
4352218822Sdim	    { _PDATA,  scPData  },
4353218822Sdim	    { _XDATA,  scXData  },
4354218822Sdim	    { _RCONST, scRConst }
4355218822Sdim	  };
4356218822Sdim
4357218822Sdim	  output_section = h->root.u.def.section->output_section;
4358218822Sdim	  name = bfd_section_name (output_section->owner, output_section);
4359218822Sdim
4360218822Sdim	  for (i = 0; i < ARRAY_SIZE (section_storage_classes); i++)
4361218822Sdim	    if (streq (name, section_storage_classes[i].name))
4362218822Sdim	      {
4363218822Sdim		h->esym.asym.sc = section_storage_classes[i].sc;
4364218822Sdim		break;
4365218822Sdim	      }
4366218822Sdim
4367218822Sdim	  if (i == ARRAY_SIZE (section_storage_classes))
4368218822Sdim	    h->esym.asym.sc = scAbs;
4369218822Sdim	}
4370218822Sdim
4371218822Sdim      h->esym.asym.reserved = 0;
4372218822Sdim      h->esym.asym.index = indexNil;
4373218822Sdim    }
4374218822Sdim  else if (h->esym.ifd != -1)
4375218822Sdim    {
4376218822Sdim      struct ecoff_debug_info *debug;
4377218822Sdim
4378218822Sdim      /* Adjust the FDR index for the symbol by that used for the
4379218822Sdim	 input BFD.  */
4380218822Sdim      debug = &ecoff_data (h->abfd)->debug_info;
4381218822Sdim      BFD_ASSERT (h->esym.ifd >= 0
4382218822Sdim		  && h->esym.ifd < debug->symbolic_header.ifdMax);
4383218822Sdim      h->esym.ifd = debug->ifdmap[h->esym.ifd];
4384218822Sdim    }
4385218822Sdim
4386218822Sdim  switch (h->root.type)
4387218822Sdim    {
4388218822Sdim    default:
4389218822Sdim    case bfd_link_hash_warning:
4390218822Sdim    case bfd_link_hash_new:
4391218822Sdim      abort ();
4392218822Sdim    case bfd_link_hash_undefined:
4393218822Sdim    case bfd_link_hash_undefweak:
4394218822Sdim      if (h->esym.asym.sc != scUndefined
4395218822Sdim	  && h->esym.asym.sc != scSUndefined)
4396218822Sdim	h->esym.asym.sc = scUndefined;
4397218822Sdim      break;
4398218822Sdim    case bfd_link_hash_defined:
4399218822Sdim    case bfd_link_hash_defweak:
4400218822Sdim      if (h->esym.asym.sc == scUndefined
4401218822Sdim	  || h->esym.asym.sc == scSUndefined)
4402218822Sdim	h->esym.asym.sc = scAbs;
4403218822Sdim      else if (h->esym.asym.sc == scCommon)
4404218822Sdim	h->esym.asym.sc = scBss;
4405218822Sdim      else if (h->esym.asym.sc == scSCommon)
4406218822Sdim	h->esym.asym.sc = scSBss;
4407218822Sdim      h->esym.asym.value = (h->root.u.def.value
4408218822Sdim			    + h->root.u.def.section->output_section->vma
4409218822Sdim			    + h->root.u.def.section->output_offset);
4410218822Sdim      break;
4411218822Sdim    case bfd_link_hash_common:
4412218822Sdim      if (h->esym.asym.sc != scCommon
4413218822Sdim	  && h->esym.asym.sc != scSCommon)
4414218822Sdim	h->esym.asym.sc = scCommon;
4415218822Sdim      h->esym.asym.value = h->root.u.c.size;
4416218822Sdim      break;
4417218822Sdim    case bfd_link_hash_indirect:
4418218822Sdim      /* We ignore these symbols, since the indirected symbol is
4419218822Sdim	 already in the hash table.  */
4420218822Sdim      return TRUE;
4421218822Sdim    }
4422218822Sdim
4423218822Sdim  /* bfd_ecoff_debug_one_external uses iextMax to keep track of the
4424218822Sdim     symbol number.  */
4425218822Sdim  h->indx = ecoff_data (output_bfd)->debug_info.symbolic_header.iextMax;
4426218822Sdim  h->written = 1;
4427218822Sdim
4428218822Sdim  return (bfd_ecoff_debug_one_external
4429218822Sdim	  (output_bfd, &ecoff_data (output_bfd)->debug_info,
4430218822Sdim	   &ecoff_backend (output_bfd)->debug_swap, h->root.root.string,
4431218822Sdim	   &h->esym));
4432218822Sdim}
4433218822Sdim
4434218822Sdim/* ECOFF final link routine.  This looks through all the input BFDs
4435218822Sdim   and gathers together all the debugging information, and then
4436218822Sdim   processes all the link order information.  This may cause it to
4437218822Sdim   close and reopen some input BFDs; I'll see how bad this is.  */
4438218822Sdim
4439218822Sdimbfd_boolean
4440218822Sdim_bfd_ecoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
4441218822Sdim{
4442218822Sdim  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
4443218822Sdim  struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info;
4444218822Sdim  HDRR *symhdr;
4445218822Sdim  void * handle;
4446218822Sdim  bfd *input_bfd;
4447218822Sdim  asection *o;
4448218822Sdim  struct bfd_link_order *p;
4449218822Sdim  struct extsym_info einfo;
4450218822Sdim
4451218822Sdim  /* We accumulate the debugging information counts in the symbolic
4452218822Sdim     header.  */
4453218822Sdim  symhdr = &debug->symbolic_header;
4454218822Sdim  symhdr->vstamp = 0;
4455218822Sdim  symhdr->ilineMax = 0;
4456218822Sdim  symhdr->cbLine = 0;
4457218822Sdim  symhdr->idnMax = 0;
4458218822Sdim  symhdr->ipdMax = 0;
4459218822Sdim  symhdr->isymMax = 0;
4460218822Sdim  symhdr->ioptMax = 0;
4461218822Sdim  symhdr->iauxMax = 0;
4462218822Sdim  symhdr->issMax = 0;
4463218822Sdim  symhdr->issExtMax = 0;
4464218822Sdim  symhdr->ifdMax = 0;
4465218822Sdim  symhdr->crfd = 0;
4466218822Sdim  symhdr->iextMax = 0;
4467218822Sdim
4468218822Sdim  /* We accumulate the debugging information itself in the debug_info
4469218822Sdim     structure.  */
4470218822Sdim  debug->line = NULL;
4471218822Sdim  debug->external_dnr = NULL;
4472218822Sdim  debug->external_pdr = NULL;
4473218822Sdim  debug->external_sym = NULL;
4474218822Sdim  debug->external_opt = NULL;
4475218822Sdim  debug->external_aux = NULL;
4476218822Sdim  debug->ss = NULL;
4477218822Sdim  debug->ssext = debug->ssext_end = NULL;
4478218822Sdim  debug->external_fdr = NULL;
4479218822Sdim  debug->external_rfd = NULL;
4480218822Sdim  debug->external_ext = debug->external_ext_end = NULL;
4481218822Sdim
4482218822Sdim  handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info);
4483218822Sdim  if (handle == NULL)
4484218822Sdim    return FALSE;
4485218822Sdim
4486218822Sdim  /* Accumulate the debugging symbols from each input BFD.  */
4487218822Sdim  for (input_bfd = info->input_bfds;
4488218822Sdim       input_bfd != NULL;
4489218822Sdim       input_bfd = input_bfd->link_next)
4490218822Sdim    {
4491218822Sdim      bfd_boolean ret;
4492218822Sdim
4493218822Sdim      if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour)
4494218822Sdim	{
4495218822Sdim	  /* Arbitrarily set the symbolic header vstamp to the vstamp
4496218822Sdim	     of the first object file in the link.  */
4497218822Sdim	  if (symhdr->vstamp == 0)
4498218822Sdim	    symhdr->vstamp
4499218822Sdim	      = ecoff_data (input_bfd)->debug_info.symbolic_header.vstamp;
4500218822Sdim	  ret = ecoff_final_link_debug_accumulate (abfd, input_bfd, info,
4501218822Sdim						   handle);
4502218822Sdim	}
4503218822Sdim      else
4504218822Sdim	ret = bfd_ecoff_debug_accumulate_other (handle, abfd,
4505218822Sdim						debug, &backend->debug_swap,
4506218822Sdim						input_bfd, info);
4507218822Sdim      if (! ret)
4508218822Sdim	return FALSE;
4509218822Sdim
4510218822Sdim      /* Combine the register masks.  */
4511218822Sdim      ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask;
4512218822Sdim      ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask;
4513218822Sdim      ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0];
4514218822Sdim      ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1];
4515218822Sdim      ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2];
4516218822Sdim      ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3];
4517218822Sdim    }
4518218822Sdim
4519218822Sdim  /* Write out the external symbols.  */
4520218822Sdim  einfo.abfd = abfd;
4521218822Sdim  einfo.info = info;
4522218822Sdim  ecoff_link_hash_traverse (ecoff_hash_table (info),
4523218822Sdim			    ecoff_link_write_external,
4524218822Sdim			    (void *) &einfo);
4525218822Sdim
4526218822Sdim  if (info->relocatable)
4527218822Sdim    {
4528218822Sdim      /* We need to make a pass over the link_orders to count up the
4529218822Sdim	 number of relocations we will need to output, so that we know
4530218822Sdim	 how much space they will take up.  */
4531218822Sdim      for (o = abfd->sections; o != NULL; o = o->next)
4532218822Sdim	{
4533218822Sdim	  o->reloc_count = 0;
4534218822Sdim	  for (p = o->map_head.link_order;
4535218822Sdim	       p != NULL;
4536218822Sdim	       p = p->next)
4537218822Sdim	    if (p->type == bfd_indirect_link_order)
4538218822Sdim	      o->reloc_count += p->u.indirect.section->reloc_count;
4539218822Sdim	    else if (p->type == bfd_section_reloc_link_order
4540218822Sdim		     || p->type == bfd_symbol_reloc_link_order)
4541218822Sdim	      ++o->reloc_count;
4542218822Sdim	}
4543218822Sdim    }
4544218822Sdim
4545218822Sdim  /* Compute the reloc and symbol file positions.  */
4546218822Sdim  ecoff_compute_reloc_file_positions (abfd);
4547218822Sdim
4548218822Sdim  /* Write out the debugging information.  */
4549218822Sdim  if (! bfd_ecoff_write_accumulated_debug (handle, abfd, debug,
4550218822Sdim					   &backend->debug_swap, info,
4551218822Sdim					   ecoff_data (abfd)->sym_filepos))
4552218822Sdim    return FALSE;
4553218822Sdim
4554218822Sdim  bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info);
4555218822Sdim
4556218822Sdim  if (info->relocatable)
4557218822Sdim    {
4558218822Sdim      /* Now reset the reloc_count field of the sections in the output
4559218822Sdim	 BFD to 0, so that we can use them to keep track of how many
4560218822Sdim	 relocs we have output thus far.  */
4561218822Sdim      for (o = abfd->sections; o != NULL; o = o->next)
4562218822Sdim	o->reloc_count = 0;
4563218822Sdim    }
4564218822Sdim
4565218822Sdim  /* Get a value for the GP register.  */
4566218822Sdim  if (ecoff_data (abfd)->gp == 0)
4567218822Sdim    {
4568218822Sdim      struct bfd_link_hash_entry *h;
4569218822Sdim
4570218822Sdim      h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
4571218822Sdim      if (h != NULL
4572218822Sdim	  && h->type == bfd_link_hash_defined)
4573218822Sdim	ecoff_data (abfd)->gp = (h->u.def.value
4574218822Sdim				 + h->u.def.section->output_section->vma
4575218822Sdim				 + h->u.def.section->output_offset);
4576218822Sdim      else if (info->relocatable)
4577218822Sdim	{
4578218822Sdim	  bfd_vma lo;
4579218822Sdim
4580218822Sdim	  /* Make up a value.  */
4581218822Sdim	  lo = (bfd_vma) -1;
4582218822Sdim	  for (o = abfd->sections; o != NULL; o = o->next)
4583218822Sdim	    {
4584218822Sdim	      if (o->vma < lo
4585218822Sdim		  && (streq (o->name, _SBSS)
4586218822Sdim		      || streq (o->name, _SDATA)
4587218822Sdim		      || streq (o->name, _LIT4)
4588218822Sdim		      || streq (o->name, _LIT8)
4589218822Sdim		      || streq (o->name, _LITA)))
4590218822Sdim		lo = o->vma;
4591218822Sdim	    }
4592218822Sdim	  ecoff_data (abfd)->gp = lo + 0x8000;
4593218822Sdim	}
4594218822Sdim      else
4595218822Sdim	{
4596218822Sdim	  /* If the relocate_section function needs to do a reloc
4597218822Sdim	     involving the GP value, it should make a reloc_dangerous
4598218822Sdim	     callback to warn that GP is not defined.  */
4599218822Sdim	}
4600218822Sdim    }
4601218822Sdim
4602218822Sdim  for (o = abfd->sections; o != NULL; o = o->next)
4603218822Sdim    {
4604218822Sdim      for (p = o->map_head.link_order;
4605218822Sdim	   p != NULL;
4606218822Sdim	   p = p->next)
4607218822Sdim	{
4608218822Sdim	  if (p->type == bfd_indirect_link_order
4609218822Sdim	      && (bfd_get_flavour (p->u.indirect.section->owner)
4610218822Sdim		  == bfd_target_ecoff_flavour))
4611218822Sdim	    {
4612218822Sdim	      if (! ecoff_indirect_link_order (abfd, info, o, p))
4613218822Sdim		return FALSE;
4614218822Sdim	    }
4615218822Sdim	  else if (p->type == bfd_section_reloc_link_order
4616218822Sdim		   || p->type == bfd_symbol_reloc_link_order)
4617218822Sdim	    {
4618218822Sdim	      if (! ecoff_reloc_link_order (abfd, info, o, p))
4619218822Sdim		return FALSE;
4620218822Sdim	    }
4621218822Sdim	  else
4622218822Sdim	    {
4623218822Sdim	      if (! _bfd_default_link_order (abfd, info, o, p))
4624218822Sdim		return FALSE;
4625218822Sdim	    }
4626218822Sdim	}
4627218822Sdim    }
4628218822Sdim
4629218822Sdim  bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax;
4630218822Sdim
4631218822Sdim  ecoff_data (abfd)->linker = TRUE;
4632218822Sdim
4633218822Sdim  return TRUE;
4634218822Sdim}
4635