133965Sjdp/* coffgrok.c
2218822Sdim   Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2007
3104834Sobrien   Free Software Foundation, Inc.
433965Sjdp
533965SjdpThis file is part of GNU Binutils.
633965Sjdp
733965SjdpThis program is free software; you can redistribute it and/or modify
833965Sjdpit under the terms of the GNU General Public License as published by
933965Sjdpthe Free Software Foundation; either version 2 of the License, or
1033965Sjdp(at your option) any later version.
1133965Sjdp
1233965SjdpThis program is distributed in the hope that it will be useful,
1333965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965SjdpGNU General Public License for more details.
1633965Sjdp
1733965SjdpYou should have received a copy of the GNU General Public License
1833965Sjdpalong with this program; if not, write to the Free Software
19218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2033965Sjdp
2133965Sjdp/* Written by Steve Chamberlain (sac@cygnus.com)
2233965Sjdp
2333965Sjdp   This module reads a coff file and builds a really simple type tree
2433965Sjdp   which can be read by other programs.  The first application is a
2533965Sjdp   coff->sysroff converter.  It can be tested with coffdump.c.
2633965Sjdp
2733965Sjdp*/
2833965Sjdp
29218822Sdim#include "sysdep.h"
30104834Sobrien#include "bfd.h"
31104834Sobrien#include "libiberty.h"
3233965Sjdp
3333965Sjdp#include "coff/internal.h"
3433965Sjdp#include "../bfd/libcoff.h"
35218822Sdim#include "bucomm.h"
3633965Sjdp#include "coffgrok.h"
37218822Sdim
38218822Sdimstatic int lofile = 1;
3933965Sjdpstatic struct coff_scope *top_scope;
4033965Sjdpstatic struct coff_scope *file_scope;
4133965Sjdpstatic struct coff_ofile *ofile;
4233965Sjdp
43218822Sdimstatic struct coff_symbol *last_function_symbol;
44218822Sdimstatic struct coff_type *last_function_type;
45218822Sdimstatic struct coff_type *last_struct;
46218822Sdimstatic struct coff_type *last_enum;
47218822Sdimstatic struct coff_sfile *cur_sfile;
4833965Sjdp
4933965Sjdpstatic struct coff_symbol **tindex;
5033965Sjdp
5133965Sjdp
5233965Sjdpstatic asymbol **syms;
5333965Sjdpstatic long symcount;
5433965Sjdp
5533965Sjdp#define N(x) ((x)->_n._n_nptr[1])
5633965Sjdp
5733965Sjdpstatic struct coff_ptr_struct *rawsyms;
5833965Sjdpstatic int rawcount;
5933965Sjdpstatic bfd *abfd;
6089857Sobrien
61130561Sobrien#define PTR_SIZE	4
62130561Sobrien#define SHORT_SIZE	2
63130561Sobrien#define INT_SIZE	4
64130561Sobrien#define LONG_SIZE	4
65130561Sobrien#define FLOAT_SIZE	4
66130561Sobrien#define DOUBLE_SIZE	8
6733965Sjdp
6833965Sjdp#define INDEXOF(p)  ((struct coff_ptr_struct *)(p)-(rawsyms))
6933965Sjdp
70130561Sobrienstatic struct coff_scope *empty_scope (void);
71130561Sobrienstatic struct coff_symbol *empty_symbol (void);
72130561Sobrienstatic void push_scope (int);
73130561Sobrienstatic void pop_scope (void);
74130561Sobrienstatic void do_sections_p1 (struct coff_ofile *);
75130561Sobrienstatic void do_sections_p2 (struct coff_ofile *);
76130561Sobrienstatic struct coff_where *do_where (int);
77130561Sobrienstatic struct coff_line *do_lines (int, char *);
78130561Sobrienstatic struct coff_type *do_type (int);
79130561Sobrienstatic struct coff_visible *do_visible (int);
80130561Sobrienstatic int do_define (int, struct coff_scope *);
81130561Sobrienstatic struct coff_ofile *doit (void);
8289857Sobrien
8333965Sjdpstatic struct coff_scope *
84130561Sobrienempty_scope (void)
8533965Sjdp{
8633965Sjdp  struct coff_scope *l;
8733965Sjdp  l = (struct coff_scope *) (xcalloc (sizeof (struct coff_scope), 1));
8833965Sjdp  return l;
8933965Sjdp}
9033965Sjdp
9133965Sjdpstatic struct coff_symbol *
92130561Sobrienempty_symbol (void)
9333965Sjdp{
9433965Sjdp  return (struct coff_symbol *) (xcalloc (sizeof (struct coff_symbol), 1));
9533965Sjdp}
9633965Sjdp
9733965Sjdp/*int l;*/
9833965Sjdpstatic void
99130561Sobrienpush_scope (int link)
10033965Sjdp{
10133965Sjdp  struct coff_scope *n = empty_scope ();
10233965Sjdp  if (link)
10333965Sjdp    {
10433965Sjdp      if (top_scope)
10533965Sjdp	{
10633965Sjdp	  if (top_scope->list_tail)
10733965Sjdp	    {
10833965Sjdp	      top_scope->list_tail->next = n;
10933965Sjdp	    }
11033965Sjdp	  else
11133965Sjdp	    {
11233965Sjdp	      top_scope->list_head = n;
11333965Sjdp	    }
11433965Sjdp	  top_scope->list_tail = n;
11533965Sjdp	}
11633965Sjdp    }
11733965Sjdp  n->parent = top_scope;
11833965Sjdp
11933965Sjdp  top_scope = n;
12033965Sjdp}
12133965Sjdp
12233965Sjdpstatic void
123130561Sobrienpop_scope (void)
12433965Sjdp{
12533965Sjdp  top_scope = top_scope->parent;
12633965Sjdp}
12733965Sjdp
12833965Sjdpstatic void
129130561Sobriendo_sections_p1 (struct coff_ofile *head)
13033965Sjdp{
13133965Sjdp  asection *section;
13233965Sjdp  int idx;
13333965Sjdp  struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1,
13433965Sjdp					     sizeof (struct coff_section)));
13533965Sjdp  head->nsections = abfd->section_count + 1;
13633965Sjdp  head->sections = all;
13733965Sjdp
13833965Sjdp  for (idx = 0, section = abfd->sections; section; section = section->next, idx++)
13933965Sjdp    {
14033965Sjdp      long relsize;
14133965Sjdp      int i = section->target_index;
14233965Sjdp      arelent **relpp;
14333965Sjdp      long relcount;
14433965Sjdp
14533965Sjdp      relsize = bfd_get_reloc_upper_bound (abfd, section);
14633965Sjdp      if (relsize < 0)
14733965Sjdp	bfd_fatal (bfd_get_filename (abfd));
14833965Sjdp      if (relsize == 0)
149104834Sobrien	continue;
15033965Sjdp      relpp = (arelent **) xmalloc (relsize);
15133965Sjdp      relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
15233965Sjdp      if (relcount < 0)
15333965Sjdp	bfd_fatal (bfd_get_filename (abfd));
15433965Sjdp
15533965Sjdp      head->sections[i].name = (char *) (section->name);
15633965Sjdp      head->sections[i].code = section->flags & SEC_CODE;
15733965Sjdp      head->sections[i].data = section->flags & SEC_DATA;
15833965Sjdp      if (strcmp (section->name, ".bss") == 0)
15933965Sjdp	head->sections[i].data = 1;
16038889Sjdp      head->sections[i].address = section->lma;
161218822Sdim      head->sections[i].size = bfd_get_section_size (section);
16233965Sjdp      head->sections[i].number = idx;
16333965Sjdp      head->sections[i].nrelocs = section->reloc_count;
16433965Sjdp      head->sections[i].relocs =
16533965Sjdp	(struct coff_reloc *) (xcalloc (section->reloc_count,
16633965Sjdp					sizeof (struct coff_reloc)));
16733965Sjdp      head->sections[i].bfd_section = section;
16833965Sjdp    }
16933965Sjdp  head->sections[0].name = "ABSOLUTE";
17033965Sjdp  head->sections[0].code = 0;
17133965Sjdp  head->sections[0].data = 0;
17233965Sjdp  head->sections[0].address = 0;
17333965Sjdp  head->sections[0].size = 0;
17433965Sjdp  head->sections[0].number = 0;
17533965Sjdp}
17633965Sjdp
17733965Sjdpstatic void
178130561Sobriendo_sections_p2 (struct coff_ofile *head)
17933965Sjdp{
18033965Sjdp  asection *section;
18133965Sjdp  for (section = abfd->sections; section; section = section->next)
18233965Sjdp    {
18338889Sjdp      unsigned int j;
18438889Sjdp
18533965Sjdp      for (j = 0; j < section->reloc_count; j++)
18633965Sjdp	{
18733965Sjdp	  int idx;
18833965Sjdp	  int i = section->target_index;
18933965Sjdp	  struct coff_reloc *r = head->sections[i].relocs + j;
19033965Sjdp	  arelent *sr = section->relocation + j;
19133965Sjdp	  r->offset = sr->address;
19233965Sjdp	  r->addend = sr->addend;
19333965Sjdp	  idx = ((coff_symbol_type *) (sr->sym_ptr_ptr[0]))->native - rawsyms;
19433965Sjdp	  r->symbol = tindex[idx];
19533965Sjdp	}
19633965Sjdp    }
19733965Sjdp}
19833965Sjdp
19933965Sjdpstatic struct coff_where *
200130561Sobriendo_where (int i)
20133965Sjdp{
20233965Sjdp  struct internal_syment *sym = &rawsyms[i].u.syment;
20333965Sjdp  struct coff_where *where =
20433965Sjdp    (struct coff_where *) (xmalloc (sizeof (struct coff_where)));
20533965Sjdp  where->offset = sym->n_value;
20633965Sjdp
20733965Sjdp  if (sym->n_scnum == -1)
20833965Sjdp    sym->n_scnum = 0;
20933965Sjdp
21033965Sjdp  switch (sym->n_sclass)
21133965Sjdp    {
21233965Sjdp    case C_FIELD:
21333965Sjdp      where->where = coff_where_member_of_struct;
21433965Sjdp      where->offset = sym->n_value / 8;
21533965Sjdp      where->bitoffset = sym->n_value % 8;
21633965Sjdp      where->bitsize = rawsyms[i + 1].u.auxent.x_sym.x_misc.x_lnsz.x_size;
21733965Sjdp      break;
21833965Sjdp    case C_MOE:
21933965Sjdp      where->where = coff_where_member_of_enum;
22033965Sjdp      break;
22133965Sjdp    case C_MOS:
22233965Sjdp    case C_MOU:
22333965Sjdp      where->where = coff_where_member_of_struct;
22433965Sjdp      break;
22533965Sjdp    case C_AUTO:
22633965Sjdp    case C_ARG:
22733965Sjdp      where->where = coff_where_stack;
22833965Sjdp      break;
22933965Sjdp    case C_EXT:
23033965Sjdp    case C_STAT:
23133965Sjdp    case C_EXTDEF:
23233965Sjdp    case C_LABEL:
23333965Sjdp      where->where = coff_where_memory;
23433965Sjdp      where->section = &ofile->sections[sym->n_scnum];
23533965Sjdp      break;
23633965Sjdp    case C_REG:
23733965Sjdp    case C_REGPARM:
23833965Sjdp      where->where = coff_where_register;
23933965Sjdp      break;
24033965Sjdp    case C_ENTAG:
24133965Sjdp      where->where = coff_where_entag;
24233965Sjdp      break;
24333965Sjdp    case C_STRTAG:
24433965Sjdp    case C_UNTAG:
24533965Sjdp      where->where = coff_where_strtag;
24633965Sjdp      break;
24733965Sjdp    case C_TPDEF:
24833965Sjdp      where->where = coff_where_typedef;
24933965Sjdp      break;
25033965Sjdp    default:
25133965Sjdp      abort ();
25233965Sjdp      break;
25333965Sjdp    }
25433965Sjdp  return where;
25533965Sjdp}
25633965Sjdp
25733965Sjdpstatic
25833965Sjdpstruct coff_line *
259130561Sobriendo_lines (int i, char *name ATTRIBUTE_UNUSED)
26033965Sjdp{
26133965Sjdp  struct coff_line *res = (struct coff_line *) xcalloc (sizeof (struct coff_line), 1);
26233965Sjdp  asection *s;
26338889Sjdp  unsigned int l;
26438889Sjdp
26533965Sjdp  /* Find out if this function has any line numbers in the table */
26633965Sjdp  for (s = abfd->sections; s; s = s->next)
26733965Sjdp    {
26833965Sjdp      for (l = 0; l < s->lineno_count; l++)
26933965Sjdp	{
27033965Sjdp	  if (s->lineno[l].line_number == 0)
27133965Sjdp	    {
27233965Sjdp	      if (rawsyms + i == ((coff_symbol_type *) (&(s->lineno[l].u.sym[0])))->native)
27333965Sjdp		{
27433965Sjdp		  /* These lines are for this function - so count them and stick them on */
27533965Sjdp		  int c = 0;
27633965Sjdp		  /* Find the linenumber of the top of the function, since coff linenumbers
277104834Sobrien		     are relative to the start of the function.  */
27833965Sjdp		  int start_line = rawsyms[i + 3].u.auxent.x_sym.x_misc.x_lnsz.x_lnno;
27933965Sjdp
28033965Sjdp		  l++;
28133965Sjdp		  for (c = 0; s->lineno[l + c + 1].line_number; c++)
28233965Sjdp		    ;
28333965Sjdp
28433965Sjdp		  /* Add two extra records, one for the prologue and one for the epilogue */
28533965Sjdp		  c += 1;
28633965Sjdp		  res->nlines = c;
28733965Sjdp		  res->lines = (int *) (xcalloc (sizeof (int), c));
28833965Sjdp		  res->addresses = (int *) (xcalloc (sizeof (int), c));
28933965Sjdp		  res->lines[0] = start_line;
29033965Sjdp		  res->addresses[0] = rawsyms[i].u.syment.n_value - s->vma;
29133965Sjdp		  for (c = 0; s->lineno[l + c + 1].line_number; c++)
29233965Sjdp		    {
29333965Sjdp		      res->lines[c + 1] = s->lineno[l + c].line_number + start_line - 1;
29433965Sjdp		      res->addresses[c + 1] = s->lineno[l + c].u.offset;
29533965Sjdp		    }
29633965Sjdp		  return res;
29733965Sjdp		}
29833965Sjdp	    }
29933965Sjdp	}
30033965Sjdp    }
30133965Sjdp  return res;
30233965Sjdp}
30333965Sjdp
30433965Sjdpstatic
30533965Sjdpstruct coff_type *
306130561Sobriendo_type (int i)
30733965Sjdp{
30833965Sjdp  struct internal_syment *sym = &rawsyms[i].u.syment;
30933965Sjdp  union internal_auxent *aux = &rawsyms[i + 1].u.auxent;
31033965Sjdp  struct coff_type *res =
31133965Sjdp    (struct coff_type *) xmalloc (sizeof (struct coff_type));
31233965Sjdp  int type = sym->n_type;
31333965Sjdp  int which_dt = 0;
31433965Sjdp  int dimind = 0;
31533965Sjdp
31633965Sjdp  res->type = coff_basic_type;
31733965Sjdp  res->u.basic = type & 0xf;
31833965Sjdp
31933965Sjdp  switch (type & 0xf)
32033965Sjdp    {
32133965Sjdp    case T_NULL:
32233965Sjdp    case T_VOID:
32333965Sjdp      if (sym->n_numaux && sym->n_sclass == C_STAT)
32433965Sjdp	{
32533965Sjdp	  /* This is probably a section definition */
32633965Sjdp	  res->type = coff_secdef_type;
32733965Sjdp	  res->size = aux->x_scn.x_scnlen;
32833965Sjdp	}
32933965Sjdp      else
33033965Sjdp	{
33133965Sjdp	  if (type == 0)
33233965Sjdp	    {
33333965Sjdp	      /* Don't know what this is, let's make it a simple int */
33433965Sjdp	      res->size = INT_SIZE;
33533965Sjdp	      res->u.basic = T_UINT;
33633965Sjdp	    }
33733965Sjdp	  else
33833965Sjdp	    {
33933965Sjdp	      /* Else it could be a function or pointer to void */
34033965Sjdp	      res->size = 0;
34133965Sjdp	    }
34233965Sjdp	}
34333965Sjdp      break;
34433965Sjdp
34533965Sjdp
34633965Sjdp      break;
34733965Sjdp    case T_UCHAR:
34833965Sjdp    case T_CHAR:
34933965Sjdp      res->size = 1;
35033965Sjdp      break;
35133965Sjdp    case T_USHORT:
35233965Sjdp    case T_SHORT:
35333965Sjdp      res->size = SHORT_SIZE;
35433965Sjdp      break;
35533965Sjdp    case T_UINT:
35633965Sjdp    case T_INT:
35733965Sjdp      res->size = INT_SIZE;
35833965Sjdp      break;
35933965Sjdp    case T_ULONG:
36033965Sjdp    case T_LONG:
36133965Sjdp      res->size = LONG_SIZE;
36233965Sjdp      break;
36333965Sjdp    case T_FLOAT:
36433965Sjdp      res->size = FLOAT_SIZE;
36533965Sjdp      break;
36633965Sjdp    case T_DOUBLE:
36733965Sjdp      res->size = DOUBLE_SIZE;
36833965Sjdp      break;
36933965Sjdp    case T_STRUCT:
37033965Sjdp    case T_UNION:
37133965Sjdp      if (sym->n_numaux)
37233965Sjdp	{
37333965Sjdp	  if (aux->x_sym.x_tagndx.p)
37433965Sjdp	    {
375130561Sobrien	      /* Referring to a struct defined elsewhere */
37633965Sjdp	      res->type = coff_structref_type;
37733965Sjdp	      res->u.astructref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
37833965Sjdp	      res->size = res->u.astructref.ref ?
37933965Sjdp		res->u.astructref.ref->type->size : 0;
38033965Sjdp	    }
38133965Sjdp	  else
38233965Sjdp	    {
38333965Sjdp	      /* A definition of a struct */
38433965Sjdp	      last_struct = res;
38533965Sjdp	      res->type = coff_structdef_type;
38633965Sjdp	      res->u.astructdef.elements = empty_scope ();
38733965Sjdp	      res->u.astructdef.idx = 0;
38833965Sjdp	      res->u.astructdef.isstruct = (type & 0xf) == T_STRUCT;
38933965Sjdp	      res->size = aux->x_sym.x_misc.x_lnsz.x_size;
39033965Sjdp	    }
39133965Sjdp	}
39233965Sjdp      else
39333965Sjdp	{
394130561Sobrien	  /* No auxents - it's anonymous */
39533965Sjdp	  res->type = coff_structref_type;
39633965Sjdp	  res->u.astructref.ref = 0;
39733965Sjdp	  res->size = 0;
39833965Sjdp	}
39933965Sjdp      break;
40033965Sjdp    case T_ENUM:
40133965Sjdp      if (aux->x_sym.x_tagndx.p)
40233965Sjdp	{
403130561Sobrien	  /* Referring to a enum defined elsewhere */
40433965Sjdp	  res->type = coff_enumref_type;
40533965Sjdp	  res->u.aenumref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
40633965Sjdp	  res->size = res->u.aenumref.ref->type->size;
40733965Sjdp	}
40833965Sjdp      else
40933965Sjdp	{
41033965Sjdp	  /* A definition of an enum */
41133965Sjdp	  last_enum = res;
41233965Sjdp	  res->type = coff_enumdef_type;
41333965Sjdp	  res->u.aenumdef.elements = empty_scope ();
41433965Sjdp	  res->size = aux->x_sym.x_misc.x_lnsz.x_size;
41533965Sjdp	}
41633965Sjdp      break;
41733965Sjdp    case T_MOE:
41833965Sjdp      break;
41933965Sjdp    }
42033965Sjdp
42133965Sjdp  for (which_dt = 5; which_dt >= 0; which_dt--)
42233965Sjdp    {
42333965Sjdp      switch ((type >> ((which_dt * 2) + 4)) & 0x3)
42433965Sjdp	{
42533965Sjdp	case 0:
42633965Sjdp	  break;
42733965Sjdp	case DT_ARY:
42833965Sjdp	  {
42933965Sjdp	    struct coff_type *ptr = ((struct coff_type *)
43033965Sjdp				     xmalloc (sizeof (struct coff_type)));
43133965Sjdp	    int els = (dimind < DIMNUM
43233965Sjdp		       ? aux->x_sym.x_fcnary.x_ary.x_dimen[dimind]
43333965Sjdp		       : 0);
43433965Sjdp	    ++dimind;
43533965Sjdp	    ptr->type = coff_array_type;
43633965Sjdp	    ptr->size = els * res->size;
43733965Sjdp	    ptr->u.array.dim = els;
43833965Sjdp	    ptr->u.array.array_of = res;
43933965Sjdp	    res = ptr;
44033965Sjdp	    break;
44133965Sjdp	  }
44233965Sjdp	case DT_PTR:
44333965Sjdp	  {
44433965Sjdp	    struct coff_type *ptr =
44533965Sjdp	      (struct coff_type *) xmalloc (sizeof (struct coff_type));
44633965Sjdp	    ptr->size = PTR_SIZE;
44733965Sjdp	    ptr->type = coff_pointer_type;
44833965Sjdp	    ptr->u.pointer.points_to = res;
44933965Sjdp	    res = ptr;
45033965Sjdp	    break;
45133965Sjdp	  }
45233965Sjdp	case DT_FCN:
45333965Sjdp	  {
45433965Sjdp	    struct coff_type *ptr
45533965Sjdp	      = (struct coff_type *) xmalloc (sizeof (struct coff_type));
45633965Sjdp	    ptr->size = 0;
45733965Sjdp	    ptr->type = coff_function_type;
45833965Sjdp	    ptr->u.function.function_returns = res;
45933965Sjdp	    ptr->u.function.parameters = empty_scope ();
46033965Sjdp	    ptr->u.function.lines = do_lines (i, sym->_n._n_nptr[1]);
46133965Sjdp	    ptr->u.function.code = 0;
46233965Sjdp	    last_function_type = ptr;
46333965Sjdp	    res = ptr;
46433965Sjdp	    break;
46533965Sjdp	  }
46633965Sjdp	}
46733965Sjdp    }
46833965Sjdp  return res;
46933965Sjdp}
47033965Sjdp
47133965Sjdpstatic struct coff_visible *
472130561Sobriendo_visible (int i)
47333965Sjdp{
47433965Sjdp  struct internal_syment *sym = &rawsyms[i].u.syment;
47533965Sjdp  struct coff_visible *visible =
47633965Sjdp    (struct coff_visible *) (xmalloc (sizeof (struct coff_visible)));
47733965Sjdp  enum coff_vis_type t;
47833965Sjdp  switch (sym->n_sclass)
47933965Sjdp    {
48033965Sjdp    case C_MOS:
48133965Sjdp    case C_MOU:
48233965Sjdp    case C_FIELD:
48333965Sjdp      t = coff_vis_member_of_struct;
48433965Sjdp      break;
48533965Sjdp    case C_MOE:
48633965Sjdp      t = coff_vis_member_of_enum;
48733965Sjdp      break;
48833965Sjdp
48933965Sjdp    case C_REGPARM:
49033965Sjdp      t = coff_vis_regparam;
49133965Sjdp      break;
49233965Sjdp
49333965Sjdp    case C_REG:
49433965Sjdp      t = coff_vis_register;
49533965Sjdp      break;
49633965Sjdp    case C_STRTAG:
49733965Sjdp    case C_UNTAG:
49833965Sjdp    case C_ENTAG:
49933965Sjdp    case C_TPDEF:
50033965Sjdp      t = coff_vis_tag;
50133965Sjdp      break;
50233965Sjdp    case C_AUTOARG:
50333965Sjdp    case C_ARG:
50433965Sjdp      t = coff_vis_autoparam;
50533965Sjdp      break;
50633965Sjdp    case C_AUTO:
50733965Sjdp
50833965Sjdp
50933965Sjdp      t = coff_vis_auto;
51033965Sjdp      break;
51133965Sjdp    case C_LABEL:
51233965Sjdp    case C_STAT:
51333965Sjdp      t = coff_vis_int_def;
51433965Sjdp      break;
51533965Sjdp    case C_EXT:
51633965Sjdp      if (sym->n_scnum == N_UNDEF)
51733965Sjdp	{
51833965Sjdp	  if (sym->n_value)
51933965Sjdp	    t = coff_vis_common;
52033965Sjdp	  else
52133965Sjdp	    t = coff_vis_ext_ref;
52233965Sjdp	}
52333965Sjdp      else
52433965Sjdp	t = coff_vis_ext_def;
52533965Sjdp      break;
52633965Sjdp    default:
52733965Sjdp      abort ();
52833965Sjdp      break;
52933965Sjdp
53033965Sjdp    }
53133965Sjdp  visible->type = t;
53233965Sjdp  return visible;
53333965Sjdp}
53433965Sjdp
53533965Sjdpstatic int
536130561Sobriendo_define (int i, struct coff_scope *b)
53733965Sjdp{
53833965Sjdp  static int symbol_index;
53933965Sjdp  struct internal_syment *sym = &rawsyms[i].u.syment;
54033965Sjdp
54133965Sjdp  /* Define a symbol and attach to block b */
54233965Sjdp  struct coff_symbol *s = empty_symbol ();
54333965Sjdp
54433965Sjdp  s->number = ++symbol_index;
54533965Sjdp  s->name = sym->_n._n_nptr[1];
54633965Sjdp  s->sfile = cur_sfile;
54733965Sjdp  /* Glue onto the ofile list */
54833965Sjdp  if (lofile >= 0)
54933965Sjdp    {
55033965Sjdp      if (ofile->symbol_list_tail)
55133965Sjdp	ofile->symbol_list_tail->next_in_ofile_list = s;
55233965Sjdp      else
55333965Sjdp	ofile->symbol_list_head = s;
55433965Sjdp      ofile->symbol_list_tail = s;
55533965Sjdp      /* And the block list */
55633965Sjdp    }
55733965Sjdp  if (b->vars_tail)
55833965Sjdp    b->vars_tail->next = s;
55933965Sjdp  else
56033965Sjdp    b->vars_head = s;
56133965Sjdp
56233965Sjdp  b->vars_tail = s;
56333965Sjdp  b->nvars++;
56433965Sjdp  s->type = do_type (i);
56533965Sjdp  s->where = do_where (i);
56633965Sjdp  s->visible = do_visible (i);
56733965Sjdp
56833965Sjdp  tindex[i] = s;
56933965Sjdp
57033965Sjdp  /* We remember the lowest address in each section for each source file */
57133965Sjdp
57233965Sjdp  if (s->where->where == coff_where_memory
57333965Sjdp      && s->type->type == coff_secdef_type)
57433965Sjdp    {
57533965Sjdp      struct coff_isection *is = cur_sfile->section + s->where->section->number;
57633965Sjdp
57733965Sjdp      if (!is->init)
57833965Sjdp	{
57933965Sjdp	  is->low = s->where->offset;
58033965Sjdp	  is->high = s->where->offset + s->type->size;
58133965Sjdp	  is->init = 1;
58233965Sjdp	  is->parent = s->where->section;
58333965Sjdp	}
58433965Sjdp
58533965Sjdp    }
58633965Sjdp
58733965Sjdp  if (s->type->type == coff_function_type)
58833965Sjdp    last_function_symbol = s;
58933965Sjdp
59033965Sjdp  return i + sym->n_numaux + 1;
59133965Sjdp}
59233965Sjdp
59333965Sjdp
59433965Sjdpstatic
59533965Sjdpstruct coff_ofile *
596130561Sobriendoit (void)
59733965Sjdp{
59833965Sjdp  int i;
59933965Sjdp  int infile = 0;
60033965Sjdp  struct coff_ofile *head =
601104834Sobrien    (struct coff_ofile *) xmalloc (sizeof (struct coff_ofile));
60233965Sjdp  ofile = head;
60333965Sjdp  head->source_head = 0;
60433965Sjdp  head->source_tail = 0;
60533965Sjdp  head->nsources = 0;
60633965Sjdp  head->symbol_list_tail = 0;
60733965Sjdp  head->symbol_list_head = 0;
60833965Sjdp  do_sections_p1 (head);
60933965Sjdp  push_scope (1);
61033965Sjdp
61133965Sjdp  for (i = 0; i < rawcount;)
61233965Sjdp    {
61333965Sjdp      struct internal_syment *sym = &rawsyms[i].u.syment;
61433965Sjdp      switch (sym->n_sclass)
61533965Sjdp	{
61633965Sjdp	case C_FILE:
61733965Sjdp	  {
61833965Sjdp	    /* new source file announced */
61933965Sjdp	    struct coff_sfile *n =
62033965Sjdp	      (struct coff_sfile *) xmalloc (sizeof (struct coff_sfile));
62133965Sjdp	    n->section = (struct coff_isection *) xcalloc (sizeof (struct coff_isection), abfd->section_count + 1);
62233965Sjdp	    cur_sfile = n;
62333965Sjdp	    n->name = sym->_n._n_nptr[1];
62433965Sjdp	    n->next = 0;
62533965Sjdp
62633965Sjdp	    if (infile)
62733965Sjdp	      {
62833965Sjdp		pop_scope ();
62933965Sjdp	      }
63033965Sjdp	    infile = 1;
63133965Sjdp	    push_scope (1);
63233965Sjdp	    file_scope = n->scope = top_scope;
63333965Sjdp
63433965Sjdp	    if (head->source_tail)
63533965Sjdp	      head->source_tail->next = n;
63633965Sjdp	    else
63733965Sjdp	      head->source_head = n;
63833965Sjdp	    head->source_tail = n;
63933965Sjdp	    head->nsources++;
64033965Sjdp	    i += sym->n_numaux + 1;
64133965Sjdp	  }
64233965Sjdp	  break;
64333965Sjdp	case C_FCN:
64433965Sjdp	  {
64533965Sjdp	    char *name = sym->_n._n_nptr[1];
64633965Sjdp	    if (name[1] == 'b')
64733965Sjdp	      {
64833965Sjdp		/* Function start */
64933965Sjdp		push_scope (0);
65033965Sjdp		last_function_type->u.function.code = top_scope;
65133965Sjdp		top_scope->sec = ofile->sections + sym->n_scnum;
65233965Sjdp		top_scope->offset = sym->n_value;
65333965Sjdp	      }
65433965Sjdp	    else
65533965Sjdp	      {
65633965Sjdp		top_scope->size = sym->n_value - top_scope->offset + 1;
65733965Sjdp		pop_scope ();
65833965Sjdp
65933965Sjdp	      }
66033965Sjdp	    i += sym->n_numaux + 1;
66133965Sjdp	  }
66233965Sjdp	  break;
66333965Sjdp
66433965Sjdp	case C_BLOCK:
66533965Sjdp	  {
66633965Sjdp	    char *name = sym->_n._n_nptr[1];
66733965Sjdp	    if (name[1] == 'b')
66833965Sjdp	      {
66933965Sjdp		/* Block start */
67033965Sjdp		push_scope (1);
67133965Sjdp		top_scope->sec = ofile->sections + sym->n_scnum;
67233965Sjdp		top_scope->offset = sym->n_value;
67333965Sjdp
67433965Sjdp	      }
67533965Sjdp	    else
67633965Sjdp	      {
67733965Sjdp		top_scope->size = sym->n_value - top_scope->offset + 1;
67833965Sjdp		pop_scope ();
67933965Sjdp	      }
68033965Sjdp	    i += sym->n_numaux + 1;
68133965Sjdp	  }
68233965Sjdp	  break;
68333965Sjdp	case C_REGPARM:
68433965Sjdp	case C_ARG:
68533965Sjdp	  i = do_define (i, last_function_symbol->type->u.function.parameters);
68633965Sjdp	  break;
68733965Sjdp	case C_MOS:
68833965Sjdp	case C_MOU:
68933965Sjdp	case C_FIELD:
69033965Sjdp	  i = do_define (i, last_struct->u.astructdef.elements);
69133965Sjdp	  break;
69233965Sjdp	case C_MOE:
69333965Sjdp	  i = do_define (i, last_enum->u.aenumdef.elements);
69433965Sjdp	  break;
69533965Sjdp	case C_STRTAG:
69633965Sjdp	case C_ENTAG:
69733965Sjdp	case C_UNTAG:
69833965Sjdp	  /* Various definition */
69933965Sjdp	  i = do_define (i, top_scope);
70033965Sjdp	  break;
70133965Sjdp	case C_EXT:
70233965Sjdp	case C_LABEL:
70333965Sjdp	  i = do_define (i, file_scope);
70433965Sjdp	  break;
70533965Sjdp	case C_STAT:
70633965Sjdp	case C_TPDEF:
70733965Sjdp	case C_AUTO:
70833965Sjdp	case C_REG:
70933965Sjdp	  i = do_define (i, top_scope);
71033965Sjdp	  break;
71133965Sjdp	default:
71233965Sjdp	  abort ();
71333965Sjdp	case C_EOS:
71433965Sjdp	  i += sym->n_numaux + 1;
71533965Sjdp	  break;
71633965Sjdp	}
71733965Sjdp    }
71833965Sjdp  do_sections_p2 (head);
71933965Sjdp  return head;
72033965Sjdp}
72133965Sjdp
72233965Sjdpstruct coff_ofile *
723130561Sobriencoff_grok (bfd *inabfd)
72433965Sjdp{
72533965Sjdp  long storage;
72633965Sjdp  struct coff_ofile *p;
72733965Sjdp  abfd = inabfd;
72833965Sjdp  storage = bfd_get_symtab_upper_bound (abfd);
72933965Sjdp
73033965Sjdp  if (storage < 0)
73133965Sjdp    bfd_fatal (abfd->filename);
73233965Sjdp
73333965Sjdp  syms = (asymbol **) xmalloc (storage);
73433965Sjdp  symcount = bfd_canonicalize_symtab (abfd, syms);
73533965Sjdp  if (symcount < 0)
73633965Sjdp    bfd_fatal (abfd->filename);
73733965Sjdp  rawsyms = obj_raw_syments (abfd);
73833965Sjdp  rawcount = obj_raw_syment_count (abfd);;
73933965Sjdp  tindex = (struct coff_symbol **) (xcalloc (sizeof (struct coff_symbol *), rawcount));
74033965Sjdp
74133965Sjdp  p = doit ();
74233965Sjdp  return p;
74333965Sjdp}
744