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