133965Sjdp/* srconv.c -- Sysroff conversion program
2218822Sdim   Copyright 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3218822Sdim   2005, 2007 Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GNU Binutils.
633965Sjdp
733965Sjdp   This program is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2 of the License, or
1033965Sjdp   (at your option) any later version.
1133965Sjdp
1233965Sjdp   This program is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with this program; if not, write to the Free Software
19218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim   02110-1301, USA.  */
2133965Sjdp
2233965Sjdp/* Written by Steve Chamberlain (sac@cygnus.com)
2333965Sjdp
2433965Sjdp   This program can be used to convert a coff object file
2533965Sjdp   into a Hitachi OM/LM (Sysroff) format.
2633965Sjdp
2733965Sjdp   All debugging information is preserved */
2833965Sjdp
29218822Sdim#include "sysdep.h"
30104834Sobrien#include "bfd.h"
3133965Sjdp#include "bucomm.h"
3233965Sjdp#include "sysroff.h"
3333965Sjdp#include "coffgrok.h"
34104834Sobrien#include "libiberty.h"
35104834Sobrien#include "getopt.h"
3633965Sjdp
3733965Sjdp#include "coff/internal.h"
3833965Sjdp#include "../bfd/libcoff.h"
3933965Sjdp
4033965Sjdp/*#define FOOP1 1 */
4133965Sjdp
4238889Sjdpstatic int addrsize;
4338889Sjdpstatic char *toolname;
4438889Sjdpstatic char **rnames;
4538889Sjdp
46130561Sobrienstatic int get_member_id (int);
47130561Sobrienstatic int get_ordinary_id (int);
48130561Sobrienstatic char *section_translate (char *);
49130561Sobrienstatic char *strip_suffix (char *);
50218822Sdimstatic void checksum (FILE *, unsigned char *, int, int);
51218822Sdimstatic void writeINT (int, unsigned char *, int *, int, FILE *);
52218822Sdimstatic void writeBITS (int, unsigned char *, int *, int);
53218822Sdimstatic void writeBARRAY (barray, unsigned char *, int *, int, FILE *);
54218822Sdimstatic void writeCHARS (char *, unsigned char *, int *, int, FILE *);
55130561Sobrienstatic void wr_tr (void);
56130561Sobrienstatic void wr_un (struct coff_ofile *, struct coff_sfile *, int, int);
57130561Sobrienstatic void wr_hd (struct coff_ofile *);
58130561Sobrienstatic void wr_sh (struct coff_ofile *, struct coff_section *);
59130561Sobrienstatic void wr_ob (struct coff_ofile *, struct coff_section *);
60130561Sobrienstatic void wr_rl (struct coff_ofile *, struct coff_section *);
61130561Sobrienstatic void wr_object_body (struct coff_ofile *);
6289857Sobrienstatic void wr_dps_start
63130561Sobrien  (struct coff_sfile *, struct coff_section *, struct coff_scope *, int, int);
64130561Sobrienstatic void wr_dps_end (struct coff_section *, struct coff_scope *, int);
65130561Sobrienstatic int *nints (int);
6689857Sobrienstatic void walk_tree_type_1
67130561Sobrien  (struct coff_sfile *, struct coff_symbol *, struct coff_type *, int);
6889857Sobrienstatic void walk_tree_type
69130561Sobrien  (struct coff_sfile *, struct coff_symbol *, struct coff_type *, int);
7089857Sobrienstatic void walk_tree_symbol
71130561Sobrien  (struct coff_sfile *, struct coff_section *, struct coff_symbol *, int);
7289857Sobrienstatic void walk_tree_scope
73130561Sobrien  (struct coff_section *, struct coff_sfile *, struct coff_scope *, int, int);
74130561Sobrienstatic void walk_tree_sfile (struct coff_section *, struct coff_sfile *);
75130561Sobrienstatic void wr_program_structure (struct coff_ofile *, struct coff_sfile *);
76130561Sobrienstatic void wr_du (struct coff_ofile *, struct coff_sfile *, int);
77130561Sobrienstatic void wr_dus (struct coff_ofile *, struct coff_sfile *);
78130561Sobrienstatic int find_base (struct coff_sfile *, struct coff_section *);
79130561Sobrienstatic void wr_dln (struct coff_ofile *, struct coff_sfile *, int);
80130561Sobrienstatic void wr_globals (struct coff_ofile *, struct coff_sfile *, int);
81130561Sobrienstatic void wr_debug (struct coff_ofile *);
82130561Sobrienstatic void wr_cs (void);
83130561Sobrienstatic int wr_sc (struct coff_ofile *, struct coff_sfile *);
84130561Sobrienstatic void wr_er (struct coff_ofile *, struct coff_sfile *, int);
85130561Sobrienstatic void wr_ed (struct coff_ofile *, struct coff_sfile *, int);
86130561Sobrienstatic void wr_unit_info (struct coff_ofile *);
87130561Sobrienstatic void wr_module (struct coff_ofile *);
88130561Sobrienstatic int align (int);
89130561Sobrienstatic void prescan (struct coff_ofile *);
90130561Sobrienstatic void show_usage (FILE *, int);
91130561Sobrienextern int main (int, char **);
9233965Sjdp
9333965Sjdpstatic FILE *file;
9433965Sjdpstatic bfd *abfd;
9533965Sjdpstatic int debug = 0;
9633965Sjdpstatic int quick = 0;
9733965Sjdpstatic int noprescan = 0;
9833965Sjdpstatic struct coff_ofile *tree;
99104834Sobrien/* Obsolete ??
10033965Sjdp   static int absolute_p;
10133965Sjdp */
10233965Sjdp
10333965Sjdpstatic int segmented_p;
10433965Sjdpstatic int code;
10533965Sjdp
10633965Sjdpstatic int ids1[20000];
10733965Sjdpstatic int ids2[20000];
10833965Sjdp
10933965Sjdpstatic int base1 = 0x18;
11033965Sjdpstatic int base2 = 0x2018;
11133965Sjdp
11233965Sjdpstatic int
113130561Sobrienget_member_id (int x)
11433965Sjdp{
11533965Sjdp  if (ids2[x])
11689857Sobrien    return ids2[x];
11789857Sobrien
11833965Sjdp  ids2[x] = base2++;
11933965Sjdp  return ids2[x];
12033965Sjdp}
12133965Sjdp
12233965Sjdpstatic int
123130561Sobrienget_ordinary_id (int x)
12433965Sjdp{
12533965Sjdp  if (ids1[x])
12689857Sobrien    return ids1[x];
12789857Sobrien
12833965Sjdp  ids1[x] = base1++;
12933965Sjdp  return ids1[x];
13033965Sjdp}
13133965Sjdpstatic char *
132130561Sobriensection_translate (char *n)
13333965Sjdp{
13433965Sjdp  if (strcmp (n, ".text") == 0)
13533965Sjdp    return "P";
13633965Sjdp  if (strcmp (n, ".data") == 0)
13733965Sjdp    return "D";
13833965Sjdp  if (strcmp (n, ".bss") == 0)
13933965Sjdp    return "B";
14033965Sjdp  return n;
14133965Sjdp}
14233965Sjdp
14333965Sjdp#define DATE "940201073000";	/* Just a time on my birthday */
14433965Sjdp
14533965Sjdpstatic
14633965Sjdpchar *
147130561Sobrienstrip_suffix (char *name)
14833965Sjdp{
14933965Sjdp  int i;
15033965Sjdp  char *res;
15189857Sobrien
15233965Sjdp  for (i = 0; name[i] != 0 && name[i] != '.'; i++)
15333965Sjdp    ;
15433965Sjdp  res = (char *) xmalloc (i + 1);
15533965Sjdp  memcpy (res, name, i);
15633965Sjdp  res[i] = 0;
15733965Sjdp  return res;
15833965Sjdp}
15933965Sjdp
16033965Sjdp/* IT LEN stuff CS */
16133965Sjdpstatic void
162218822Sdimchecksum (FILE *file, unsigned char *ptr, int size, int code)
16333965Sjdp{
16433965Sjdp  int j;
16533965Sjdp  int last;
16633965Sjdp  int sum = 0;
16733965Sjdp  int bytes = size / 8;
16889857Sobrien
16933965Sjdp  last = !(code & 0xff00);
17033965Sjdp  if (size & 0x7)
17133965Sjdp    abort ();
17233965Sjdp  ptr[0] = code | (last ? 0x80 : 0);
17333965Sjdp  ptr[1] = bytes + 1;
17433965Sjdp
17533965Sjdp  for (j = 0; j < bytes; j++)
17689857Sobrien    sum += ptr[j];
17789857Sobrien
17889857Sobrien  /* Glue on a checksum too.  */
17933965Sjdp  ptr[bytes] = ~sum;
18033965Sjdp  fwrite (ptr, bytes + 1, 1, file);
18133965Sjdp}
18233965Sjdp
18333965Sjdp
18433965Sjdpstatic void
185218822SdimwriteINT (int n, unsigned char *ptr, int *idx, int size, FILE *file)
18633965Sjdp{
18733965Sjdp  int byte = *idx / 8;
18833965Sjdp
18933965Sjdp  if (size == -2)
19038889Sjdp    size = addrsize;
19133965Sjdp  else if (size == -1)
19233965Sjdp    size = 0;
19333965Sjdp
19433965Sjdp  if (byte > 240)
19533965Sjdp    {
19689857Sobrien      /* Lets write out that record and do another one.  */
19733965Sjdp      checksum (file, ptr, *idx, code | 0x1000);
19833965Sjdp      *idx = 16;
19933965Sjdp      byte = *idx / 8;
20033965Sjdp    }
20189857Sobrien
20233965Sjdp  switch (size)
20333965Sjdp    {
20433965Sjdp    case 0:
20533965Sjdp      break;
20633965Sjdp    case 1:
20733965Sjdp      ptr[byte] = n;
20833965Sjdp      break;
20933965Sjdp    case 2:
21033965Sjdp      ptr[byte + 0] = n >> 8;
21133965Sjdp      ptr[byte + 1] = n;
21233965Sjdp      break;
21333965Sjdp    case 4:
21433965Sjdp      ptr[byte + 0] = n >> 24;
21533965Sjdp      ptr[byte + 1] = n >> 16;
21633965Sjdp      ptr[byte + 2] = n >> 8;
21733965Sjdp      ptr[byte + 3] = n >> 0;
21833965Sjdp      break;
21933965Sjdp    default:
22033965Sjdp      abort ();
22133965Sjdp    }
22233965Sjdp  *idx += size * 8;
22333965Sjdp}
22433965Sjdp
22533965Sjdpstatic void
226218822SdimwriteBITS (int val, unsigned char *ptr, int *idx, int size)
22733965Sjdp{
22833965Sjdp  int byte = *idx / 8;
22933965Sjdp  int bit = *idx % 8;
23033965Sjdp  int old;
23189857Sobrien
23233965Sjdp  *idx += size;
23333965Sjdp
23433965Sjdp  old = ptr[byte];
23589857Sobrien  /* Turn off all about to change bits.  */
23633965Sjdp  old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1));
23789857Sobrien  /* Turn on the bits we want.  */
23833965Sjdp  old |= (val & ((1 << size) - 1)) << (8 - bit - size);
23933965Sjdp  ptr[byte] = old;
24033965Sjdp}
24133965Sjdp
24233965Sjdpstatic void
243218822SdimwriteBARRAY (barray data, unsigned char *ptr, int *idx,
244218822Sdim	     int size ATTRIBUTE_UNUSED, FILE *file)
24533965Sjdp{
24633965Sjdp  int i;
24789857Sobrien
24833965Sjdp  writeINT (data.len, ptr, idx, 1, file);
24933965Sjdp  for (i = 0; i < data.len; i++)
25089857Sobrien    writeINT (data.data[i], ptr, idx, 1, file);
25133965Sjdp}
25233965Sjdp
25333965Sjdpstatic void
254218822SdimwriteCHARS (char *string, unsigned char *ptr, int *idx, int size, FILE *file)
25533965Sjdp{
25633965Sjdp  int i = *idx / 8;
25733965Sjdp
25833965Sjdp  if (i > 240)
25933965Sjdp    {
26089857Sobrien      /* Lets write out that record and do another one.  */
26133965Sjdp      checksum (file, ptr, *idx, code | 0x1000);
26233965Sjdp      *idx = 16;
26333965Sjdp      i = *idx / 8;
26433965Sjdp    }
26533965Sjdp
26633965Sjdp  if (size == 0)
26733965Sjdp    {
26889857Sobrien      /* Variable length string.  */
26933965Sjdp      size = strlen (string);
27033965Sjdp      ptr[i++] = size;
27133965Sjdp    }
27233965Sjdp
27389857Sobrien  /* BUG WAITING TO HAPPEN.  */
27433965Sjdp  memcpy (ptr + i, string, size);
27533965Sjdp  i += size;
27633965Sjdp  *idx = i * 8;
27733965Sjdp}
27833965Sjdp
27933965Sjdp#define SYSROFF_SWAP_OUT
28033965Sjdp#include "sysroff.c"
28133965Sjdp
28233965Sjdpstatic char *rname_sh[] =
28333965Sjdp{
28433965Sjdp  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
28533965Sjdp};
28633965Sjdp
28733965Sjdpstatic char *rname_h8300[] =
28833965Sjdp{
28933965Sjdp  "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR"
29033965Sjdp};
29133965Sjdp
29233965Sjdpstatic void
293130561Sobrienwr_tr (void)
29433965Sjdp{
29589857Sobrien  /* The TR block is not normal - it doesn't have any contents.  */
29633965Sjdp
29789857Sobrien  static char b[] =
29889857Sobrien    {
29989857Sobrien      0xff,			/* IT */
30089857Sobrien      0x03,			/* RL */
30189857Sobrien      0xfd,			/* CS */
30289857Sobrien    };
30333965Sjdp  fwrite (b, 1, sizeof (b), file);
30433965Sjdp}
30533965Sjdp
30633965Sjdpstatic void
307130561Sobrienwr_un (struct coff_ofile *ptr, struct coff_sfile *sfile, int first,
308130561Sobrien       int nsecs ATTRIBUTE_UNUSED)
30933965Sjdp{
31033965Sjdp  struct IT_un un;
31133965Sjdp  struct coff_symbol *s;
31233965Sjdp
31333965Sjdp  un.spare1 = 0;
31433965Sjdp
31538889Sjdp  if (bfd_get_file_flags (abfd) & EXEC_P)
31633965Sjdp    un.format = FORMAT_LM;
31733965Sjdp  else
31833965Sjdp    un.format = FORMAT_OM;
31933965Sjdp  un.spare1 = 0;
32033965Sjdp
321218822Sdim  /* Don't count the abs section.  */
322218822Sdim  un.nsections = ptr->nsections - 1;
32333965Sjdp
32433965Sjdp  un.nextdefs = 0;
32533965Sjdp  un.nextrefs = 0;
32689857Sobrien  /* Count all the undefined and defined variables with global scope.  */
32733965Sjdp
32833965Sjdp  if (first)
32933965Sjdp    {
33033965Sjdp      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
33133965Sjdp	{
33233965Sjdp	  if (s->visible->type == coff_vis_ext_def
33333965Sjdp	      || s->visible->type == coff_vis_common)
33433965Sjdp	    un.nextdefs++;
33533965Sjdp
33633965Sjdp	  if (s->visible->type == coff_vis_ext_ref)
33733965Sjdp	    un.nextrefs++;
33833965Sjdp	}
33933965Sjdp    }
34038889Sjdp  un.tool = toolname;
34133965Sjdp  un.tcd = DATE;
34233965Sjdp  un.linker = "L_GX00";
34333965Sjdp  un.lcd = DATE;
34433965Sjdp  un.name = sfile->name;
34533965Sjdp  sysroff_swap_un_out (file, &un);
34633965Sjdp}
34733965Sjdp
34833965Sjdpstatic void
349130561Sobrienwr_hd (struct coff_ofile *p)
35033965Sjdp{
35133965Sjdp  struct IT_hd hd;
35233965Sjdp
35333965Sjdp  hd.spare1 = 0;
35438889Sjdp  if (bfd_get_file_flags (abfd) & EXEC_P)
35589857Sobrien    hd.mt = MTYPE_ABS_LM;
35633965Sjdp  else
35789857Sobrien    hd.mt = MTYPE_OMS_OR_LMS;
35889857Sobrien
35933965Sjdp  hd.cd = DATE;
36033965Sjdp
36133965Sjdp  hd.nu = p->nsources;		/* Always one unit */
36233965Sjdp  hd.code = 0;			/* Always ASCII */
36333965Sjdp  hd.ver = "0200";		/* Version 2.00 */
36489857Sobrien
36538889Sjdp  switch (bfd_get_arch (abfd))
36633965Sjdp    {
36733965Sjdp    case bfd_arch_h8300:
36833965Sjdp      hd.au = 8;
36933965Sjdp      hd.si = 0;
37033965Sjdp      hd.spcsz = 32;
37133965Sjdp      hd.segsz = 0;
37233965Sjdp      hd.segsh = 0;
37338889Sjdp      switch (bfd_get_mach (abfd))
37438889Sjdp	{
37538889Sjdp	case bfd_mach_h8300:
37638889Sjdp	  hd.cpu = "H8300";
37738889Sjdp	  hd.afl = 2;
37838889Sjdp	  addrsize = 2;
37938889Sjdp	  toolname = "C_H8/300";
38038889Sjdp	  break;
38138889Sjdp	case bfd_mach_h8300h:
38238889Sjdp	  hd.cpu = "H8300H";
38338889Sjdp	  hd.afl = 4;
38438889Sjdp	  addrsize = 4;
38538889Sjdp	  toolname = "C_H8/300H";
38638889Sjdp	  break;
38738889Sjdp	case bfd_mach_h8300s:
38838889Sjdp	  hd.cpu = "H8300S";
38938889Sjdp	  hd.afl = 4;
39038889Sjdp	  addrsize = 4;
39138889Sjdp	  toolname = "C_H8/300S";
39238889Sjdp	  break;
39338889Sjdp	default:
39438889Sjdp	  abort();
39538889Sjdp	}
39638889Sjdp      rnames = rname_h8300;
39733965Sjdp      break;
39833965Sjdp    case bfd_arch_sh:
39933965Sjdp      hd.au = 8;
40033965Sjdp      hd.si = 0;
40133965Sjdp      hd.afl = 4;
40233965Sjdp      hd.spcsz = 32;
40333965Sjdp      hd.segsz = 0;
40433965Sjdp      hd.segsh = 0;
40533965Sjdp      hd.cpu = "SH";
40638889Sjdp      addrsize = 4;
40738889Sjdp      toolname = "C_SH";
40838889Sjdp      rnames = rname_sh;
40933965Sjdp      break;
41033965Sjdp    default:
41133965Sjdp      abort ();
41233965Sjdp    }
41333965Sjdp
41438889Sjdp  if (! bfd_get_file_flags(abfd) & EXEC_P)
41533965Sjdp    {
41633965Sjdp      hd.ep = 0;
41733965Sjdp    }
41833965Sjdp  else
41933965Sjdp    {
42033965Sjdp      hd.ep = 1;
42133965Sjdp      hd.uan = 0;
42233965Sjdp      hd.sa = 0;
42333965Sjdp      hd.sad = 0;
42433965Sjdp      hd.address = bfd_get_start_address (abfd);
42533965Sjdp    }
42633965Sjdp
42733965Sjdp  hd.os = "";
42833965Sjdp  hd.sys = "";
42938889Sjdp  hd.mn = strip_suffix (bfd_get_filename (abfd));
43033965Sjdp
43133965Sjdp  sysroff_swap_hd_out (file, &hd);
43233965Sjdp}
43333965Sjdp
43433965Sjdp
43533965Sjdpstatic void
436130561Sobrienwr_sh (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_section *sec)
43733965Sjdp{
43833965Sjdp  struct IT_sh sh;
43933965Sjdp  sh.unit = 0;
44033965Sjdp  sh.section = sec->number;
44133965Sjdp#ifdef FOOP1
44233965Sjdp  sh.section = 0;
44333965Sjdp#endif
44433965Sjdp  sysroff_swap_sh_out (file, &sh);
44533965Sjdp}
44633965Sjdp
44733965Sjdp
44833965Sjdpstatic void
449130561Sobrienwr_ob (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_section *section)
45033965Sjdp{
45138889Sjdp  bfd_size_type i;
45233965Sjdp  int first = 1;
45333965Sjdp  unsigned char stuff[200];
45433965Sjdp
45533965Sjdp  i = 0;
456218822Sdim  while (i < bfd_get_section_size (section->bfd_section))
45733965Sjdp    {
45833965Sjdp      struct IT_ob ob;
45989857Sobrien      int todo = 200;		/* Copy in 200 byte lumps.  */
46089857Sobrien
46133965Sjdp      ob.spare = 0;
462218822Sdim      if (i + todo > bfd_get_section_size (section->bfd_section))
463218822Sdim	todo = bfd_get_section_size (section->bfd_section) - i;
46433965Sjdp
46533965Sjdp      if (first)
46633965Sjdp	{
46733965Sjdp	  ob.saf = 1;
46838889Sjdp	  if (bfd_get_file_flags (abfd) & EXEC_P)
46933965Sjdp	    ob.address = section->address;
47033965Sjdp	  else
47133965Sjdp	    ob.address = 0;
47233965Sjdp
47333965Sjdp	  first = 0;
47433965Sjdp	}
47533965Sjdp      else
47633965Sjdp	{
47733965Sjdp	  ob.saf = 0;
47833965Sjdp	}
47933965Sjdp
48089857Sobrien      ob.cpf = 0;		/* Never compress.  */
48133965Sjdp      ob.data.len = todo;
48233965Sjdp      bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo);
48333965Sjdp      ob.data.data = stuff;
48433965Sjdp      sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ );
48533965Sjdp      i += todo;
48633965Sjdp    }
48789857Sobrien
48889857Sobrien  /* Now fill the rest with blanks.  */
48938889Sjdp  while (i < (bfd_size_type) section->size)
49033965Sjdp    {
49133965Sjdp      struct IT_ob ob;
49289857Sobrien      int todo = 200;		/* Copy in 200 byte lumps.  */
49389857Sobrien
49433965Sjdp      ob.spare = 0;
49538889Sjdp      if (i + todo > (bfd_size_type) section->size)
49633965Sjdp	todo = section->size - i;
49733965Sjdp      ob.saf = 0;
49833965Sjdp
49989857Sobrien      ob.cpf = 0;		/* Never compress.  */
50033965Sjdp      ob.data.len = todo;
50133965Sjdp      memset (stuff, 0, todo);
50233965Sjdp      ob.data.data = stuff;
50333965Sjdp      sysroff_swap_ob_out (file, &ob);
50433965Sjdp      i += todo;
50533965Sjdp    }
50689857Sobrien  /* Now fill the rest with blanks.  */
50733965Sjdp}
50833965Sjdp
50933965Sjdpstatic void
510130561Sobrienwr_rl (struct coff_ofile *ptr ATTRIBUTE_UNUSED, struct coff_section *sec)
51133965Sjdp{
51233965Sjdp  int nr = sec->nrelocs;
51333965Sjdp  int i;
51489857Sobrien
51533965Sjdp  for (i = 0; i < nr; i++)
51633965Sjdp    {
51733965Sjdp      struct coff_reloc *r = sec->relocs + i;
51833965Sjdp      struct coff_symbol *ref;
51933965Sjdp      struct IT_rl rl;
52089857Sobrien
52133965Sjdp      rl.apol = 0;
52233965Sjdp      rl.boundary = 0;
52333965Sjdp      rl.segment = 1;
52433965Sjdp      rl.sign = 0;
52533965Sjdp      rl.check = 0;
52633965Sjdp      rl.addr = r->offset;
52733965Sjdp      rl.bitloc = 0;
52889857Sobrien      rl.flen = 32;		/* SH Specific.  */
52989857Sobrien
53089857Sobrien      /* What sort of reloc ? Look in the section to find out.  */
53133965Sjdp      ref = r->symbol;
53233965Sjdp      if (ref->visible->type == coff_vis_ext_ref)
53333965Sjdp	{
53489857Sobrien	  rl.bcount = 4;	/* Always 4 for us.  */
53533965Sjdp	  rl.op = OP_EXT_REF;
53633965Sjdp	  rl.symn = ref->er_number;
53733965Sjdp	}
53833965Sjdp      else if (ref->visible->type == coff_vis_common)
53933965Sjdp	{
54089857Sobrien	  rl.bcount = 11;	/* Always 11 for us.  */
54133965Sjdp	  rl.op = OP_SEC_REF;
54233965Sjdp	  rl.secn = ref->where->section->number;
54333965Sjdp	  rl.copcode_is_3 = 3;
54433965Sjdp	  rl.alength_is_4 = 4;
54533965Sjdp	  rl.addend = ref->where->offset - ref->where->section->address;
54633965Sjdp	  rl.aopcode_is_0x20 = 0x20;
54733965Sjdp	}
54833965Sjdp      else
54933965Sjdp	{
55089857Sobrien	  rl.bcount = 11;	/* Always 11 for us.  */
55133965Sjdp	  rl.op = OP_SEC_REF;
55233965Sjdp	  rl.secn = ref->where->section->number;
55333965Sjdp	  rl.copcode_is_3 = 3;
55433965Sjdp	  rl.alength_is_4 = 4;
55533965Sjdp	  rl.addend = -ref->where->section->address;
55633965Sjdp	  rl.aopcode_is_0x20 = 0x20;
55733965Sjdp	}
55889857Sobrien
55933965Sjdp      rl.end = 0xff;
56089857Sobrien
56189857Sobrien      if (   rl.op == OP_SEC_REF
56233965Sjdp	  || rl.op == OP_EXT_REF)
56389857Sobrien	sysroff_swap_rl_out (file, &rl);
56433965Sjdp    }
56533965Sjdp}
56633965Sjdp
56733965Sjdpstatic void
568130561Sobrienwr_object_body (struct coff_ofile *p)
56933965Sjdp{
57033965Sjdp  int i;
57189857Sobrien
57233965Sjdp  for (i = 1; i < p->nsections; i++)
57333965Sjdp    {
57433965Sjdp      wr_sh (p, p->sections + i);
57533965Sjdp      wr_ob (p, p->sections + i);
57633965Sjdp      wr_rl (p, p->sections + i);
57733965Sjdp    }
57833965Sjdp}
57933965Sjdp
58033965Sjdpstatic void
581130561Sobrienwr_dps_start (struct coff_sfile *sfile,
582130561Sobrien	      struct coff_section *section ATTRIBUTE_UNUSED,
583130561Sobrien	      struct coff_scope *scope, int type, int nest)
58433965Sjdp{
58533965Sjdp  struct IT_dps dps;
58689857Sobrien
58733965Sjdp  dps.end = 0;
58833965Sjdp  dps.opt = 0;
58933965Sjdp  dps.type = type;
59089857Sobrien
59133965Sjdp  if (scope->sec)
59233965Sjdp    {
59333965Sjdp      dps.san = scope->sec->number;
59433965Sjdp      dps.address = scope->offset - find_base (sfile, scope->sec);
59533965Sjdp      dps.block_size = scope->size;
59689857Sobrien
59733965Sjdp      if (debug)
59833965Sjdp	{
59933965Sjdp	  printf ("DPS %s %d %x\n",
60033965Sjdp		  sfile->name,
60133965Sjdp		  nest,
60233965Sjdp		  dps.address);
60333965Sjdp	}
60433965Sjdp    }
60533965Sjdp  else
60633965Sjdp    {
60733965Sjdp      dps.san = 0;
60833965Sjdp      dps.address = 0;
60933965Sjdp      dps.block_size = 0;
61033965Sjdp    }
61133965Sjdp
61233965Sjdp  dps.nesting = nest;
61333965Sjdp  dps.neg = 0x1001;
61433965Sjdp  sysroff_swap_dps_out (file, &dps);
61533965Sjdp}
61633965Sjdp
61733965Sjdpstatic void
618130561Sobrienwr_dps_end (struct coff_section *section ATTRIBUTE_UNUSED,
619130561Sobrien	    struct coff_scope *scope ATTRIBUTE_UNUSED, int type)
62033965Sjdp{
62133965Sjdp  struct IT_dps dps;
62289857Sobrien
62333965Sjdp  dps.end = 1;
62433965Sjdp  dps.type = type;
62533965Sjdp  sysroff_swap_dps_out (file, &dps);
62633965Sjdp}
62733965Sjdp
62833965Sjdpstatic int *
629130561Sobriennints (int x)
63033965Sjdp{
63133965Sjdp  return (int *) (xcalloc (sizeof (int), x));
63233965Sjdp}
63333965Sjdp
63433965Sjdpstatic void
635130561Sobrienwalk_tree_type_1 (struct coff_sfile *sfile, struct coff_symbol *symbol,
636130561Sobrien		  struct coff_type *type, int nest)
63733965Sjdp{
63833965Sjdp  switch (type->type)
63933965Sjdp    {
64033965Sjdp    case coff_secdef_type:
64133965Sjdp    case coff_basic_type:
64233965Sjdp      {
64333965Sjdp	struct IT_dbt dbt;
64433965Sjdp
64533965Sjdp	switch (type->u.basic)
64633965Sjdp	  {
64733965Sjdp	  case T_NULL:
64833965Sjdp	  case T_VOID:
64933965Sjdp	    dbt.btype = BTYPE_VOID;
65033965Sjdp	    dbt.sign = BTYPE_UNSPEC;
65133965Sjdp	    dbt.fptype = FPTYPE_NOTSPEC;
65233965Sjdp	    break;
65389857Sobrien
65433965Sjdp	  case T_CHAR:
65533965Sjdp	    dbt.btype = BTYPE_CHAR;
65633965Sjdp	    dbt.sign = BTYPE_UNSPEC;
65733965Sjdp	    dbt.fptype = FPTYPE_NOTSPEC;
65833965Sjdp	    break;
65989857Sobrien
66033965Sjdp	  case T_SHORT:
66133965Sjdp	  case T_INT:
66233965Sjdp	  case T_LONG:
66333965Sjdp	    dbt.btype = BTYPE_INT;
66433965Sjdp	    dbt.sign = SIGN_SIGNED;
66533965Sjdp	    dbt.fptype = FPTYPE_NOTSPEC;
66633965Sjdp	    break;
66789857Sobrien
66833965Sjdp	  case T_FLOAT:
66933965Sjdp	    dbt.btype = BTYPE_FLOAT;
67033965Sjdp	    dbt.fptype = FPTYPE_SINGLE;
67133965Sjdp	    break;
67289857Sobrien
67333965Sjdp	  case T_DOUBLE:
67433965Sjdp	    dbt.btype = BTYPE_FLOAT;
67533965Sjdp	    dbt.fptype = FPTYPE_DOUBLE;
67633965Sjdp	    break;
67789857Sobrien
67833965Sjdp	  case T_LNGDBL:
67933965Sjdp	    dbt.btype = BTYPE_FLOAT;
68033965Sjdp	    dbt.fptype = FPTYPE_EXTENDED;
68133965Sjdp	    break;
68289857Sobrien
68333965Sjdp	  case T_UCHAR:
68433965Sjdp	    dbt.btype = BTYPE_CHAR;
68533965Sjdp	    dbt.sign = SIGN_UNSIGNED;
68633965Sjdp	    dbt.fptype = FPTYPE_NOTSPEC;
68733965Sjdp	    break;
68889857Sobrien
68933965Sjdp	  case T_USHORT:
69033965Sjdp	  case T_UINT:
69133965Sjdp	  case T_ULONG:
69233965Sjdp	    dbt.btype = BTYPE_INT;
69333965Sjdp	    dbt.sign = SIGN_UNSIGNED;
69433965Sjdp	    dbt.fptype = FPTYPE_NOTSPEC;
69533965Sjdp	    break;
69633965Sjdp	  }
69789857Sobrien
69833965Sjdp	dbt.bitsize = type->size;
69933965Sjdp	dbt.neg = 0x1001;
70033965Sjdp	sysroff_swap_dbt_out (file, &dbt);
70133965Sjdp	break;
70233965Sjdp      }
70389857Sobrien
70433965Sjdp    case coff_pointer_type:
70533965Sjdp      {
70633965Sjdp	struct IT_dpt dpt;
70789857Sobrien
708218822Sdim	dpt.dunno = 0;
70933965Sjdp	walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1);
71033965Sjdp	dpt.neg = 0x1001;
71133965Sjdp	sysroff_swap_dpt_out (file, &dpt);
71233965Sjdp	break;
71333965Sjdp      }
71433965Sjdp
71533965Sjdp    case coff_function_type:
71633965Sjdp      {
71733965Sjdp	struct IT_dfp dfp;
71833965Sjdp	struct coff_symbol *param;
71989857Sobrien
72033965Sjdp	dfp.end = 0;
72133965Sjdp	dfp.spare = 0;
72233965Sjdp	dfp.nparams = type->u.function.parameters->nvars;
72333965Sjdp	dfp.neg = 0x1001;
72433965Sjdp
72533965Sjdp	walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1);
72633965Sjdp
72733965Sjdp	sysroff_swap_dfp_out (file, &dfp);
72833965Sjdp
72933965Sjdp	for (param = type->u.function.parameters->vars_head;
73033965Sjdp	     param;
73133965Sjdp	     param = param->next)
73289857Sobrien	  walk_tree_symbol (sfile, 0, param, nest);
73389857Sobrien
73433965Sjdp	dfp.end = 1;
73533965Sjdp	sysroff_swap_dfp_out (file, &dfp);
73633965Sjdp	break;
73733965Sjdp      }
73833965Sjdp
73933965Sjdp    case coff_structdef_type:
74033965Sjdp      {
74133965Sjdp	struct IT_dbt dbt;
74233965Sjdp	struct IT_dds dds;
74333965Sjdp	struct coff_symbol *member;
74489857Sobrien
74533965Sjdp	dds.spare = 0;
74633965Sjdp	dbt.btype = BTYPE_STRUCT;
74733965Sjdp	dbt.bitsize = type->size;
74833965Sjdp	dbt.sign = SIGN_UNSPEC;
74933965Sjdp	dbt.fptype = FPTYPE_NOTSPEC;
75033965Sjdp	dbt.sid = get_member_id (type->u.astructdef.idx);
75133965Sjdp	dbt.neg = 0x1001;
75233965Sjdp	sysroff_swap_dbt_out (file, &dbt);
75333965Sjdp	dds.end = 0;
75433965Sjdp	dds.neg = 0x1001;
75533965Sjdp	sysroff_swap_dds_out (file, &dds);
75689857Sobrien
75733965Sjdp	for (member = type->u.astructdef.elements->vars_head;
75833965Sjdp	     member;
75933965Sjdp	     member = member->next)
76089857Sobrien	  walk_tree_symbol (sfile, 0, member, nest + 1);
76133965Sjdp
76233965Sjdp	dds.end = 1;
76333965Sjdp	sysroff_swap_dds_out (file, &dds);
76433965Sjdp
76533965Sjdp      }
76633965Sjdp      break;
76789857Sobrien
76833965Sjdp    case coff_structref_type:
76933965Sjdp      {
77033965Sjdp	struct IT_dbt dbt;
77189857Sobrien
77233965Sjdp	dbt.btype = BTYPE_TAG;
77333965Sjdp	dbt.bitsize = type->size;
77433965Sjdp	dbt.sign = SIGN_UNSPEC;
77533965Sjdp	dbt.fptype = FPTYPE_NOTSPEC;
77689857Sobrien
77733965Sjdp	if (type->u.astructref.ref)
77889857Sobrien	  dbt.sid = get_member_id (type->u.astructref.ref->number);
77933965Sjdp	else
78089857Sobrien	  dbt.sid = 0;
78133965Sjdp
78233965Sjdp	dbt.neg = 0x1001;
78333965Sjdp	sysroff_swap_dbt_out (file, &dbt);
78433965Sjdp      }
78533965Sjdp      break;
78689857Sobrien
78733965Sjdp    case coff_array_type:
78833965Sjdp      {
78933965Sjdp	struct IT_dar dar;
79033965Sjdp	int j;
79189857Sobrien	int dims = 1;		/* Only output one dimension at a time.  */
79289857Sobrien
79333965Sjdp	dar.dims = dims;
79433965Sjdp	dar.variable = nints (dims);
79533965Sjdp	dar.subtype = nints (dims);
79633965Sjdp	dar.spare = nints (dims);
79733965Sjdp	dar.max_variable = nints (dims);
79833965Sjdp	dar.maxspare = nints (dims);
79933965Sjdp	dar.max = nints (dims);
80033965Sjdp	dar.min_variable = nints (dims);
80133965Sjdp	dar.min = nints (dims);
80233965Sjdp	dar.minspare = nints (dims);
80333965Sjdp	dar.neg = 0x1001;
80433965Sjdp	dar.length = type->size / type->u.array.dim;
80589857Sobrien
80633965Sjdp	for (j = 0; j < dims; j++)
80733965Sjdp	  {
80833965Sjdp	    dar.variable[j] = VARIABLE_FIXED;
80933965Sjdp	    dar.subtype[j] = SUB_INTEGER;
81033965Sjdp	    dar.spare[j] = 0;
81133965Sjdp	    dar.max_variable[j] = 0;
81233965Sjdp	    dar.max[j] = type->u.array.dim;
81333965Sjdp	    dar.min_variable[j] = 0;
81433965Sjdp	    dar.min[j] = 1;	/* Why isn't this 0 ? */
81533965Sjdp	  }
81633965Sjdp	walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1);
81733965Sjdp	sysroff_swap_dar_out (file, &dar);
81833965Sjdp      }
81933965Sjdp      break;
82089857Sobrien
82133965Sjdp    case coff_enumdef_type:
82233965Sjdp      {
82333965Sjdp	struct IT_dbt dbt;
82433965Sjdp	struct IT_den den;
82533965Sjdp	struct coff_symbol *member;
82689857Sobrien
82733965Sjdp	dbt.btype = BTYPE_ENUM;
82833965Sjdp	dbt.bitsize = type->size;
82933965Sjdp	dbt.sign = SIGN_UNSPEC;
83033965Sjdp	dbt.fptype = FPTYPE_NOTSPEC;
83133965Sjdp	dbt.sid = get_member_id (type->u.aenumdef.idx);
83233965Sjdp	dbt.neg = 0x1001;
83333965Sjdp	sysroff_swap_dbt_out (file, &dbt);
83433965Sjdp
83533965Sjdp	den.end = 0;
83633965Sjdp	den.neg = 0x1001;
83733965Sjdp	den.spare = 0;
83833965Sjdp	sysroff_swap_den_out (file, &den);
83989857Sobrien
84033965Sjdp	for (member = type->u.aenumdef.elements->vars_head;
84133965Sjdp	     member;
84233965Sjdp	     member = member->next)
84389857Sobrien	  walk_tree_symbol (sfile, 0, member, nest + 1);
84433965Sjdp
84533965Sjdp	den.end = 1;
84633965Sjdp	sysroff_swap_den_out (file, &den);
84733965Sjdp      }
84833965Sjdp      break;
84933965Sjdp
85033965Sjdp    case coff_enumref_type:
85133965Sjdp      {
85233965Sjdp	struct IT_dbt dbt;
85389857Sobrien
85433965Sjdp	dbt.btype = BTYPE_TAG;
85533965Sjdp	dbt.bitsize = type->size;
85633965Sjdp	dbt.sign = SIGN_UNSPEC;
85733965Sjdp	dbt.fptype = FPTYPE_NOTSPEC;
85833965Sjdp	dbt.sid = get_member_id (type->u.aenumref.ref->number);
85933965Sjdp	dbt.neg = 0x1001;
86033965Sjdp	sysroff_swap_dbt_out (file, &dbt);
86133965Sjdp      }
86233965Sjdp      break;
86389857Sobrien
86433965Sjdp    default:
86533965Sjdp      abort ();
86633965Sjdp    }
86733965Sjdp}
86833965Sjdp
869104834Sobrien/* Obsolete ?
87033965Sjdp   static void
87133965Sjdp   dty_start ()
87233965Sjdp   {
87333965Sjdp   struct IT_dty dty;
87433965Sjdp   dty.end = 0;
87533965Sjdp   dty.neg = 0x1001;
87633965Sjdp   dty.spare = 0;
87733965Sjdp   sysroff_swap_dty_out (file, &dty);
87833965Sjdp   }
87933965Sjdp
88033965Sjdp   static void
88133965Sjdp   dty_stop ()
88233965Sjdp   {
88333965Sjdp   struct IT_dty dty;
88433965Sjdp   dty.end = 0;
88533965Sjdp   dty.neg = 0x1001;
88633965Sjdp   dty.end = 1;
88733965Sjdp   sysroff_swap_dty_out (file, &dty);
88833965Sjdp   }
88933965Sjdp
89033965Sjdp
89133965Sjdp   static void
89233965Sjdp   dump_tree_structure (sfile, symbol, type, nest)
89333965Sjdp   struct coff_sfile *sfile;
89433965Sjdp   struct coff_symbol *symbol;
89533965Sjdp   struct coff_type *type;
89633965Sjdp   int nest;
89733965Sjdp   {
89833965Sjdp   if (symbol->type->type == coff_function_type)
89933965Sjdp   {
90033965Sjdp
90133965Sjdp
90233965Sjdp   }
90333965Sjdp
90433965Sjdp   }
90533965Sjdp */
90633965Sjdp
90733965Sjdpstatic void
908130561Sobrienwalk_tree_type (struct coff_sfile *sfile, struct coff_symbol *symbol,
909130561Sobrien		struct coff_type *type, int nest)
91033965Sjdp{
91133965Sjdp  if (symbol->type->type == coff_function_type)
91233965Sjdp    {
91389857Sobrien      struct IT_dty dty;
91433965Sjdp
91533965Sjdp      dty.end = 0;
91633965Sjdp      dty.neg = 0x1001;
91733965Sjdp
91833965Sjdp      sysroff_swap_dty_out (file, &dty);
91933965Sjdp      walk_tree_type_1 (sfile, symbol, type, nest);
92033965Sjdp      dty.end = 1;
92133965Sjdp      sysroff_swap_dty_out (file, &dty);
92233965Sjdp
92333965Sjdp      wr_dps_start (sfile,
92433965Sjdp		    symbol->where->section,
92533965Sjdp		    symbol->type->u.function.code,
92633965Sjdp		    BLOCK_TYPE_FUNCTION, nest);
92733965Sjdp      wr_dps_start (sfile, symbol->where->section,
92833965Sjdp		    symbol->type->u.function.code,
92933965Sjdp		    BLOCK_TYPE_BLOCK, nest);
93033965Sjdp      walk_tree_scope (symbol->where->section,
93133965Sjdp		       sfile,
93233965Sjdp		       symbol->type->u.function.code,
93333965Sjdp		       nest + 1, BLOCK_TYPE_BLOCK);
93433965Sjdp
93533965Sjdp      wr_dps_end (symbol->where->section,
93633965Sjdp		  symbol->type->u.function.code,
93733965Sjdp		  BLOCK_TYPE_BLOCK);
93833965Sjdp      wr_dps_end (symbol->where->section,
93933965Sjdp		  symbol->type->u.function.code, BLOCK_TYPE_FUNCTION);
94033965Sjdp    }
94133965Sjdp  else
94233965Sjdp    {
94333965Sjdp      struct IT_dty dty;
94489857Sobrien
94533965Sjdp      dty.end = 0;
94633965Sjdp      dty.neg = 0x1001;
94733965Sjdp      sysroff_swap_dty_out (file, &dty);
94833965Sjdp      walk_tree_type_1 (sfile, symbol, type, nest);
94933965Sjdp      dty.end = 1;
95033965Sjdp      sysroff_swap_dty_out (file, &dty);
95133965Sjdp    }
95233965Sjdp}
95333965Sjdp
95433965Sjdpstatic void
955130561Sobrienwalk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBUTE_UNUSED, struct coff_symbol *symbol, int nest)
95633965Sjdp{
95733965Sjdp  struct IT_dsy dsy;
95833965Sjdp
95989857Sobrien  memset (&dsy, 0, sizeof(dsy));
96033965Sjdp  dsy.nesting = nest;
96133965Sjdp
96233965Sjdp  switch (symbol->type->type)
96333965Sjdp    {
96433965Sjdp    case coff_function_type:
96533965Sjdp      dsy.type = STYPE_FUNC;
96633965Sjdp      dsy.assign = 1;
96733965Sjdp      break;
96889857Sobrien
96933965Sjdp    case coff_structref_type:
97033965Sjdp    case coff_pointer_type:
97133965Sjdp    case coff_array_type:
97233965Sjdp    case coff_basic_type:
97333965Sjdp    case coff_enumref_type:
97433965Sjdp      dsy.type = STYPE_VAR;
97533965Sjdp      dsy.assign = 1;
97633965Sjdp      break;
97789857Sobrien
97833965Sjdp    case coff_enumdef_type:
97933965Sjdp      dsy.type = STYPE_TAG;
98033965Sjdp      dsy.assign = 0;
98133965Sjdp      dsy.magic = 2;
98233965Sjdp      break;
98389857Sobrien
98433965Sjdp    case coff_structdef_type:
98533965Sjdp      dsy.type = STYPE_TAG;
98633965Sjdp      dsy.assign = 0;
98733965Sjdp      dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1;
98833965Sjdp      break;
98989857Sobrien
99033965Sjdp    case coff_secdef_type:
99133965Sjdp      return;
99289857Sobrien
99333965Sjdp    default:
99433965Sjdp      abort ();
99533965Sjdp    }
99633965Sjdp
99733965Sjdp  if (symbol->where->where == coff_where_member_of_struct)
99833965Sjdp    {
99933965Sjdp      dsy.assign = 0;
100033965Sjdp      dsy.type = STYPE_MEMBER;
100133965Sjdp    }
100289857Sobrien
100333965Sjdp  if (symbol->where->where == coff_where_member_of_enum)
100433965Sjdp    {
100533965Sjdp      dsy.type = STYPE_ENUM;
100633965Sjdp      dsy.assign = 0;
100733965Sjdp      dsy.evallen = 4;
100833965Sjdp      dsy.evalue = symbol->where->offset;
100933965Sjdp    }
101033965Sjdp
101133965Sjdp  if (symbol->type->type == coff_structdef_type
101233965Sjdp      || symbol->where->where == coff_where_entag
101333965Sjdp      || symbol->where->where == coff_where_strtag)
101433965Sjdp    {
101533965Sjdp      dsy.snumber = get_member_id (symbol->number);
101633965Sjdp    }
101733965Sjdp  else
101833965Sjdp    {
101933965Sjdp      dsy.snumber = get_ordinary_id (symbol->number);
102033965Sjdp    }
102133965Sjdp
102233965Sjdp  dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name;
102333965Sjdp
102433965Sjdp  switch (symbol->visible->type)
102533965Sjdp    {
102633965Sjdp    case coff_vis_common:
102733965Sjdp    case coff_vis_ext_def:
102833965Sjdp      dsy.ainfo = AINFO_STATIC_EXT_DEF;
102933965Sjdp      break;
103089857Sobrien
103133965Sjdp    case coff_vis_ext_ref:
103233965Sjdp      dsy.ainfo = AINFO_STATIC_EXT_REF;
103333965Sjdp      break;
103489857Sobrien
103533965Sjdp    case coff_vis_int_def:
103633965Sjdp      dsy.ainfo = AINFO_STATIC_INT;
103733965Sjdp      break;
103889857Sobrien
103933965Sjdp    case coff_vis_auto:
104033965Sjdp    case coff_vis_autoparam:
104133965Sjdp      dsy.ainfo = AINFO_AUTO;
104233965Sjdp      break;
104389857Sobrien
104433965Sjdp    case coff_vis_register:
104533965Sjdp    case coff_vis_regparam:
104633965Sjdp      dsy.ainfo = AINFO_REG;
104733965Sjdp      break;
104833965Sjdp      break;
104989857Sobrien
105033965Sjdp    case coff_vis_tag:
105133965Sjdp    case coff_vis_member_of_struct:
105233965Sjdp    case coff_vis_member_of_enum:
105333965Sjdp      break;
105489857Sobrien
105533965Sjdp    default:
105633965Sjdp      abort ();
105733965Sjdp    }
105833965Sjdp
105933965Sjdp  dsy.dlength = symbol->type->size;
106089857Sobrien
106133965Sjdp  switch (symbol->where->where)
106233965Sjdp    {
106333965Sjdp    case coff_where_memory:
106433965Sjdp
106533965Sjdp      dsy.section = symbol->where->section->number;
106633965Sjdp#ifdef FOOP
106733965Sjdp      dsy.section = 0;
106833965Sjdp#endif
106933965Sjdp      break;
107089857Sobrien
107133965Sjdp    case coff_where_member_of_struct:
107233965Sjdp    case coff_where_member_of_enum:
107333965Sjdp    case coff_where_stack:
107433965Sjdp    case coff_where_register:
107533965Sjdp    case coff_where_unknown:
107633965Sjdp    case coff_where_strtag:
107733965Sjdp    case coff_where_entag:
107833965Sjdp    case coff_where_typedef:
107933965Sjdp      break;
108089857Sobrien
108133965Sjdp    default:
108233965Sjdp      abort ();
108333965Sjdp    }
108433965Sjdp
108533965Sjdp  switch (symbol->where->where)
108633965Sjdp    {
108733965Sjdp    case coff_where_memory:
108833965Sjdp      dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section);
108933965Sjdp      break;
109089857Sobrien
109133965Sjdp    case coff_where_stack:
109233965Sjdp      dsy.address = symbol->where->offset;
109333965Sjdp      break;
109489857Sobrien
109533965Sjdp    case coff_where_member_of_struct:
109633965Sjdp      if (symbol->where->bitsize)
109733965Sjdp	{
109833965Sjdp	  int bits = (symbol->where->offset * 8 + symbol->where->bitoffset);
109933965Sjdp	  dsy.bitunit = 1;
110033965Sjdp	  dsy.field_len = symbol->where->bitsize;
110133965Sjdp	  dsy.field_off = (bits / 32) * 4;
110233965Sjdp	  dsy.field_bitoff = bits % 32;
110333965Sjdp	}
110433965Sjdp      else
110533965Sjdp	{
110633965Sjdp	  dsy.bitunit = 0;
110733965Sjdp
110833965Sjdp	  dsy.field_len = symbol->type->size;
110933965Sjdp	  dsy.field_off = symbol->where->offset;
111033965Sjdp	}
111133965Sjdp      break;
111289857Sobrien
111333965Sjdp    case coff_where_member_of_enum:
111433965Sjdp      /*      dsy.bitunit = 0;
111533965Sjdp         dsy.field_len  = symbol->type->size;
111633965Sjdp         dsy.field_off = symbol->where->offset; */
111733965Sjdp      break;
111889857Sobrien
111933965Sjdp    case coff_where_register:
112033965Sjdp    case coff_where_unknown:
112133965Sjdp    case coff_where_strtag:
112233965Sjdp    case coff_where_entag:
112333965Sjdp    case coff_where_typedef:
112433965Sjdp      break;
112589857Sobrien
112633965Sjdp    default:
112733965Sjdp      abort ();
112833965Sjdp    }
112933965Sjdp
113033965Sjdp  if (symbol->where->where == coff_where_register)
113138889Sjdp    dsy.reg = rnames[symbol->where->offset];
113233965Sjdp
113333965Sjdp  switch (symbol->visible->type)
113433965Sjdp    {
113533965Sjdp    case coff_vis_common:
113689857Sobrien      /* We do this 'cause common C symbols are treated as extdefs.  */
113733965Sjdp    case coff_vis_ext_def:
113833965Sjdp    case coff_vis_ext_ref:
113933965Sjdp      dsy.ename = symbol->name;
114033965Sjdp      break;
114133965Sjdp
114233965Sjdp    case coff_vis_regparam:
114333965Sjdp    case coff_vis_autoparam:
114433965Sjdp      dsy.type = STYPE_PARAMETER;
114533965Sjdp      break;
114633965Sjdp
114733965Sjdp    case coff_vis_int_def:
114833965Sjdp    case coff_vis_auto:
114933965Sjdp    case coff_vis_register:
115033965Sjdp    case coff_vis_tag:
115133965Sjdp    case coff_vis_member_of_struct:
115233965Sjdp    case coff_vis_member_of_enum:
115333965Sjdp      break;
115489857Sobrien
115533965Sjdp    default:
115633965Sjdp      abort ();
115733965Sjdp    }
115833965Sjdp
115933965Sjdp  dsy.sfn = 0;
116033965Sjdp  dsy.sln = 2;
116133965Sjdp  dsy.neg = 0x1001;
116233965Sjdp
116333965Sjdp  sysroff_swap_dsy_out (file, &dsy);
116433965Sjdp
116533965Sjdp  walk_tree_type (sfile, symbol, symbol->type, nest);
116633965Sjdp}
116733965Sjdp
116833965Sjdpstatic void
1169130561Sobrienwalk_tree_scope (struct coff_section *section, struct coff_sfile *sfile, struct coff_scope *scope, int nest, int type)
117033965Sjdp{
117133965Sjdp  struct coff_symbol *vars;
117233965Sjdp  struct coff_scope *child;
117333965Sjdp
117433965Sjdp  if (scope->vars_head
117533965Sjdp      || (scope->list_head && scope->list_head->vars_head))
117633965Sjdp    {
117733965Sjdp      wr_dps_start (sfile, section, scope, type, nest);
117833965Sjdp
117933965Sjdp      if (nest == 0)
118033965Sjdp	wr_globals (tree, sfile, nest + 1);
118133965Sjdp
118233965Sjdp      for (vars = scope->vars_head; vars; vars = vars->next)
118389857Sobrien	walk_tree_symbol (sfile, section, vars, nest);
118433965Sjdp
118533965Sjdp      for (child = scope->list_head; child; child = child->next)
118689857Sobrien	walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK);
118733965Sjdp
118833965Sjdp      wr_dps_end (section, scope, type);
118933965Sjdp    }
119033965Sjdp}
119189857Sobrien
119233965Sjdpstatic void
1193130561Sobrienwalk_tree_sfile (struct coff_section *section, struct coff_sfile *sfile)
119433965Sjdp{
119533965Sjdp  walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT);
119633965Sjdp}
119733965Sjdp
119833965Sjdpstatic void
1199130561Sobrienwr_program_structure (struct coff_ofile *p, struct coff_sfile *sfile)
120033965Sjdp{
120133965Sjdp  walk_tree_sfile (p->sections + 4, sfile);
120233965Sjdp}
120333965Sjdp
120433965Sjdpstatic void
1205130561Sobrienwr_du (struct coff_ofile *p, struct coff_sfile *sfile, int n)
120633965Sjdp{
120733965Sjdp  struct IT_du du;
120833965Sjdp  int lim;
120933965Sjdp  int i;
121033965Sjdp  int j;
121133965Sjdp  unsigned int *lowest = (unsigned *) nints (p->nsections);
121233965Sjdp  unsigned int *highest = (unsigned *) nints (p->nsections);
121389857Sobrien
121438889Sjdp  du.format = bfd_get_file_flags (abfd) & EXEC_P ? 0 : 1;
121533965Sjdp  du.optimized = 0;
121633965Sjdp  du.stackfrmt = 0;
121733965Sjdp  du.spare = 0;
121833965Sjdp  du.unit = n;
121933965Sjdp  du.sections = p->nsections - 1;
122033965Sjdp  du.san = (int *) xcalloc (sizeof (int), du.sections);
122133965Sjdp  du.address = nints (du.sections);
122233965Sjdp  du.length = nints (du.sections);
122333965Sjdp
122433965Sjdp  for (i = 0; i < du.sections; i++)
122533965Sjdp    {
122633965Sjdp      lowest[i] = ~0;
122733965Sjdp      highest[i] = 0;
122833965Sjdp    }
122933965Sjdp
123033965Sjdp  lim = du.sections;
123133965Sjdp  for (j = 0; j < lim; j++)
123233965Sjdp    {
123333965Sjdp      int src = j;
123433965Sjdp      int dst = j;
123589857Sobrien
123633965Sjdp      du.san[dst] = dst;
123789857Sobrien
123833965Sjdp      if (sfile->section[src].init)
123933965Sjdp	{
124033965Sjdp	  du.length[dst]
124133965Sjdp	    = sfile->section[src].high - sfile->section[src].low + 1;
124233965Sjdp	  du.address[dst]
124333965Sjdp	    = sfile->section[src].low;
124433965Sjdp	}
124533965Sjdp      else
124633965Sjdp	{
124733965Sjdp	  du.length[dst] = 0;
124833965Sjdp	  du.address[dst] = 0;
124933965Sjdp	}
125089857Sobrien
125133965Sjdp      if (debug)
125233965Sjdp	{
125333965Sjdp	  if (sfile->section[src].parent)
125433965Sjdp	    {
125533965Sjdp	      printf (" section %6s 0x%08x..0x%08x\n",
125633965Sjdp		      sfile->section[src].parent->name,
125733965Sjdp		      du.address[dst],
125833965Sjdp		      du.address[dst] + du.length[dst] - 1);
125933965Sjdp	    }
126033965Sjdp	}
126189857Sobrien
126233965Sjdp      du.sections = dst + 1;
126333965Sjdp    }
126433965Sjdp
126533965Sjdp  du.tool = "c_gcc";
126633965Sjdp  du.date = DATE;
126733965Sjdp
126833965Sjdp  sysroff_swap_du_out (file, &du);
126933965Sjdp}
127033965Sjdp
127133965Sjdpstatic void
1272130561Sobrienwr_dus (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_sfile *sfile)
127333965Sjdp{
127433965Sjdp  struct IT_dus dus;
127533965Sjdp
127633965Sjdp  dus.efn = 0x1001;
127733965Sjdp  dus.ns = 1;			/* p->nsources; sac 14 jul 94 */
127833965Sjdp  dus.drb = nints (dus.ns);
127933965Sjdp  dus.fname = (char **) xcalloc (sizeof (char *), dus.ns);
128033965Sjdp  dus.spare = nints (dus.ns);
128133965Sjdp  dus.ndir = 0;
128289857Sobrien  /* Find the filenames.  */
128333965Sjdp  dus.drb[0] = 0;
128433965Sjdp  dus.fname[0] = sfile->name;
128533965Sjdp
128633965Sjdp  sysroff_swap_dus_out (file, &dus);
128733965Sjdp
128833965Sjdp}
128933965Sjdp
129033965Sjdp/* Find the offset of the .text section for this sfile in the
129189857Sobrien   .text section for the output file.  */
129233965Sjdp
129333965Sjdpstatic int
1294130561Sobrienfind_base (struct coff_sfile *sfile, struct coff_section *section)
129533965Sjdp{
129633965Sjdp  return sfile->section[section->number].low;
129733965Sjdp}
129877298Sobrien
129933965Sjdpstatic void
1300130561Sobrienwr_dln (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_sfile *sfile,
1301130561Sobrien	int n ATTRIBUTE_UNUSED)
130233965Sjdp{
130333965Sjdp  /* Count up all the linenumbers */
130433965Sjdp
130533965Sjdp  struct coff_symbol *sy;
130633965Sjdp  int lc = 0;
130733965Sjdp  struct IT_dln dln;
130833965Sjdp
130933965Sjdp  int idx;
131033965Sjdp
131133965Sjdp  for (sy = sfile->scope->vars_head;
131233965Sjdp       sy;
131333965Sjdp       sy = sy->next)
131433965Sjdp    {
131533965Sjdp      struct coff_type *t = sy->type;
131633965Sjdp      if (t->type == coff_function_type)
131733965Sjdp	{
131833965Sjdp	  struct coff_line *l = t->u.function.lines;
131933965Sjdp	  if (l)
132033965Sjdp	    lc += l->nlines;
132133965Sjdp	}
132233965Sjdp    }
132333965Sjdp
132433965Sjdp  dln.sfn = nints (lc);
132533965Sjdp  dln.sln = nints (lc);
132633965Sjdp  dln.cc = nints (lc);
132733965Sjdp  dln.section = nints (lc);
132833965Sjdp
132933965Sjdp  dln.from_address = nints (lc);
133033965Sjdp  dln.to_address = nints (lc);
133133965Sjdp
133233965Sjdp
133333965Sjdp  dln.neg = 0x1001;
133433965Sjdp
133533965Sjdp  dln.nln = lc;
133633965Sjdp
133733965Sjdp  /* Run through once more and fill up the structure */
133833965Sjdp  idx = 0;
133933965Sjdp  for (sy = sfile->scope->vars_head;
134033965Sjdp       sy;
134133965Sjdp       sy = sy->next)
134233965Sjdp    {
134333965Sjdp      if (sy->type->type == coff_function_type)
134433965Sjdp	{
134533965Sjdp	  int i;
134633965Sjdp	  struct coff_line *l = sy->type->u.function.lines;
134733965Sjdp	  if (l)
134833965Sjdp	    {
134933965Sjdp	      int base = find_base (sfile, sy->where->section);
135033965Sjdp	      for (i = 0; i < l->nlines; i++)
135133965Sjdp		{
135233965Sjdp		  dln.section[idx] = sy->where->section->number;
135333965Sjdp		  dln.sfn[idx] = 0;
135433965Sjdp		  dln.sln[idx] = l->lines[i];
135533965Sjdp		  dln.from_address[idx] =
135633965Sjdp		    l->addresses[i] + sy->where->section->address - base;
135733965Sjdp		  dln.cc[idx] = 0;
135833965Sjdp		  if (idx)
135933965Sjdp		    dln.to_address[idx - 1] = dln.from_address[idx];
136033965Sjdp		  idx++;
136133965Sjdp
136233965Sjdp		}
136333965Sjdp	      dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2;
136433965Sjdp	    }
136533965Sjdp	}
136633965Sjdp    }
136733965Sjdp  if (lc)
136833965Sjdp    sysroff_swap_dln_out (file, &dln);
136933965Sjdp}
137033965Sjdp
137189857Sobrien/* Write the global symbols out to the debug info.  */
137289857Sobrien
137333965Sjdpstatic void
1374130561Sobrienwr_globals (struct coff_ofile *p, struct coff_sfile *sfile,
1375130561Sobrien	    int n ATTRIBUTE_UNUSED)
137633965Sjdp{
137733965Sjdp  struct coff_symbol *sy;
137889857Sobrien
137933965Sjdp  for (sy = p->symbol_list_head;
138033965Sjdp       sy;
138133965Sjdp       sy = sy->next_in_ofile_list)
138233965Sjdp    {
138333965Sjdp      if (sy->visible->type == coff_vis_ext_def
138433965Sjdp	  || sy->visible->type == coff_vis_ext_ref)
138533965Sjdp	{
138633965Sjdp	  /* Only write out symbols if they belong to
138789857Sobrien	     the current source file.  */
138833965Sjdp	  if (sy->sfile == sfile)
138933965Sjdp	    walk_tree_symbol (sfile, 0, sy, 0);
139033965Sjdp	}
139133965Sjdp    }
139233965Sjdp}
139333965Sjdp
139433965Sjdpstatic void
1395130561Sobrienwr_debug (struct coff_ofile *p)
139633965Sjdp{
139733965Sjdp  struct coff_sfile *sfile;
139833965Sjdp  int n = 0;
139989857Sobrien
140033965Sjdp  for (sfile = p->source_head;
140133965Sjdp       sfile;
140233965Sjdp       sfile = sfile->next)
140333965Sjdp    {
140433965Sjdp      if (debug)
140589857Sobrien	printf ("%s\n", sfile->name);
140689857Sobrien
140733965Sjdp      wr_du (p, sfile, n);
140833965Sjdp      wr_dus (p, sfile);
140933965Sjdp      wr_program_structure (p, sfile);
141033965Sjdp      wr_dln (p, sfile, n);
141133965Sjdp      n++;
141233965Sjdp    }
141333965Sjdp}
141433965Sjdp
141533965Sjdpstatic void
1416130561Sobrienwr_cs (void)
141733965Sjdp{
141833965Sjdp  /* It seems that the CS struct is not normal - the size is wrong
141989857Sobrien     heres one I prepared earlier.  */
142089857Sobrien  static char b[] =
142189857Sobrien    {
142233965Sjdp    0x80,			/* IT */
142333965Sjdp    0x21,			/* RL */
142433965Sjdp    0x00,			/* number of chars in variable length part */
1425104834Sobrien    0x80,			/* hd */
1426104834Sobrien    0x00,			/* hs */
1427104834Sobrien    0x80,			/* un */
1428104834Sobrien    0x00,			/* us */
1429104834Sobrien    0x80,			/* sc */
1430104834Sobrien    0x00,			/* ss */
1431104834Sobrien    0x80,			/* er */
1432104834Sobrien    0x80,			/* ed */
1433104834Sobrien    0x80,			/* sh */
1434104834Sobrien    0x80,			/* ob */
1435104834Sobrien    0x80,			/* rl */
143633965Sjdp    0x80,			/* du */
143733965Sjdp    0x80,			/* dps */
143833965Sjdp    0x80,			/* dsy */
143933965Sjdp    0x80,			/* dty */
144033965Sjdp    0x80,			/* dln */
144133965Sjdp    0x80,			/* dso */
144233965Sjdp    0x80,			/* dus */
144333965Sjdp    0x00,			/* dss */
144433965Sjdp    0x80,			/* dbt */
144533965Sjdp    0x00,			/* dpp */
144633965Sjdp    0x80,			/* dfp */
144733965Sjdp    0x80,			/* den */
144833965Sjdp    0x80,			/* dds */
144933965Sjdp    0x80,			/* dar */
145033965Sjdp    0x80,			/* dpt */
145133965Sjdp    0x00,			/* dul */
145233965Sjdp    0x00,			/* dse */
145333965Sjdp    0x00,			/* dot */
145433965Sjdp    0xDE			/* CS */
145533965Sjdp  };
145633965Sjdp  fwrite (b, 1, sizeof (b), file);
145733965Sjdp}
145833965Sjdp
145933965Sjdp/* Write out the SC records for a unit.  Create an SC
146033965Sjdp   for all the sections which appear in the output file, even
146189857Sobrien   if there isn't an equivalent one on the input.  */
146233965Sjdp
146333965Sjdpstatic int
1464130561Sobrienwr_sc (struct coff_ofile *ptr, struct coff_sfile *sfile)
146533965Sjdp{
146633965Sjdp  int i;
146789857Sobrien  int scount = 0;
146889857Sobrien  /* First work out the total number of sections.  */
146933965Sjdp  int total_sec = ptr->nsections;
147033965Sjdp  struct myinfo
147133965Sjdp    {
147233965Sjdp      struct coff_section *sec;
147333965Sjdp      struct coff_symbol *symbol;
147433965Sjdp    };
147533965Sjdp  struct coff_symbol *symbol;
147633965Sjdp  struct myinfo *info
147733965Sjdp    = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo));
147833965Sjdp
147933965Sjdp
148033965Sjdp  for (i = 0; i < total_sec; i++)
148133965Sjdp    {
148233965Sjdp      info[i].sec = ptr->sections + i;
148333965Sjdp      info[i].symbol = 0;
148433965Sjdp    }
148533965Sjdp
148633965Sjdp  for (symbol = sfile->scope->vars_head;
148733965Sjdp       symbol;
148833965Sjdp       symbol = symbol->next)
148933965Sjdp    {
149033965Sjdp
149133965Sjdp      if (symbol->type->type == coff_secdef_type)
149233965Sjdp	{
149333965Sjdp	  for (i = 0; i < total_sec; i++)
149433965Sjdp	    {
149533965Sjdp	      if (symbol->where->section == info[i].sec)
149633965Sjdp		{
149733965Sjdp		  info[i].symbol = symbol;
149833965Sjdp		  break;
149933965Sjdp		}
150033965Sjdp	    }
150133965Sjdp	}
150233965Sjdp    }
150333965Sjdp
150433965Sjdp  /* Now output all the section info, and fake up some stuff for sections
150589857Sobrien     we don't have.  */
150633965Sjdp  for (i = 1; i < total_sec; i++)
150733965Sjdp    {
150833965Sjdp      struct IT_sc sc;
150933965Sjdp      char *name;
151089857Sobrien
151133965Sjdp      symbol = info[i].symbol;
151233965Sjdp      sc.spare = 0;
151333965Sjdp      sc.spare1 = 0;
151489857Sobrien
151533965Sjdp      if (!symbol)
151633965Sjdp	{
151789857Sobrien	  /* Don't have a symbol set aside for this section, which means
151889857Sobrien	     that nothing in this file does anything for the section.  */
151938889Sjdp	  sc.format = !(bfd_get_file_flags (abfd) & EXEC_P);
152033965Sjdp	  sc.addr = 0;
152133965Sjdp	  sc.length = 0;
152233965Sjdp	  name = info[i].sec->name;
152333965Sjdp	}
152433965Sjdp      else
152533965Sjdp	{
152638889Sjdp	  if (bfd_get_file_flags (abfd) & EXEC_P)
152733965Sjdp	    {
152833965Sjdp	      sc.format = 0;
152933965Sjdp	      sc.addr = symbol->where->offset;
153033965Sjdp	    }
153133965Sjdp	  else
153233965Sjdp	    {
153333965Sjdp	      sc.format = 1;
153433965Sjdp	      sc.addr = 0;
153533965Sjdp	    }
153633965Sjdp	  sc.length = symbol->type->size;
153733965Sjdp	  name = symbol->name;
153833965Sjdp	}
153933965Sjdp
154033965Sjdp      sc.align = 4;
154133965Sjdp      sc.concat = CONCAT_SIMPLE;
154233965Sjdp      sc.read = 3;
154333965Sjdp      sc.write = 3;
154433965Sjdp      sc.exec = 3;
154533965Sjdp      sc.init = 3;
154633965Sjdp      sc.mode = 3;
154733965Sjdp      sc.spare = 0;
154833965Sjdp      sc.segadd = 0;
154989857Sobrien      sc.spare1 = 0;		/* If not zero, then it doesn't work.  */
155033965Sjdp      sc.name = section_translate (name);
155189857Sobrien
155233965Sjdp      if (strlen (sc.name) == 1)
155333965Sjdp	{
155433965Sjdp	  switch (sc.name[0])
155533965Sjdp	    {
155633965Sjdp	    case 'D':
155733965Sjdp	    case 'B':
155833965Sjdp	      sc.contents = CONTENTS_DATA;
155933965Sjdp	      break;
156089857Sobrien
156133965Sjdp	    default:
156233965Sjdp	      sc.contents = CONTENTS_CODE;
156333965Sjdp	    }
156433965Sjdp	}
156533965Sjdp      else
156633965Sjdp	{
156733965Sjdp	  sc.contents = CONTENTS_CODE;
156833965Sjdp	}
1569218822Sdim
1570218822Sdim      sysroff_swap_sc_out (file, &sc);
1571218822Sdim      scount++;
157233965Sjdp    }
157389857Sobrien  return scount;
157433965Sjdp}
157533965Sjdp
157689857Sobrien/* Write out the ER records for a unit.  */
157733965Sjdp
157833965Sjdpstatic void
1579130561Sobrienwr_er (struct coff_ofile *ptr, struct coff_sfile *sfile ATTRIBUTE_UNUSED,
1580130561Sobrien       int first)
158133965Sjdp{
158233965Sjdp  int idx = 0;
158333965Sjdp  struct coff_symbol *sym;
158489857Sobrien
158533965Sjdp  if (first)
158633965Sjdp    {
158733965Sjdp      for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list)
158833965Sjdp	{
158933965Sjdp	  if (sym->visible->type == coff_vis_ext_ref)
159033965Sjdp	    {
159133965Sjdp	      struct IT_er er;
159289857Sobrien
159333965Sjdp	      er.spare = 0;
159433965Sjdp	      er.type = ER_NOTSPEC;
159533965Sjdp	      er.name = sym->name;
159633965Sjdp	      sysroff_swap_er_out (file, &er);
159733965Sjdp	      sym->er_number = idx++;
159833965Sjdp	    }
159933965Sjdp	}
160033965Sjdp    }
160133965Sjdp}
160233965Sjdp
160389857Sobrien/* Write out the ED records for a unit.  */
160489857Sobrien
160533965Sjdpstatic void
1606130561Sobrienwr_ed (struct coff_ofile *ptr, struct coff_sfile *sfile ATTRIBUTE_UNUSED,
1607130561Sobrien       int first)
160833965Sjdp{
160933965Sjdp  struct coff_symbol *s;
161089857Sobrien
161133965Sjdp  if (first)
161233965Sjdp    {
161333965Sjdp      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
161433965Sjdp	{
161533965Sjdp	  if (s->visible->type == coff_vis_ext_def
161633965Sjdp	      || s->visible->type == coff_vis_common)
161733965Sjdp	    {
161833965Sjdp	      struct IT_ed ed;
161933965Sjdp
162033965Sjdp	      ed.section = s->where->section->number;
162133965Sjdp	      ed.spare = 0;
162289857Sobrien
162333965Sjdp	      if (s->where->section->data)
162433965Sjdp		{
162533965Sjdp		  ed.type = ED_TYPE_DATA;
162633965Sjdp		}
162733965Sjdp	      else if (s->where->section->code & SEC_CODE)
162833965Sjdp		{
162933965Sjdp		  ed.type = ED_TYPE_ENTRY;
163033965Sjdp		}
163133965Sjdp	      else
163233965Sjdp		{
163333965Sjdp		  ed.type = ED_TYPE_NOTSPEC;
163433965Sjdp		  ed.type = ED_TYPE_DATA;
163533965Sjdp		}
163689857Sobrien
163733965Sjdp	      ed.address = s->where->offset - s->where->section->address;
163833965Sjdp	      ed.name = s->name;
163933965Sjdp	      sysroff_swap_ed_out (file, &ed);
164033965Sjdp	    }
164133965Sjdp	}
164233965Sjdp    }
164333965Sjdp}
164433965Sjdp
164533965Sjdpstatic void
1646130561Sobrienwr_unit_info (struct coff_ofile *ptr)
164733965Sjdp{
164833965Sjdp  struct coff_sfile *sfile;
164933965Sjdp  int first = 1;
165089857Sobrien
165133965Sjdp  for (sfile = ptr->source_head;
165233965Sjdp       sfile;
165333965Sjdp       sfile = sfile->next)
165433965Sjdp    {
165533965Sjdp      long p1;
165633965Sjdp      long p2;
165733965Sjdp      int nsecs;
165889857Sobrien
165933965Sjdp      p1 = ftell (file);
166033965Sjdp      wr_un (ptr, sfile, first, 0);
166133965Sjdp      nsecs = wr_sc (ptr, sfile);
166233965Sjdp      p2 = ftell (file);
166333965Sjdp      fseek (file, p1, SEEK_SET);
166433965Sjdp      wr_un (ptr, sfile, first, nsecs);
1665104834Sobrien      fseek (file, p2, SEEK_SET);
166633965Sjdp      wr_er (ptr, sfile, first);
166733965Sjdp      wr_ed (ptr, sfile, first);
166833965Sjdp      first = 0;
166933965Sjdp    }
167033965Sjdp}
167133965Sjdp
167233965Sjdpstatic void
1673130561Sobrienwr_module (struct coff_ofile *p)
167433965Sjdp{
167533965Sjdp  wr_cs ();
167633965Sjdp  wr_hd (p);
167733965Sjdp  wr_unit_info (p);
167833965Sjdp  wr_object_body (p);
167933965Sjdp  wr_debug (p);
168033965Sjdp  wr_tr ();
168133965Sjdp}
168233965Sjdp
168333965Sjdpstatic int
1684130561Sobrienalign (int x)
168533965Sjdp{
168633965Sjdp  return (x + 3) & ~3;
168733965Sjdp}
168833965Sjdp
168933965Sjdp/* Find all the common variables and turn them into
169089857Sobrien   ordinary defs - dunno why, but thats what hitachi does with 'em.  */
169133965Sjdp
169233965Sjdpstatic void
1693130561Sobrienprescan (struct coff_ofile *tree)
169433965Sjdp{
169533965Sjdp  struct coff_symbol *s;
169633965Sjdp  struct coff_section *common_section;
169789857Sobrien
169889857Sobrien  /* Find the common section - always section 3.  */
169933965Sjdp  common_section = tree->sections + 3;
170089857Sobrien
170133965Sjdp  for (s = tree->symbol_list_head;
170233965Sjdp       s;
170333965Sjdp       s = s->next_in_ofile_list)
170433965Sjdp    {
170533965Sjdp      if (s->visible->type == coff_vis_common)
170633965Sjdp	{
170733965Sjdp	  struct coff_where *w = s->where;
170833965Sjdp	  /*      s->visible->type = coff_vis_ext_def; leave it as common */
170933965Sjdp	  common_section->size = align (common_section->size);
171033965Sjdp	  w->offset = common_section->size + common_section->address;
171133965Sjdp	  w->section = common_section;
171233965Sjdp	  common_section->size += s->type->size;
171333965Sjdp	  common_section->size = align (common_section->size);
171433965Sjdp	}
171533965Sjdp    }
171633965Sjdp}
171733965Sjdp
171833965Sjdpchar *program_name;
171933965Sjdp
172033965Sjdpstatic void
1721130561Sobrienshow_usage (FILE *file, int status)
172233965Sjdp{
172389857Sobrien  fprintf (file, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
172489857Sobrien  fprintf (file, _("Convert a COFF object file into a SYSROFF object file\n"));
172589857Sobrien  fprintf (file, _(" The options are:\n\
1726218822Sdim  -q --quick       (Obsolete - ignored)\n\
172789857Sobrien  -n --noprescan   Do not perform a scan to convert commons into defs\n\
172889857Sobrien  -d --debug       Display information about what is being done\n\
1729218822Sdim  @<file>          Read options from <file>\n\
173089857Sobrien  -h --help        Display this information\n\
173189857Sobrien  -v --version     Print the program's version number\n"));
173289857Sobrien
1733218822Sdim  if (REPORT_BUGS_TO[0] && status == 0)
173489857Sobrien    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
173533965Sjdp  exit (status);
173633965Sjdp}
173733965Sjdp
173833965Sjdpint
1739130561Sobrienmain (int ac, char **av)
174033965Sjdp{
174133965Sjdp  int opt;
174233965Sjdp  static struct option long_options[] =
174333965Sjdp  {
174433965Sjdp    {"debug", no_argument, 0, 'd'},
174533965Sjdp    {"quick", no_argument, 0, 'q'},
174633965Sjdp    {"noprescan", no_argument, 0, 'n'},
174733965Sjdp    {"help", no_argument, 0, 'h'},
174833965Sjdp    {"version", no_argument, 0, 'V'},
174933965Sjdp    {NULL, no_argument, 0, 0}
175033965Sjdp  };
175133965Sjdp  char **matching;
175233965Sjdp  char *input_file;
175360484Sobrien  char *output_file;
175433965Sjdp
175560484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
175660484Sobrien  setlocale (LC_MESSAGES, "");
175760484Sobrien#endif
175889857Sobrien#if defined (HAVE_SETLOCALE)
175989857Sobrien  setlocale (LC_CTYPE, "");
176089857Sobrien#endif
176160484Sobrien  bindtextdomain (PACKAGE, LOCALEDIR);
176260484Sobrien  textdomain (PACKAGE);
176360484Sobrien
176433965Sjdp  program_name = av[0];
176533965Sjdp  xmalloc_set_program_name (program_name);
176633965Sjdp
1767218822Sdim  expandargv (&ac, &av);
1768218822Sdim
176989857Sobrien  while ((opt = getopt_long (ac, av, "dHhVvqn", long_options,
177033965Sjdp			     (int *) NULL))
177133965Sjdp	 != EOF)
177233965Sjdp    {
177333965Sjdp      switch (opt)
177433965Sjdp	{
177533965Sjdp	case 'q':
177633965Sjdp	  quick = 1;
177733965Sjdp	  break;
177833965Sjdp	case 'n':
177933965Sjdp	  noprescan = 1;
178033965Sjdp	  break;
178133965Sjdp	case 'd':
178233965Sjdp	  debug = 1;
178333965Sjdp	  break;
178489857Sobrien	case 'H':
178533965Sjdp	case 'h':
178689857Sobrien	  show_usage (stdout, 0);
178733965Sjdp	  /*NOTREACHED */
178889857Sobrien	case 'v':
178933965Sjdp	case 'V':
179089857Sobrien	  print_version ("srconv");
179133965Sjdp	  exit (0);
179233965Sjdp	  /*NOTREACHED */
179333965Sjdp	case 0:
179433965Sjdp	  break;
179533965Sjdp	default:
179633965Sjdp	  show_usage (stderr, 1);
179733965Sjdp	  /*NOTREACHED */
179833965Sjdp	}
179933965Sjdp    }
180033965Sjdp
180133965Sjdp  /* The input and output files may be named on the command line.  */
180233965Sjdp  output_file = NULL;
180333965Sjdp  if (optind < ac)
180433965Sjdp    {
180533965Sjdp      input_file = av[optind];
180633965Sjdp      ++optind;
180733965Sjdp      if (optind < ac)
180833965Sjdp	{
180933965Sjdp	  output_file = av[optind];
181033965Sjdp	  ++optind;
181133965Sjdp	  if (optind < ac)
181233965Sjdp	    show_usage (stderr, 1);
181333965Sjdp	  if (strcmp (input_file, output_file) == 0)
181433965Sjdp	    {
181560484Sobrien	      fatal (_("input and output files must be different"));
181633965Sjdp	    }
181733965Sjdp	}
181833965Sjdp    }
181933965Sjdp  else
182033965Sjdp    input_file = 0;
182133965Sjdp
182233965Sjdp  if (!input_file)
182333965Sjdp    {
182460484Sobrien      fatal (_("no input file specified"));
182533965Sjdp    }
182633965Sjdp
182733965Sjdp  if (!output_file)
182833965Sjdp    {
182933965Sjdp      /* Take a .o off the input file and stick on a .obj.  If
183033965Sjdp         it doesn't end in .o, then stick a .obj on anyway */
183133965Sjdp
183233965Sjdp      int len = strlen (input_file);
183389857Sobrien
183433965Sjdp      output_file = xmalloc (len + 5);
183533965Sjdp      strcpy (output_file, input_file);
183689857Sobrien
183733965Sjdp      if (len > 3
183833965Sjdp	  && output_file[len - 2] == '.'
183933965Sjdp	  && output_file[len - 1] == 'o')
184033965Sjdp	{
184133965Sjdp	  output_file[len] = 'b';
184233965Sjdp	  output_file[len + 1] = 'j';
184333965Sjdp	  output_file[len + 2] = 0;
184433965Sjdp	}
184533965Sjdp      else
184633965Sjdp	{
184733965Sjdp	  strcat (output_file, ".obj");
184833965Sjdp	}
184933965Sjdp    }
185033965Sjdp
185133965Sjdp  abfd = bfd_openr (input_file, 0);
185233965Sjdp
185333965Sjdp  if (!abfd)
185433965Sjdp    bfd_fatal (input_file);
185533965Sjdp
185633965Sjdp  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
185733965Sjdp    {
185833965Sjdp      bfd_nonfatal (input_file);
185989857Sobrien
186033965Sjdp      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
186133965Sjdp	{
186233965Sjdp	  list_matching_formats (matching);
186333965Sjdp	  free (matching);
186433965Sjdp	}
186533965Sjdp      exit (1);
186633965Sjdp    }
186733965Sjdp
186833965Sjdp  file = fopen (output_file, FOPEN_WB);
186933965Sjdp
187033965Sjdp  if (!file)
187189857Sobrien    fatal (_("unable to open output file %s"), output_file);
187233965Sjdp
187333965Sjdp  if (debug)
187433965Sjdp    printf ("ids %d %d\n", base1, base2);
187589857Sobrien
187633965Sjdp  tree = coff_grok (abfd);
187789857Sobrien
187833965Sjdp  if (!noprescan)
187933965Sjdp    prescan (tree);
188089857Sobrien
188133965Sjdp  wr_module (tree);
188233965Sjdp  return 0;
188333965Sjdp}
1884