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