coffgrok.c revision 33965
1/* coffgrok.c
2   Copyright (C) 1994, 95, 1997 Free Software Foundation, Inc.
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
18Foundation, 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 "bucomm.h"
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 ();
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)
83     int link;
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));
133      if (relsize == 0)
134        continue;
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;
145      head->sections[i].address = section->vma;
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;
189  struct coff_where *where =
190    (struct coff_where *) (xmalloc (sizeof (struct coff_where)));
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;
298  struct coff_type *res =
299    (struct coff_type *) xmalloc (sizeof (struct coff_type));
300  int type = sym->n_type;
301  int which_dt = 0;
302  int dimind = 0;
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 ();
375	      res->u.astructdef.idx = 0;
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	  {
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;
429	  }
430	case DT_PTR:
431	  {
432	    struct coff_type *ptr =
433	      (struct coff_type *) xmalloc (sizeof (struct coff_type));
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	  {
442	    struct coff_type *ptr
443	      = (struct coff_type *) xmalloc (sizeof (struct coff_type));
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;
464  struct coff_visible *visible =
465    (struct coff_visible *) (xmalloc (sizeof (struct coff_visible)));
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;
591  struct coff_ofile *head =
592  (struct coff_ofile *) xmalloc (sizeof (struct coff_ofile));
593  ofile = head;
594  head->source_head = 0;
595  head->source_tail = 0;
596  head->nsources = 0;
597  head->symbol_list_tail = 0;
598  head->symbol_list_head = 0;
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 */
610	    struct coff_sfile *n =
611	      (struct coff_sfile *) xmalloc (sizeof (struct coff_sfile));
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
733  p = doit ();
734  return p;
735}
736