133965Sjdp/* A.out "format 1" file handling code for BFD.
289857Sobrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
3218822Sdim   2001, 2002, 2003, 2004, 2005, 2006, 2007
438889Sjdp   Free Software Foundation, Inc.
533965Sjdp   Written by Cygnus Support.
633965Sjdp
7218822Sdim   This file is part of BFD, the Binary File Descriptor library.
833965Sjdp
9218822Sdim   This program is free software; you can redistribute it and/or modify
10218822Sdim   it under the terms of the GNU General Public License as published by
11218822Sdim   the Free Software Foundation; either version 2 of the License, or
12218822Sdim   (at your option) any later version.
1333965Sjdp
14218822Sdim   This program is distributed in the hope that it will be useful,
15218822Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
16218822Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17218822Sdim   GNU General Public License for more details.
1833965Sjdp
19218822Sdim   You should have received a copy of the GNU General Public License
20218822Sdim   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 "libbfd.h"
2633965Sjdp
2733965Sjdp#include "aout/sun4.h"
28218822Sdim#include "libaout.h"		/* BFD a.out internal data structures.  */
2933965Sjdp
3033965Sjdp#include "aout/aout64.h"
3133965Sjdp#include "aout/stab_gnu.h"
3233965Sjdp#include "aout/ar.h"
3333965Sjdp
3433965Sjdp/* This is needed to reject a NewsOS file, e.g. in
3533965Sjdp   gdb/testsuite/gdb.t10/crossload.exp. <kingdon@cygnus.com>
3633965Sjdp   I needed to add M_UNKNOWN to recognize a 68000 object, so this will
3777298Sobrien   probably no longer reject a NewsOS object.  <ian@cygnus.com>.  */
3833965Sjdp#ifndef MACHTYPE_OK
3933965Sjdp#define MACHTYPE_OK(mtype) \
4033965Sjdp  (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \
4133965Sjdp   || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \
4233965Sjdp       && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))
4333965Sjdp#endif
4433965Sjdp
45218822Sdim/* The file @code{aoutf1.h} contains the code for BFD's
46218822Sdim   a.out back end.  Control over the generated back end is given by these
47218822Sdim   two preprocessor names:
48218822Sdim   @table @code
49218822Sdim   @item ARCH_SIZE
50218822Sdim   This value should be either 32 or 64, depending upon the size of an
51218822Sdim   int in the target format. It changes the sizes of the structs which
52218822Sdim   perform the memory/disk mapping of structures.
5333965Sjdp
54218822Sdim   The 64 bit backend may only be used if the host compiler supports 64
55218822Sdim   ints (eg long long with gcc), by defining the name @code{BFD_HOST_64_BIT} in @code{bfd.h}.
56218822Sdim   With this name defined, @emph{all} bfd operations are performed with 64bit
57218822Sdim   arithmetic, not just those to a 64bit target.
5833965Sjdp
59218822Sdim   @item TARGETNAME
60218822Sdim   The name put into the target vector.
61218822Sdim   @item
62218822Sdim   @end table.  */
6333965Sjdp
6433965Sjdp#if ARCH_SIZE == 64
6533965Sjdp#define sunos_set_arch_mach sunos_64_set_arch_mach
6633965Sjdp#define sunos_write_object_contents aout_64_sunos4_write_object_contents
6733965Sjdp#else
6833965Sjdp#define sunos_set_arch_mach sunos_32_set_arch_mach
6933965Sjdp#define sunos_write_object_contents aout_32_sunos4_write_object_contents
7033965Sjdp#endif
7133965Sjdp
7233965Sjdp/* Merge backend data into the output file.
7333965Sjdp   This is necessary on sparclet-aout where we want the resultant machine
7433965Sjdp   number to be M_SPARCLET if any input file is M_SPARCLET.  */
7533965Sjdp
7633965Sjdp#define MY_bfd_merge_private_bfd_data sunos_merge_private_bfd_data
7733965Sjdp
78130561Sobrienstatic bfd_boolean
79218822Sdimsunos_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
8033965Sjdp{
8133965Sjdp  if (bfd_get_flavour (ibfd) != bfd_target_aout_flavour
8233965Sjdp      || bfd_get_flavour (obfd) != bfd_target_aout_flavour)
83130561Sobrien    return TRUE;
8433965Sjdp
8533965Sjdp  if (bfd_get_arch (obfd) == bfd_arch_sparc)
8633965Sjdp    {
8733965Sjdp      if (bfd_get_mach (obfd) < bfd_get_mach (ibfd))
8833965Sjdp	bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd));
8933965Sjdp    }
9033965Sjdp
91130561Sobrien  return TRUE;
9233965Sjdp}
9333965Sjdp
9433965Sjdp/* This is either sunos_32_set_arch_mach or sunos_64_set_arch_mach,
9533965Sjdp   depending upon ARCH_SIZE.  */
9633965Sjdp
9733965Sjdpstatic void
98218822Sdimsunos_set_arch_mach (bfd *abfd, enum machine_type machtype)
9933965Sjdp{
10033965Sjdp  /* Determine the architecture and machine type of the object file.  */
10133965Sjdp  enum bfd_architecture arch;
10289857Sobrien  unsigned long machine;
103218822Sdim
10433965Sjdp  switch (machtype)
10533965Sjdp    {
10633965Sjdp    case M_UNKNOWN:
10733965Sjdp      /* Some Sun3s make magic numbers without cpu types in them, so
10877298Sobrien	 we'll default to the 68000.  */
10933965Sjdp      arch = bfd_arch_m68k;
11038889Sjdp      machine = bfd_mach_m68000;
11133965Sjdp      break;
11233965Sjdp
11333965Sjdp    case M_68010:
11433965Sjdp    case M_HP200:
11533965Sjdp      arch = bfd_arch_m68k;
11638889Sjdp      machine = bfd_mach_m68010;
11733965Sjdp      break;
11833965Sjdp
11933965Sjdp    case M_68020:
12033965Sjdp    case M_HP300:
12133965Sjdp      arch = bfd_arch_m68k;
12238889Sjdp      machine = bfd_mach_m68020;
12333965Sjdp      break;
12433965Sjdp
12533965Sjdp    case M_SPARC:
12633965Sjdp      arch = bfd_arch_sparc;
12733965Sjdp      machine = 0;
12833965Sjdp      break;
12933965Sjdp
13033965Sjdp    case M_SPARCLET:
13133965Sjdp      arch = bfd_arch_sparc;
13233965Sjdp      machine = bfd_mach_sparc_sparclet;
13333965Sjdp      break;
13433965Sjdp
13560484Sobrien    case M_SPARCLITE_LE:
13660484Sobrien      arch = bfd_arch_sparc;
13760484Sobrien      machine = bfd_mach_sparc_sparclite_le;
13860484Sobrien      break;
13960484Sobrien
14033965Sjdp    case M_386:
14133965Sjdp    case M_386_DYNIX:
14233965Sjdp      arch = bfd_arch_i386;
14333965Sjdp      machine = 0;
14433965Sjdp      break;
14533965Sjdp
14633965Sjdp    case M_HPUX:
14733965Sjdp      arch = bfd_arch_m68k;
14833965Sjdp      machine = 0;
14933965Sjdp      break;
15033965Sjdp
15133965Sjdp    default:
15233965Sjdp      arch = bfd_arch_obscure;
15333965Sjdp      machine = 0;
15433965Sjdp      break;
15533965Sjdp    }
15633965Sjdp  bfd_set_arch_mach (abfd, arch, machine);
15733965Sjdp}
15833965Sjdp
15933965Sjdp#define SET_ARCH_MACH(ABFD, EXEC) \
16077298Sobrien  NAME(sunos,set_arch_mach) (ABFD, N_MACHTYPE (EXEC)); \
16133965Sjdp  choose_reloc_size(ABFD);
16233965Sjdp
163218822Sdim/* Determine the size of a relocation entry, based on the architecture.  */
164218822Sdim
16533965Sjdpstatic void
166218822Sdimchoose_reloc_size (bfd *abfd)
16733965Sjdp{
16833965Sjdp  switch (bfd_get_arch (abfd))
16933965Sjdp    {
17033965Sjdp    case bfd_arch_sparc:
17133965Sjdp      obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
17233965Sjdp      break;
17333965Sjdp    default:
17433965Sjdp      obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
17533965Sjdp      break;
17633965Sjdp    }
17733965Sjdp}
17833965Sjdp
17933965Sjdp/* Write an object file in SunOS format.  Section contents have
18033965Sjdp   already been written.  We write the file header, symbols, and
18133965Sjdp   relocation.  The real name of this function is either
18233965Sjdp   aout_64_sunos4_write_object_contents or
18333965Sjdp   aout_32_sunos4_write_object_contents, depending upon ARCH_SIZE.  */
18433965Sjdp
185130561Sobrienstatic bfd_boolean
186218822Sdimsunos_write_object_contents (bfd *abfd)
18733965Sjdp{
18833965Sjdp  struct external_exec exec_bytes;
18933965Sjdp  struct internal_exec *execp = exec_hdr (abfd);
19033965Sjdp
19133965Sjdp  /* Magic number, maestro, please!  */
19233965Sjdp  switch (bfd_get_arch (abfd))
19333965Sjdp    {
19433965Sjdp    case bfd_arch_m68k:
19533965Sjdp      switch (bfd_get_mach (abfd))
19633965Sjdp	{
19738889Sjdp	case bfd_mach_m68000:
19833965Sjdp	  N_SET_MACHTYPE (*execp, M_UNKNOWN);
19933965Sjdp	  break;
20038889Sjdp	case bfd_mach_m68010:
20133965Sjdp	  N_SET_MACHTYPE (*execp, M_68010);
20233965Sjdp	  break;
20333965Sjdp	default:
20438889Sjdp	case bfd_mach_m68020:
20533965Sjdp	  N_SET_MACHTYPE (*execp, M_68020);
20633965Sjdp	  break;
20733965Sjdp	}
20833965Sjdp      break;
20933965Sjdp    case bfd_arch_sparc:
21033965Sjdp      switch (bfd_get_mach (abfd))
21133965Sjdp	{
21233965Sjdp	case bfd_mach_sparc_sparclet:
21333965Sjdp	  N_SET_MACHTYPE (*execp, M_SPARCLET);
21433965Sjdp	  break;
21560484Sobrien	case bfd_mach_sparc_sparclite_le:
21660484Sobrien	  N_SET_MACHTYPE (*execp, M_SPARCLITE_LE);
21760484Sobrien	  break;
21833965Sjdp	default:
21933965Sjdp	  N_SET_MACHTYPE (*execp, M_SPARC);
22033965Sjdp	  break;
22133965Sjdp	}
22233965Sjdp      break;
22333965Sjdp    case bfd_arch_i386:
22433965Sjdp      N_SET_MACHTYPE (*execp, M_386);
22533965Sjdp      break;
22633965Sjdp    default:
22733965Sjdp      N_SET_MACHTYPE (*execp, M_UNKNOWN);
22833965Sjdp    }
22933965Sjdp
23033965Sjdp  choose_reloc_size (abfd);
23133965Sjdp
23233965Sjdp  N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);
23333965Sjdp
23489857Sobrien  N_SET_DYNAMIC (*execp, (long)(bfd_get_file_flags (abfd) & DYNAMIC));
23533965Sjdp
23633965Sjdp  WRITE_HEADERS (abfd, execp);
23733965Sjdp
238130561Sobrien  return TRUE;
23933965Sjdp}
24033965Sjdp
241218822Sdim/* Core files.  */
24233965Sjdp
243218822Sdim#define CORE_MAGIC   0x080456
24433965Sjdp#define CORE_NAMELEN 16
24533965Sjdp
24633965Sjdp/* The core structure is taken from the Sun documentation.
24733965Sjdp  Unfortunately, they don't document the FPA structure, or at least I
24833965Sjdp  can't find it easily.  Fortunately the core header contains its own
24933965Sjdp  length.  So this shouldn't cause problems, except for c_ucode, which
25077298Sobrien  so far we don't use but is easy to find with a little arithmetic.  */
25133965Sjdp
25233965Sjdp/* But the reg structure can be gotten from the SPARC processor handbook.
25333965Sjdp  This really should be in a GNU include file though so that gdb can use
25477298Sobrien  the same info.  */
25533965Sjdpstruct regs
25633965Sjdp{
25733965Sjdp  int r_psr;
25833965Sjdp  int r_pc;
25933965Sjdp  int r_npc;
26033965Sjdp  int r_y;
26133965Sjdp  int r_g1;
26233965Sjdp  int r_g2;
26333965Sjdp  int r_g3;
26433965Sjdp  int r_g4;
26533965Sjdp  int r_g5;
26633965Sjdp  int r_g6;
26733965Sjdp  int r_g7;
26833965Sjdp  int r_o0;
26933965Sjdp  int r_o1;
27033965Sjdp  int r_o2;
27133965Sjdp  int r_o3;
27233965Sjdp  int r_o4;
27333965Sjdp  int r_o5;
27433965Sjdp  int r_o6;
27533965Sjdp  int r_o7;
27633965Sjdp};
27733965Sjdp
27833965Sjdp/* Taken from Sun documentation: */
27933965Sjdp
28033965Sjdp/* FIXME:  It's worse than we expect.  This struct contains TWO substructs
28133965Sjdp  neither of whose size we know, WITH STUFF IN BETWEEN THEM!  We can't
28233965Sjdp  even portably access the stuff in between!  */
28333965Sjdp
28433965Sjdpstruct external_sparc_core
285218822Sdim{
286218822Sdim  int c_magic;				/* Corefile magic number.  */
287218822Sdim  int c_len;				/* Sizeof (struct core).  */
28833965Sjdp#define	SPARC_CORE_LEN	432
289218822Sdim  struct regs c_regs;			/* General purpose registers -- MACHDEP SIZE.  */
290218822Sdim  struct external_exec c_aouthdr;	/* A.out header.  */
291218822Sdim  int c_signo;				/* Killing signal, if any.  */
292218822Sdim  int c_tsize;				/* Text size (bytes).  */
293218822Sdim  int c_dsize;				/* Data size (bytes).  */
294218822Sdim  int c_ssize;				/* Stack size (bytes).  */
295218822Sdim  char c_cmdname[CORE_NAMELEN + 1];	/* Command name.  */
296218822Sdim  double fp_stuff[1];			/* External FPU state (size unknown by us).  */
297218822Sdim  /* The type "double" is critical here, for alignment.
298218822Sdim     SunOS declares a struct here, but the struct's
299218822Sdim     alignment is double since it contains doubles.  */
300218822Sdim  int c_ucode;				/* Exception no. from u_code.  */
301218822Sdim  /* This member is not accessible by name since
302218822Sdim     we don't portably know the size of fp_stuff.  */
303218822Sdim};
30433965Sjdp
30533965Sjdp/* Core files generated by the BCP (the part of Solaris which allows
30633965Sjdp   it to run SunOS4 a.out files).  */
30733965Sjdpstruct external_solaris_bcp_core
308218822Sdim{
309218822Sdim  int c_magic;				/* Corefile magic number.  */
310218822Sdim  int c_len;				/* Sizeof (struct core).  */
31133965Sjdp#define	SOLARIS_BCP_CORE_LEN	456
312218822Sdim  struct regs c_regs;			/* General purpose registers -- MACHDEP SIZE.  */
313218822Sdim  int c_exdata_vp;			/* Exdata structure.  */
314218822Sdim  int c_exdata_tsize;
315218822Sdim  int c_exdata_dsize;
316218822Sdim  int c_exdata_bsize;
317218822Sdim  int c_exdata_lsize;
318218822Sdim  int c_exdata_nshlibs;
319218822Sdim  short c_exdata_mach;
320218822Sdim  short c_exdata_mag;
321218822Sdim  int c_exdata_toffset;
322218822Sdim  int c_exdata_doffset;
323218822Sdim  int c_exdata_loffset;
324218822Sdim  int c_exdata_txtorg;
325218822Sdim  int c_exdata_datorg;
326218822Sdim  int c_exdata_entloc;
327218822Sdim  int c_signo;				/* Killing signal, if any.  */
328218822Sdim  int c_tsize;				/* Text size (bytes).  */
329218822Sdim  int c_dsize;				/* Data size (bytes).  */
330218822Sdim  int c_ssize;				/* Stack size (bytes).  */
331218822Sdim  char c_cmdname[CORE_NAMELEN + 1];	/* Command name.  */
332218822Sdim  double fp_stuff[1];			/* External FPU state (size unknown by us).  */
333218822Sdim  /* The type "double" is critical here, for alignment.
334218822Sdim     SunOS declares a struct here, but the struct's
335218822Sdim     alignment is double since it contains doubles.  */
336218822Sdim  int c_ucode;				/* Exception no. from u_code.  */
337218822Sdim  /* This member is not accessible by name since
338218822Sdim     we don't portably know the size of fp_stuff.  */
339218822Sdim};
34033965Sjdp
34133965Sjdpstruct external_sun3_core
342218822Sdim{
343218822Sdim  int c_magic;				/* Corefile magic number.  */
344218822Sdim  int c_len;				/* Sizeof (struct core).  */
345218822Sdim#define	SUN3_CORE_LEN	826		/* As of SunOS 4.1.1.  */
346218822Sdim  int c_regs[18];			/* General purpose registers -- MACHDEP SIZE.  */
347218822Sdim  struct external_exec c_aouthdr;	/* A.out header.  */
348218822Sdim  int c_signo;				/* Killing signal, if any.  */
349218822Sdim  int c_tsize;				/* Text size (bytes).  */
350218822Sdim  int c_dsize;				/* Data size (bytes).  */
351218822Sdim  int c_ssize;				/* Stack size (bytes).  */
352218822Sdim  char c_cmdname[CORE_NAMELEN + 1];	/* Command name.  */
353218822Sdim  double fp_stuff[1];			/* External FPU state (size unknown by us).  */
354218822Sdim  /* The type "double" is critical here, for alignment.
355218822Sdim     SunOS declares a struct here, but the struct's
356218822Sdim     alignment is double since it contains doubles.  */
357218822Sdim  int c_ucode;				/* Exception no. from u_code.  */
358218822Sdim  /* This member is not accessible by name since
359218822Sdim     we don't portably know the size of fp_stuff.  */
360218822Sdim};
36133965Sjdp
36233965Sjdpstruct internal_sunos_core
363218822Sdim{
364218822Sdim  int c_magic;				/* Corefile magic number.  */
365218822Sdim  int c_len;				/* Sizeof (struct core).  */
366218822Sdim  long c_regs_pos;			/* File offset of General purpose registers.  */
367218822Sdim  int c_regs_size;			/* Size of General purpose registers.  */
368218822Sdim  struct internal_exec c_aouthdr;	/* A.out header.  */
369218822Sdim  int c_signo;				/* Killing signal, if any.  */
370218822Sdim  int c_tsize;				/* Text size (bytes).  */
371218822Sdim  int c_dsize;				/* Data size (bytes).  */
372218822Sdim  bfd_vma c_data_addr;			/* Data start (address).  */
373218822Sdim  int c_ssize;				/* Stack size (bytes).  */
374218822Sdim  bfd_vma c_stacktop;			/* Stack top (address).  */
375218822Sdim  char c_cmdname[CORE_NAMELEN + 1];	/* Command name.  */
376218822Sdim  long fp_stuff_pos;			/* File offset of external FPU state (regs).  */
377218822Sdim  int fp_stuff_size;			/* Size of it.  */
378218822Sdim  int c_ucode;				/* Exception no. from u_code.  */
379218822Sdim};
38033965Sjdp
381218822Sdim/* Byte-swap in the Sun-3 core structure.  */
38233965Sjdp
38333965Sjdpstatic void
384218822Sdimswapcore_sun3 (bfd *abfd, char *ext, struct internal_sunos_core *intcore)
38533965Sjdp{
38633965Sjdp  struct external_sun3_core *extcore = (struct external_sun3_core *) ext;
38733965Sjdp
38889857Sobrien  intcore->c_magic = H_GET_32 (abfd, &extcore->c_magic);
38989857Sobrien  intcore->c_len = H_GET_32 (abfd, &extcore->c_len);
390218822Sdim  intcore->c_regs_pos = offsetof (struct external_sun3_core, c_regs);
39133965Sjdp  intcore->c_regs_size = sizeof (extcore->c_regs);
39233965Sjdp#if ARCH_SIZE == 64
39333965Sjdp  aout_64_swap_exec_header_in
39433965Sjdp#else
39533965Sjdp  aout_32_swap_exec_header_in
39633965Sjdp#endif
39733965Sjdp    (abfd, &extcore->c_aouthdr, &intcore->c_aouthdr);
39889857Sobrien  intcore->c_signo = H_GET_32 (abfd, &extcore->c_signo);
39989857Sobrien  intcore->c_tsize = H_GET_32 (abfd, &extcore->c_tsize);
40089857Sobrien  intcore->c_dsize = H_GET_32 (abfd, &extcore->c_dsize);
40133965Sjdp  intcore->c_data_addr = N_DATADDR (intcore->c_aouthdr);
40289857Sobrien  intcore->c_ssize = H_GET_32 (abfd, &extcore->c_ssize);
40333965Sjdp  memcpy (intcore->c_cmdname, extcore->c_cmdname, sizeof (intcore->c_cmdname));
404218822Sdim  intcore->fp_stuff_pos = offsetof (struct external_sun3_core, fp_stuff);
40577298Sobrien  /* FP stuff takes up whole rest of struct, except c_ucode.  */
40633965Sjdp  intcore->fp_stuff_size = intcore->c_len - (sizeof extcore->c_ucode) -
407218822Sdim    offsetof (struct external_sun3_core, fp_stuff);
408218822Sdim  /* Ucode is the last thing in the struct -- just before the end.  */
40989857Sobrien  intcore->c_ucode = H_GET_32 (abfd,
41089857Sobrien			       (intcore->c_len
41189857Sobrien				- sizeof (extcore->c_ucode)
41289857Sobrien				+ (unsigned char *) extcore));
413218822Sdim  intcore->c_stacktop = 0x0E000000;	/* By experimentation.  */
41433965Sjdp}
41533965Sjdp
416218822Sdim/* Byte-swap in the Sparc core structure.  */
417218822Sdim
41833965Sjdpstatic void
419218822Sdimswapcore_sparc (bfd *abfd, char *ext, struct internal_sunos_core *intcore)
42033965Sjdp{
42133965Sjdp  struct external_sparc_core *extcore = (struct external_sparc_core *) ext;
42233965Sjdp
42389857Sobrien  intcore->c_magic = H_GET_32 (abfd, &extcore->c_magic);
42489857Sobrien  intcore->c_len = H_GET_32 (abfd, &extcore->c_len);
425218822Sdim  intcore->c_regs_pos = offsetof (struct external_sparc_core, c_regs);
42633965Sjdp  intcore->c_regs_size = sizeof (extcore->c_regs);
42733965Sjdp#if ARCH_SIZE == 64
42833965Sjdp  aout_64_swap_exec_header_in
42933965Sjdp#else
43033965Sjdp  aout_32_swap_exec_header_in
43133965Sjdp#endif
43233965Sjdp    (abfd, &extcore->c_aouthdr, &intcore->c_aouthdr);
43389857Sobrien  intcore->c_signo = H_GET_32 (abfd, &extcore->c_signo);
43489857Sobrien  intcore->c_tsize = H_GET_32 (abfd, &extcore->c_tsize);
43589857Sobrien  intcore->c_dsize = H_GET_32 (abfd, &extcore->c_dsize);
43633965Sjdp  intcore->c_data_addr = N_DATADDR (intcore->c_aouthdr);
43789857Sobrien  intcore->c_ssize = H_GET_32 (abfd, &extcore->c_ssize);
43833965Sjdp  memcpy (intcore->c_cmdname, extcore->c_cmdname, sizeof (intcore->c_cmdname));
439218822Sdim  intcore->fp_stuff_pos = offsetof (struct external_sparc_core, fp_stuff);
44077298Sobrien  /* FP stuff takes up whole rest of struct, except c_ucode.  */
44133965Sjdp  intcore->fp_stuff_size = intcore->c_len - (sizeof extcore->c_ucode) -
442218822Sdim    offsetof (struct external_sparc_core, fp_stuff);
443218822Sdim  /* Ucode is the last thing in the struct -- just before the end.  */
44489857Sobrien  intcore->c_ucode = H_GET_32 (abfd,
44589857Sobrien			       (intcore->c_len
44689857Sobrien				- sizeof (extcore->c_ucode)
44789857Sobrien				+ (unsigned char *) extcore));
44833965Sjdp
44933965Sjdp  /* Supposedly the user stack grows downward from the bottom of kernel memory.
45033965Sjdp     Presuming that this remains true, this definition will work.  */
45133965Sjdp  /* Now sun has provided us with another challenge.  The value is different
45233965Sjdp     for sparc2 and sparc10 (both running SunOS 4.1.3).  We pick one or
45333965Sjdp     the other based on the current value of the stack pointer.  This
45433965Sjdp     loses (a) if the stack pointer has been clobbered, or (b) if the stack
45533965Sjdp     is larger than 128 megabytes.
45633965Sjdp
45733965Sjdp     It's times like these you're glad they're switching to ELF.
45833965Sjdp
45933965Sjdp     Note that using include files or nlist on /vmunix would be wrong,
46033965Sjdp     because we want the value for this core file, no matter what kind of
46133965Sjdp     machine we were compiled on or are running on.  */
46233965Sjdp#define SPARC_USRSTACK_SPARC2 ((bfd_vma)0xf8000000)
46333965Sjdp#define SPARC_USRSTACK_SPARC10 ((bfd_vma)0xf0000000)
46433965Sjdp  {
465218822Sdim    bfd_vma sp = H_GET_32 (abfd, &extcore->c_regs.r_o6);
46633965Sjdp    if (sp < SPARC_USRSTACK_SPARC10)
46733965Sjdp      intcore->c_stacktop = SPARC_USRSTACK_SPARC10;
46833965Sjdp    else
46933965Sjdp      intcore->c_stacktop = SPARC_USRSTACK_SPARC2;
47033965Sjdp  }
47133965Sjdp}
47233965Sjdp
473218822Sdim/* Byte-swap in the Solaris BCP core structure.  */
474218822Sdim
47533965Sjdpstatic void
476218822Sdimswapcore_solaris_bcp (bfd *abfd, char *ext, struct internal_sunos_core *intcore)
47733965Sjdp{
47833965Sjdp  struct external_solaris_bcp_core *extcore =
47933965Sjdp    (struct external_solaris_bcp_core *) ext;
48033965Sjdp
48189857Sobrien  intcore->c_magic = H_GET_32 (abfd, &extcore->c_magic);
48289857Sobrien  intcore->c_len = H_GET_32 (abfd, &extcore->c_len);
483218822Sdim  intcore->c_regs_pos = offsetof (struct external_solaris_bcp_core, c_regs);
48433965Sjdp  intcore->c_regs_size = sizeof (extcore->c_regs);
48533965Sjdp
48633965Sjdp  /* The Solaris BCP exdata structure does not contain an a_syms field,
48733965Sjdp     so we are unable to synthesize an internal exec header.
48833965Sjdp     Luckily we are able to figure out the start address of the data section,
48933965Sjdp     which is the only thing needed from the internal exec header,
49033965Sjdp     from the exdata structure.
49133965Sjdp
49233965Sjdp     As of Solaris 2.3, BCP core files for statically linked executables
49333965Sjdp     are buggy. The exdata structure is not properly filled in, and
49433965Sjdp     the data section is written from address zero instead of the data
49533965Sjdp     start address.  */
496218822Sdim  memset ((void *) &intcore->c_aouthdr, 0, sizeof (struct internal_exec));
49789857Sobrien  intcore->c_data_addr = H_GET_32 (abfd, &extcore->c_exdata_datorg);
49889857Sobrien  intcore->c_signo = H_GET_32 (abfd, &extcore->c_signo);
49989857Sobrien  intcore->c_tsize = H_GET_32 (abfd, &extcore->c_tsize);
50089857Sobrien  intcore->c_dsize = H_GET_32 (abfd, &extcore->c_dsize);
50189857Sobrien  intcore->c_ssize = H_GET_32 (abfd, &extcore->c_ssize);
50233965Sjdp  memcpy (intcore->c_cmdname, extcore->c_cmdname, sizeof (intcore->c_cmdname));
50333965Sjdp  intcore->fp_stuff_pos =
504218822Sdim    offsetof (struct external_solaris_bcp_core, fp_stuff);
50577298Sobrien  /* FP stuff takes up whole rest of struct, except c_ucode.  */
50633965Sjdp  intcore->fp_stuff_size = intcore->c_len - (sizeof extcore->c_ucode) -
507218822Sdim    offsetof (struct external_solaris_bcp_core, fp_stuff);
50833965Sjdp  /* Ucode is the last thing in the struct -- just before the end */
50989857Sobrien  intcore->c_ucode = H_GET_32 (abfd,
51089857Sobrien			       (intcore->c_len
51189857Sobrien				- sizeof (extcore->c_ucode)
51289857Sobrien				+ (unsigned char *) extcore));
51333965Sjdp
51433965Sjdp  /* Supposedly the user stack grows downward from the bottom of kernel memory.
51533965Sjdp     Presuming that this remains true, this definition will work.  */
51633965Sjdp  /* Now sun has provided us with another challenge.  The value is different
51733965Sjdp     for sparc2 and sparc10 (both running SunOS 4.1.3).  We pick one or
51833965Sjdp     the other based on the current value of the stack pointer.  This
51933965Sjdp     loses (a) if the stack pointer has been clobbered, or (b) if the stack
52033965Sjdp     is larger than 128 megabytes.
52133965Sjdp
52233965Sjdp     It's times like these you're glad they're switching to ELF.
52333965Sjdp
52433965Sjdp     Note that using include files or nlist on /vmunix would be wrong,
52533965Sjdp     because we want the value for this core file, no matter what kind of
52633965Sjdp     machine we were compiled on or are running on.  */
52733965Sjdp#define SPARC_USRSTACK_SPARC2 ((bfd_vma)0xf8000000)
52833965Sjdp#define SPARC_USRSTACK_SPARC10 ((bfd_vma)0xf0000000)
52933965Sjdp  {
530218822Sdim    bfd_vma sp = H_GET_32 (abfd, &extcore->c_regs.r_o6);
53133965Sjdp    if (sp < SPARC_USRSTACK_SPARC10)
53233965Sjdp      intcore->c_stacktop = SPARC_USRSTACK_SPARC10;
53333965Sjdp    else
53433965Sjdp      intcore->c_stacktop = SPARC_USRSTACK_SPARC2;
53533965Sjdp  }
53633965Sjdp}
53733965Sjdp
538218822Sdim/* Need this cast because ptr is really void *.  */
539218822Sdim#define core_hdr(bfd)      ((bfd)->tdata.sun_core_data)
540218822Sdim#define core_datasec(bfd)  (core_hdr (bfd)->data_section)
541218822Sdim#define core_stacksec(bfd) (core_hdr (bfd)->stack_section)
542218822Sdim#define core_regsec(bfd)   (core_hdr (bfd)->reg_section)
543218822Sdim#define core_reg2sec(bfd)  (core_hdr (bfd)->reg2_section)
54433965Sjdp
545218822Sdim/* These are stored in the bfd's tdata.  */
54633965Sjdpstruct sun_core_struct
54733965Sjdp{
548218822Sdim  struct internal_sunos_core *hdr;	/* Core file header.  */
54933965Sjdp  asection *data_section;
55033965Sjdp  asection *stack_section;
55133965Sjdp  asection *reg_section;
55233965Sjdp  asection *reg2_section;
55333965Sjdp};
55433965Sjdp
55533965Sjdpstatic const bfd_target *
556218822Sdimsunos4_core_file_p (bfd *abfd)
55733965Sjdp{
558218822Sdim  unsigned char longbuf[4];	/* Raw bytes of various header fields.  */
55989857Sobrien  bfd_size_type core_size, amt;
56033965Sjdp  unsigned long core_mag;
56133965Sjdp  struct internal_sunos_core *core;
56233965Sjdp  char *extcore;
56333965Sjdp  struct mergem
56433965Sjdp    {
56533965Sjdp      struct sun_core_struct suncoredata;
56633965Sjdp      struct internal_sunos_core internal_sunos_core;
56733965Sjdp      char external_core[1];
56889857Sobrien    } *mergem;
569218822Sdim  flagword flags;
57033965Sjdp
571218822Sdim  if (bfd_bread ((void *) longbuf, (bfd_size_type) sizeof (longbuf), abfd)
57289857Sobrien      != sizeof (longbuf))
573218822Sdim    return NULL;
57489857Sobrien  core_mag = H_GET_32 (abfd, longbuf);
57533965Sjdp
57633965Sjdp  if (core_mag != CORE_MAGIC)
577218822Sdim    return NULL;
57833965Sjdp
57933965Sjdp  /* SunOS core headers can vary in length; second word is size; */
580218822Sdim  if (bfd_bread ((void *) longbuf, (bfd_size_type) sizeof (longbuf), abfd)
58189857Sobrien      != sizeof (longbuf))
582218822Sdim    return NULL;
58389857Sobrien  core_size = H_GET_32 (abfd, longbuf);
584218822Sdim  /* Sanity check.  */
58533965Sjdp  if (core_size > 20000)
586218822Sdim    return NULL;
58733965Sjdp
58889857Sobrien  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
589218822Sdim    return NULL;
59033965Sjdp
59189857Sobrien  amt = core_size + sizeof (struct mergem);
592218822Sdim  mergem = bfd_zalloc (abfd, amt);
59333965Sjdp  if (mergem == NULL)
594218822Sdim    return NULL;
59533965Sjdp
59633965Sjdp  extcore = mergem->external_core;
59733965Sjdp
598218822Sdim  if ((bfd_bread ((void *) extcore, core_size, abfd)) != core_size)
59933965Sjdp    {
60089857Sobrien    loser:
60133965Sjdp      bfd_release (abfd, (char *) mergem);
60289857Sobrien      abfd->tdata.any = NULL;
60389857Sobrien      bfd_section_list_clear (abfd);
604218822Sdim      return NULL;
60533965Sjdp    }
60633965Sjdp
60733965Sjdp  /* Validate that it's a core file we know how to handle, due to sun
60833965Sjdp     botching the positioning of registers and other fields in a machine
60933965Sjdp     dependent way.  */
61033965Sjdp  core = &mergem->internal_sunos_core;
61133965Sjdp  switch (core_size)
61233965Sjdp    {
61333965Sjdp    case SPARC_CORE_LEN:
61433965Sjdp      swapcore_sparc (abfd, extcore, core);
61533965Sjdp      break;
61633965Sjdp    case SUN3_CORE_LEN:
61733965Sjdp      swapcore_sun3 (abfd, extcore, core);
61833965Sjdp      break;
61933965Sjdp    case SOLARIS_BCP_CORE_LEN:
62033965Sjdp      swapcore_solaris_bcp (abfd, extcore, core);
62133965Sjdp      break;
62233965Sjdp    default:
623218822Sdim      bfd_set_error (bfd_error_system_call);	/* FIXME.  */
62489857Sobrien      goto loser;
62533965Sjdp    }
62633965Sjdp
62733965Sjdp  abfd->tdata.sun_core_data = &mergem->suncoredata;
62833965Sjdp  abfd->tdata.sun_core_data->hdr = core;
62933965Sjdp
63089857Sobrien  /* Create the sections.  */
631218822Sdim  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
632218822Sdim  core_stacksec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".stack",
633218822Sdim							     flags);
63433965Sjdp  if (core_stacksec (abfd) == NULL)
63589857Sobrien    /* bfd_release frees everything allocated after it's arg.  */
63689857Sobrien    goto loser;
63789857Sobrien
638218822Sdim  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
639218822Sdim  core_datasec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".data",
640218822Sdim							    flags);
64133965Sjdp  if (core_datasec (abfd) == NULL)
64289857Sobrien    goto loser;
64389857Sobrien
644218822Sdim  flags = SEC_HAS_CONTENTS;
645218822Sdim  core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg",
646218822Sdim							   flags);
64733965Sjdp  if (core_regsec (abfd) == NULL)
64889857Sobrien    goto loser;
64989857Sobrien
650218822Sdim  flags = SEC_HAS_CONTENTS;
651218822Sdim  core_reg2sec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg2",
652218822Sdim							    flags);
65333965Sjdp  if (core_reg2sec (abfd) == NULL)
65489857Sobrien    goto loser;
65533965Sjdp
656218822Sdim  core_stacksec (abfd)->size = core->c_ssize;
657218822Sdim  core_datasec (abfd)->size = core->c_dsize;
658218822Sdim  core_regsec (abfd)->size = core->c_regs_size;
659218822Sdim  core_reg2sec (abfd)->size = core->fp_stuff_size;
66033965Sjdp
66133965Sjdp  core_stacksec (abfd)->vma = (core->c_stacktop - core->c_ssize);
66233965Sjdp  core_datasec (abfd)->vma = core->c_data_addr;
66333965Sjdp  core_regsec (abfd)->vma = 0;
66433965Sjdp  core_reg2sec (abfd)->vma = 0;
66533965Sjdp
66633965Sjdp  core_stacksec (abfd)->filepos = core->c_len + core->c_dsize;
66733965Sjdp  core_datasec (abfd)->filepos = core->c_len;
668218822Sdim  /* We'll access the regs afresh in the core file, like any section:  */
66933965Sjdp  core_regsec (abfd)->filepos = (file_ptr) core->c_regs_pos;
67033965Sjdp  core_reg2sec (abfd)->filepos = (file_ptr) core->fp_stuff_pos;
67133965Sjdp
672218822Sdim  /* Align to word at least.  */
67333965Sjdp  core_stacksec (abfd)->alignment_power = 2;
67433965Sjdp  core_datasec (abfd)->alignment_power = 2;
67533965Sjdp  core_regsec (abfd)->alignment_power = 2;
67633965Sjdp  core_reg2sec (abfd)->alignment_power = 2;
67733965Sjdp
67833965Sjdp  return abfd->xvec;
67933965Sjdp}
68033965Sjdp
68133965Sjdpstatic char *
682218822Sdimsunos4_core_file_failing_command (bfd *abfd)
68333965Sjdp{
68433965Sjdp  return core_hdr (abfd)->hdr->c_cmdname;
68533965Sjdp}
68633965Sjdp
68733965Sjdpstatic int
688218822Sdimsunos4_core_file_failing_signal (bfd *abfd)
68933965Sjdp{
69033965Sjdp  return core_hdr (abfd)->hdr->c_signo;
69133965Sjdp}
69233965Sjdp
693130561Sobrienstatic bfd_boolean
694218822Sdimsunos4_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
69533965Sjdp{
69633965Sjdp  if (core_bfd->xvec != exec_bfd->xvec)
69733965Sjdp    {
69833965Sjdp      bfd_set_error (bfd_error_system_call);
699130561Sobrien      return FALSE;
70033965Sjdp    }
70133965Sjdp
70277298Sobrien  /* Solaris core files do not include an aouthdr.  */
70333965Sjdp  if ((core_hdr (core_bfd)->hdr)->c_len == SOLARIS_BCP_CORE_LEN)
704130561Sobrien    return TRUE;
70533965Sjdp
706218822Sdim  return memcmp ((char *) &((core_hdr (core_bfd)->hdr)->c_aouthdr),
707218822Sdim		 (char *) exec_hdr (exec_bfd),
708218822Sdim		 sizeof (struct internal_exec)) == 0;
70933965Sjdp}
71033965Sjdp
71133965Sjdp#define MY_set_sizes sunos4_set_sizes
712218822Sdim
713130561Sobrienstatic bfd_boolean
714218822Sdimsunos4_set_sizes (bfd *abfd)
71533965Sjdp{
71633965Sjdp  switch (bfd_get_arch (abfd))
71733965Sjdp    {
71833965Sjdp    default:
719130561Sobrien      return FALSE;
72033965Sjdp    case bfd_arch_sparc:
72133965Sjdp      adata (abfd).page_size = 0x2000;
72233965Sjdp      adata (abfd).segment_size = 0x2000;
72333965Sjdp      adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
724130561Sobrien      return TRUE;
72533965Sjdp    case bfd_arch_m68k:
72633965Sjdp      adata (abfd).page_size = 0x2000;
72733965Sjdp      adata (abfd).segment_size = 0x20000;
72833965Sjdp      adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
729130561Sobrien      return TRUE;
73033965Sjdp    }
73133965Sjdp}
73233965Sjdp
73333965Sjdp/* We default to setting the toolversion field to 1, as is required by
73433965Sjdp   SunOS.  */
73533965Sjdp#ifndef MY_exec_hdr_flags
73633965Sjdp#define MY_exec_hdr_flags 1
73733965Sjdp#endif
73833965Sjdp
73933965Sjdp#ifndef MY_entry_is_text_address
74033965Sjdp#define MY_entry_is_text_address 0
74133965Sjdp#endif
74233965Sjdp#ifndef MY_add_dynamic_symbols
74333965Sjdp#define MY_add_dynamic_symbols 0
74433965Sjdp#endif
74533965Sjdp#ifndef MY_add_one_symbol
74633965Sjdp#define MY_add_one_symbol 0
74733965Sjdp#endif
74833965Sjdp#ifndef MY_link_dynamic_object
74933965Sjdp#define MY_link_dynamic_object 0
75033965Sjdp#endif
75133965Sjdp#ifndef MY_write_dynamic_symbol
75233965Sjdp#define MY_write_dynamic_symbol 0
75333965Sjdp#endif
75433965Sjdp#ifndef MY_check_dynamic_reloc
75533965Sjdp#define MY_check_dynamic_reloc 0
75633965Sjdp#endif
75733965Sjdp#ifndef MY_finish_dynamic_link
75833965Sjdp#define MY_finish_dynamic_link 0
75933965Sjdp#endif
76033965Sjdp
76189857Sobrienstatic const struct aout_backend_data sunos4_aout_backend =
76233965Sjdp{
763218822Sdim  0,				/* Zmagic files are not contiguous.  */
764218822Sdim  1,				/* Text includes header.  */
76533965Sjdp  MY_entry_is_text_address,
76633965Sjdp  MY_exec_hdr_flags,
767218822Sdim  0,				/* Default text vma.  */
76833965Sjdp  sunos4_set_sizes,
769218822Sdim  0,				/* Header is counted in zmagic text.  */
77033965Sjdp  MY_add_dynamic_symbols,
77133965Sjdp  MY_add_one_symbol,
77233965Sjdp  MY_link_dynamic_object,
77333965Sjdp  MY_write_dynamic_symbol,
77433965Sjdp  MY_check_dynamic_reloc,
77533965Sjdp  MY_finish_dynamic_link
77633965Sjdp};
77733965Sjdp
77833965Sjdp#define	MY_core_file_failing_command 	sunos4_core_file_failing_command
77933965Sjdp#define	MY_core_file_failing_signal	sunos4_core_file_failing_signal
78033965Sjdp#define	MY_core_file_matches_executable_p sunos4_core_file_matches_executable_p
78133965Sjdp
78233965Sjdp#define MY_bfd_debug_info_start		bfd_void
78333965Sjdp#define MY_bfd_debug_info_end		bfd_void
784218822Sdim#define MY_bfd_debug_info_accumulate	(void (*) (bfd *, struct bfd_section *)) bfd_void
78533965Sjdp#define MY_core_file_p			sunos4_core_file_p
786218822Sdim#define MY_write_object_contents	NAME(aout, sunos4_write_object_contents)
787218822Sdim#define MY_backend_data			& sunos4_aout_backend
78833965Sjdp
78933965Sjdp#ifndef TARGET_IS_LITTLE_ENDIAN_P
79033965Sjdp#define TARGET_IS_BIG_ENDIAN_P
79133965Sjdp#endif
79233965Sjdp
79333965Sjdp#include "aout-target.h"
794