* Makefile.am (MOSTLYCLEANFILES): Remove tmpdir.
[deliverable/binutils-gdb.git] / binutils / coffgrok.c
CommitLineData
4725d7ae 1/* coffgrok.c
b4b91a53 2 Copyright (C) 1994, 95, 1997 Free Software Foundation, Inc.
4725d7ae
SC
3
4This file is part of GNU Binutils.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
b4b91a53 18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
4725d7ae
SC
19
20/* Written by Steve Chamberlain (sac@cygnus.com)
21
22 This module reads a coff file and builds a really simple type tree
23 which can be read by other programs. The first application is a
24 coff->sysroff converter. It can be tested with coffdump.c.
25
26*/
27
28#include <bfd.h>
958998b7 29#include "bucomm.h"
4725d7ae
SC
30
31#include "coff/internal.h"
32#include "../bfd/libcoff.h"
33#include "coffgrok.h"
34int lofile = 1;
35static struct coff_scope *top_scope;
36static struct coff_scope *file_scope;
37static struct coff_ofile *ofile;
38
39struct coff_symbol *last_function_symbol;
40struct coff_type *last_function_type;
41struct coff_type *last_struct;
42struct coff_type *last_enum;
43struct coff_sfile *cur_sfile;
44
45static struct coff_symbol **tindex;
46
47
48static asymbol **syms;
49static long symcount;
50
51#define N(x) ((x)->_n._n_nptr[1])
52
53static struct coff_ptr_struct *rawsyms;
54static int rawcount;
55static bfd *abfd;
56extern char *xcalloc ();
4725d7ae
SC
57#define PTR_SIZE 4
58#define SHORT_SIZE 2
59#define INT_SIZE 4
60#define LONG_SIZE 4
61#define FLOAT_SIZE 4
62#define DOUBLE_SIZE 8
63
64#define INDEXOF(p) ((struct coff_ptr_struct *)(p)-(rawsyms))
65
66static struct coff_scope *
67empty_scope ()
68{
69 struct coff_scope *l;
70 l = (struct coff_scope *) (xcalloc (sizeof (struct coff_scope), 1));
71 return l;
72}
73
74static struct coff_symbol *
75empty_symbol ()
76{
77 return (struct coff_symbol *) (xcalloc (sizeof (struct coff_symbol), 1));
78}
79
80/*int l;*/
81static void
82push_scope (link)
958998b7 83 int link;
4725d7ae
SC
84{
85 struct coff_scope *n = empty_scope ();
86 if (link)
87 {
88 if (top_scope)
89 {
90 if (top_scope->list_tail)
91 {
92 top_scope->list_tail->next = n;
93 }
94 else
95 {
96 top_scope->list_head = n;
97 }
98 top_scope->list_tail = n;
99 }
100 }
101 n->parent = top_scope;
102
103 top_scope = n;
104}
105
106static void
107pop_scope ()
108{
109 top_scope = top_scope->parent;
110}
111
112static void
113do_sections_p1 (head)
114 struct coff_ofile *head;
115{
116 asection *section;
117 int idx;
118 struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1,
119 sizeof (struct coff_section)));
120 head->nsections = abfd->section_count + 1;
121 head->sections = all;
122
123 for (idx = 0, section = abfd->sections; section; section = section->next, idx++)
124 {
125 long relsize;
126 int i = section->target_index;
127 arelent **relpp;
128 long relcount;
129
130 relsize = bfd_get_reloc_upper_bound (abfd, section);
131 if (relsize < 0)
132 bfd_fatal (bfd_get_filename (abfd));
b4b91a53
RH
133 if (relsize == 0)
134 continue;
4725d7ae
SC
135 relpp = (arelent **) xmalloc (relsize);
136 relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
137 if (relcount < 0)
138 bfd_fatal (bfd_get_filename (abfd));
139
140 head->sections[i].name = (char *) (section->name);
141 head->sections[i].code = section->flags & SEC_CODE;
142 head->sections[i].data = section->flags & SEC_DATA;
143 if (strcmp (section->name, ".bss") == 0)
144 head->sections[i].data = 1;
b4b91a53 145 head->sections[i].address = section->lma;
4725d7ae
SC
146 head->sections[i].size = section->_raw_size;
147 head->sections[i].number = idx;
148 head->sections[i].nrelocs = section->reloc_count;
149 head->sections[i].relocs =
150 (struct coff_reloc *) (xcalloc (section->reloc_count,
151 sizeof (struct coff_reloc)));
152 head->sections[i].bfd_section = section;
153 }
154 head->sections[0].name = "ABSOLUTE";
155 head->sections[0].code = 0;
156 head->sections[0].data = 0;
157 head->sections[0].address = 0;
158 head->sections[0].size = 0;
159 head->sections[0].number = 0;
160}
161
162static void
163do_sections_p2 (head)
164 struct coff_ofile *head;
165{
166 asection *section;
167 for (section = abfd->sections; section; section = section->next)
168 {
169 int j;
170 for (j = 0; j < section->reloc_count; j++)
171 {
172 int idx;
173 int i = section->target_index;
174 struct coff_reloc *r = head->sections[i].relocs + j;
175 arelent *sr = section->relocation + j;
176 r->offset = sr->address;
177 r->addend = sr->addend;
178 idx = ((coff_symbol_type *) (sr->sym_ptr_ptr[0]))->native - rawsyms;
179 r->symbol = tindex[idx];
180 }
181 }
182}
183
184static struct coff_where *
185do_where (i)
186 int i;
187{
188 struct internal_syment *sym = &rawsyms[i].u.syment;
b4b91a53
RH
189 struct coff_where *where =
190 (struct coff_where *) (xmalloc (sizeof (struct coff_where)));
4725d7ae
SC
191 where->offset = sym->n_value;
192
193 if (sym->n_scnum == -1)
194 sym->n_scnum = 0;
195
196 switch (sym->n_sclass)
197 {
198 case C_FIELD:
199 where->where = coff_where_member_of_struct;
200 where->offset = sym->n_value / 8;
201 where->bitoffset = sym->n_value % 8;
202 where->bitsize = rawsyms[i + 1].u.auxent.x_sym.x_misc.x_lnsz.x_size;
203 break;
204 case C_MOE:
205 where->where = coff_where_member_of_enum;
206 break;
207 case C_MOS:
208 case C_MOU:
209 where->where = coff_where_member_of_struct;
210 break;
211 case C_AUTO:
212 case C_ARG:
213 where->where = coff_where_stack;
214 break;
215 case C_EXT:
216 case C_STAT:
217 case C_EXTDEF:
218 case C_LABEL:
219 where->where = coff_where_memory;
220 where->section = &ofile->sections[sym->n_scnum];
221 break;
222 case C_REG:
223 case C_REGPARM:
224 where->where = coff_where_register;
225 break;
226 case C_ENTAG:
227 where->where = coff_where_entag;
228 break;
229 case C_STRTAG:
230 case C_UNTAG:
231 where->where = coff_where_strtag;
232 break;
233 case C_TPDEF:
234 where->where = coff_where_typedef;
235 break;
236 default:
237 abort ();
238 break;
239 }
240 return where;
241}
242
243static
244struct coff_line *
245do_lines (i, name)
246 int i;
247 char *name;
248{
249 struct coff_line *res = (struct coff_line *) xcalloc (sizeof (struct coff_line), 1);
250 asection *s;
251 int l;
252 /* Find out if this function has any line numbers in the table */
253 for (s = abfd->sections; s; s = s->next)
254 {
255 for (l = 0; l < s->lineno_count; l++)
256 {
257 if (s->lineno[l].line_number == 0)
258 {
259 if (rawsyms + i == ((coff_symbol_type *) (&(s->lineno[l].u.sym[0])))->native)
260 {
261 /* These lines are for this function - so count them and stick them on */
262 int c = 0;
263 /* Find the linenumber of the top of the function, since coff linenumbers
264 are relative to the start of the function. */
265 int start_line = rawsyms[i + 3].u.auxent.x_sym.x_misc.x_lnsz.x_lnno;
266
267 l++;
268 for (c = 0; s->lineno[l + c + 1].line_number; c++)
269 ;
270
271 /* Add two extra records, one for the prologue and one for the epilogue */
272 c += 1;
273 res->nlines = c;
274 res->lines = (int *) (xcalloc (sizeof (int), c));
275 res->addresses = (int *) (xcalloc (sizeof (int), c));
276 res->lines[0] = start_line;
277 res->addresses[0] = rawsyms[i].u.syment.n_value - s->vma;
278 for (c = 0; s->lineno[l + c + 1].line_number; c++)
279 {
280 res->lines[c + 1] = s->lineno[l + c].line_number + start_line - 1;
281 res->addresses[c + 1] = s->lineno[l + c].u.offset;
282 }
283 return res;
284 }
285 }
286 }
287 }
288 return res;
289}
290
291static
292struct coff_type *
293do_type (i)
294 int i;
295{
296 struct internal_syment *sym = &rawsyms[i].u.syment;
297 union internal_auxent *aux = &rawsyms[i + 1].u.auxent;
b4b91a53
RH
298 struct coff_type *res =
299 (struct coff_type *) xmalloc (sizeof (struct coff_type));
4725d7ae
SC
300 int type = sym->n_type;
301 int which_dt = 0;
b4b91a53 302 int dimind = 0;
4725d7ae
SC
303
304 res->type = coff_basic_type;
305 res->u.basic = type & 0xf;
306
307 switch (type & 0xf)
308 {
309 case T_NULL:
310 case T_VOID:
311 if (sym->n_numaux && sym->n_sclass == C_STAT)
312 {
313 /* This is probably a section definition */
314 res->type = coff_secdef_type;
315 res->size = aux->x_scn.x_scnlen;
316 }
317 else
318 {
319 if (type == 0)
320 {
321 /* Don't know what this is, let's make it a simple int */
322 res->size = INT_SIZE;
323 res->u.basic = T_UINT;
324 }
325 else
326 {
327 /* Else it could be a function or pointer to void */
328 res->size = 0;
329 }
330 }
331 break;
332
333
334 break;
335 case T_UCHAR:
336 case T_CHAR:
337 res->size = 1;
338 break;
339 case T_USHORT:
340 case T_SHORT:
341 res->size = SHORT_SIZE;
342 break;
343 case T_UINT:
344 case T_INT:
345 res->size = INT_SIZE;
346 break;
347 case T_ULONG:
348 case T_LONG:
349 res->size = LONG_SIZE;
350 break;
351 case T_FLOAT:
352 res->size = FLOAT_SIZE;
353 break;
354 case T_DOUBLE:
355 res->size = DOUBLE_SIZE;
356 break;
357 case T_STRUCT:
358 case T_UNION:
359 if (sym->n_numaux)
360 {
361 if (aux->x_sym.x_tagndx.p)
362 {
363 /* Refering to a struct defined elsewhere */
364 res->type = coff_structref_type;
365 res->u.astructref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
366 res->size = res->u.astructref.ref ?
367 res->u.astructref.ref->type->size : 0;
368 }
369 else
370 {
371 /* A definition of a struct */
372 last_struct = res;
373 res->type = coff_structdef_type;
374 res->u.astructdef.elements = empty_scope ();
958998b7 375 res->u.astructdef.idx = 0;
4725d7ae
SC
376 res->u.astructdef.isstruct = (type & 0xf) == T_STRUCT;
377 res->size = aux->x_sym.x_misc.x_lnsz.x_size;
378 }
379 }
380 else
381 {
382 /* No auxents - it's anonynmous */
383 res->type = coff_structref_type;
384 res->u.astructref.ref = 0;
385 res->size = 0;
386 }
387 break;
388 case T_ENUM:
389 if (aux->x_sym.x_tagndx.p)
390 {
391 /* Refering to a enum defined elsewhere */
392 res->type = coff_enumref_type;
393 res->u.aenumref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
394 res->size = res->u.aenumref.ref->type->size;
395 }
396 else
397 {
398 /* A definition of an enum */
399 last_enum = res;
400 res->type = coff_enumdef_type;
401 res->u.aenumdef.elements = empty_scope ();
402 res->size = aux->x_sym.x_misc.x_lnsz.x_size;
403 }
404 break;
405 case T_MOE:
406 break;
407 }
408
409 for (which_dt = 5; which_dt >= 0; which_dt--)
410 {
411 switch ((type >> ((which_dt * 2) + 4)) & 0x3)
412 {
413 case 0:
414 break;
415 case DT_ARY:
416 {
b4b91a53
RH
417 struct coff_type *ptr = ((struct coff_type *)
418 xmalloc (sizeof (struct coff_type)));
419 int els = (dimind < DIMNUM
420 ? aux->x_sym.x_fcnary.x_ary.x_dimen[dimind]
421 : 0);
422 ++dimind;
423 ptr->type = coff_array_type;
424 ptr->size = els * res->size;
425 ptr->u.array.dim = els;
426 ptr->u.array.array_of = res;
427 res = ptr;
428 break;
4725d7ae 429 }
4725d7ae
SC
430 case DT_PTR:
431 {
b4b91a53
RH
432 struct coff_type *ptr =
433 (struct coff_type *) xmalloc (sizeof (struct coff_type));
4725d7ae
SC
434 ptr->size = PTR_SIZE;
435 ptr->type = coff_pointer_type;
436 ptr->u.pointer.points_to = res;
437 res = ptr;
438 break;
439 }
440 case DT_FCN:
441 {
b4b91a53
RH
442 struct coff_type *ptr
443 = (struct coff_type *) xmalloc (sizeof (struct coff_type));
4725d7ae
SC
444 ptr->size = 0;
445 ptr->type = coff_function_type;
446 ptr->u.function.function_returns = res;
447 ptr->u.function.parameters = empty_scope ();
448 ptr->u.function.lines = do_lines (i, sym->_n._n_nptr[1]);
449 ptr->u.function.code = 0;
450 last_function_type = ptr;
451 res = ptr;
452 break;
453 }
454 }
455 }
456 return res;
457}
458
459static struct coff_visible *
460do_visible (i)
461 int i;
462{
463 struct internal_syment *sym = &rawsyms[i].u.syment;
b4b91a53
RH
464 struct coff_visible *visible =
465 (struct coff_visible *) (xmalloc (sizeof (struct coff_visible)));
4725d7ae
SC
466 enum coff_vis_type t;
467 switch (sym->n_sclass)
468 {
469 case C_MOS:
470 case C_MOU:
471 case C_FIELD:
472 t = coff_vis_member_of_struct;
473 break;
474 case C_MOE:
475 t = coff_vis_member_of_enum;
476 break;
477
478 case C_REGPARM:
479 t = coff_vis_regparam;
480 break;
481
482 case C_REG:
483 t = coff_vis_register;
484 break;
485 case C_STRTAG:
486 case C_UNTAG:
487 case C_ENTAG:
488 case C_TPDEF:
489 t = coff_vis_tag;
490 break;
491 case C_AUTOARG:
492 case C_ARG:
493 t = coff_vis_autoparam;
494 break;
495 case C_AUTO:
496
497
498 t = coff_vis_auto;
499 break;
500 case C_LABEL:
501 case C_STAT:
502 t = coff_vis_int_def;
503 break;
504 case C_EXT:
505 if (sym->n_scnum == N_UNDEF)
506 {
507 if (sym->n_value)
508 t = coff_vis_common;
509 else
510 t = coff_vis_ext_ref;
511 }
512 else
513 t = coff_vis_ext_def;
514 break;
515 default:
516 abort ();
517 break;
518
519 }
520 visible->type = t;
521 return visible;
522}
523
524static int
525do_define (i, b)
526 int i;
527 struct coff_scope *b;
528{
529 static int symbol_index;
530 struct internal_syment *sym = &rawsyms[i].u.syment;
531
532 /* Define a symbol and attach to block b */
533 struct coff_symbol *s = empty_symbol ();
534
535 s->number = ++symbol_index;
536 s->name = sym->_n._n_nptr[1];
537 s->sfile = cur_sfile;
538 /* Glue onto the ofile list */
539 if (lofile >= 0)
540 {
541 if (ofile->symbol_list_tail)
542 ofile->symbol_list_tail->next_in_ofile_list = s;
543 else
544 ofile->symbol_list_head = s;
545 ofile->symbol_list_tail = s;
546 /* And the block list */
547 }
548 if (b->vars_tail)
549 b->vars_tail->next = s;
550 else
551 b->vars_head = s;
552
553 b->vars_tail = s;
554 b->nvars++;
555 s->type = do_type (i);
556 s->where = do_where (i);
557 s->visible = do_visible (i);
558
559 tindex[i] = s;
560
561 /* We remember the lowest address in each section for each source file */
562
563 if (s->where->where == coff_where_memory
564 && s->type->type == coff_secdef_type)
565 {
566 struct coff_isection *is = cur_sfile->section + s->where->section->number;
567
568 if (!is->init)
569 {
570 is->low = s->where->offset;
571 is->high = s->where->offset + s->type->size;
572 is->init = 1;
573 is->parent = s->where->section;
574 }
575
576 }
577
578 if (s->type->type == coff_function_type)
579 last_function_symbol = s;
580
581 return i + sym->n_numaux + 1;
582}
583
584
585static
586struct coff_ofile *
587doit ()
588{
589 int i;
590 int infile = 0;
958998b7
ILT
591 struct coff_ofile *head =
592 (struct coff_ofile *) xmalloc (sizeof (struct coff_ofile));
4725d7ae
SC
593 ofile = head;
594 head->source_head = 0;
595 head->source_tail = 0;
958998b7
ILT
596 head->nsources = 0;
597 head->symbol_list_tail = 0;
598 head->symbol_list_head = 0;
4725d7ae
SC
599 do_sections_p1 (head);
600 push_scope (1);
601
602 for (i = 0; i < rawcount;)
603 {
604 struct internal_syment *sym = &rawsyms[i].u.syment;
605 switch (sym->n_sclass)
606 {
607 case C_FILE:
608 {
609 /* new source file announced */
b4b91a53
RH
610 struct coff_sfile *n =
611 (struct coff_sfile *) xmalloc (sizeof (struct coff_sfile));
4725d7ae
SC
612 n->section = (struct coff_isection *) xcalloc (sizeof (struct coff_isection), abfd->section_count + 1);
613 cur_sfile = n;
614 n->name = sym->_n._n_nptr[1];
615 n->next = 0;
616
617 if (infile)
618 {
619 pop_scope ();
620 }
621 infile = 1;
622 push_scope (1);
623 file_scope = n->scope = top_scope;
624
625 if (head->source_tail)
626 head->source_tail->next = n;
627 else
628 head->source_head = n;
629 head->source_tail = n;
630 head->nsources++;
631 i += sym->n_numaux + 1;
632 }
633 break;
634 case C_FCN:
635 {
636 char *name = sym->_n._n_nptr[1];
637 if (name[1] == 'b')
638 {
639 /* Function start */
640 push_scope (0);
641 last_function_type->u.function.code = top_scope;
642 top_scope->sec = ofile->sections + sym->n_scnum;
643 top_scope->offset = sym->n_value;
644 }
645 else
646 {
647 top_scope->size = sym->n_value - top_scope->offset + 1;
648 pop_scope ();
649
650 }
651 i += sym->n_numaux + 1;
652 }
653 break;
654
655 case C_BLOCK:
656 {
657 char *name = sym->_n._n_nptr[1];
658 if (name[1] == 'b')
659 {
660 /* Block start */
661 push_scope (1);
662 top_scope->sec = ofile->sections + sym->n_scnum;
663 top_scope->offset = sym->n_value;
664
665 }
666 else
667 {
668 top_scope->size = sym->n_value - top_scope->offset + 1;
669 pop_scope ();
670 }
671 i += sym->n_numaux + 1;
672 }
673 break;
674 case C_REGPARM:
675 case C_ARG:
676 i = do_define (i, last_function_symbol->type->u.function.parameters);
677 break;
678 case C_MOS:
679 case C_MOU:
680 case C_FIELD:
681 i = do_define (i, last_struct->u.astructdef.elements);
682 break;
683 case C_MOE:
684 i = do_define (i, last_enum->u.aenumdef.elements);
685 break;
686 case C_STRTAG:
687 case C_ENTAG:
688 case C_UNTAG:
689 /* Various definition */
690 i = do_define (i, top_scope);
691 break;
692 case C_EXT:
693 case C_LABEL:
694 i = do_define (i, file_scope);
695 break;
696 case C_STAT:
697 case C_TPDEF:
698 case C_AUTO:
699 case C_REG:
700 i = do_define (i, top_scope);
701 break;
702 default:
703 abort ();
704 case C_EOS:
705 i += sym->n_numaux + 1;
706 break;
707 }
708 }
709 do_sections_p2 (head);
710 return head;
711}
712
713struct coff_ofile *
714coff_grok (inabfd)
715 bfd *inabfd;
716{
717 long storage;
718 struct coff_ofile *p;
719 abfd = inabfd;
720 storage = bfd_get_symtab_upper_bound (abfd);
721
722 if (storage < 0)
723 bfd_fatal (abfd->filename);
724
725 syms = (asymbol **) xmalloc (storage);
726 symcount = bfd_canonicalize_symtab (abfd, syms);
727 if (symcount < 0)
728 bfd_fatal (abfd->filename);
729 rawsyms = obj_raw_syments (abfd);
730 rawcount = obj_raw_syment_count (abfd);;
731 tindex = (struct coff_symbol **) (xcalloc (sizeof (struct coff_symbol *), rawcount));
732
958998b7 733 p = doit ();
4725d7ae
SC
734 return p;
735}
This page took 0.193145 seconds and 4 git commands to generate.