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