srconv.c revision 104834
1235614Sgnn/* srconv.c -- Sysroff conversion program
2235614Sgnn   Copyright 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
3235614Sgnn   Free Software Foundation, Inc.
4235614Sgnn
5235614Sgnn   This file is part of GNU Binutils.
6235614Sgnn
7235614Sgnn   This program is free software; you can redistribute it and/or modify
8235614Sgnn   it under the terms of the GNU General Public License as published by
9235614Sgnn   the Free Software Foundation; either version 2 of the License, or
10235614Sgnn   (at your option) any later version.
11235614Sgnn
12235614Sgnn   This program is distributed in the hope that it will be useful,
13235614Sgnn   but WITHOUT ANY WARRANTY; without even the implied warranty of
14235614Sgnn   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15235614Sgnn   GNU General Public License for more details.
16235614Sgnn
17235614Sgnn   You should have received a copy of the GNU General Public License
18235614Sgnn   along with this program; if not, write to the Free Software
19235614Sgnn   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20235614Sgnn   02111-1307, USA.  */
21235614Sgnn
22235614Sgnn/* Written by Steve Chamberlain (sac@cygnus.com)
23235614Sgnn
24235614Sgnn   This program can be used to convert a coff object file
25235614Sgnn   into a Hitachi OM/LM (Sysroff) format.
26235614Sgnn
27235614Sgnn   All debugging information is preserved */
28235614Sgnn
29235614Sgnn#include "bfd.h"
30235614Sgnn#include "bucomm.h"
31235614Sgnn#include "sysroff.h"
32235614Sgnn#include "coffgrok.h"
33235614Sgnn#include "libiberty.h"
34235614Sgnn#include "getopt.h"
35235614Sgnn
36235614Sgnn#include "coff/internal.h"
37235614Sgnn#include "../bfd/libcoff.h"
38235614Sgnn
39235614Sgnn/*#define FOOP1 1 */
40235614Sgnn
41235614Sgnnstatic int addrsize;
42235614Sgnnstatic char *toolname;
43235614Sgnnstatic char **rnames;
44235614Sgnn
45235614Sgnnstatic int get_member_id PARAMS ((int));
46235614Sgnnstatic int get_ordinary_id PARAMS ((int));
47235614Sgnnstatic char *section_translate PARAMS ((char *));
48235614Sgnnstatic char *strip_suffix PARAMS ((char *));
49235614Sgnnstatic void checksum PARAMS ((FILE *, char *, int, int));
50235614Sgnnstatic void writeINT PARAMS ((int, char *, int *, int, FILE *));
51235614Sgnnstatic void writeBITS PARAMS ((int, char *, int *, int));
52235614Sgnnstatic void writeBARRAY PARAMS ((barray, char *, int *, int, FILE *));
53235614Sgnnstatic void writeCHARS PARAMS ((char *, char *, int *, int, FILE *));
54235614Sgnnstatic void wr_tr PARAMS ((void));
55235614Sgnnstatic void wr_un PARAMS ((struct coff_ofile *, struct coff_sfile *, int, int));
56235614Sgnnstatic void wr_hd PARAMS ((struct coff_ofile *));
57235614Sgnnstatic void wr_sh PARAMS ((struct coff_ofile *, struct coff_section *));
58235614Sgnnstatic void wr_ob PARAMS ((struct coff_ofile *, struct coff_section *));
59235614Sgnnstatic void wr_rl PARAMS ((struct coff_ofile *, struct coff_section *));
60235614Sgnnstatic void wr_object_body PARAMS ((struct coff_ofile *));
61235614Sgnnstatic void wr_dps_start
62235614Sgnn  PARAMS ((struct coff_sfile *, struct coff_section *, struct coff_scope *,
63235614Sgnn	   int, int));
64235614Sgnnstatic void wr_dps_end
65235614Sgnn  PARAMS ((struct coff_section *, struct coff_scope *, int));
66235614Sgnnstatic int *nints PARAMS ((int));
67235614Sgnnstatic void walk_tree_type_1
68235614Sgnn  PARAMS ((struct coff_sfile *, struct coff_symbol *, struct coff_type *,
69235614Sgnn	   int));
70235614Sgnnstatic void walk_tree_type
71235614Sgnn  PARAMS ((struct coff_sfile *, struct coff_symbol *, struct coff_type *,
72235614Sgnn	   int));
73235614Sgnnstatic void walk_tree_symbol
74235614Sgnn  PARAMS ((struct coff_sfile *, struct coff_section *,
75	   struct coff_symbol *, int));
76static void walk_tree_scope
77  PARAMS ((struct coff_section *, struct coff_sfile *, struct coff_scope *,
78	   int, int));
79static void walk_tree_sfile
80  PARAMS ((struct coff_section *, struct coff_sfile *));
81static void wr_program_structure
82  PARAMS ((struct coff_ofile *, struct coff_sfile *));
83static void wr_du PARAMS ((struct coff_ofile *, struct coff_sfile *, int));
84static void wr_dus PARAMS ((struct coff_ofile *, struct coff_sfile *));
85static int find_base PARAMS ((struct coff_sfile *, struct coff_section *));
86static void wr_dln PARAMS ((struct coff_ofile *, struct coff_sfile *, int));
87static void wr_globals
88  PARAMS ((struct coff_ofile *, struct coff_sfile *, int));
89static void wr_debug PARAMS ((struct coff_ofile *));
90static void wr_cs PARAMS ((void));
91static int wr_sc PARAMS ((struct coff_ofile *, struct coff_sfile *));
92static void wr_er PARAMS ((struct coff_ofile *, struct coff_sfile *, int));
93static void wr_ed PARAMS ((struct coff_ofile *, struct coff_sfile *, int));
94static void wr_unit_info PARAMS ((struct coff_ofile *));
95static void wr_module PARAMS ((struct coff_ofile *));
96static int align PARAMS ((int));
97static void prescan PARAMS ((struct coff_ofile *));
98static void show_usage PARAMS ((FILE *, int));
99extern int main PARAMS ((int, char **));
100
101static FILE *file;
102static bfd *abfd;
103static int debug = 0;
104static int quick = 0;
105static int noprescan = 0;
106static struct coff_ofile *tree;
107/* Obsolete ??
108   static int absolute_p;
109 */
110
111static int segmented_p;
112static int code;
113
114static int ids1[20000];
115static int ids2[20000];
116
117static int base1 = 0x18;
118static int base2 = 0x2018;
119
120static int
121get_member_id (x)
122     int x;
123{
124  if (ids2[x])
125    return ids2[x];
126
127  ids2[x] = base2++;
128  return ids2[x];
129}
130
131static int
132get_ordinary_id (x)
133     int x;
134{
135  if (ids1[x])
136    return ids1[x];
137
138  ids1[x] = base1++;
139  return ids1[x];
140}
141static char *
142section_translate (n)
143     char *n;
144{
145  if (strcmp (n, ".text") == 0)
146    return "P";
147  if (strcmp (n, ".data") == 0)
148    return "D";
149  if (strcmp (n, ".bss") == 0)
150    return "B";
151  return n;
152}
153
154#define DATE "940201073000";	/* Just a time on my birthday */
155
156static
157char *
158strip_suffix (name)
159     char *name;
160{
161  int i;
162  char *res;
163
164  for (i = 0; name[i] != 0 && name[i] != '.'; i++)
165    ;
166  res = (char *) xmalloc (i + 1);
167  memcpy (res, name, i);
168  res[i] = 0;
169  return res;
170}
171
172/* IT LEN stuff CS */
173static void
174checksum (file, ptr, size, code)
175     FILE *file;
176     char *ptr;
177     int size;
178     int code;
179{
180  int j;
181  int last;
182  int sum = 0;
183  int bytes = size / 8;
184
185  last = !(code & 0xff00);
186  if (size & 0x7)
187    abort ();
188  ptr[0] = code | (last ? 0x80 : 0);
189  ptr[1] = bytes + 1;
190
191  for (j = 0; j < bytes; j++)
192    sum += ptr[j];
193
194  /* Glue on a checksum too.  */
195  ptr[bytes] = ~sum;
196  fwrite (ptr, bytes + 1, 1, file);
197}
198
199
200static void
201writeINT (n, ptr, idx, size, file)
202     int n;
203     char *ptr;
204     int *idx;
205     int size;
206     FILE *file;
207{
208  int byte = *idx / 8;
209
210  if (size == -2)
211    size = addrsize;
212  else if (size == -1)
213    size = 0;
214
215  if (byte > 240)
216    {
217      /* Lets write out that record and do another one.  */
218      checksum (file, ptr, *idx, code | 0x1000);
219      *idx = 16;
220      byte = *idx / 8;
221    }
222
223  switch (size)
224    {
225    case 0:
226      break;
227    case 1:
228      ptr[byte] = n;
229      break;
230    case 2:
231      ptr[byte + 0] = n >> 8;
232      ptr[byte + 1] = n;
233      break;
234    case 4:
235      ptr[byte + 0] = n >> 24;
236      ptr[byte + 1] = n >> 16;
237      ptr[byte + 2] = n >> 8;
238      ptr[byte + 3] = n >> 0;
239      break;
240    default:
241      abort ();
242    }
243  *idx += size * 8;
244}
245
246static void
247writeBITS (val, ptr, idx, size)
248     int val;
249     char *ptr;
250     int *idx;
251     int size;
252{
253  int byte = *idx / 8;
254  int bit = *idx % 8;
255  int old;
256
257  *idx += size;
258
259  old = ptr[byte];
260  /* Turn off all about to change bits.  */
261  old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1));
262  /* Turn on the bits we want.  */
263  old |= (val & ((1 << size) - 1)) << (8 - bit - size);
264  ptr[byte] = old;
265}
266
267static void
268writeBARRAY (data, ptr, idx, size, file)
269     barray data;
270     char *ptr;
271     int *idx;
272     int size ATTRIBUTE_UNUSED;
273     FILE *file;
274{
275  int i;
276
277  writeINT (data.len, ptr, idx, 1, file);
278  for (i = 0; i < data.len; i++)
279    writeINT (data.data[i], ptr, idx, 1, file);
280}
281
282static void
283writeCHARS (string, ptr, idx, size, file)
284     char *string;
285     char *ptr;
286     int *idx;
287     int size;
288     FILE *file;
289{
290  int i = *idx / 8;
291
292  if (i > 240)
293    {
294      /* Lets write out that record and do another one.  */
295      checksum (file, ptr, *idx, code | 0x1000);
296      *idx = 16;
297      i = *idx / 8;
298    }
299
300  if (size == 0)
301    {
302      /* Variable length string.  */
303      size = strlen (string);
304      ptr[i++] = size;
305    }
306
307  /* BUG WAITING TO HAPPEN.  */
308  memcpy (ptr + i, string, size);
309  i += size;
310  *idx = i * 8;
311}
312
313#define SYSROFF_SWAP_OUT
314#include "sysroff.c"
315
316static char *rname_sh[] =
317{
318  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
319};
320
321static char *rname_h8300[] =
322{
323  "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR"
324};
325
326static void
327wr_tr ()
328{
329  /* The TR block is not normal - it doesn't have any contents.  */
330
331  static char b[] =
332    {
333      0xff,			/* IT */
334      0x03,			/* RL */
335      0xfd,			/* CS */
336    };
337  fwrite (b, 1, sizeof (b), file);
338}
339
340static void
341wr_un (ptr, sfile, first, nsecs)
342     struct coff_ofile *ptr;
343     struct coff_sfile *sfile;
344     int first;
345     int nsecs ATTRIBUTE_UNUSED;
346{
347  struct IT_un un;
348  struct coff_symbol *s;
349
350  un.spare1 = 0;
351
352  if (bfd_get_file_flags (abfd) & EXEC_P)
353    un.format = FORMAT_LM;
354  else
355    un.format = FORMAT_OM;
356  un.spare1 = 0;
357
358#if 1
359  un.nsections = ptr->nsections - 1;	/*  Don't count the abs section.  */
360#else
361  /*NEW - only count sections with size.  */
362  un.nsections = nsecs;
363#endif
364
365  un.nextdefs = 0;
366  un.nextrefs = 0;
367  /* Count all the undefined and defined variables with global scope.  */
368
369  if (first)
370    {
371      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
372	{
373	  if (s->visible->type == coff_vis_ext_def
374	      || s->visible->type == coff_vis_common)
375	    un.nextdefs++;
376
377	  if (s->visible->type == coff_vis_ext_ref)
378	    un.nextrefs++;
379	}
380    }
381  un.tool = toolname;
382  un.tcd = DATE;
383  un.linker = "L_GX00";
384  un.lcd = DATE;
385  un.name = sfile->name;
386  sysroff_swap_un_out (file, &un);
387}
388
389static void
390wr_hd (p)
391     struct coff_ofile *p;
392{
393  struct IT_hd hd;
394
395  hd.spare1 = 0;
396  if (bfd_get_file_flags (abfd) & EXEC_P)
397    hd.mt = MTYPE_ABS_LM;
398  else
399    hd.mt = MTYPE_OMS_OR_LMS;
400
401  hd.cd = DATE;
402
403  hd.nu = p->nsources;		/* Always one unit */
404  hd.code = 0;			/* Always ASCII */
405  hd.ver = "0200";		/* Version 2.00 */
406
407  switch (bfd_get_arch (abfd))
408    {
409    case bfd_arch_h8300:
410      hd.au = 8;
411      hd.si = 0;
412      hd.spcsz = 32;
413      hd.segsz = 0;
414      hd.segsh = 0;
415      switch (bfd_get_mach (abfd))
416	{
417	case bfd_mach_h8300:
418	  hd.cpu = "H8300";
419	  hd.afl = 2;
420	  addrsize = 2;
421	  toolname = "C_H8/300";
422	  break;
423	case bfd_mach_h8300h:
424	  hd.cpu = "H8300H";
425	  hd.afl = 4;
426	  addrsize = 4;
427	  toolname = "C_H8/300H";
428	  break;
429	case bfd_mach_h8300s:
430	  hd.cpu = "H8300S";
431	  hd.afl = 4;
432	  addrsize = 4;
433	  toolname = "C_H8/300S";
434	  break;
435	default:
436	  abort();
437	}
438      rnames = rname_h8300;
439      break;
440    case bfd_arch_sh:
441      hd.au = 8;
442      hd.si = 0;
443      hd.afl = 4;
444      hd.spcsz = 32;
445      hd.segsz = 0;
446      hd.segsh = 0;
447      hd.cpu = "SH";
448      addrsize = 4;
449      toolname = "C_SH";
450      rnames = rname_sh;
451      break;
452    default:
453      abort ();
454    }
455
456  if (! bfd_get_file_flags(abfd) & EXEC_P)
457    {
458      hd.ep = 0;
459    }
460  else
461    {
462      hd.ep = 1;
463      hd.uan = 0;
464      hd.sa = 0;
465      hd.sad = 0;
466      hd.address = bfd_get_start_address (abfd);
467    }
468
469  hd.os = "";
470  hd.sys = "";
471  hd.mn = strip_suffix (bfd_get_filename (abfd));
472
473  sysroff_swap_hd_out (file, &hd);
474}
475
476
477static void
478wr_sh (p, sec)
479     struct coff_ofile *p ATTRIBUTE_UNUSED;
480     struct coff_section *sec;
481{
482  struct IT_sh sh;
483  sh.unit = 0;
484  sh.section = sec->number;
485#ifdef FOOP1
486  sh.section = 0;
487#endif
488  sysroff_swap_sh_out (file, &sh);
489}
490
491
492static void
493wr_ob (p, section)
494     struct coff_ofile *p ATTRIBUTE_UNUSED;
495     struct coff_section *section;
496{
497  bfd_size_type i;
498  int first = 1;
499  unsigned char stuff[200];
500
501  i = 0;
502  while (i < section->bfd_section->_raw_size)
503    {
504      struct IT_ob ob;
505      int todo = 200;		/* Copy in 200 byte lumps.  */
506
507      ob.spare = 0;
508      if (i + todo > section->bfd_section->_raw_size)
509	todo = section->bfd_section->_raw_size - i;
510
511      if (first)
512	{
513	  ob.saf = 1;
514	  if (bfd_get_file_flags (abfd) & EXEC_P)
515	    ob.address = section->address;
516	  else
517	    ob.address = 0;
518
519	  first = 0;
520	}
521      else
522	{
523	  ob.saf = 0;
524	}
525
526      ob.cpf = 0;		/* Never compress.  */
527      ob.data.len = todo;
528      bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo);
529      ob.data.data = stuff;
530      sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ );
531      i += todo;
532    }
533
534  /* Now fill the rest with blanks.  */
535  while (i < (bfd_size_type) section->size)
536    {
537      struct IT_ob ob;
538      int todo = 200;		/* Copy in 200 byte lumps.  */
539
540      ob.spare = 0;
541      if (i + todo > (bfd_size_type) section->size)
542	todo = section->size - i;
543      ob.saf = 0;
544
545      ob.cpf = 0;		/* Never compress.  */
546      ob.data.len = todo;
547      memset (stuff, 0, todo);
548      ob.data.data = stuff;
549      sysroff_swap_ob_out (file, &ob);
550      i += todo;
551    }
552  /* Now fill the rest with blanks.  */
553}
554
555static void
556wr_rl (ptr, sec)
557     struct coff_ofile *ptr ATTRIBUTE_UNUSED;
558     struct coff_section *sec;
559{
560  int nr = sec->nrelocs;
561  int i;
562
563  for (i = 0; i < nr; i++)
564    {
565      struct coff_reloc *r = sec->relocs + i;
566      struct coff_symbol *ref;
567      struct IT_rl rl;
568
569      rl.apol = 0;
570      rl.boundary = 0;
571      rl.segment = 1;
572      rl.sign = 0;
573      rl.check = 0;
574      rl.addr = r->offset;
575      rl.bitloc = 0;
576      rl.flen = 32;		/* SH Specific.  */
577
578      /* What sort of reloc ? Look in the section to find out.  */
579      ref = r->symbol;
580      if (ref->visible->type == coff_vis_ext_ref)
581	{
582	  rl.bcount = 4;	/* Always 4 for us.  */
583	  rl.op = OP_EXT_REF;
584	  rl.symn = ref->er_number;
585	}
586      else if (ref->visible->type == coff_vis_common)
587	{
588	  rl.bcount = 11;	/* Always 11 for us.  */
589	  rl.op = OP_SEC_REF;
590	  rl.secn = ref->where->section->number;
591	  rl.copcode_is_3 = 3;
592	  rl.alength_is_4 = 4;
593	  rl.addend = ref->where->offset - ref->where->section->address;
594	  rl.aopcode_is_0x20 = 0x20;
595	}
596      else
597	{
598	  rl.bcount = 11;	/* Always 11 for us.  */
599	  rl.op = OP_SEC_REF;
600	  rl.secn = ref->where->section->number;
601	  rl.copcode_is_3 = 3;
602	  rl.alength_is_4 = 4;
603	  rl.addend = -ref->where->section->address;
604	  rl.aopcode_is_0x20 = 0x20;
605	}
606
607      rl.end = 0xff;
608
609      if (   rl.op == OP_SEC_REF
610	  || rl.op == OP_EXT_REF)
611	sysroff_swap_rl_out (file, &rl);
612    }
613}
614
615static void
616wr_object_body (p)
617     struct coff_ofile *p;
618{
619  int i;
620
621  for (i = 1; i < p->nsections; i++)
622    {
623      wr_sh (p, p->sections + i);
624      wr_ob (p, p->sections + i);
625      wr_rl (p, p->sections + i);
626    }
627}
628
629static void
630wr_dps_start (sfile, section, scope, type, nest)
631     struct coff_sfile *sfile;
632     struct coff_section *section ATTRIBUTE_UNUSED;
633     struct coff_scope *scope;
634     int type;
635     int nest;
636{
637  struct IT_dps dps;
638
639  dps.end = 0;
640  dps.opt = 0;
641  dps.type = type;
642
643  if (scope->sec)
644    {
645      dps.san = scope->sec->number;
646      dps.address = scope->offset - find_base (sfile, scope->sec);
647      dps.block_size = scope->size;
648
649      if (debug)
650	{
651	  printf ("DPS %s %d %x\n",
652		  sfile->name,
653		  nest,
654		  dps.address);
655	}
656    }
657  else
658    {
659      dps.san = 0;
660      dps.address = 0;
661      dps.block_size = 0;
662    }
663
664  dps.nesting = nest;
665  dps.neg = 0x1001;
666  sysroff_swap_dps_out (file, &dps);
667}
668
669static void
670wr_dps_end (section, scope, type)
671     struct coff_section *section ATTRIBUTE_UNUSED;
672     struct coff_scope *scope ATTRIBUTE_UNUSED;
673     int type;
674{
675  struct IT_dps dps;
676
677  dps.end = 1;
678  dps.type = type;
679  sysroff_swap_dps_out (file, &dps);
680}
681
682static int *
683nints (x)
684     int x;
685{
686  return (int *) (xcalloc (sizeof (int), x));
687}
688
689static void
690walk_tree_type_1 (sfile, symbol, type, nest)
691     struct coff_sfile *sfile;
692     struct coff_symbol *symbol;
693     struct coff_type *type;
694     int nest;
695{
696  switch (type->type)
697    {
698    case coff_secdef_type:
699    case coff_basic_type:
700      {
701	struct IT_dbt dbt;
702
703	switch (type->u.basic)
704	  {
705	  case T_NULL:
706	  case T_VOID:
707	    dbt.btype = BTYPE_VOID;
708	    dbt.sign = BTYPE_UNSPEC;
709	    dbt.fptype = FPTYPE_NOTSPEC;
710	    break;
711
712	  case T_CHAR:
713	    dbt.btype = BTYPE_CHAR;
714	    dbt.sign = BTYPE_UNSPEC;
715	    dbt.fptype = FPTYPE_NOTSPEC;
716	    break;
717
718	  case T_SHORT:
719	  case T_INT:
720	  case T_LONG:
721	    dbt.btype = BTYPE_INT;
722	    dbt.sign = SIGN_SIGNED;
723	    dbt.fptype = FPTYPE_NOTSPEC;
724	    break;
725
726	  case T_FLOAT:
727	    dbt.btype = BTYPE_FLOAT;
728	    dbt.fptype = FPTYPE_SINGLE;
729	    break;
730
731	  case T_DOUBLE:
732	    dbt.btype = BTYPE_FLOAT;
733	    dbt.fptype = FPTYPE_DOUBLE;
734	    break;
735
736	  case T_LNGDBL:
737	    dbt.btype = BTYPE_FLOAT;
738	    dbt.fptype = FPTYPE_EXTENDED;
739	    break;
740
741	  case T_UCHAR:
742	    dbt.btype = BTYPE_CHAR;
743	    dbt.sign = SIGN_UNSIGNED;
744	    dbt.fptype = FPTYPE_NOTSPEC;
745	    break;
746
747	  case T_USHORT:
748	  case T_UINT:
749	  case T_ULONG:
750	    dbt.btype = BTYPE_INT;
751	    dbt.sign = SIGN_UNSIGNED;
752	    dbt.fptype = FPTYPE_NOTSPEC;
753	    break;
754	  }
755
756	dbt.bitsize = type->size;
757	dbt.neg = 0x1001;
758	sysroff_swap_dbt_out (file, &dbt);
759	break;
760      }
761
762    case coff_pointer_type:
763      {
764	struct IT_dpt dpt;
765
766	walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1);
767	dpt.neg = 0x1001;
768	sysroff_swap_dpt_out (file, &dpt);
769	break;
770      }
771
772    case coff_function_type:
773      {
774	struct IT_dfp dfp;
775	struct coff_symbol *param;
776
777	dfp.end = 0;
778	dfp.spare = 0;
779	dfp.nparams = type->u.function.parameters->nvars;
780	dfp.neg = 0x1001;
781
782	walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1);
783
784	sysroff_swap_dfp_out (file, &dfp);
785
786	for (param = type->u.function.parameters->vars_head;
787	     param;
788	     param = param->next)
789	  walk_tree_symbol (sfile, 0, param, nest);
790
791	dfp.end = 1;
792	sysroff_swap_dfp_out (file, &dfp);
793	break;
794      }
795
796    case coff_structdef_type:
797      {
798	struct IT_dbt dbt;
799	struct IT_dds dds;
800	struct coff_symbol *member;
801
802	dds.spare = 0;
803	dbt.btype = BTYPE_STRUCT;
804	dbt.bitsize = type->size;
805	dbt.sign = SIGN_UNSPEC;
806	dbt.fptype = FPTYPE_NOTSPEC;
807	dbt.sid = get_member_id (type->u.astructdef.idx);
808	dbt.neg = 0x1001;
809	sysroff_swap_dbt_out (file, &dbt);
810	dds.end = 0;
811	dds.neg = 0x1001;
812	sysroff_swap_dds_out (file, &dds);
813
814	for (member = type->u.astructdef.elements->vars_head;
815	     member;
816	     member = member->next)
817	  walk_tree_symbol (sfile, 0, member, nest + 1);
818
819	dds.end = 1;
820	sysroff_swap_dds_out (file, &dds);
821
822      }
823      break;
824
825    case coff_structref_type:
826      {
827	struct IT_dbt dbt;
828
829	dbt.btype = BTYPE_TAG;
830	dbt.bitsize = type->size;
831	dbt.sign = SIGN_UNSPEC;
832	dbt.fptype = FPTYPE_NOTSPEC;
833
834	if (type->u.astructref.ref)
835	  dbt.sid = get_member_id (type->u.astructref.ref->number);
836	else
837	  dbt.sid = 0;
838
839	dbt.neg = 0x1001;
840	sysroff_swap_dbt_out (file, &dbt);
841      }
842      break;
843
844    case coff_array_type:
845      {
846	struct IT_dar dar;
847	int j;
848	int dims = 1;		/* Only output one dimension at a time.  */
849
850	dar.dims = dims;
851	dar.variable = nints (dims);
852	dar.subtype = nints (dims);
853	dar.spare = nints (dims);
854	dar.max_variable = nints (dims);
855	dar.maxspare = nints (dims);
856	dar.max = nints (dims);
857	dar.min_variable = nints (dims);
858	dar.min = nints (dims);
859	dar.minspare = nints (dims);
860	dar.neg = 0x1001;
861	dar.length = type->size / type->u.array.dim;
862
863	for (j = 0; j < dims; j++)
864	  {
865	    dar.variable[j] = VARIABLE_FIXED;
866	    dar.subtype[j] = SUB_INTEGER;
867	    dar.spare[j] = 0;
868	    dar.max_variable[j] = 0;
869	    dar.max[j] = type->u.array.dim;
870	    dar.min_variable[j] = 0;
871	    dar.min[j] = 1;	/* Why isn't this 0 ? */
872	  }
873	walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1);
874	sysroff_swap_dar_out (file, &dar);
875      }
876      break;
877
878    case coff_enumdef_type:
879      {
880	struct IT_dbt dbt;
881	struct IT_den den;
882	struct coff_symbol *member;
883
884	dbt.btype = BTYPE_ENUM;
885	dbt.bitsize = type->size;
886	dbt.sign = SIGN_UNSPEC;
887	dbt.fptype = FPTYPE_NOTSPEC;
888	dbt.sid = get_member_id (type->u.aenumdef.idx);
889	dbt.neg = 0x1001;
890	sysroff_swap_dbt_out (file, &dbt);
891
892	den.end = 0;
893	den.neg = 0x1001;
894	den.spare = 0;
895	sysroff_swap_den_out (file, &den);
896
897	for (member = type->u.aenumdef.elements->vars_head;
898	     member;
899	     member = member->next)
900	  walk_tree_symbol (sfile, 0, member, nest + 1);
901
902	den.end = 1;
903	sysroff_swap_den_out (file, &den);
904      }
905      break;
906
907    case coff_enumref_type:
908      {
909	struct IT_dbt dbt;
910
911	dbt.btype = BTYPE_TAG;
912	dbt.bitsize = type->size;
913	dbt.sign = SIGN_UNSPEC;
914	dbt.fptype = FPTYPE_NOTSPEC;
915	dbt.sid = get_member_id (type->u.aenumref.ref->number);
916	dbt.neg = 0x1001;
917	sysroff_swap_dbt_out (file, &dbt);
918      }
919      break;
920
921    default:
922      abort ();
923    }
924}
925
926/* Obsolete ?
927   static void
928   dty_start ()
929   {
930   struct IT_dty dty;
931   dty.end = 0;
932   dty.neg = 0x1001;
933   dty.spare = 0;
934   sysroff_swap_dty_out (file, &dty);
935   }
936
937   static void
938   dty_stop ()
939   {
940   struct IT_dty dty;
941   dty.end = 0;
942   dty.neg = 0x1001;
943   dty.end = 1;
944   sysroff_swap_dty_out (file, &dty);
945   }
946
947
948   static void
949   dump_tree_structure (sfile, symbol, type, nest)
950   struct coff_sfile *sfile;
951   struct coff_symbol *symbol;
952   struct coff_type *type;
953   int nest;
954   {
955   if (symbol->type->type == coff_function_type)
956   {
957
958
959   }
960
961   }
962 */
963
964static void
965walk_tree_type (sfile, symbol, type, nest)
966     struct coff_sfile *sfile;
967     struct coff_symbol *symbol;
968     struct coff_type *type;
969     int nest;
970{
971  if (symbol->type->type == coff_function_type)
972    {
973      struct IT_dty dty;
974
975      dty.end = 0;
976      dty.neg = 0x1001;
977
978      sysroff_swap_dty_out (file, &dty);
979      walk_tree_type_1 (sfile, symbol, type, nest);
980      dty.end = 1;
981      sysroff_swap_dty_out (file, &dty);
982
983      wr_dps_start (sfile,
984		    symbol->where->section,
985		    symbol->type->u.function.code,
986		    BLOCK_TYPE_FUNCTION, nest);
987      wr_dps_start (sfile, symbol->where->section,
988		    symbol->type->u.function.code,
989		    BLOCK_TYPE_BLOCK, nest);
990      walk_tree_scope (symbol->where->section,
991		       sfile,
992		       symbol->type->u.function.code,
993		       nest + 1, BLOCK_TYPE_BLOCK);
994
995      wr_dps_end (symbol->where->section,
996		  symbol->type->u.function.code,
997		  BLOCK_TYPE_BLOCK);
998      wr_dps_end (symbol->where->section,
999		  symbol->type->u.function.code, BLOCK_TYPE_FUNCTION);
1000    }
1001  else
1002    {
1003      struct IT_dty dty;
1004
1005      dty.end = 0;
1006      dty.neg = 0x1001;
1007      sysroff_swap_dty_out (file, &dty);
1008      walk_tree_type_1 (sfile, symbol, type, nest);
1009      dty.end = 1;
1010      sysroff_swap_dty_out (file, &dty);
1011    }
1012}
1013
1014static void
1015walk_tree_symbol (sfile, section, symbol, nest)
1016     struct coff_sfile *sfile;
1017     struct coff_section *section ATTRIBUTE_UNUSED;
1018     struct coff_symbol *symbol;
1019     int nest;
1020{
1021  struct IT_dsy dsy;
1022
1023  memset (&dsy, 0, sizeof(dsy));
1024  dsy.nesting = nest;
1025
1026  switch (symbol->type->type)
1027    {
1028    case coff_function_type:
1029      dsy.type = STYPE_FUNC;
1030      dsy.assign = 1;
1031      break;
1032
1033    case coff_structref_type:
1034    case coff_pointer_type:
1035    case coff_array_type:
1036    case coff_basic_type:
1037    case coff_enumref_type:
1038      dsy.type = STYPE_VAR;
1039      dsy.assign = 1;
1040      break;
1041
1042    case coff_enumdef_type:
1043      dsy.type = STYPE_TAG;
1044      dsy.assign = 0;
1045      dsy.magic = 2;
1046      break;
1047
1048    case coff_structdef_type:
1049      dsy.type = STYPE_TAG;
1050      dsy.assign = 0;
1051      dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1;
1052      break;
1053
1054    case coff_secdef_type:
1055      return;
1056
1057    default:
1058      abort ();
1059    }
1060
1061  if (symbol->where->where == coff_where_member_of_struct)
1062    {
1063      dsy.assign = 0;
1064      dsy.type = STYPE_MEMBER;
1065    }
1066
1067  if (symbol->where->where == coff_where_member_of_enum)
1068    {
1069      dsy.type = STYPE_ENUM;
1070      dsy.assign = 0;
1071      dsy.evallen = 4;
1072      dsy.evalue = symbol->where->offset;
1073    }
1074
1075  if (symbol->type->type == coff_structdef_type
1076      || symbol->where->where == coff_where_entag
1077      || symbol->where->where == coff_where_strtag)
1078    {
1079      dsy.snumber = get_member_id (symbol->number);
1080    }
1081  else
1082    {
1083      dsy.snumber = get_ordinary_id (symbol->number);
1084    }
1085
1086  dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name;
1087
1088  switch (symbol->visible->type)
1089    {
1090    case coff_vis_common:
1091    case coff_vis_ext_def:
1092      dsy.ainfo = AINFO_STATIC_EXT_DEF;
1093      break;
1094
1095    case coff_vis_ext_ref:
1096      dsy.ainfo = AINFO_STATIC_EXT_REF;
1097      break;
1098
1099    case coff_vis_int_def:
1100      dsy.ainfo = AINFO_STATIC_INT;
1101      break;
1102
1103    case coff_vis_auto:
1104    case coff_vis_autoparam:
1105      dsy.ainfo = AINFO_AUTO;
1106      break;
1107
1108    case coff_vis_register:
1109    case coff_vis_regparam:
1110      dsy.ainfo = AINFO_REG;
1111      break;
1112      break;
1113
1114    case coff_vis_tag:
1115    case coff_vis_member_of_struct:
1116    case coff_vis_member_of_enum:
1117      break;
1118
1119    default:
1120      abort ();
1121    }
1122
1123  dsy.dlength = symbol->type->size;
1124
1125  switch (symbol->where->where)
1126    {
1127    case coff_where_memory:
1128
1129      dsy.section = symbol->where->section->number;
1130#ifdef FOOP
1131      dsy.section = 0;
1132#endif
1133      break;
1134
1135    case coff_where_member_of_struct:
1136    case coff_where_member_of_enum:
1137    case coff_where_stack:
1138    case coff_where_register:
1139    case coff_where_unknown:
1140    case coff_where_strtag:
1141    case coff_where_entag:
1142    case coff_where_typedef:
1143      break;
1144
1145    default:
1146      abort ();
1147    }
1148
1149  switch (symbol->where->where)
1150    {
1151    case coff_where_memory:
1152      dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section);
1153      break;
1154
1155    case coff_where_stack:
1156      dsy.address = symbol->where->offset;
1157      break;
1158
1159    case coff_where_member_of_struct:
1160      if (symbol->where->bitsize)
1161	{
1162	  int bits = (symbol->where->offset * 8 + symbol->where->bitoffset);
1163	  dsy.bitunit = 1;
1164	  dsy.field_len = symbol->where->bitsize;
1165	  dsy.field_off = (bits / 32) * 4;
1166	  dsy.field_bitoff = bits % 32;
1167	}
1168      else
1169	{
1170	  dsy.bitunit = 0;
1171
1172	  dsy.field_len = symbol->type->size;
1173	  dsy.field_off = symbol->where->offset;
1174	}
1175      break;
1176
1177    case coff_where_member_of_enum:
1178      /*      dsy.bitunit = 0;
1179         dsy.field_len  = symbol->type->size;
1180         dsy.field_off = symbol->where->offset; */
1181      break;
1182
1183    case coff_where_register:
1184    case coff_where_unknown:
1185    case coff_where_strtag:
1186    case coff_where_entag:
1187    case coff_where_typedef:
1188      break;
1189
1190    default:
1191      abort ();
1192    }
1193
1194  if (symbol->where->where == coff_where_register)
1195    dsy.reg = rnames[symbol->where->offset];
1196
1197  switch (symbol->visible->type)
1198    {
1199    case coff_vis_common:
1200      /* We do this 'cause common C symbols are treated as extdefs.  */
1201    case coff_vis_ext_def:
1202    case coff_vis_ext_ref:
1203      dsy.ename = symbol->name;
1204      break;
1205
1206    case coff_vis_regparam:
1207    case coff_vis_autoparam:
1208      dsy.type = STYPE_PARAMETER;
1209      break;
1210
1211    case coff_vis_int_def:
1212    case coff_vis_auto:
1213    case coff_vis_register:
1214    case coff_vis_tag:
1215    case coff_vis_member_of_struct:
1216    case coff_vis_member_of_enum:
1217      break;
1218
1219    default:
1220      abort ();
1221    }
1222
1223  dsy.sfn = 0;
1224  dsy.sln = 2;
1225  dsy.neg = 0x1001;
1226
1227  sysroff_swap_dsy_out (file, &dsy);
1228
1229  walk_tree_type (sfile, symbol, symbol->type, nest);
1230}
1231
1232static void
1233walk_tree_scope (section, sfile, scope, nest, type)
1234     struct coff_section *section;
1235     struct coff_sfile *sfile;
1236     struct coff_scope *scope;
1237     int nest;
1238     int type;
1239{
1240  struct coff_symbol *vars;
1241  struct coff_scope *child;
1242
1243  if (scope->vars_head
1244      || (scope->list_head && scope->list_head->vars_head))
1245    {
1246      wr_dps_start (sfile, section, scope, type, nest);
1247
1248      if (nest == 0)
1249	wr_globals (tree, sfile, nest + 1);
1250
1251      for (vars = scope->vars_head; vars; vars = vars->next)
1252	walk_tree_symbol (sfile, section, vars, nest);
1253
1254      for (child = scope->list_head; child; child = child->next)
1255	walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK);
1256
1257      wr_dps_end (section, scope, type);
1258    }
1259}
1260
1261static void
1262walk_tree_sfile (section, sfile)
1263     struct coff_section *section;
1264     struct coff_sfile *sfile;
1265{
1266  walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT);
1267}
1268
1269static void
1270wr_program_structure (p, sfile)
1271     struct coff_ofile *p;
1272     struct coff_sfile *sfile;
1273{
1274  walk_tree_sfile (p->sections + 4, sfile);
1275}
1276
1277static void
1278wr_du (p, sfile, n)
1279     struct coff_ofile *p;
1280     struct coff_sfile *sfile;
1281     int n;
1282{
1283  struct IT_du du;
1284  int lim;
1285#if 0
1286  struct coff_symbol *symbol;
1287  static int incit = 0x500000;
1288  int used = 0;
1289#endif
1290  int i;
1291  int j;
1292  unsigned int *lowest = (unsigned *) nints (p->nsections);
1293  unsigned int *highest = (unsigned *) nints (p->nsections);
1294
1295  du.format = bfd_get_file_flags (abfd) & EXEC_P ? 0 : 1;
1296  du.optimized = 0;
1297  du.stackfrmt = 0;
1298  du.spare = 0;
1299  du.unit = n;
1300  du.sections = p->nsections - 1;
1301  du.san = (int *) xcalloc (sizeof (int), du.sections);
1302  du.address = nints (du.sections);
1303  du.length = nints (du.sections);
1304
1305  for (i = 0; i < du.sections; i++)
1306    {
1307      lowest[i] = ~0;
1308      highest[i] = 0;
1309    }
1310
1311  /* Look through all the symbols and try and work out the extents in this
1312     source file.  */
1313#if 0
1314  for (symbol = sfile->scope->vars_head;
1315       symbol;
1316       symbol = symbol->next)
1317    {
1318      if (symbol->type->type == coff_secdef_type)
1319	{
1320	  unsigned int low = symbol->where->offset;
1321	  unsigned int high = symbol->where->offset + symbol->type->size - 1;
1322	  struct coff_section *section = symbol->where->section;
1323
1324	  int sn = section->number;
1325	  if (low < lowest[sn])
1326	    lowest[sn] = low;
1327	  if (high > highest[sn])
1328	    highest[sn] = high;
1329	}
1330    }
1331
1332  for (i = 0; i < du.sections; i++)
1333    {
1334      if (highest[i] == 0)
1335	lowest[i] = highest[i] = incit;
1336
1337      du.san[used] = i;
1338      du.length[used] = highest[i] - lowest[i];
1339      du.address[used] = bfd_get_file_flags (abfd) & EXEC_P ? lowest[i] : 0;
1340
1341      if (debug)
1342	{
1343	  printf (" section %6s 0x%08x..0x%08x\n",
1344		  p->sections[i + 1].name,
1345		  lowest[i],
1346		  highest[i]);
1347	}
1348      used++;
1349    }
1350#endif
1351
1352  lim = du.sections;
1353  for (j = 0; j < lim; j++)
1354    {
1355      int src = j;
1356      int dst = j;
1357
1358      du.san[dst] = dst;
1359
1360      if (sfile->section[src].init)
1361	{
1362	  du.length[dst]
1363	    = sfile->section[src].high - sfile->section[src].low + 1;
1364	  du.address[dst]
1365	    = sfile->section[src].low;
1366	}
1367      else
1368	{
1369	  du.length[dst] = 0;
1370	  du.address[dst] = 0;
1371	}
1372
1373      if (debug)
1374	{
1375	  if (sfile->section[src].parent)
1376	    {
1377	      printf (" section %6s 0x%08x..0x%08x\n",
1378		      sfile->section[src].parent->name,
1379		      du.address[dst],
1380		      du.address[dst] + du.length[dst] - 1);
1381	    }
1382	}
1383
1384      du.sections = dst + 1;
1385    }
1386
1387  du.tool = "c_gcc";
1388  du.date = DATE;
1389
1390  sysroff_swap_du_out (file, &du);
1391}
1392
1393static void
1394wr_dus (p, sfile)
1395     struct coff_ofile *p ATTRIBUTE_UNUSED;
1396     struct coff_sfile *sfile;
1397{
1398  struct IT_dus dus;
1399
1400  dus.efn = 0x1001;
1401  dus.ns = 1;			/* p->nsources; sac 14 jul 94 */
1402  dus.drb = nints (dus.ns);
1403  dus.fname = (char **) xcalloc (sizeof (char *), dus.ns);
1404  dus.spare = nints (dus.ns);
1405  dus.ndir = 0;
1406  /* Find the filenames.  */
1407#if 0
1408  i = 0;
1409
1410  for (sfile = p->source_head;
1411       sfile;
1412       sfile = sfile->next)
1413    {
1414      dus.drb[i] = 0;
1415      dus.spare[i] = 0;
1416      dus.fname[i] = sfile->name;
1417      i++;
1418    }
1419#else
1420  dus.drb[0] = 0;
1421  dus.fname[0] = sfile->name;
1422#endif
1423
1424  sysroff_swap_dus_out (file, &dus);
1425
1426}
1427
1428/* Find the offset of the .text section for this sfile in the
1429   .text section for the output file.  */
1430
1431static int
1432find_base (sfile, section)
1433     struct coff_sfile *sfile;
1434     struct coff_section *section;
1435{
1436  return sfile->section[section->number].low;
1437}
1438
1439static void
1440wr_dln (p, sfile, n)
1441     struct coff_ofile *p ATTRIBUTE_UNUSED;
1442     struct coff_sfile *sfile;
1443     int n ATTRIBUTE_UNUSED;
1444
1445{
1446#if 0
1447  if (n == 0)
1448    {
1449      /* Count up all the linenumbers */
1450      struct coff_symbol *sy;
1451      int lc = 0;
1452      struct IT_dln dln;
1453
1454      int idx;
1455
1456      for (sy = p->symbol_list_head;
1457	   sy;
1458	   sy = sy->next_in_ofile_list)
1459	{
1460	  struct coff_type *t = sy->type;
1461	  if (t->type == coff_function_type)
1462	    {
1463	      struct coff_line *l = t->u.function.lines;
1464	      lc += l->nlines;
1465	    }
1466	}
1467
1468      dln.sfn = nints (lc);
1469      dln.sln = nints (lc);
1470      dln.lln = nints (lc);
1471      dln.section = nints (lc);
1472
1473      dln.from_address = nints (lc);
1474      dln.to_address = nints (lc);
1475
1476
1477      dln.neg = 0x1001;
1478
1479      dln.nln = lc;
1480
1481      /* Run through once more and fill up the structure */
1482      idx = 0;
1483      for (sy = p->symbol_list_head;
1484	   sy;
1485	   sy = sy->next_in_ofile_list)
1486	{
1487	  if (sy->type->type == coff_function_type)
1488	    {
1489	      int i;
1490	      struct coff_line *l = sy->type->u.function.lines;
1491	      for (i = 0; i < l->nlines; i++)
1492		{
1493		  dln.section[idx] = sy->where->section->number;
1494		  dln.sfn[idx] = n;
1495		  dln.sln[idx] = l->lines[i];
1496		  dln.from_address[idx] = l->addresses[i];
1497		  if (idx)
1498		    dln.to_address[idx - 1] = dln.from_address[idx];
1499		  idx++;
1500		}
1501	    }
1502	  n++;
1503	}
1504      sysroff_swap_dln_out (file, &dln);
1505    }
1506
1507#endif
1508#if 1
1509  /* Count up all the linenumbers */
1510
1511  struct coff_symbol *sy;
1512  int lc = 0;
1513  struct IT_dln dln;
1514
1515  int idx;
1516
1517  for (sy = sfile->scope->vars_head;
1518       sy;
1519       sy = sy->next)
1520    {
1521      struct coff_type *t = sy->type;
1522      if (t->type == coff_function_type)
1523	{
1524	  struct coff_line *l = t->u.function.lines;
1525	  if (l)
1526	    lc += l->nlines;
1527	}
1528    }
1529
1530  dln.sfn = nints (lc);
1531  dln.sln = nints (lc);
1532  dln.cc = nints (lc);
1533  dln.section = nints (lc);
1534
1535  dln.from_address = nints (lc);
1536  dln.to_address = nints (lc);
1537
1538
1539  dln.neg = 0x1001;
1540
1541  dln.nln = lc;
1542
1543  /* Run through once more and fill up the structure */
1544  idx = 0;
1545  for (sy = sfile->scope->vars_head;
1546       sy;
1547       sy = sy->next)
1548    {
1549      if (sy->type->type == coff_function_type)
1550	{
1551	  int i;
1552	  struct coff_line *l = sy->type->u.function.lines;
1553	  if (l)
1554	    {
1555	      int base = find_base (sfile, sy->where->section);
1556	      for (i = 0; i < l->nlines; i++)
1557		{
1558		  dln.section[idx] = sy->where->section->number;
1559		  dln.sfn[idx] = 0;
1560		  dln.sln[idx] = l->lines[i];
1561		  dln.from_address[idx] =
1562		    l->addresses[i] + sy->where->section->address - base;
1563		  dln.cc[idx] = 0;
1564		  if (idx)
1565		    dln.to_address[idx - 1] = dln.from_address[idx];
1566		  idx++;
1567
1568		}
1569	      dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2;
1570	    }
1571	}
1572    }
1573  if (lc)
1574    sysroff_swap_dln_out (file, &dln);
1575#endif
1576}
1577
1578/* Write the global symbols out to the debug info.  */
1579
1580static void
1581wr_globals (p, sfile, n)
1582     struct coff_ofile *p;
1583     struct coff_sfile *sfile;
1584     int n ATTRIBUTE_UNUSED;
1585{
1586  struct coff_symbol *sy;
1587
1588  for (sy = p->symbol_list_head;
1589       sy;
1590       sy = sy->next_in_ofile_list)
1591    {
1592      if (sy->visible->type == coff_vis_ext_def
1593	  || sy->visible->type == coff_vis_ext_ref)
1594	{
1595	  /* Only write out symbols if they belong to
1596	     the current source file.  */
1597	  if (sy->sfile == sfile)
1598	    walk_tree_symbol (sfile, 0, sy, 0);
1599	}
1600    }
1601}
1602
1603static void
1604wr_debug (p)
1605     struct coff_ofile *p;
1606{
1607  struct coff_sfile *sfile;
1608  int n = 0;
1609
1610  for (sfile = p->source_head;
1611       sfile;
1612       sfile = sfile->next)
1613    {
1614      if (debug)
1615	printf ("%s\n", sfile->name);
1616
1617      wr_du (p, sfile, n);
1618      wr_dus (p, sfile);
1619      wr_program_structure (p, sfile);
1620      wr_dln (p, sfile, n);
1621      n++;
1622    }
1623}
1624
1625static void
1626wr_cs ()
1627{
1628  /* It seems that the CS struct is not normal - the size is wrong
1629     heres one I prepared earlier.  */
1630  static char b[] =
1631    {
1632    0x80,			/* IT */
1633    0x21,			/* RL */
1634    0x00,			/* number of chars in variable length part */
1635    0x80,			/* hd */
1636    0x00,			/* hs */
1637    0x80,			/* un */
1638    0x00,			/* us */
1639    0x80,			/* sc */
1640    0x00,			/* ss */
1641    0x80,			/* er */
1642    0x80,			/* ed */
1643    0x80,			/* sh */
1644    0x80,			/* ob */
1645    0x80,			/* rl */
1646    0x80,			/* du */
1647    0x80,			/* dps */
1648    0x80,			/* dsy */
1649    0x80,			/* dty */
1650    0x80,			/* dln */
1651    0x80,			/* dso */
1652    0x80,			/* dus */
1653    0x00,			/* dss */
1654    0x80,			/* dbt */
1655    0x00,			/* dpp */
1656    0x80,			/* dfp */
1657    0x80,			/* den */
1658    0x80,			/* dds */
1659    0x80,			/* dar */
1660    0x80,			/* dpt */
1661    0x00,			/* dul */
1662    0x00,			/* dse */
1663    0x00,			/* dot */
1664    0xDE			/* CS */
1665  };
1666  fwrite (b, 1, sizeof (b), file);
1667}
1668
1669/* Write out the SC records for a unit.  Create an SC
1670   for all the sections which appear in the output file, even
1671   if there isn't an equivalent one on the input.  */
1672
1673static int
1674wr_sc (ptr, sfile)
1675     struct coff_ofile *ptr;
1676     struct coff_sfile *sfile;
1677{
1678  int i;
1679  int scount = 0;
1680  /* First work out the total number of sections.  */
1681  int total_sec = ptr->nsections;
1682  struct myinfo
1683    {
1684      struct coff_section *sec;
1685      struct coff_symbol *symbol;
1686    };
1687  struct coff_symbol *symbol;
1688  struct myinfo *info
1689    = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo));
1690
1691
1692  for (i = 0; i < total_sec; i++)
1693    {
1694      info[i].sec = ptr->sections + i;
1695      info[i].symbol = 0;
1696    }
1697
1698  for (symbol = sfile->scope->vars_head;
1699       symbol;
1700       symbol = symbol->next)
1701    {
1702
1703      if (symbol->type->type == coff_secdef_type)
1704	{
1705	  for (i = 0; i < total_sec; i++)
1706	    {
1707	      if (symbol->where->section == info[i].sec)
1708		{
1709		  info[i].symbol = symbol;
1710		  break;
1711		}
1712	    }
1713	}
1714    }
1715
1716  /* Now output all the section info, and fake up some stuff for sections
1717     we don't have.  */
1718  for (i = 1; i < total_sec; i++)
1719    {
1720      struct IT_sc sc;
1721      char *name;
1722
1723      symbol = info[i].symbol;
1724      sc.spare = 0;
1725      sc.spare1 = 0;
1726
1727      if (!symbol)
1728	{
1729	  /* Don't have a symbol set aside for this section, which means
1730	     that nothing in this file does anything for the section.  */
1731	  sc.format = !(bfd_get_file_flags (abfd) & EXEC_P);
1732	  sc.addr = 0;
1733	  sc.length = 0;
1734	  name = info[i].sec->name;
1735	}
1736      else
1737	{
1738	  if (bfd_get_file_flags (abfd) & EXEC_P)
1739	    {
1740	      sc.format = 0;
1741	      sc.addr = symbol->where->offset;
1742	    }
1743	  else
1744	    {
1745	      sc.format = 1;
1746	      sc.addr = 0;
1747	    }
1748	  sc.length = symbol->type->size;
1749	  name = symbol->name;
1750	}
1751
1752      sc.align = 4;
1753      sc.concat = CONCAT_SIMPLE;
1754      sc.read = 3;
1755      sc.write = 3;
1756      sc.exec = 3;
1757      sc.init = 3;
1758      sc.mode = 3;
1759      sc.spare = 0;
1760      sc.segadd = 0;
1761      sc.spare1 = 0;		/* If not zero, then it doesn't work.  */
1762      sc.name = section_translate (name);
1763
1764      if (strlen (sc.name) == 1)
1765	{
1766	  switch (sc.name[0])
1767	    {
1768	    case 'D':
1769	    case 'B':
1770	      sc.contents = CONTENTS_DATA;
1771	      break;
1772
1773	    default:
1774	      sc.contents = CONTENTS_CODE;
1775	    }
1776	}
1777      else
1778	{
1779	  sc.contents = CONTENTS_CODE;
1780	}
1781#if 0
1782      /* NEW */
1783      if (sc.length)
1784	{
1785#endif
1786	  sysroff_swap_sc_out (file, &sc);
1787	  scount++;
1788#if 0
1789	}
1790#endif
1791    }
1792  return scount;
1793}
1794
1795/* Write out the ER records for a unit.  */
1796
1797static void
1798wr_er (ptr, sfile, first)
1799     struct coff_ofile *ptr;
1800     struct coff_sfile *sfile ATTRIBUTE_UNUSED;
1801     int first;
1802{
1803  int idx = 0;
1804  struct coff_symbol *sym;
1805
1806  if (first)
1807    {
1808      for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list)
1809	{
1810	  if (sym->visible->type == coff_vis_ext_ref)
1811	    {
1812	      struct IT_er er;
1813
1814	      er.spare = 0;
1815	      er.type = ER_NOTSPEC;
1816	      er.name = sym->name;
1817	      sysroff_swap_er_out (file, &er);
1818	      sym->er_number = idx++;
1819	    }
1820	}
1821    }
1822}
1823
1824/* Write out the ED records for a unit.  */
1825
1826static void
1827wr_ed (ptr, sfile, first)
1828     struct coff_ofile *ptr;
1829     struct coff_sfile *sfile ATTRIBUTE_UNUSED;
1830     int first;
1831{
1832  struct coff_symbol *s;
1833
1834  if (first)
1835    {
1836      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
1837	{
1838	  if (s->visible->type == coff_vis_ext_def
1839	      || s->visible->type == coff_vis_common)
1840	    {
1841	      struct IT_ed ed;
1842
1843	      ed.section = s->where->section->number;
1844	      ed.spare = 0;
1845
1846	      if (s->where->section->data)
1847		{
1848		  ed.type = ED_TYPE_DATA;
1849		}
1850	      else if (s->where->section->code & SEC_CODE)
1851		{
1852		  ed.type = ED_TYPE_ENTRY;
1853		}
1854	      else
1855		{
1856		  ed.type = ED_TYPE_NOTSPEC;
1857		  ed.type = ED_TYPE_DATA;
1858		}
1859
1860	      ed.address = s->where->offset - s->where->section->address;
1861	      ed.name = s->name;
1862	      sysroff_swap_ed_out (file, &ed);
1863	    }
1864	}
1865    }
1866}
1867
1868static void
1869wr_unit_info (ptr)
1870     struct coff_ofile *ptr;
1871{
1872  struct coff_sfile *sfile;
1873  int first = 1;
1874
1875  for (sfile = ptr->source_head;
1876       sfile;
1877       sfile = sfile->next)
1878    {
1879      long p1;
1880      long p2;
1881      int nsecs;
1882
1883      p1 = ftell (file);
1884      wr_un (ptr, sfile, first, 0);
1885      nsecs = wr_sc (ptr, sfile);
1886      p2 = ftell (file);
1887      fseek (file, p1, SEEK_SET);
1888      wr_un (ptr, sfile, first, nsecs);
1889      fseek (file, p2, SEEK_SET);
1890      wr_er (ptr, sfile, first);
1891      wr_ed (ptr, sfile, first);
1892      first = 0;
1893    }
1894}
1895
1896static void
1897wr_module (p)
1898     struct coff_ofile *p;
1899{
1900  wr_cs ();
1901  wr_hd (p);
1902  wr_unit_info (p);
1903  wr_object_body (p);
1904  wr_debug (p);
1905  wr_tr ();
1906}
1907
1908static int
1909align (x)
1910     int x;
1911{
1912  return (x + 3) & ~3;
1913}
1914
1915/* Find all the common variables and turn them into
1916   ordinary defs - dunno why, but thats what hitachi does with 'em.  */
1917
1918static void
1919prescan (tree)
1920     struct coff_ofile *tree;
1921{
1922  struct coff_symbol *s;
1923  struct coff_section *common_section;
1924
1925  /* Find the common section - always section 3.  */
1926  common_section = tree->sections + 3;
1927
1928  for (s = tree->symbol_list_head;
1929       s;
1930       s = s->next_in_ofile_list)
1931    {
1932      if (s->visible->type == coff_vis_common)
1933	{
1934	  struct coff_where *w = s->where;
1935	  /*      s->visible->type = coff_vis_ext_def; leave it as common */
1936	  common_section->size = align (common_section->size);
1937	  w->offset = common_section->size + common_section->address;
1938	  w->section = common_section;
1939	  common_section->size += s->type->size;
1940	  common_section->size = align (common_section->size);
1941	}
1942    }
1943}
1944
1945char *program_name;
1946
1947static void
1948show_usage (file, status)
1949     FILE *file;
1950     int status;
1951{
1952  fprintf (file, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
1953  fprintf (file, _("Convert a COFF object file into a SYSROFF object file\n"));
1954  fprintf (file, _(" The options are:\n\
1955  -q --quick       (Obsolete - ignoerd)\n\
1956  -n --noprescan   Do not perform a scan to convert commons into defs\n\
1957  -d --debug       Display information about what is being done\n\
1958  -h --help        Display this information\n\
1959  -v --version     Print the program's version number\n"));
1960
1961  if (status == 0)
1962    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
1963  exit (status);
1964}
1965
1966int
1967main (ac, av)
1968     int ac;
1969     char *av[];
1970{
1971  int opt;
1972  static struct option long_options[] =
1973  {
1974    {"debug", no_argument, 0, 'd'},
1975    {"quick", no_argument, 0, 'q'},
1976    {"noprescan", no_argument, 0, 'n'},
1977    {"help", no_argument, 0, 'h'},
1978    {"version", no_argument, 0, 'V'},
1979    {NULL, no_argument, 0, 0}
1980  };
1981  char **matching;
1982  char *input_file;
1983  char *output_file;
1984
1985#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
1986  setlocale (LC_MESSAGES, "");
1987#endif
1988#if defined (HAVE_SETLOCALE)
1989  setlocale (LC_CTYPE, "");
1990#endif
1991  bindtextdomain (PACKAGE, LOCALEDIR);
1992  textdomain (PACKAGE);
1993
1994  program_name = av[0];
1995  xmalloc_set_program_name (program_name);
1996
1997  while ((opt = getopt_long (ac, av, "dHhVvqn", long_options,
1998			     (int *) NULL))
1999	 != EOF)
2000    {
2001      switch (opt)
2002	{
2003	case 'q':
2004	  quick = 1;
2005	  break;
2006	case 'n':
2007	  noprescan = 1;
2008	  break;
2009	case 'd':
2010	  debug = 1;
2011	  break;
2012	case 'H':
2013	case 'h':
2014	  show_usage (stdout, 0);
2015	  /*NOTREACHED */
2016	case 'v':
2017	case 'V':
2018	  print_version ("srconv");
2019	  exit (0);
2020	  /*NOTREACHED */
2021	case 0:
2022	  break;
2023	default:
2024	  show_usage (stderr, 1);
2025	  /*NOTREACHED */
2026	}
2027    }
2028
2029  /* The input and output files may be named on the command line.  */
2030  output_file = NULL;
2031  if (optind < ac)
2032    {
2033      input_file = av[optind];
2034      ++optind;
2035      if (optind < ac)
2036	{
2037	  output_file = av[optind];
2038	  ++optind;
2039	  if (optind < ac)
2040	    show_usage (stderr, 1);
2041	  if (strcmp (input_file, output_file) == 0)
2042	    {
2043	      fatal (_("input and output files must be different"));
2044	    }
2045	}
2046    }
2047  else
2048    input_file = 0;
2049
2050  if (!input_file)
2051    {
2052      fatal (_("no input file specified"));
2053    }
2054
2055  if (!output_file)
2056    {
2057      /* Take a .o off the input file and stick on a .obj.  If
2058         it doesn't end in .o, then stick a .obj on anyway */
2059
2060      int len = strlen (input_file);
2061
2062      output_file = xmalloc (len + 5);
2063      strcpy (output_file, input_file);
2064
2065      if (len > 3
2066	  && output_file[len - 2] == '.'
2067	  && output_file[len - 1] == 'o')
2068	{
2069	  output_file[len] = 'b';
2070	  output_file[len + 1] = 'j';
2071	  output_file[len + 2] = 0;
2072	}
2073      else
2074	{
2075	  strcat (output_file, ".obj");
2076	}
2077    }
2078
2079  abfd = bfd_openr (input_file, 0);
2080
2081  if (!abfd)
2082    bfd_fatal (input_file);
2083
2084  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
2085    {
2086      bfd_nonfatal (input_file);
2087
2088      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
2089	{
2090	  list_matching_formats (matching);
2091	  free (matching);
2092	}
2093      exit (1);
2094    }
2095
2096  file = fopen (output_file, FOPEN_WB);
2097
2098  if (!file)
2099    fatal (_("unable to open output file %s"), output_file);
2100
2101  if (debug)
2102    printf ("ids %d %d\n", base1, base2);
2103
2104  tree = coff_grok (abfd);
2105
2106  if (!noprescan)
2107    prescan (tree);
2108
2109  wr_module (tree);
2110  return 0;
2111}
2112