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