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