133965Sjdp/* ECOFF debugging support.
2218822Sdim   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3218822Sdim   2003, 2004, 2005, 2006
478828Sobrien   Free Software Foundation, Inc.
533965Sjdp   Contributed by Cygnus Support.
633965Sjdp   This file was put together by Ian Lance Taylor <ian@cygnus.com>.  A
733965Sjdp   good deal of it comes directly from mips-tfile.c, by Michael
833965Sjdp   Meissner <meissner@osf.org>.
933965Sjdp
1033965Sjdp   This file is part of GAS.
1133965Sjdp
1233965Sjdp   GAS is free software; you can redistribute it and/or modify
1333965Sjdp   it under the terms of the GNU General Public License as published by
1433965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1533965Sjdp   any later version.
1633965Sjdp
1733965Sjdp   GAS is distributed in the hope that it will be useful,
1833965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1933965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2033965Sjdp   GNU General Public License for more details.
2133965Sjdp
2233965Sjdp   You should have received a copy of the GNU General Public License
2333965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
24218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
25218822Sdim   02110-1301, USA.  */
2633965Sjdp
2733965Sjdp#include "as.h"
2833965Sjdp
2933965Sjdp/* This file is compiled conditionally for those targets which use
3033965Sjdp   ECOFF debugging information (e.g., MIPS ECOFF, MIPS ELF, Alpha
3133965Sjdp   ECOFF).  */
3233965Sjdp
3360484Sobrien#include "ecoff.h"
3460484Sobrien
3533965Sjdp#ifdef ECOFF_DEBUGGING
3633965Sjdp
3733965Sjdp#include "coff/internal.h"
3833965Sjdp#include "coff/symconst.h"
3933965Sjdp#include "aout/stab_gnu.h"
4033965Sjdp
4189857Sobrien#include "safe-ctype.h"
4233965Sjdp
4333965Sjdp/* Why isn't this in coff/sym.h?  */
4433965Sjdp#define ST_RFDESCAPE 0xfff
4533965Sjdp
4633965Sjdp/* This file constructs the information used by the ECOFF debugging
4733965Sjdp   format.  It just builds a large block of data.
4833965Sjdp
4933965Sjdp   We support both ECOFF style debugging and stabs debugging (the
5033965Sjdp   stabs symbols are encapsulated in ECOFF symbols).  This should let
5133965Sjdp   us handle anything the compiler might throw at us.  */
5233965Sjdp
5333965Sjdp/* Here is a brief description of the MIPS ECOFF symbol table, by
5433965Sjdp   Michael Meissner.  The MIPS symbol table has the following pieces:
5533965Sjdp
5633965Sjdp	Symbolic Header
5733965Sjdp	    |
5833965Sjdp	    +--	Auxiliary Symbols
5933965Sjdp	    |
6033965Sjdp	    +--	Dense number table
6133965Sjdp	    |
6233965Sjdp	    +--	Optimizer Symbols
6333965Sjdp	    |
6433965Sjdp	    +--	External Strings
6533965Sjdp	    |
6633965Sjdp	    +--	External Symbols
6733965Sjdp	    |
6833965Sjdp	    +--	Relative file descriptors
6933965Sjdp	    |
7033965Sjdp	    +--	File table
7133965Sjdp		    |
7233965Sjdp		    +--	Procedure table
7333965Sjdp		    |
7433965Sjdp		    +--	Line number table
7533965Sjdp		    |
7633965Sjdp		    +--	Local Strings
7733965Sjdp		    |
7833965Sjdp		    +--	Local Symbols
7933965Sjdp
8033965Sjdp   The symbolic header points to each of the other tables, and also
8133965Sjdp   contains the number of entries.  It also contains a magic number
8233965Sjdp   and MIPS compiler version number, such as 2.0.
8333965Sjdp
8433965Sjdp   The auxiliary table is a series of 32 bit integers, that are
8533965Sjdp   referenced as needed from the local symbol table.  Unlike standard
8633965Sjdp   COFF, the aux.  information does not follow the symbol that uses
8733965Sjdp   it, but rather is a separate table.  In theory, this would allow
8833965Sjdp   the MIPS compilers to collapse duplicate aux. entries, but I've not
8933965Sjdp   noticed this happening with the 1.31 compiler suite.  The different
9033965Sjdp   types of aux. entries are:
9133965Sjdp
9233965Sjdp    1)	dnLow: Low bound on array dimension.
9333965Sjdp
9433965Sjdp    2)	dnHigh: High bound on array dimension.
9533965Sjdp
9633965Sjdp    3)	isym: Index to the local symbol which is the start of the
9733965Sjdp	function for the end of function first aux. entry.
9833965Sjdp
9933965Sjdp    4)	width: Width of structures and bitfields.
10033965Sjdp
10133965Sjdp    5)	count: Count of ranges for variant part.
10233965Sjdp
10333965Sjdp    6)	rndx: A relative index into the symbol table.  The relative
10433965Sjdp	index field has two parts: rfd which is a pointer into the
10533965Sjdp	relative file index table or ST_RFDESCAPE which says the next
10633965Sjdp	aux. entry is the file number, and index: which is the pointer
10733965Sjdp	into the local symbol within a given file table.  This is for
10833965Sjdp	things like references to types defined in another file.
10933965Sjdp
11033965Sjdp    7)	Type information: This is like the COFF type bits, except it
11133965Sjdp	is 32 bits instead of 16; they still have room to add new
11233965Sjdp	basic types; and they can handle more than 6 levels of array,
11333965Sjdp	pointer, function, etc.  Each type information field contains
11433965Sjdp	the following structure members:
11533965Sjdp
11633965Sjdp	    a)	fBitfield: a bit that says this is a bitfield, and the
11733965Sjdp		size in bits follows as the next aux. entry.
11833965Sjdp
11933965Sjdp	    b)	continued: a bit that says the next aux. entry is a
12033965Sjdp		continuation of the current type information (in case
12133965Sjdp		there are more than 6 levels of array/ptr/function).
12233965Sjdp
12333965Sjdp	    c)	bt: an integer containing the base type before adding
12433965Sjdp		array, pointer, function, etc. qualifiers.  The
12533965Sjdp		current base types that I have documentation for are:
12633965Sjdp
12733965Sjdp			btNil		-- undefined
12833965Sjdp			btAdr		-- address - integer same size as ptr
12933965Sjdp			btChar		-- character
13033965Sjdp			btUChar		-- unsigned character
13133965Sjdp			btShort		-- short
13233965Sjdp			btUShort	-- unsigned short
13333965Sjdp			btInt		-- int
13433965Sjdp			btUInt		-- unsigned int
13533965Sjdp			btLong		-- long
13633965Sjdp			btULong		-- unsigned long
13733965Sjdp			btFloat		-- float (real)
13833965Sjdp			btDouble	-- Double (real)
13933965Sjdp			btStruct	-- Structure (Record)
14033965Sjdp			btUnion		-- Union (variant)
14133965Sjdp			btEnum		-- Enumerated
14233965Sjdp			btTypedef	-- defined via a typedef isymRef
14333965Sjdp			btRange		-- subrange of int
14433965Sjdp			btSet		-- pascal sets
14533965Sjdp			btComplex	-- fortran complex
14633965Sjdp			btDComplex	-- fortran double complex
14733965Sjdp			btIndirect	-- forward or unnamed typedef
14833965Sjdp			btFixedDec	-- Fixed Decimal
14933965Sjdp			btFloatDec	-- Float Decimal
15033965Sjdp			btString	-- Varying Length Character String
15133965Sjdp			btBit		-- Aligned Bit String
15233965Sjdp			btPicture	-- Picture
15333965Sjdp			btVoid		-- Void (MIPS cc revision >= 2.00)
15433965Sjdp
15533965Sjdp	    d)	tq0 - tq5: type qualifier fields as needed.  The
15633965Sjdp		current type qualifier fields I have documentation for
15733965Sjdp		are:
15833965Sjdp
15933965Sjdp			tqNil		-- no more qualifiers
16033965Sjdp			tqPtr		-- pointer
16133965Sjdp			tqProc		-- procedure
16233965Sjdp			tqArray		-- array
16333965Sjdp			tqFar		-- 8086 far pointers
16433965Sjdp			tqVol		-- volatile
16533965Sjdp
16633965Sjdp   The dense number table is used in the front ends, and disappears by
16733965Sjdp   the time the .o is created.
16833965Sjdp
16933965Sjdp   With the 1.31 compiler suite, the optimization symbols don't seem
17033965Sjdp   to be used as far as I can tell.
17133965Sjdp
17233965Sjdp   The linker is the first entity that creates the relative file
17333965Sjdp   descriptor table, and I believe it is used so that the individual
17433965Sjdp   file table pointers don't have to be rewritten when the objects are
17533965Sjdp   merged together into the program file.
17633965Sjdp
17733965Sjdp   Unlike COFF, the basic symbol & string tables are split into
17833965Sjdp   external and local symbols/strings.  The relocation information
17933965Sjdp   only goes off of the external symbol table, and the debug
18033965Sjdp   information only goes off of the internal symbol table.  The
18133965Sjdp   external symbols can have links to an appropriate file index and
18233965Sjdp   symbol within the file to give it the appropriate type information.
18333965Sjdp   Because of this, the external symbols are actually larger than the
18433965Sjdp   internal symbols (to contain the link information), and contain the
18533965Sjdp   local symbol structure as a member, though this member is not the
18633965Sjdp   first member of the external symbol structure (!).  I suspect this
18733965Sjdp   split is to make strip easier to deal with.
18833965Sjdp
18933965Sjdp   Each file table has offsets for where the line numbers, local
19033965Sjdp   strings, local symbols, and procedure table starts from within the
19133965Sjdp   global tables, and the indexs are reset to 0 for each of those
19233965Sjdp   tables for the file.
19333965Sjdp
19433965Sjdp   The procedure table contains the binary equivalents of the .ent
19533965Sjdp   (start of the function address), .frame (what register is the
19633965Sjdp   virtual frame pointer, constant offset from the register to obtain
19733965Sjdp   the VFP, and what register holds the return address), .mask/.fmask
19833965Sjdp   (bitmask of saved registers, and where the first register is stored
19933965Sjdp   relative to the VFP) assembler directives.  It also contains the
20033965Sjdp   low and high bounds of the line numbers if debugging is turned on.
20133965Sjdp
20233965Sjdp   The line number table is a compressed form of the normal COFF line
20333965Sjdp   table.  Each line number entry is either 1 or 3 bytes long, and
20433965Sjdp   contains a signed delta from the previous line, and an unsigned
20533965Sjdp   count of the number of instructions this statement takes.
20633965Sjdp
20733965Sjdp   The local symbol table contains the following fields:
20833965Sjdp
20933965Sjdp    1)	iss: index to the local string table giving the name of the
21033965Sjdp	symbol.
21133965Sjdp
21233965Sjdp    2)	value: value of the symbol (address, register number, etc.).
21333965Sjdp
21433965Sjdp    3)	st: symbol type.  The current symbol types are:
21533965Sjdp
21633965Sjdp	    stNil	  -- Nuthin' special
21733965Sjdp	    stGlobal	  -- external symbol
21833965Sjdp	    stStatic	  -- static
21933965Sjdp	    stParam	  -- procedure argument
22033965Sjdp	    stLocal	  -- local variable
22133965Sjdp	    stLabel	  -- label
22233965Sjdp	    stProc	  -- External Procedure
22333965Sjdp	    stBlock	  -- beginning of block
22433965Sjdp	    stEnd	  -- end (of anything)
22533965Sjdp	    stMember	  -- member (of anything)
22633965Sjdp	    stTypedef	  -- type definition
22733965Sjdp	    stFile	  -- file name
22833965Sjdp	    stRegReloc	  -- register relocation
22933965Sjdp	    stForward	  -- forwarding address
23033965Sjdp	    stStaticProc  -- Static procedure
23133965Sjdp	    stConstant	  -- const
23233965Sjdp
23333965Sjdp    4)	sc: storage class.  The current storage classes are:
23433965Sjdp
23533965Sjdp	    scText	  -- text symbol
23633965Sjdp	    scData	  -- initialized data symbol
23733965Sjdp	    scBss	  -- un-initialized data symbol
23833965Sjdp	    scRegister	  -- value of symbol is register number
23933965Sjdp	    scAbs	  -- value of symbol is absolute
24033965Sjdp	    scUndefined   -- who knows?
24133965Sjdp	    scCdbLocal	  -- variable's value is IN se->va.??
24233965Sjdp	    scBits	  -- this is a bit field
24333965Sjdp	    scCdbSystem	  -- value is IN debugger's address space
24433965Sjdp	    scRegImage	  -- register value saved on stack
24533965Sjdp	    scInfo	  -- symbol contains debugger information
24633965Sjdp	    scUserStruct  -- addr in struct user for current process
24733965Sjdp	    scSData	  -- load time only small data
24833965Sjdp	    scSBss	  -- load time only small common
24933965Sjdp	    scRData	  -- load time only read only data
25033965Sjdp	    scVar	  -- Var parameter (fortranpascal)
25133965Sjdp	    scCommon	  -- common variable
25233965Sjdp	    scSCommon	  -- small common
25333965Sjdp	    scVarRegister -- Var parameter in a register
25433965Sjdp	    scVariant	  -- Variant record
25533965Sjdp	    scSUndefined  -- small undefined(external) data
25633965Sjdp	    scInit	  -- .init section symbol
25733965Sjdp
25833965Sjdp    5)	index: pointer to a local symbol or aux. entry.
25933965Sjdp
26033965Sjdp   For the following program:
26133965Sjdp
26233965Sjdp	#include <stdio.h>
26333965Sjdp
26433965Sjdp	main(){
26533965Sjdp		printf("Hello World!\n");
26633965Sjdp		return 0;
26733965Sjdp	}
26833965Sjdp
26933965Sjdp   Mips-tdump produces the following information:
27033965Sjdp
27133965Sjdp   Global file header:
27233965Sjdp       magic number             0x162
27333965Sjdp       # sections               2
27433965Sjdp       timestamp                645311799, Wed Jun 13 17:16:39 1990
27533965Sjdp       symbolic header offset   284
27633965Sjdp       symbolic header size     96
27733965Sjdp       optional header          56
27833965Sjdp       flags                    0x0
27933965Sjdp
28033965Sjdp   Symbolic header, magic number = 0x7009, vstamp = 1.31:
28133965Sjdp
28233965Sjdp       Info                      Offset      Number       Bytes
28333965Sjdp       ====                      ======      ======      =====
28433965Sjdp
28533965Sjdp       Line numbers                 380           4           4 [13]
28633965Sjdp       Dense numbers                  0           0           0
28733965Sjdp       Procedures Tables            384           1          52
28833965Sjdp       Local Symbols                436          16         192
28933965Sjdp       Optimization Symbols           0           0           0
29033965Sjdp       Auxiliary Symbols            628          39         156
29133965Sjdp       Local Strings                784          80          80
29233965Sjdp       External Strings             864         144         144
29333965Sjdp       File Tables                 1008           2         144
29433965Sjdp       Relative Files                 0           0           0
29533965Sjdp       External Symbols            1152          20         320
29633965Sjdp
29733965Sjdp   File #0, "hello2.c"
29833965Sjdp
29933965Sjdp       Name index  = 1          Readin      = No
30033965Sjdp       Merge       = No         Endian      = LITTLE
30133965Sjdp       Debug level = G2         Language    = C
30233965Sjdp       Adr         = 0x00000000
30333965Sjdp
30433965Sjdp       Info                       Start      Number        Size      Offset
30533965Sjdp       ====                       =====      ======        ====      ======
30633965Sjdp       Local strings                  0          15          15         784
30733965Sjdp       Local symbols                  0           6          72         436
30833965Sjdp       Line numbers                   0          13          13         380
30933965Sjdp       Optimization symbols           0           0           0           0
31033965Sjdp       Procedures                     0           1          52         384
31133965Sjdp       Auxiliary symbols              0          14          56         628
31233965Sjdp       Relative Files                 0           0           0           0
31333965Sjdp
31433965Sjdp    There are 6 local symbols, starting at 436
31533965Sjdp
31633965Sjdp	Symbol# 0: "hello2.c"
31733965Sjdp	    End+1 symbol  = 6
31833965Sjdp	    String index  = 1
31933965Sjdp	    Storage class = Text        Index  = 6
32033965Sjdp	    Symbol type   = File        Value  = 0
32133965Sjdp
32233965Sjdp	Symbol# 1: "main"
32333965Sjdp	    End+1 symbol  = 5
32433965Sjdp	    Type          = int
32533965Sjdp	    String index  = 10
32633965Sjdp	    Storage class = Text        Index  = 12
32733965Sjdp	    Symbol type   = Proc        Value  = 0
32833965Sjdp
32933965Sjdp	Symbol# 2: ""
33033965Sjdp	    End+1 symbol  = 4
33133965Sjdp	    String index  = 0
33233965Sjdp	    Storage class = Text        Index  = 4
33333965Sjdp	    Symbol type   = Block       Value  = 8
33433965Sjdp
33533965Sjdp	Symbol# 3: ""
33633965Sjdp	    First symbol  = 2
33733965Sjdp	    String index  = 0
33833965Sjdp	    Storage class = Text        Index  = 2
33933965Sjdp	    Symbol type   = End         Value  = 28
34033965Sjdp
34133965Sjdp	Symbol# 4: "main"
34233965Sjdp	    First symbol  = 1
34333965Sjdp	    String index  = 10
34433965Sjdp	    Storage class = Text        Index  = 1
34533965Sjdp	    Symbol type   = End         Value  = 52
34633965Sjdp
34733965Sjdp	Symbol# 5: "hello2.c"
34833965Sjdp	    First symbol  = 0
34933965Sjdp	    String index  = 1
35033965Sjdp	    Storage class = Text        Index  = 0
35133965Sjdp	    Symbol type   = End         Value  = 0
35233965Sjdp
35333965Sjdp    There are 14 auxiliary table entries, starting at 628.
35433965Sjdp
35533965Sjdp	* #0               0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
35633965Sjdp	* #1              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
35733965Sjdp	* #2               8, [   8/      0], [ 2 0:0 0:0:0:0:0:0]
35833965Sjdp	* #3              16, [  16/      0], [ 4 0:0 0:0:0:0:0:0]
35933965Sjdp	* #4              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
36033965Sjdp	* #5              32, [  32/      0], [ 8 0:0 0:0:0:0:0:0]
36133965Sjdp	* #6              40, [  40/      0], [10 0:0 0:0:0:0:0:0]
36233965Sjdp	* #7              44, [  44/      0], [11 0:0 0:0:0:0:0:0]
36333965Sjdp	* #8              12, [  12/      0], [ 3 0:0 0:0:0:0:0:0]
36433965Sjdp	* #9              20, [  20/      0], [ 5 0:0 0:0:0:0:0:0]
36533965Sjdp	* #10             28, [  28/      0], [ 7 0:0 0:0:0:0:0:0]
36633965Sjdp	* #11             36, [  36/      0], [ 9 0:0 0:0:0:0:0:0]
36733965Sjdp	  #12              5, [   5/      0], [ 1 1:0 0:0:0:0:0:0]
36833965Sjdp	  #13             24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
36933965Sjdp
37033965Sjdp    There are 1 procedure descriptor entries, starting at 0.
37133965Sjdp
37233965Sjdp	Procedure descriptor 0:
37333965Sjdp	    Name index   = 10          Name          = "main"
37433965Sjdp	    .mask 0x80000000,-4        .fmask 0x00000000,0
37533965Sjdp	    .frame $29,24,$31
37633965Sjdp	    Opt. start   = -1          Symbols start = 1
37733965Sjdp	    First line # = 3           Last line #   = 6
37833965Sjdp	    Line Offset  = 0           Address       = 0x00000000
37933965Sjdp
38033965Sjdp	There are 4 bytes holding line numbers, starting at 380.
38133965Sjdp	    Line           3,   delta     0,   count  2
38233965Sjdp	    Line           4,   delta     1,   count  3
38333965Sjdp	    Line           5,   delta     1,   count  2
38433965Sjdp	    Line           6,   delta     1,   count  6
38533965Sjdp
38633965Sjdp   File #1, "/usr/include/stdio.h"
38733965Sjdp
38833965Sjdp    Name index  = 1          Readin      = No
38933965Sjdp    Merge       = Yes        Endian      = LITTLE
39033965Sjdp    Debug level = G2         Language    = C
39133965Sjdp    Adr         = 0x00000000
39233965Sjdp
39333965Sjdp    Info                       Start      Number        Size      Offset
39433965Sjdp    ====                       =====      ======        ====      ======
39533965Sjdp    Local strings                 15          65          65         799
39633965Sjdp    Local symbols                  6          10         120         508
39733965Sjdp    Line numbers                   0           0           0         380
39833965Sjdp    Optimization symbols           0           0           0           0
39933965Sjdp    Procedures                     1           0           0         436
40033965Sjdp    Auxiliary symbols             14          25         100         684
40133965Sjdp    Relative Files                 0           0           0           0
40233965Sjdp
40333965Sjdp    There are 10 local symbols, starting at 442
40433965Sjdp
40533965Sjdp	Symbol# 0: "/usr/include/stdio.h"
40633965Sjdp	    End+1 symbol  = 10
40733965Sjdp	    String index  = 1
40833965Sjdp	    Storage class = Text        Index  = 10
40933965Sjdp	    Symbol type   = File        Value  = 0
41033965Sjdp
41133965Sjdp	Symbol# 1: "_iobuf"
41233965Sjdp	    End+1 symbol  = 9
41333965Sjdp	    String index  = 22
41433965Sjdp	    Storage class = Info        Index  = 9
41533965Sjdp	    Symbol type   = Block       Value  = 20
41633965Sjdp
41733965Sjdp	Symbol# 2: "_cnt"
41833965Sjdp	    Type          = int
41933965Sjdp	    String index  = 29
42033965Sjdp	    Storage class = Info        Index  = 4
42133965Sjdp	    Symbol type   = Member      Value  = 0
42233965Sjdp
42333965Sjdp	Symbol# 3: "_ptr"
42433965Sjdp	    Type          = ptr to char
42533965Sjdp	    String index  = 34
42633965Sjdp	    Storage class = Info        Index  = 15
42733965Sjdp	    Symbol type   = Member      Value  = 32
42833965Sjdp
42933965Sjdp	Symbol# 4: "_base"
43033965Sjdp	    Type          = ptr to char
43133965Sjdp	    String index  = 39
43233965Sjdp	    Storage class = Info        Index  = 16
43333965Sjdp	    Symbol type   = Member      Value  = 64
43433965Sjdp
43533965Sjdp	Symbol# 5: "_bufsiz"
43633965Sjdp	    Type          = int
43733965Sjdp	    String index  = 45
43833965Sjdp	    Storage class = Info        Index  = 4
43933965Sjdp	    Symbol type   = Member      Value  = 96
44033965Sjdp
44133965Sjdp	Symbol# 6: "_flag"
44233965Sjdp	    Type          = short
44333965Sjdp	    String index  = 53
44433965Sjdp	    Storage class = Info        Index  = 3
44533965Sjdp	    Symbol type   = Member      Value  = 128
44633965Sjdp
44733965Sjdp	Symbol# 7: "_file"
44833965Sjdp	    Type          = char
44933965Sjdp	    String index  = 59
45033965Sjdp	    Storage class = Info        Index  = 2
45133965Sjdp	    Symbol type   = Member      Value  = 144
45233965Sjdp
45333965Sjdp	Symbol# 8: ""
45433965Sjdp	    First symbol  = 1
45533965Sjdp	    String index  = 0
45633965Sjdp	    Storage class = Info        Index  = 1
45733965Sjdp	    Symbol type   = End         Value  = 0
45833965Sjdp
45933965Sjdp	Symbol# 9: "/usr/include/stdio.h"
46033965Sjdp	    First symbol  = 0
46133965Sjdp	    String index  = 1
46233965Sjdp	    Storage class = Text        Index  = 0
46333965Sjdp	    Symbol type   = End         Value  = 0
46433965Sjdp
46533965Sjdp    There are 25 auxiliary table entries, starting at 642.
46633965Sjdp
46733965Sjdp	* #14             -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
46833965Sjdp	  #15          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
46933965Sjdp	  #16          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
47033965Sjdp	* #17         196656, [  48/     48], [12 0:0 3:0:0:0:0:0]
47133965Sjdp	* #18           8191, [4095/      1], [63 1:1 0:0:0:0:f:1]
47233965Sjdp	* #19              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
47333965Sjdp	* #20          20479, [4095/      4], [63 1:1 0:0:0:0:f:4]
47433965Sjdp	* #21              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
47533965Sjdp	* #22              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
47633965Sjdp	* #23              2, [   2/      0], [ 0 0:1 0:0:0:0:0:0]
47733965Sjdp	* #24            160, [ 160/      0], [40 0:0 0:0:0:0:0:0]
47833965Sjdp	* #25              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
47933965Sjdp	* #26              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48033965Sjdp	* #27              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48133965Sjdp	* #28              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48233965Sjdp	* #29              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48333965Sjdp	* #30              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48433965Sjdp	* #31              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48533965Sjdp	* #32              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48633965Sjdp	* #33              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48733965Sjdp	* #34              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48833965Sjdp	* #35              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
48933965Sjdp	* #36              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
49033965Sjdp	* #37              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
49133965Sjdp	* #38              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
49233965Sjdp
49333965Sjdp    There are 0 procedure descriptor entries, starting at 1.
49433965Sjdp
49533965Sjdp   There are 20 external symbols, starting at 1152
49633965Sjdp
49733965Sjdp	Symbol# 0: "_iob"
49833965Sjdp	    Type          = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
49933965Sjdp	    String index  = 0           Ifd    = 1
50033965Sjdp	    Storage class = Nil         Index  = 17
50133965Sjdp	    Symbol type   = Global      Value  = 60
50233965Sjdp
50333965Sjdp	Symbol# 1: "fopen"
50433965Sjdp	    String index  = 5           Ifd    = 1
50533965Sjdp	    Storage class = Nil         Index  = 1048575
50633965Sjdp	    Symbol type   = Proc        Value  = 0
50733965Sjdp
50833965Sjdp	Symbol# 2: "fdopen"
50933965Sjdp	    String index  = 11          Ifd    = 1
51033965Sjdp	    Storage class = Nil         Index  = 1048575
51133965Sjdp	    Symbol type   = Proc        Value  = 0
51233965Sjdp
51333965Sjdp	Symbol# 3: "freopen"
51433965Sjdp	    String index  = 18          Ifd    = 1
51533965Sjdp	    Storage class = Nil         Index  = 1048575
51633965Sjdp	    Symbol type   = Proc        Value  = 0
51733965Sjdp
51833965Sjdp	Symbol# 4: "popen"
51933965Sjdp	    String index  = 26          Ifd    = 1
52033965Sjdp	    Storage class = Nil         Index  = 1048575
52133965Sjdp	    Symbol type   = Proc        Value  = 0
52233965Sjdp
52333965Sjdp	Symbol# 5: "tmpfile"
52433965Sjdp	    String index  = 32          Ifd    = 1
52533965Sjdp	    Storage class = Nil         Index  = 1048575
52633965Sjdp	    Symbol type   = Proc        Value  = 0
52733965Sjdp
52833965Sjdp	Symbol# 6: "ftell"
52933965Sjdp	    String index  = 40          Ifd    = 1
53033965Sjdp	    Storage class = Nil         Index  = 1048575
53133965Sjdp	    Symbol type   = Proc        Value  = 0
53233965Sjdp
53333965Sjdp	Symbol# 7: "rewind"
53433965Sjdp	    String index  = 46          Ifd    = 1
53533965Sjdp	    Storage class = Nil         Index  = 1048575
53633965Sjdp	    Symbol type   = Proc        Value  = 0
53733965Sjdp
53833965Sjdp	Symbol# 8: "setbuf"
53933965Sjdp	    String index  = 53          Ifd    = 1
54033965Sjdp	    Storage class = Nil         Index  = 1048575
54133965Sjdp	    Symbol type   = Proc        Value  = 0
54233965Sjdp
54333965Sjdp	Symbol# 9: "setbuffer"
54433965Sjdp	    String index  = 60          Ifd    = 1
54533965Sjdp	    Storage class = Nil         Index  = 1048575
54633965Sjdp	    Symbol type   = Proc        Value  = 0
54733965Sjdp
54833965Sjdp	Symbol# 10: "setlinebuf"
54933965Sjdp	    String index  = 70          Ifd    = 1
55033965Sjdp	    Storage class = Nil         Index  = 1048575
55133965Sjdp	    Symbol type   = Proc        Value  = 0
55233965Sjdp
55333965Sjdp	Symbol# 11: "fgets"
55433965Sjdp	    String index  = 81          Ifd    = 1
55533965Sjdp	    Storage class = Nil         Index  = 1048575
55633965Sjdp	    Symbol type   = Proc        Value  = 0
55733965Sjdp
55833965Sjdp	Symbol# 12: "gets"
55933965Sjdp	    String index  = 87          Ifd    = 1
56033965Sjdp	    Storage class = Nil         Index  = 1048575
56133965Sjdp	    Symbol type   = Proc        Value  = 0
56233965Sjdp
56333965Sjdp	Symbol# 13: "ctermid"
56433965Sjdp	    String index  = 92          Ifd    = 1
56533965Sjdp	    Storage class = Nil         Index  = 1048575
56633965Sjdp	    Symbol type   = Proc        Value  = 0
56733965Sjdp
56833965Sjdp	Symbol# 14: "cuserid"
56933965Sjdp	    String index  = 100         Ifd    = 1
57033965Sjdp	    Storage class = Nil         Index  = 1048575
57133965Sjdp	    Symbol type   = Proc        Value  = 0
57233965Sjdp
57333965Sjdp	Symbol# 15: "tempnam"
57433965Sjdp	    String index  = 108         Ifd    = 1
57533965Sjdp	    Storage class = Nil         Index  = 1048575
57633965Sjdp	    Symbol type   = Proc        Value  = 0
57733965Sjdp
57833965Sjdp	Symbol# 16: "tmpnam"
57933965Sjdp	    String index  = 116         Ifd    = 1
58033965Sjdp	    Storage class = Nil         Index  = 1048575
58133965Sjdp	    Symbol type   = Proc        Value  = 0
58233965Sjdp
58333965Sjdp	Symbol# 17: "sprintf"
58433965Sjdp	    String index  = 123         Ifd    = 1
58533965Sjdp	    Storage class = Nil         Index  = 1048575
58633965Sjdp	    Symbol type   = Proc        Value  = 0
58733965Sjdp
58833965Sjdp	Symbol# 18: "main"
58933965Sjdp	    Type          = int
59033965Sjdp	    String index  = 131         Ifd    = 0
59133965Sjdp	    Storage class = Text        Index  = 1
59233965Sjdp	    Symbol type   = Proc        Value  = 0
59333965Sjdp
59433965Sjdp	Symbol# 19: "printf"
59533965Sjdp	    String index  = 136         Ifd    = 0
59633965Sjdp	    Storage class = Undefined   Index  = 1048575
59733965Sjdp	    Symbol type   = Proc        Value  = 0
59833965Sjdp
59933965Sjdp   The following auxiliary table entries were unused:
60033965Sjdp
60133965Sjdp    #0               0  0x00000000  void
60233965Sjdp    #2               8  0x00000008  char
60333965Sjdp    #3              16  0x00000010  short
60433965Sjdp    #4              24  0x00000018  int
60533965Sjdp    #5              32  0x00000020  long
60633965Sjdp    #6              40  0x00000028  float
60733965Sjdp    #7              44  0x0000002c  double
60833965Sjdp    #8              12  0x0000000c  unsigned char
60933965Sjdp    #9              20  0x00000014  unsigned short
61033965Sjdp    #10             28  0x0000001c  unsigned int
61133965Sjdp    #11             36  0x00000024  unsigned long
61233965Sjdp    #14              0  0x00000000  void
61333965Sjdp    #15             24  0x00000018  int
61433965Sjdp    #19             32  0x00000020  long
61533965Sjdp    #20             40  0x00000028  float
61633965Sjdp    #21             44  0x0000002c  double
61733965Sjdp    #22             12  0x0000000c  unsigned char
61833965Sjdp    #23             20  0x00000014  unsigned short
61933965Sjdp    #24             28  0x0000001c  unsigned int
62033965Sjdp    #25             36  0x00000024  unsigned long
62133965Sjdp    #26             48  0x00000030  struct no name { ifd = -1, index = 1048575 }
62233965Sjdp*/
62333965Sjdp
62433965Sjdp/* Redefinition of of storage classes as an enumeration for better
62533965Sjdp   debugging.  */
62633965Sjdp
62733965Sjdptypedef enum sc {
62833965Sjdp  sc_Nil	 = scNil,	  /* no storage class */
62933965Sjdp  sc_Text	 = scText,	  /* text symbol */
63033965Sjdp  sc_Data	 = scData,	  /* initialized data symbol */
63133965Sjdp  sc_Bss	 = scBss,	  /* un-initialized data symbol */
63233965Sjdp  sc_Register	 = scRegister,	  /* value of symbol is register number */
63333965Sjdp  sc_Abs	 = scAbs,	  /* value of symbol is absolute */
63433965Sjdp  sc_Undefined	 = scUndefined,	  /* who knows? */
63533965Sjdp  sc_CdbLocal	 = scCdbLocal,	  /* variable's value is IN se->va.?? */
63633965Sjdp  sc_Bits	 = scBits,	  /* this is a bit field */
63733965Sjdp  sc_CdbSystem	 = scCdbSystem,	  /* value is IN CDB's address space */
63833965Sjdp  sc_RegImage	 = scRegImage,	  /* register value saved on stack */
63933965Sjdp  sc_Info	 = scInfo,	  /* symbol contains debugger information */
64033965Sjdp  sc_UserStruct	 = scUserStruct,  /* addr in struct user for current process */
64133965Sjdp  sc_SData	 = scSData,	  /* load time only small data */
64233965Sjdp  sc_SBss	 = scSBss,	  /* load time only small common */
64333965Sjdp  sc_RData	 = scRData,	  /* load time only read only data */
64433965Sjdp  sc_Var	 = scVar,	  /* Var parameter (fortran,pascal) */
64533965Sjdp  sc_Common	 = scCommon,	  /* common variable */
64633965Sjdp  sc_SCommon	 = scSCommon,	  /* small common */
64733965Sjdp  sc_VarRegister = scVarRegister, /* Var parameter in a register */
64833965Sjdp  sc_Variant	 = scVariant,	  /* Variant record */
64933965Sjdp  sc_SUndefined	 = scSUndefined,  /* small undefined(external) data */
65033965Sjdp  sc_Init	 = scInit,	  /* .init section symbol */
65133965Sjdp  sc_Max	 = scMax	  /* Max storage class+1 */
65233965Sjdp} sc_t;
65333965Sjdp
65433965Sjdp/* Redefinition of symbol type.  */
65533965Sjdp
65633965Sjdptypedef enum st {
65733965Sjdp  st_Nil	= stNil,	/* Nuthin' special */
65833965Sjdp  st_Global	= stGlobal,	/* external symbol */
65933965Sjdp  st_Static	= stStatic,	/* static */
66033965Sjdp  st_Param	= stParam,	/* procedure argument */
66133965Sjdp  st_Local	= stLocal,	/* local variable */
66233965Sjdp  st_Label	= stLabel,	/* label */
66333965Sjdp  st_Proc	= stProc,	/*     "      "	 Procedure */
66433965Sjdp  st_Block	= stBlock,	/* beginning of block */
66533965Sjdp  st_End	= stEnd,	/* end (of anything) */
66633965Sjdp  st_Member	= stMember,	/* member (of anything	- struct/union/enum */
66733965Sjdp  st_Typedef	= stTypedef,	/* type definition */
66833965Sjdp  st_File	= stFile,	/* file name */
66933965Sjdp  st_RegReloc	= stRegReloc,	/* register relocation */
67033965Sjdp  st_Forward	= stForward,	/* forwarding address */
67133965Sjdp  st_StaticProc	= stStaticProc,	/* load time only static procs */
67233965Sjdp  st_Constant	= stConstant,	/* const */
67333965Sjdp  st_Str	= stStr,	/* string */
67433965Sjdp  st_Number	= stNumber,	/* pure number (ie. 4 NOR 2+2) */
67533965Sjdp  st_Expr	= stExpr,	/* 2+2 vs. 4 */
67633965Sjdp  st_Type	= stType,	/* post-coercion SER */
67733965Sjdp  st_Max	= stMax		/* max type+1 */
67833965Sjdp} st_t;
67933965Sjdp
68033965Sjdp/* Redefinition of type qualifiers.  */
68133965Sjdp
68233965Sjdptypedef enum tq {
68333965Sjdp  tq_Nil	= tqNil,	/* bt is what you see */
68433965Sjdp  tq_Ptr	= tqPtr,	/* pointer */
68533965Sjdp  tq_Proc	= tqProc,	/* procedure */
68633965Sjdp  tq_Array	= tqArray,	/* duh */
68733965Sjdp  tq_Far	= tqFar,	/* longer addressing - 8086/8 land */
68833965Sjdp  tq_Vol	= tqVol,	/* volatile */
68933965Sjdp  tq_Max	= tqMax		/* Max type qualifier+1 */
69033965Sjdp} tq_t;
69133965Sjdp
69233965Sjdp/* Redefinition of basic types.  */
69333965Sjdp
69433965Sjdptypedef enum bt {
69533965Sjdp  bt_Nil	= btNil,	/* undefined */
69633965Sjdp  bt_Adr	= btAdr,	/* address - integer same size as pointer */
69733965Sjdp  bt_Char	= btChar,	/* character */
69833965Sjdp  bt_UChar	= btUChar,	/* unsigned character */
69933965Sjdp  bt_Short	= btShort,	/* short */
70033965Sjdp  bt_UShort	= btUShort,	/* unsigned short */
70133965Sjdp  bt_Int	= btInt,	/* int */
70233965Sjdp  bt_UInt	= btUInt,	/* unsigned int */
70333965Sjdp  bt_Long	= btLong,	/* long */
70433965Sjdp  bt_ULong	= btULong,	/* unsigned long */
70533965Sjdp  bt_Float	= btFloat,	/* float (real) */
70633965Sjdp  bt_Double	= btDouble,	/* Double (real) */
70733965Sjdp  bt_Struct	= btStruct,	/* Structure (Record) */
70833965Sjdp  bt_Union	= btUnion,	/* Union (variant) */
70933965Sjdp  bt_Enum	= btEnum,	/* Enumerated */
71033965Sjdp  bt_Typedef	= btTypedef,	/* defined via a typedef, isymRef points */
71133965Sjdp  bt_Range	= btRange,	/* subrange of int */
71233965Sjdp  bt_Set	= btSet,	/* pascal sets */
71333965Sjdp  bt_Complex	= btComplex,	/* fortran complex */
71433965Sjdp  bt_DComplex	= btDComplex,	/* fortran double complex */
71533965Sjdp  bt_Indirect	= btIndirect,	/* forward or unnamed typedef */
71633965Sjdp  bt_FixedDec	= btFixedDec,	/* Fixed Decimal */
71733965Sjdp  bt_FloatDec	= btFloatDec,	/* Float Decimal */
71833965Sjdp  bt_String	= btString,	/* Varying Length Character String */
71933965Sjdp  bt_Bit	= btBit,	/* Aligned Bit String */
72033965Sjdp  bt_Picture	= btPicture,	/* Picture */
72133965Sjdp  bt_Void	= btVoid,	/* Void */
72233965Sjdp  bt_Max	= btMax		/* Max basic type+1 */
72333965Sjdp} bt_t;
72433965Sjdp
72533965Sjdp#define N_TQ itqMax
72633965Sjdp
72733965Sjdp/* States for whether to hash type or not.  */
72833965Sjdptypedef enum hash_state {
72977298Sobrien  hash_no	= 0,		/* Don't hash type */
73077298Sobrien  hash_yes	= 1,		/* OK to hash type, or use previous hash */
73177298Sobrien  hash_record	= 2		/* OK to record hash, but don't use prev.  */
73233965Sjdp} hash_state_t;
73333965Sjdp
73433965Sjdp/* Types of different sized allocation requests.  */
73533965Sjdpenum alloc_type {
73633965Sjdp  alloc_type_none,		/* dummy value */
73733965Sjdp  alloc_type_scope,		/* nested scopes linked list */
73833965Sjdp  alloc_type_vlinks,		/* glue linking pages in varray */
73933965Sjdp  alloc_type_shash,		/* string hash element */
74033965Sjdp  alloc_type_thash,		/* type hash element */
74133965Sjdp  alloc_type_tag,		/* struct/union/tag element */
74233965Sjdp  alloc_type_forward,		/* element to hold unknown tag */
74333965Sjdp  alloc_type_thead,		/* head of type hash list */
74433965Sjdp  alloc_type_varray,		/* general varray allocation */
74533965Sjdp  alloc_type_lineno,		/* line number list */
74633965Sjdp  alloc_type_last		/* last+1 element for array bounds */
74733965Sjdp};
74833965Sjdp
74933965Sjdp/* Types of auxiliary type information.  */
75033965Sjdpenum aux_type {
75133965Sjdp  aux_tir,			/* TIR type information */
75233965Sjdp  aux_rndx,			/* relative index into symbol table */
75333965Sjdp  aux_dnLow,			/* low dimension */
75433965Sjdp  aux_dnHigh,			/* high dimension */
75533965Sjdp  aux_isym,			/* symbol table index (end of proc) */
75633965Sjdp  aux_iss,			/* index into string space (not used) */
75733965Sjdp  aux_width,			/* width for non-default sized struc fields */
75833965Sjdp  aux_count			/* count of ranges for variant arm */
75933965Sjdp};
76033965Sjdp
76133965Sjdp/* Structures to provide n-number of virtual arrays, each of which can
76233965Sjdp   grow linearly, and which are written in the object file as
76333965Sjdp   sequential pages.  On systems with a BSD malloc, the
76433965Sjdp   MAX_CLUSTER_PAGES should be 1 less than a power of two, since
76533965Sjdp   malloc adds it's overhead, and rounds up to the next power of 2.
76633965Sjdp   Pages are linked together via a linked list.
76733965Sjdp
76833965Sjdp   If PAGE_SIZE is > 4096, the string length in the shash_t structure
76933965Sjdp   can't be represented (assuming there are strings > 4096 bytes).  */
77033965Sjdp
77138889Sjdp/* FIXME: Yes, there can be such strings while emitting C++ class debug
77277298Sobrien   info.  Templates are the offender here, the test case in question
77338889Sjdp   having a mangled class name of
77438889Sjdp
77538889Sjdp     t7rb_tree4Z4xkeyZt4pair2ZC4xkeyZt7xsocket1Z4UserZt9select1st2Zt4pair\
77638889Sjdp     2ZC4xkeyZt7xsocket1Z4UserZ4xkeyZt4less1Z4xkey
77738889Sjdp
77838889Sjdp   Repeat that a couple dozen times while listing the class members and
77938889Sjdp   you've got strings over 4k.  Hack around this for now by increasing
78038889Sjdp   the page size.  A proper solution would abandon this structure scheme
78138889Sjdp   certainly for very large strings, and possibly entirely.  */
78238889Sjdp
78333965Sjdp#ifndef PAGE_SIZE
78438889Sjdp#define PAGE_SIZE (8*1024)	/* size of varray pages */
78533965Sjdp#endif
78633965Sjdp
78733965Sjdp#define PAGE_USIZE ((unsigned long) PAGE_SIZE)
78833965Sjdp
78933965Sjdp#ifndef MAX_CLUSTER_PAGES	/* # pages to get from system */
79033965Sjdp#define MAX_CLUSTER_PAGES 63
79133965Sjdp#endif
79233965Sjdp
79333965Sjdp/* Linked list connecting separate page allocations.  */
79433965Sjdptypedef struct vlinks {
79533965Sjdp  struct vlinks	*prev;		/* previous set of pages */
79633965Sjdp  struct vlinks *next;		/* next set of pages */
79733965Sjdp  union  page   *datum;		/* start of page */
79833965Sjdp  unsigned long	 start_index;	/* starting index # of page */
79933965Sjdp} vlinks_t;
80033965Sjdp
80133965Sjdp/* Virtual array header.  */
80233965Sjdptypedef struct varray {
80333965Sjdp  vlinks_t	*first;			/* first page link */
80433965Sjdp  vlinks_t	*last;			/* last page link */
80533965Sjdp  unsigned long	 num_allocated;		/* # objects allocated */
80633965Sjdp  unsigned short object_size;		/* size in bytes of each object */
80733965Sjdp  unsigned short objects_per_page;	/* # objects that can fit on a page */
80833965Sjdp  unsigned short objects_last_page;	/* # objects allocated on last page */
80933965Sjdp} varray_t;
81033965Sjdp
81133965Sjdp#ifndef MALLOC_CHECK
81233965Sjdp#define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
81333965Sjdp#else
81433965Sjdp#define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
81533965Sjdp#endif
81633965Sjdp
81733965Sjdp#define INIT_VARRAY(type) {	/* macro to initialize a varray */	\
81833965Sjdp  (vlinks_t *)0,		/* first */				\
81933965Sjdp  (vlinks_t *)0,		/* last */				\
82033965Sjdp  0,				/* num_allocated */			\
82133965Sjdp  sizeof (type),		/* object_size */			\
82233965Sjdp  OBJECTS_PER_PAGE (type),	/* objects_per_page */			\
82333965Sjdp  OBJECTS_PER_PAGE (type),	/* objects_last_page */			\
82433965Sjdp}
82533965Sjdp
82677298Sobrien/* Master type for indexes within the symbol table.  */
82733965Sjdptypedef unsigned long symint_t;
82833965Sjdp
82933965Sjdp/* Linked list support for nested scopes (file, block, structure, etc.).  */
83033965Sjdptypedef struct scope {
83133965Sjdp  struct scope	*prev;		/* previous scope level */
83233965Sjdp  struct scope	*free;		/* free list pointer */
83333965Sjdp  struct localsym *lsym;	/* pointer to local symbol node */
83433965Sjdp  st_t		 type;		/* type of the node */
83533965Sjdp} scope_t;
83633965Sjdp
83733965Sjdp/* For a local symbol we store a gas symbol as well as the debugging
83833965Sjdp   information we generate.  The gas symbol will be NULL if this is
83933965Sjdp   only a debugging symbol.  */
84033965Sjdptypedef struct localsym {
84133965Sjdp  const char *name;		/* symbol name */
84233965Sjdp  symbolS *as_sym;		/* symbol as seen by gas */
84333965Sjdp  bfd_vma addend;		/* addend to as_sym value */
84433965Sjdp  struct efdr *file_ptr;	/* file pointer */
84533965Sjdp  struct ecoff_proc *proc_ptr;	/* proc pointer */
84633965Sjdp  struct localsym *begin_ptr;	/* symbol at start of block */
84733965Sjdp  struct ecoff_aux *index_ptr;	/* index value to be filled in */
84833965Sjdp  struct forward *forward_ref;	/* forward references to this symbol */
84933965Sjdp  long sym_index;		/* final symbol index */
85033965Sjdp  EXTR ecoff_sym;		/* ECOFF debugging symbol */
85133965Sjdp} localsym_t;
85233965Sjdp
85333965Sjdp/* For aux information we keep the type and the data.  */
85433965Sjdptypedef struct ecoff_aux {
85533965Sjdp  enum aux_type type;		/* aux type */
85633965Sjdp  AUXU data;			/* aux data */
85733965Sjdp} aux_t;
85833965Sjdp
85933965Sjdp/* For a procedure we store the gas symbol as well as the PDR
86033965Sjdp   debugging information.  */
86133965Sjdptypedef struct ecoff_proc {
86233965Sjdp  localsym_t *sym;		/* associated symbol */
86333965Sjdp  PDR pdr;			/* ECOFF debugging info */
86433965Sjdp} proc_t;
86533965Sjdp
86633965Sjdp/* Number of proc_t structures allocated.  */
86733965Sjdpstatic unsigned long proc_cnt;
86833965Sjdp
86933965Sjdp/* Forward reference list for tags referenced, but not yet defined.  */
87033965Sjdptypedef struct forward {
87133965Sjdp  struct forward *next;		/* next forward reference */
87233965Sjdp  struct forward *free;		/* free list pointer */
87333965Sjdp  aux_t		 *ifd_ptr;	/* pointer to store file index */
87433965Sjdp  aux_t		 *index_ptr;	/* pointer to store symbol index */
87533965Sjdp} forward_t;
87633965Sjdp
87733965Sjdp/* Linked list support for tags.  The first tag in the list is always
87833965Sjdp   the current tag for that block.  */
87933965Sjdptypedef struct tag {
88033965Sjdp  struct tag	 *free;		/* free list pointer */
88133965Sjdp  struct shash	 *hash_ptr;	/* pointer to the hash table head */
88233965Sjdp  struct tag	 *same_name;	/* tag with same name in outer scope */
88333965Sjdp  struct tag	 *same_block;	/* next tag defined in the same block.  */
88433965Sjdp  struct forward *forward_ref;	/* list of forward references */
88533965Sjdp  bt_t		  basic_type;	/* bt_Struct, bt_Union, or bt_Enum */
88633965Sjdp  symint_t	  ifd;		/* file # tag defined in */
88733965Sjdp  localsym_t	 *sym;		/* file's local symbols */
88833965Sjdp} tag_t;
88933965Sjdp
89033965Sjdp/* Head of a block's linked list of tags.  */
89133965Sjdptypedef struct thead {
89233965Sjdp  struct thead	*prev;		/* previous block */
89333965Sjdp  struct thead	*free;		/* free list pointer */
89433965Sjdp  struct tag	*first_tag;	/* first tag in block defined */
89533965Sjdp} thead_t;
89633965Sjdp
89733965Sjdp/* Union containing pointers to each the small structures which are freed up.  */
89833965Sjdptypedef union small_free {
89933965Sjdp  scope_t	*f_scope;	/* scope structure */
90033965Sjdp  thead_t	*f_thead;	/* tag head structure */
90133965Sjdp  tag_t		*f_tag;		/* tag element structure */
90233965Sjdp  forward_t	*f_forward;	/* forward tag reference */
90333965Sjdp} small_free_t;
90433965Sjdp
90533965Sjdp/* String hash table entry.  */
90633965Sjdp
90733965Sjdptypedef struct shash {
90833965Sjdp  char		*string;	/* string we are hashing */
90933965Sjdp  symint_t	 indx;		/* index within string table */
91033965Sjdp  EXTR		*esym_ptr;	/* global symbol pointer */
91133965Sjdp  localsym_t	*sym_ptr;	/* local symbol pointer */
91233965Sjdp  localsym_t	*end_ptr;	/* symbol pointer to end block */
91333965Sjdp  tag_t		*tag_ptr;	/* tag pointer */
91433965Sjdp  proc_t	*proc_ptr;	/* procedure descriptor pointer */
91533965Sjdp} shash_t;
91633965Sjdp
91733965Sjdp/* Type hash table support.  The size of the hash table must fit
91833965Sjdp   within a page with the other extended file descriptor information.
91933965Sjdp   Because unique types which are hashed are fewer in number than
92033965Sjdp   strings, we use a smaller hash value.  */
92133965Sjdp
92233965Sjdp#define HASHBITS 30
92333965Sjdp
92433965Sjdp#ifndef THASH_SIZE
92533965Sjdp#define THASH_SIZE 113
92633965Sjdp#endif
92733965Sjdp
92833965Sjdptypedef struct thash {
92933965Sjdp  struct thash	*next;		/* next hash value */
93033965Sjdp  AUXU		 type;		/* type we are hashing */
93133965Sjdp  symint_t	 indx;		/* index within string table */
93233965Sjdp} thash_t;
93333965Sjdp
93433965Sjdp/* Extended file descriptor that contains all of the support necessary
93533965Sjdp   to add things to each file separately.  */
93633965Sjdptypedef struct efdr {
93733965Sjdp  FDR		 fdr;		/* File header to be written out */
93833965Sjdp  FDR		*orig_fdr;	/* original file header */
93933965Sjdp  char		*name;		/* filename */
94033965Sjdp  int		 fake;		/* whether this is faked .file */
94133965Sjdp  symint_t	 void_type;	/* aux. pointer to 'void' type */
94233965Sjdp  symint_t	 int_type;	/* aux. pointer to 'int' type */
94333965Sjdp  scope_t	*cur_scope;	/* current nested scopes */
94433965Sjdp  symint_t	 file_index;	/* current file number */
94533965Sjdp  int		 nested_scopes;	/* # nested scopes */
94633965Sjdp  varray_t	 strings;	/* local strings */
94733965Sjdp  varray_t	 symbols;	/* local symbols */
94833965Sjdp  varray_t	 procs;		/* procedures */
94933965Sjdp  varray_t	 aux_syms;	/* auxiliary symbols */
95033965Sjdp  struct efdr	*next_file;	/* next file descriptor */
95133965Sjdp				/* string/type hash tables */
95233965Sjdp  struct hash_control *str_hash;	/* string hash table */
95333965Sjdp  thash_t	*thash_head[THASH_SIZE];
95433965Sjdp} efdr_t;
95533965Sjdp
95633965Sjdp/* Pre-initialized extended file structure.  */
95777298Sobrienstatic const efdr_t init_file = {
95833965Sjdp  {			/* FDR structure */
95933965Sjdp    0,			/* adr:		memory address of beginning of file */
96033965Sjdp    0,			/* rss:		file name (of source, if known) */
96133965Sjdp    0,			/* issBase:	file's string space */
96233965Sjdp    0,			/* cbSs:	number of bytes in the ss */
96333965Sjdp    0,			/* isymBase:	beginning of symbols */
96433965Sjdp    0,			/* csym:	count file's of symbols */
96533965Sjdp    0,			/* ilineBase:	file's line symbols */
96633965Sjdp    0,			/* cline:	count of file's line symbols */
96733965Sjdp    0,			/* ioptBase:	file's optimization entries */
96833965Sjdp    0,			/* copt:	count of file's optimization entries */
96933965Sjdp    0,			/* ipdFirst:	start of procedures for this file */
97033965Sjdp    0,			/* cpd:		count of procedures for this file */
97133965Sjdp    0,			/* iauxBase:	file's auxiliary entries */
97233965Sjdp    0,			/* caux:	count of file's auxiliary entries */
97333965Sjdp    0,			/* rfdBase:	index into the file indirect table */
97433965Sjdp    0,			/* crfd:	count file indirect entries */
97533965Sjdp    langC,		/* lang:	language for this file */
97633965Sjdp    1,			/* fMerge:	whether this file can be merged */
97733965Sjdp    0,			/* fReadin:	true if read in (not just created) */
97833965Sjdp    TARGET_BYTES_BIG_ENDIAN,  /* fBigendian:	if 1, compiled on big endian machine */
97933965Sjdp    GLEVEL_2,		/* glevel:	level this file was compiled with */
98033965Sjdp    0,			/* reserved:	reserved for future use */
98133965Sjdp    0,			/* cbLineOffset: byte offset from header for this file ln's */
98233965Sjdp    0,			/* cbLine:	size of lines for this file */
98333965Sjdp  },
98433965Sjdp
98533965Sjdp  (FDR *)0,		/* orig_fdr:	original file header pointer */
98633965Sjdp  (char *)0,		/* name:	pointer to filename */
98733965Sjdp  0,			/* fake:	whether this is a faked .file */
98833965Sjdp  0,			/* void_type:	ptr to aux node for void type */
98933965Sjdp  0,			/* int_type:	ptr to aux node for int type */
99033965Sjdp  (scope_t *)0,		/* cur_scope:	current scope being processed */
99133965Sjdp  0,			/* file_index:	current file # */
99233965Sjdp  0,			/* nested_scopes: # nested scopes */
99333965Sjdp  INIT_VARRAY (char),	/* strings:	local string varray */
99433965Sjdp  INIT_VARRAY (localsym_t),	/* symbols:	local symbols varray */
99533965Sjdp  INIT_VARRAY (proc_t),	/* procs:	procedure varray */
99633965Sjdp  INIT_VARRAY (aux_t),	/* aux_syms:	auxiliary symbols varray */
99733965Sjdp
99833965Sjdp  (struct efdr *)0,	/* next_file:	next file structure */
99933965Sjdp
100033965Sjdp  (struct hash_control *)0,	/* str_hash:	string hash table */
100133965Sjdp  { 0 },		/* thash_head:	type hash table */
100233965Sjdp};
100333965Sjdp
100433965Sjdpstatic efdr_t *first_file;			/* first file descriptor */
100533965Sjdpstatic efdr_t **last_file_ptr = &first_file;	/* file descriptor tail */
100633965Sjdp
100733965Sjdp/* Line number information is kept in a list until the assembly is
100833965Sjdp   finished.  */
100933965Sjdptypedef struct lineno_list {
101033965Sjdp  struct lineno_list *next;	/* next element in list */
101133965Sjdp  efdr_t *file;			/* file this line is in */
101233965Sjdp  proc_t *proc;			/* procedure this line is in */
101333965Sjdp  fragS *frag;			/* fragment this line number is in */
101433965Sjdp  unsigned long paddr;		/* offset within fragment */
101533965Sjdp  long lineno;			/* actual line number */
101633965Sjdp} lineno_list_t;
101733965Sjdp
101833965Sjdpstatic lineno_list_t *first_lineno;
101933965Sjdpstatic lineno_list_t *last_lineno;
102033965Sjdpstatic lineno_list_t **last_lineno_ptr = &first_lineno;
102133965Sjdp
102233965Sjdp/* Sometimes there will be some .loc statements before a .ent.  We
102333965Sjdp   keep them in this list so that we can fill in the procedure pointer
102433965Sjdp   after we see the .ent.  */
102533965Sjdpstatic lineno_list_t *noproc_lineno;
102633965Sjdp
102733965Sjdp/* Union of various things that are held in pages.  */
102833965Sjdptypedef union page {
102933965Sjdp  char		byte	[ PAGE_SIZE ];
103033965Sjdp  unsigned char	ubyte	[ PAGE_SIZE ];
103133965Sjdp  efdr_t	file	[ PAGE_SIZE / sizeof (efdr_t)	     ];
103233965Sjdp  FDR		ofile	[ PAGE_SIZE / sizeof (FDR)	     ];
103333965Sjdp  proc_t	proc	[ PAGE_SIZE / sizeof (proc_t)	     ];
103433965Sjdp  localsym_t	sym	[ PAGE_SIZE / sizeof (localsym_t)    ];
103533965Sjdp  aux_t		aux	[ PAGE_SIZE / sizeof (aux_t)	     ];
103633965Sjdp  DNR		dense	[ PAGE_SIZE / sizeof (DNR)	     ];
103733965Sjdp  scope_t	scope	[ PAGE_SIZE / sizeof (scope_t)	     ];
103833965Sjdp  vlinks_t	vlinks	[ PAGE_SIZE / sizeof (vlinks_t)	     ];
103933965Sjdp  shash_t	shash	[ PAGE_SIZE / sizeof (shash_t)	     ];
104033965Sjdp  thash_t	thash	[ PAGE_SIZE / sizeof (thash_t)	     ];
104133965Sjdp  tag_t		tag	[ PAGE_SIZE / sizeof (tag_t)	     ];
104233965Sjdp  forward_t	forward	[ PAGE_SIZE / sizeof (forward_t)     ];
104333965Sjdp  thead_t	thead	[ PAGE_SIZE / sizeof (thead_t)	     ];
104433965Sjdp  lineno_list_t	lineno	[ PAGE_SIZE / sizeof (lineno_list_t) ];
104538889Sjdp} page_type;
104633965Sjdp
104733965Sjdp/* Structure holding allocation information for small sized structures.  */
104833965Sjdptypedef struct alloc_info {
104933965Sjdp  char		*alloc_name;	/* name of this allocation type (must be first) */
105038889Sjdp  page_type	*cur_page;	/* current page being allocated from */
105133965Sjdp  small_free_t	 free_list;	/* current free list if any */
105233965Sjdp  int		 unallocated;	/* number of elements unallocated on page */
105333965Sjdp  int		 total_alloc;	/* total number of allocations */
105433965Sjdp  int		 total_free;	/* total number of frees */
105533965Sjdp  int		 total_pages;	/* total number of pages allocated */
105633965Sjdp} alloc_info_t;
105733965Sjdp
105833965Sjdp/* Type information collected together.  */
105933965Sjdptypedef struct type_info {
106033965Sjdp  bt_t	      basic_type;		/* basic type */
106133965Sjdp  int	      orig_type;		/* original COFF-based type */
106233965Sjdp  int	      num_tq;			/* # type qualifiers */
106333965Sjdp  int	      num_dims;			/* # dimensions */
106433965Sjdp  int	      num_sizes;		/* # sizes */
106533965Sjdp  int	      extra_sizes;		/* # extra sizes not tied with dims */
106633965Sjdp  tag_t *     tag_ptr;			/* tag pointer */
106733965Sjdp  int	      bitfield;			/* symbol is a bitfield */
106833965Sjdp  tq_t	      type_qualifiers[N_TQ];	/* type qualifiers (ptr, func, array)*/
106933965Sjdp  symint_t    dimensions     [N_TQ];	/* dimensions for each array */
107033965Sjdp  symint_t    sizes	     [N_TQ+2];	/* sizes of each array slice + size of
107133965Sjdp					   struct/union/enum + bitfield size */
107233965Sjdp} type_info_t;
107333965Sjdp
107433965Sjdp/* Pre-initialized type_info struct.  */
107533965Sjdpstatic const type_info_t type_info_init = {
107633965Sjdp  bt_Nil,				/* basic type */
107733965Sjdp  T_NULL,				/* original COFF-based type */
107833965Sjdp  0,					/* # type qualifiers */
107933965Sjdp  0,					/* # dimensions */
108033965Sjdp  0,					/* # sizes */
108133965Sjdp  0,					/* sizes not tied with dims */
108233965Sjdp  NULL,					/* ptr to tag */
108333965Sjdp  0,					/* bitfield */
108433965Sjdp  {					/* type qualifiers */
108533965Sjdp    tq_Nil,
108633965Sjdp    tq_Nil,
108733965Sjdp    tq_Nil,
108833965Sjdp    tq_Nil,
108933965Sjdp    tq_Nil,
109033965Sjdp    tq_Nil,
109133965Sjdp  },
109233965Sjdp  {					/* dimensions */
109333965Sjdp    0,
109433965Sjdp    0,
109533965Sjdp    0,
109633965Sjdp    0,
109733965Sjdp    0,
109833965Sjdp    0
109933965Sjdp  },
110033965Sjdp  {					/* sizes */
110133965Sjdp    0,
110233965Sjdp    0,
110333965Sjdp    0,
110433965Sjdp    0,
110533965Sjdp    0,
110633965Sjdp    0,
110733965Sjdp    0,
110833965Sjdp    0,
110933965Sjdp  },
111033965Sjdp};
111133965Sjdp
111233965Sjdp/* Global hash table for the tags table and global table for file
111333965Sjdp   descriptors.  */
111433965Sjdp
111577298Sobrienstatic varray_t file_desc = INIT_VARRAY (efdr_t);
111633965Sjdp
111733965Sjdpstatic struct hash_control *tag_hash;
111833965Sjdp
111933965Sjdp/* Static types for int and void.  Also, remember the last function's
112033965Sjdp   type (which is set up when we encounter the declaration for the
112133965Sjdp   function, and used when the end block for the function is emitted.  */
112233965Sjdp
112333965Sjdpstatic type_info_t int_type_info;
112433965Sjdpstatic type_info_t void_type_info;
112533965Sjdpstatic type_info_t last_func_type_info;
112633965Sjdpstatic symbolS *last_func_sym_value;
112733965Sjdp
112833965Sjdp/* Convert COFF basic type to ECOFF basic type.  The T_NULL type
112933965Sjdp   really should use bt_Void, but this causes the current ecoff GDB to
113033965Sjdp   issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
113133965Sjdp   2.0) doesn't understand it, even though the compiler generates it.
113233965Sjdp   Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
113333965Sjdp   suite, but for now go with what works.
113433965Sjdp
113533965Sjdp   It would make sense for the .type and .scl directives to use the
113633965Sjdp   ECOFF numbers directly, rather than using the COFF numbers and
113733965Sjdp   mapping them.  Unfortunately, this is historically what mips-tfile
113833965Sjdp   expects, and changing gcc now would be a considerable pain (the
113933965Sjdp   native compiler generates debugging information internally, rather
114033965Sjdp   than via the assembler, so it will never use .type or .scl).  */
114133965Sjdp
114233965Sjdpstatic const bt_t map_coff_types[] = {
114333965Sjdp  bt_Nil,			/* T_NULL */
114433965Sjdp  bt_Nil,			/* T_ARG */
114533965Sjdp  bt_Char,			/* T_CHAR */
114633965Sjdp  bt_Short,			/* T_SHORT */
114733965Sjdp  bt_Int,			/* T_INT */
114833965Sjdp  bt_Long,			/* T_LONG */
114933965Sjdp  bt_Float,			/* T_FLOAT */
115033965Sjdp  bt_Double,			/* T_DOUBLE */
115133965Sjdp  bt_Struct,			/* T_STRUCT */
115233965Sjdp  bt_Union,			/* T_UNION */
115333965Sjdp  bt_Enum,			/* T_ENUM */
115433965Sjdp  bt_Enum,			/* T_MOE */
115533965Sjdp  bt_UChar,			/* T_UCHAR */
115633965Sjdp  bt_UShort,			/* T_USHORT */
115733965Sjdp  bt_UInt,			/* T_UINT */
115833965Sjdp  bt_ULong			/* T_ULONG */
115933965Sjdp};
116033965Sjdp
116133965Sjdp/* Convert COFF storage class to ECOFF storage class.  */
116233965Sjdpstatic const sc_t map_coff_storage[] = {
116333965Sjdp  sc_Nil,			/*   0: C_NULL */
116433965Sjdp  sc_Abs,			/*   1: C_AUTO	  auto var */
116533965Sjdp  sc_Undefined,			/*   2: C_EXT	  external */
116633965Sjdp  sc_Data,			/*   3: C_STAT	  static */
116733965Sjdp  sc_Register,			/*   4: C_REG	  register */
116833965Sjdp  sc_Undefined,			/*   5: C_EXTDEF  ??? */
116933965Sjdp  sc_Text,			/*   6: C_LABEL	  label */
117033965Sjdp  sc_Text,			/*   7: C_ULABEL  user label */
117133965Sjdp  sc_Info,			/*   8: C_MOS	  member of struct */
117233965Sjdp  sc_Abs,			/*   9: C_ARG	  argument */
117333965Sjdp  sc_Info,			/*  10: C_STRTAG  struct tag */
117433965Sjdp  sc_Info,			/*  11: C_MOU	  member of union */
117533965Sjdp  sc_Info,			/*  12: C_UNTAG   union tag */
117633965Sjdp  sc_Info,			/*  13: C_TPDEF	  typedef */
117733965Sjdp  sc_Data,			/*  14: C_USTATIC ??? */
117833965Sjdp  sc_Info,			/*  15: C_ENTAG	  enum tag */
117933965Sjdp  sc_Info,			/*  16: C_MOE	  member of enum */
118033965Sjdp  sc_Register,			/*  17: C_REGPARM register parameter */
118133965Sjdp  sc_Bits,			/*  18; C_FIELD	  bitfield */
118233965Sjdp  sc_Nil,			/*  19 */
118333965Sjdp  sc_Nil,			/*  20 */
118433965Sjdp  sc_Nil,			/*  21 */
118533965Sjdp  sc_Nil,			/*  22 */
118633965Sjdp  sc_Nil,			/*  23 */
118733965Sjdp  sc_Nil,			/*  24 */
118833965Sjdp  sc_Nil,			/*  25 */
118933965Sjdp  sc_Nil,			/*  26 */
119033965Sjdp  sc_Nil,			/*  27 */
119133965Sjdp  sc_Nil,			/*  28 */
119233965Sjdp  sc_Nil,			/*  29 */
119333965Sjdp  sc_Nil,			/*  30 */
119433965Sjdp  sc_Nil,			/*  31 */
119533965Sjdp  sc_Nil,			/*  32 */
119633965Sjdp  sc_Nil,			/*  33 */
119733965Sjdp  sc_Nil,			/*  34 */
119833965Sjdp  sc_Nil,			/*  35 */
119933965Sjdp  sc_Nil,			/*  36 */
120033965Sjdp  sc_Nil,			/*  37 */
120133965Sjdp  sc_Nil,			/*  38 */
120233965Sjdp  sc_Nil,			/*  39 */
120333965Sjdp  sc_Nil,			/*  40 */
120433965Sjdp  sc_Nil,			/*  41 */
120533965Sjdp  sc_Nil,			/*  42 */
120633965Sjdp  sc_Nil,			/*  43 */
120733965Sjdp  sc_Nil,			/*  44 */
120833965Sjdp  sc_Nil,			/*  45 */
120933965Sjdp  sc_Nil,			/*  46 */
121033965Sjdp  sc_Nil,			/*  47 */
121133965Sjdp  sc_Nil,			/*  48 */
121233965Sjdp  sc_Nil,			/*  49 */
121333965Sjdp  sc_Nil,			/*  50 */
121433965Sjdp  sc_Nil,			/*  51 */
121533965Sjdp  sc_Nil,			/*  52 */
121633965Sjdp  sc_Nil,			/*  53 */
121733965Sjdp  sc_Nil,			/*  54 */
121833965Sjdp  sc_Nil,			/*  55 */
121933965Sjdp  sc_Nil,			/*  56 */
122033965Sjdp  sc_Nil,			/*  57 */
122133965Sjdp  sc_Nil,			/*  58 */
122233965Sjdp  sc_Nil,			/*  59 */
122333965Sjdp  sc_Nil,			/*  60 */
122433965Sjdp  sc_Nil,			/*  61 */
122533965Sjdp  sc_Nil,			/*  62 */
122633965Sjdp  sc_Nil,			/*  63 */
122733965Sjdp  sc_Nil,			/*  64 */
122833965Sjdp  sc_Nil,			/*  65 */
122933965Sjdp  sc_Nil,			/*  66 */
123033965Sjdp  sc_Nil,			/*  67 */
123133965Sjdp  sc_Nil,			/*  68 */
123233965Sjdp  sc_Nil,			/*  69 */
123333965Sjdp  sc_Nil,			/*  70 */
123433965Sjdp  sc_Nil,			/*  71 */
123533965Sjdp  sc_Nil,			/*  72 */
123633965Sjdp  sc_Nil,			/*  73 */
123733965Sjdp  sc_Nil,			/*  74 */
123833965Sjdp  sc_Nil,			/*  75 */
123933965Sjdp  sc_Nil,			/*  76 */
124033965Sjdp  sc_Nil,			/*  77 */
124133965Sjdp  sc_Nil,			/*  78 */
124233965Sjdp  sc_Nil,			/*  79 */
124333965Sjdp  sc_Nil,			/*  80 */
124433965Sjdp  sc_Nil,			/*  81 */
124533965Sjdp  sc_Nil,			/*  82 */
124633965Sjdp  sc_Nil,			/*  83 */
124733965Sjdp  sc_Nil,			/*  84 */
124833965Sjdp  sc_Nil,			/*  85 */
124933965Sjdp  sc_Nil,			/*  86 */
125033965Sjdp  sc_Nil,			/*  87 */
125133965Sjdp  sc_Nil,			/*  88 */
125233965Sjdp  sc_Nil,			/*  89 */
125333965Sjdp  sc_Nil,			/*  90 */
125433965Sjdp  sc_Nil,			/*  91 */
125533965Sjdp  sc_Nil,			/*  92 */
125633965Sjdp  sc_Nil,			/*  93 */
125733965Sjdp  sc_Nil,			/*  94 */
125833965Sjdp  sc_Nil,			/*  95 */
125933965Sjdp  sc_Nil,			/*  96 */
126033965Sjdp  sc_Nil,			/*  97 */
126133965Sjdp  sc_Nil,			/*  98 */
126233965Sjdp  sc_Nil,			/*  99 */
126333965Sjdp  sc_Text,			/* 100: C_BLOCK  block start/end */
126433965Sjdp  sc_Text,			/* 101: C_FCN	 function start/end */
126533965Sjdp  sc_Info,			/* 102: C_EOS	 end of struct/union/enum */
126633965Sjdp  sc_Nil,			/* 103: C_FILE	 file start */
126733965Sjdp  sc_Nil,			/* 104: C_LINE	 line number */
126833965Sjdp  sc_Nil,			/* 105: C_ALIAS	 combined type info */
126933965Sjdp  sc_Nil,			/* 106: C_HIDDEN ??? */
127033965Sjdp};
127133965Sjdp
127233965Sjdp/* Convert COFF storage class to ECOFF symbol type.  */
127333965Sjdpstatic const st_t map_coff_sym_type[] = {
127433965Sjdp  st_Nil,			/*   0: C_NULL */
127533965Sjdp  st_Local,			/*   1: C_AUTO	  auto var */
127633965Sjdp  st_Global,			/*   2: C_EXT	  external */
127733965Sjdp  st_Static,			/*   3: C_STAT	  static */
127833965Sjdp  st_Local,			/*   4: C_REG	  register */
127933965Sjdp  st_Global,			/*   5: C_EXTDEF  ??? */
128033965Sjdp  st_Label,			/*   6: C_LABEL	  label */
128133965Sjdp  st_Label,			/*   7: C_ULABEL  user label */
128233965Sjdp  st_Member,			/*   8: C_MOS	  member of struct */
128333965Sjdp  st_Param,			/*   9: C_ARG	  argument */
128433965Sjdp  st_Block,			/*  10: C_STRTAG  struct tag */
128533965Sjdp  st_Member,			/*  11: C_MOU	  member of union */
128633965Sjdp  st_Block,			/*  12: C_UNTAG   union tag */
128733965Sjdp  st_Typedef,			/*  13: C_TPDEF	  typedef */
128833965Sjdp  st_Static,			/*  14: C_USTATIC ??? */
128933965Sjdp  st_Block,			/*  15: C_ENTAG	  enum tag */
129033965Sjdp  st_Member,			/*  16: C_MOE	  member of enum */
129133965Sjdp  st_Param,			/*  17: C_REGPARM register parameter */
129233965Sjdp  st_Member,			/*  18; C_FIELD	  bitfield */
129333965Sjdp  st_Nil,			/*  19 */
129433965Sjdp  st_Nil,			/*  20 */
129533965Sjdp  st_Nil,			/*  21 */
129633965Sjdp  st_Nil,			/*  22 */
129733965Sjdp  st_Nil,			/*  23 */
129833965Sjdp  st_Nil,			/*  24 */
129933965Sjdp  st_Nil,			/*  25 */
130033965Sjdp  st_Nil,			/*  26 */
130133965Sjdp  st_Nil,			/*  27 */
130233965Sjdp  st_Nil,			/*  28 */
130333965Sjdp  st_Nil,			/*  29 */
130433965Sjdp  st_Nil,			/*  30 */
130533965Sjdp  st_Nil,			/*  31 */
130633965Sjdp  st_Nil,			/*  32 */
130733965Sjdp  st_Nil,			/*  33 */
130833965Sjdp  st_Nil,			/*  34 */
130933965Sjdp  st_Nil,			/*  35 */
131033965Sjdp  st_Nil,			/*  36 */
131133965Sjdp  st_Nil,			/*  37 */
131233965Sjdp  st_Nil,			/*  38 */
131333965Sjdp  st_Nil,			/*  39 */
131433965Sjdp  st_Nil,			/*  40 */
131533965Sjdp  st_Nil,			/*  41 */
131633965Sjdp  st_Nil,			/*  42 */
131733965Sjdp  st_Nil,			/*  43 */
131833965Sjdp  st_Nil,			/*  44 */
131933965Sjdp  st_Nil,			/*  45 */
132033965Sjdp  st_Nil,			/*  46 */
132133965Sjdp  st_Nil,			/*  47 */
132233965Sjdp  st_Nil,			/*  48 */
132333965Sjdp  st_Nil,			/*  49 */
132433965Sjdp  st_Nil,			/*  50 */
132533965Sjdp  st_Nil,			/*  51 */
132633965Sjdp  st_Nil,			/*  52 */
132733965Sjdp  st_Nil,			/*  53 */
132833965Sjdp  st_Nil,			/*  54 */
132933965Sjdp  st_Nil,			/*  55 */
133033965Sjdp  st_Nil,			/*  56 */
133133965Sjdp  st_Nil,			/*  57 */
133233965Sjdp  st_Nil,			/*  58 */
133333965Sjdp  st_Nil,			/*  59 */
133433965Sjdp  st_Nil,			/*  60 */
133533965Sjdp  st_Nil,			/*  61 */
133633965Sjdp  st_Nil,			/*  62 */
133733965Sjdp  st_Nil,			/*  63 */
133833965Sjdp  st_Nil,			/*  64 */
133933965Sjdp  st_Nil,			/*  65 */
134033965Sjdp  st_Nil,			/*  66 */
134133965Sjdp  st_Nil,			/*  67 */
134233965Sjdp  st_Nil,			/*  68 */
134333965Sjdp  st_Nil,			/*  69 */
134433965Sjdp  st_Nil,			/*  70 */
134533965Sjdp  st_Nil,			/*  71 */
134633965Sjdp  st_Nil,			/*  72 */
134733965Sjdp  st_Nil,			/*  73 */
134833965Sjdp  st_Nil,			/*  74 */
134933965Sjdp  st_Nil,			/*  75 */
135033965Sjdp  st_Nil,			/*  76 */
135133965Sjdp  st_Nil,			/*  77 */
135233965Sjdp  st_Nil,			/*  78 */
135333965Sjdp  st_Nil,			/*  79 */
135433965Sjdp  st_Nil,			/*  80 */
135533965Sjdp  st_Nil,			/*  81 */
135633965Sjdp  st_Nil,			/*  82 */
135733965Sjdp  st_Nil,			/*  83 */
135833965Sjdp  st_Nil,			/*  84 */
135933965Sjdp  st_Nil,			/*  85 */
136033965Sjdp  st_Nil,			/*  86 */
136133965Sjdp  st_Nil,			/*  87 */
136233965Sjdp  st_Nil,			/*  88 */
136333965Sjdp  st_Nil,			/*  89 */
136433965Sjdp  st_Nil,			/*  90 */
136533965Sjdp  st_Nil,			/*  91 */
136633965Sjdp  st_Nil,			/*  92 */
136733965Sjdp  st_Nil,			/*  93 */
136833965Sjdp  st_Nil,			/*  94 */
136933965Sjdp  st_Nil,			/*  95 */
137033965Sjdp  st_Nil,			/*  96 */
137133965Sjdp  st_Nil,			/*  97 */
137233965Sjdp  st_Nil,			/*  98 */
137333965Sjdp  st_Nil,			/*  99 */
137433965Sjdp  st_Block,			/* 100: C_BLOCK  block start/end */
137533965Sjdp  st_Proc,			/* 101: C_FCN	 function start/end */
137633965Sjdp  st_End,			/* 102: C_EOS	 end of struct/union/enum */
137733965Sjdp  st_File,			/* 103: C_FILE	 file start */
137833965Sjdp  st_Nil,			/* 104: C_LINE	 line number */
137933965Sjdp  st_Nil,			/* 105: C_ALIAS	 combined type info */
138033965Sjdp  st_Nil,			/* 106: C_HIDDEN ??? */
138133965Sjdp};
138233965Sjdp
138333965Sjdp/* Keep track of different sized allocation requests.  */
138477298Sobrienstatic alloc_info_t alloc_counts[(int) alloc_type_last];
138533965Sjdp
138633965Sjdp/* Record whether we have seen any debugging information.  */
138733965Sjdpint ecoff_debugging_seen = 0;
138833965Sjdp
138933965Sjdp/* Various statics.  */
139033965Sjdpstatic efdr_t  *cur_file_ptr	= (efdr_t *) 0;	/* current file desc. header */
139133965Sjdpstatic proc_t  *cur_proc_ptr	= (proc_t *) 0;	/* current procedure header */
139233965Sjdpstatic proc_t  *first_proc_ptr  = (proc_t *) 0; /* first procedure header */
139333965Sjdpstatic thead_t *top_tag_head	= (thead_t *) 0; /* top level tag head */
139433965Sjdpstatic thead_t *cur_tag_head	= (thead_t *) 0; /* current tag head */
139533965Sjdp#ifdef ECOFF_DEBUG
139633965Sjdpstatic int	debug		= 0; 		/* trace functions */
139733965Sjdp#endif
139833965Sjdpstatic int	stabs_seen	= 0;		/* != 0 if stabs have been seen */
139933965Sjdp
140033965Sjdpstatic int current_file_idx;
140133965Sjdpstatic const char *current_stabs_filename;
140233965Sjdp
140333965Sjdp/* Pseudo symbol to use when putting stabs into the symbol table.  */
140433965Sjdp#ifndef STABS_SYMBOL
140533965Sjdp#define STABS_SYMBOL "@stabs"
140633965Sjdp#endif
140733965Sjdp
140833965Sjdpstatic char stabs_symbol[] = STABS_SYMBOL;
140933965Sjdp
141033965Sjdp/* Prototypes for functions defined in this file.  */
141133965Sjdp
1412130561Sobrienstatic void add_varray_page (varray_t *vp);
1413130561Sobrienstatic symint_t add_string (varray_t *vp,
1414130561Sobrien			    struct hash_control *hash_tbl,
1415130561Sobrien			    const char *str,
1416130561Sobrien			    shash_t **ret_hash);
1417130561Sobrienstatic localsym_t *add_ecoff_symbol (const char *str, st_t type,
1418130561Sobrien				     sc_t storage, symbolS *sym,
1419130561Sobrien				     bfd_vma addend, symint_t value,
1420130561Sobrien				     symint_t indx);
1421130561Sobrienstatic symint_t add_aux_sym_symint (symint_t aux_word);
1422130561Sobrienstatic symint_t add_aux_sym_rndx (int file_index, symint_t sym_index);
1423130561Sobrienstatic symint_t add_aux_sym_tir (type_info_t *t,
1424130561Sobrien				 hash_state_t state,
1425130561Sobrien				 thash_t **hash_tbl);
1426130561Sobrienstatic tag_t *get_tag (const char *tag, localsym_t *sym, bt_t basic_type);
1427130561Sobrienstatic void add_unknown_tag (tag_t *ptag);
1428130561Sobrienstatic void add_procedure (char *func);
1429130561Sobrienstatic void add_file (const char *file_name, int indx, int fake);
143033965Sjdp#ifdef ECOFF_DEBUG
1431130561Sobrienstatic char *sc_to_string (sc_t storage_class);
1432130561Sobrienstatic char *st_to_string (st_t symbol_type);
143333965Sjdp#endif
1434130561Sobrienstatic void mark_stabs (int);
1435130561Sobrienstatic char *ecoff_add_bytes (char **buf, char **bufend,
1436130561Sobrien			      char *bufptr, unsigned long need);
143733965Sjdpstatic unsigned long ecoff_padding_adjust
1438130561Sobrien  (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1439130561Sobrien   unsigned long offset, char **bufptrptr);
144033965Sjdpstatic unsigned long ecoff_build_lineno
1441130561Sobrien  (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1442130561Sobrien   unsigned long offset, long *linecntptr);
144333965Sjdpstatic unsigned long ecoff_build_symbols
1444130561Sobrien  (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1445130561Sobrien   unsigned long offset);
144633965Sjdpstatic unsigned long ecoff_build_procs
1447130561Sobrien  (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1448130561Sobrien   unsigned long offset);
144933965Sjdpstatic unsigned long ecoff_build_aux
1450130561Sobrien  (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1451130561Sobrien   unsigned long offset);
1452130561Sobrienstatic unsigned long ecoff_build_strings (char **buf, char **bufend,
1453130561Sobrien					  unsigned long offset,
1454130561Sobrien					  varray_t *vp);
145533965Sjdpstatic unsigned long ecoff_build_ss
1456130561Sobrien  (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1457130561Sobrien   unsigned long offset);
145833965Sjdpstatic unsigned long ecoff_build_fdr
1459130561Sobrien  (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1460130561Sobrien   unsigned long offset);
1461130561Sobrienstatic void ecoff_setup_ext (void);
1462130561Sobrienstatic page_type *allocate_cluster (unsigned long npages);
1463130561Sobrienstatic page_type *allocate_page (void);
1464130561Sobrienstatic scope_t *allocate_scope (void);
1465130561Sobrienstatic void free_scope (scope_t *ptr);
1466130561Sobrienstatic vlinks_t *allocate_vlinks (void);
1467130561Sobrienstatic shash_t *allocate_shash (void);
1468130561Sobrienstatic thash_t *allocate_thash (void);
1469130561Sobrienstatic tag_t *allocate_tag (void);
1470130561Sobrienstatic void free_tag (tag_t *ptr);
1471130561Sobrienstatic forward_t *allocate_forward (void);
1472130561Sobrienstatic thead_t *allocate_thead (void);
1473130561Sobrienstatic void free_thead (thead_t *ptr);
1474130561Sobrienstatic lineno_list_t *allocate_lineno_list (void);
147533965Sjdp
147633965Sjdp/* This function should be called when the assembler starts up.  */
147733965Sjdp
147833965Sjdpvoid
1479130561Sobrienecoff_read_begin_hook (void)
148033965Sjdp{
148133965Sjdp  tag_hash = hash_new ();
148233965Sjdp  top_tag_head = allocate_thead ();
148333965Sjdp  top_tag_head->first_tag = (tag_t *) NULL;
148433965Sjdp  top_tag_head->free = (thead_t *) NULL;
148533965Sjdp  top_tag_head->prev = cur_tag_head;
148633965Sjdp  cur_tag_head = top_tag_head;
148733965Sjdp}
148833965Sjdp
148933965Sjdp/* This function should be called when a symbol is created.  */
149033965Sjdp
149133965Sjdpvoid
1492130561Sobrienecoff_symbol_new_hook (symbolS *symbolP)
149333965Sjdp{
149460484Sobrien  OBJ_SYMFIELD_TYPE *obj;
149560484Sobrien
149633965Sjdp  /* Make sure that we have a file pointer, but only if we have seen a
149733965Sjdp     file.  If we haven't seen a file, then this is a probably special
149833965Sjdp     symbol created by md_begin which may required special handling at
149933965Sjdp     some point.  Creating a dummy file with a dummy name is certainly
150033965Sjdp     wrong.  */
150133965Sjdp  if (cur_file_ptr == (efdr_t *) NULL
150233965Sjdp      && seen_at_least_1_file ())
150333965Sjdp    add_file ((const char *) NULL, 0, 1);
150460484Sobrien  obj = symbol_get_obj (symbolP);
150560484Sobrien  obj->ecoff_file = cur_file_ptr;
150660484Sobrien  obj->ecoff_symbol = NULL;
150760484Sobrien  obj->ecoff_extern_size = 0;
150833965Sjdp}
150933965Sjdp
151033965Sjdp/* Add a page to a varray object.  */
151133965Sjdp
151233965Sjdpstatic void
1513130561Sobrienadd_varray_page (varray_t *vp /* varray to add page to */)
151433965Sjdp{
151533965Sjdp  vlinks_t *new_links = allocate_vlinks ();
151633965Sjdp
151733965Sjdp#ifdef MALLOC_CHECK
151833965Sjdp  if (vp->object_size > 1)
151938889Sjdp    new_links->datum = (page_type *) xcalloc (1, vp->object_size);
152033965Sjdp  else
152133965Sjdp#endif
152233965Sjdp    new_links->datum = allocate_page ();
152333965Sjdp
152477298Sobrien  alloc_counts[(int) alloc_type_varray].total_alloc++;
152577298Sobrien  alloc_counts[(int) alloc_type_varray].total_pages++;
152633965Sjdp
152733965Sjdp  new_links->start_index = vp->num_allocated;
152833965Sjdp  vp->objects_last_page = 0;
152933965Sjdp
153033965Sjdp  if (vp->first == (vlinks_t *) NULL)		/* first allocation? */
153133965Sjdp    vp->first = vp->last = new_links;
153233965Sjdp  else
153333965Sjdp    {						/* 2nd or greater allocation */
153433965Sjdp      new_links->prev = vp->last;
153533965Sjdp      vp->last->next = new_links;
153633965Sjdp      vp->last = new_links;
153733965Sjdp    }
153833965Sjdp}
153933965Sjdp
154033965Sjdp/* Add a string (and null pad) to one of the string tables.  */
154133965Sjdp
154233965Sjdpstatic symint_t
1543130561Sobrienadd_string (varray_t *vp,			/* string obstack */
1544130561Sobrien	    struct hash_control *hash_tbl,	/* ptr to hash table */
1545130561Sobrien	    const char *str,			/* string */
1546130561Sobrien	    shash_t **ret_hash			/* return hash pointer */)
154733965Sjdp{
154833965Sjdp  register unsigned long len = strlen (str);
154933965Sjdp  register shash_t *hash_ptr;
155033965Sjdp
155133965Sjdp  if (len >= PAGE_USIZE)
155289857Sobrien    as_fatal (_("string too big (%lu bytes)"), len);
155333965Sjdp
155433965Sjdp  hash_ptr = (shash_t *) hash_find (hash_tbl, str);
155533965Sjdp  if (hash_ptr == (shash_t *) NULL)
155633965Sjdp    {
155733965Sjdp      register const char *err;
155833965Sjdp
155933965Sjdp      if (vp->objects_last_page + len >= PAGE_USIZE)
156077298Sobrien	{
156177298Sobrien	  vp->num_allocated =
156277298Sobrien	    ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
156377298Sobrien	  add_varray_page (vp);
156477298Sobrien	}
156533965Sjdp
156633965Sjdp      hash_ptr = allocate_shash ();
156733965Sjdp      hash_ptr->indx = vp->num_allocated;
156833965Sjdp
156933965Sjdp      hash_ptr->string = &vp->last->datum->byte[vp->objects_last_page];
157033965Sjdp
157133965Sjdp      vp->objects_last_page += len + 1;
157233965Sjdp      vp->num_allocated += len + 1;
157333965Sjdp
157433965Sjdp      strcpy (hash_ptr->string, str);
157533965Sjdp
157633965Sjdp      err = hash_insert (hash_tbl, str, (char *) hash_ptr);
157733965Sjdp      if (err)
157889857Sobrien	as_fatal (_("inserting \"%s\" into string hash table: %s"),
157933965Sjdp		  str, err);
158033965Sjdp    }
158133965Sjdp
158233965Sjdp  if (ret_hash != (shash_t **) NULL)
158333965Sjdp    *ret_hash = hash_ptr;
158433965Sjdp
158533965Sjdp  return hash_ptr->indx;
158633965Sjdp}
158733965Sjdp
158833965Sjdp/* Add debugging information for a symbol.  */
158933965Sjdp
159033965Sjdpstatic localsym_t *
1591130561Sobrienadd_ecoff_symbol (const char *str,	/* symbol name */
1592130561Sobrien		  st_t type,		/* symbol type */
1593130561Sobrien		  sc_t storage,		/* storage class */
1594130561Sobrien		  symbolS *sym_value,	/* associated symbol.  */
1595130561Sobrien		  bfd_vma addend,	/* addend to sym_value.  */
1596130561Sobrien		  symint_t value,	/* value of symbol */
1597130561Sobrien		  symint_t indx		/* index to local/aux. syms */)
159833965Sjdp{
159933965Sjdp  localsym_t *psym;
160033965Sjdp  register scope_t *pscope;
160133965Sjdp  register thead_t *ptag_head;
160233965Sjdp  register tag_t *ptag;
160333965Sjdp  register tag_t *ptag_next;
160433965Sjdp  register varray_t *vp;
160533965Sjdp  register int scope_delta = 0;
160633965Sjdp  shash_t *hash_ptr = (shash_t *) NULL;
160733965Sjdp
160833965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
160960484Sobrien    as_fatal (_("no current file pointer"));
161033965Sjdp
161133965Sjdp  vp = &cur_file_ptr->symbols;
161233965Sjdp
161377298Sobrien  if (vp->objects_last_page == vp->objects_per_page)
161433965Sjdp    add_varray_page (vp);
161533965Sjdp
161677298Sobrien  psym = &vp->last->datum->sym[vp->objects_last_page++];
161733965Sjdp
161833965Sjdp  if (str == (const char *) NULL && sym_value != (symbolS *) NULL)
161933965Sjdp    psym->name = S_GET_NAME (sym_value);
162033965Sjdp  else
162133965Sjdp    psym->name = str;
162233965Sjdp  psym->as_sym = sym_value;
162333965Sjdp  if (sym_value != (symbolS *) NULL)
162460484Sobrien    symbol_get_obj (sym_value)->ecoff_symbol = psym;
162533965Sjdp  psym->addend = addend;
162633965Sjdp  psym->file_ptr = cur_file_ptr;
162733965Sjdp  psym->proc_ptr = cur_proc_ptr;
162833965Sjdp  psym->begin_ptr = (localsym_t *) NULL;
162933965Sjdp  psym->index_ptr = (aux_t *) NULL;
163033965Sjdp  psym->forward_ref = (forward_t *) NULL;
163133965Sjdp  psym->sym_index = -1;
163233965Sjdp  memset (&psym->ecoff_sym, 0, sizeof (EXTR));
163333965Sjdp  psym->ecoff_sym.asym.value = value;
163433965Sjdp  psym->ecoff_sym.asym.st = (unsigned) type;
163533965Sjdp  psym->ecoff_sym.asym.sc = (unsigned) storage;
163633965Sjdp  psym->ecoff_sym.asym.index = indx;
163733965Sjdp
163833965Sjdp  /* If there is an associated symbol, we wait until the end of the
163933965Sjdp     assembly before deciding where to put the name (it may be just an
164033965Sjdp     external symbol).  Otherwise, this is just a debugging symbol and
164133965Sjdp     the name should go with the current file.  */
164233965Sjdp  if (sym_value == (symbolS *) NULL)
164333965Sjdp    psym->ecoff_sym.asym.iss = ((str == (const char *) NULL)
164433965Sjdp				? 0
164533965Sjdp				: add_string (&cur_file_ptr->strings,
164633965Sjdp					      cur_file_ptr->str_hash,
164733965Sjdp					      str,
164833965Sjdp					      &hash_ptr));
164933965Sjdp
165033965Sjdp  ++vp->num_allocated;
165133965Sjdp
165233965Sjdp  if (ECOFF_IS_STAB (&psym->ecoff_sym.asym))
165333965Sjdp    return psym;
165433965Sjdp
165533965Sjdp  /* Save the symbol within the hash table if this is a static
165633965Sjdp     item, and it has a name.  */
165733965Sjdp  if (hash_ptr != (shash_t *) NULL
165833965Sjdp      && (type == st_Global || type == st_Static || type == st_Label
165933965Sjdp	  || type == st_Proc || type == st_StaticProc))
166033965Sjdp    hash_ptr->sym_ptr = psym;
166133965Sjdp
166233965Sjdp  /* push or pop a scope if appropriate.  */
166333965Sjdp  switch (type)
166433965Sjdp    {
166533965Sjdp    default:
166633965Sjdp      break;
166733965Sjdp
166833965Sjdp    case st_File:			/* beginning of file */
166933965Sjdp    case st_Proc:			/* procedure */
167033965Sjdp    case st_StaticProc:			/* static procedure */
167133965Sjdp    case st_Block:			/* begin scope */
167233965Sjdp      pscope = allocate_scope ();
167333965Sjdp      pscope->prev = cur_file_ptr->cur_scope;
167433965Sjdp      pscope->lsym = psym;
167533965Sjdp      pscope->type = type;
167633965Sjdp      cur_file_ptr->cur_scope = pscope;
167733965Sjdp
167833965Sjdp      if (type != st_File)
167933965Sjdp	scope_delta = 1;
168033965Sjdp
168133965Sjdp      /* For every block type except file, struct, union, or
168277298Sobrien         enumeration blocks, push a level on the tag stack.  We omit
168377298Sobrien         file types, so that tags can span file boundaries.  */
168433965Sjdp      if (type != st_File && storage != sc_Info)
168533965Sjdp	{
168633965Sjdp	  ptag_head = allocate_thead ();
168733965Sjdp	  ptag_head->first_tag = 0;
168833965Sjdp	  ptag_head->prev = cur_tag_head;
168933965Sjdp	  cur_tag_head = ptag_head;
169033965Sjdp	}
169133965Sjdp      break;
169233965Sjdp
169333965Sjdp    case st_End:
169433965Sjdp      pscope = cur_file_ptr->cur_scope;
169533965Sjdp      if (pscope == (scope_t *) NULL)
169660484Sobrien	as_fatal (_("too many st_End's"));
169733965Sjdp      else
169833965Sjdp	{
169933965Sjdp	  st_t begin_type = (st_t) pscope->lsym->ecoff_sym.asym.st;
170033965Sjdp
170133965Sjdp	  psym->begin_ptr = pscope->lsym;
170233965Sjdp
170333965Sjdp	  if (begin_type != st_File)
170433965Sjdp	    scope_delta = -1;
170533965Sjdp
170633965Sjdp	  /* Except for file, structure, union, or enumeration end
170733965Sjdp	     blocks remove all tags created within this scope.  */
170833965Sjdp	  if (begin_type != st_File && storage != sc_Info)
170933965Sjdp	    {
171033965Sjdp	      ptag_head = cur_tag_head;
171133965Sjdp	      cur_tag_head = ptag_head->prev;
171233965Sjdp
171333965Sjdp	      for (ptag = ptag_head->first_tag;
171433965Sjdp		   ptag != (tag_t *) NULL;
171533965Sjdp		   ptag = ptag_next)
171633965Sjdp		{
171733965Sjdp		  if (ptag->forward_ref != (forward_t *) NULL)
171833965Sjdp		    add_unknown_tag (ptag);
171933965Sjdp
172033965Sjdp		  ptag_next = ptag->same_block;
172133965Sjdp		  ptag->hash_ptr->tag_ptr = ptag->same_name;
172233965Sjdp		  free_tag (ptag);
172333965Sjdp		}
172433965Sjdp
172533965Sjdp	      free_thead (ptag_head);
172633965Sjdp	    }
172733965Sjdp
172833965Sjdp	  cur_file_ptr->cur_scope = pscope->prev;
172933965Sjdp
173033965Sjdp	  /* block begin gets next sym #.  This is set when we know
173133965Sjdp	     the symbol index value.  */
173233965Sjdp
173333965Sjdp	  /* Functions push two or more aux words as follows:
173433965Sjdp	     1st word: index+1 of the end symbol (filled in later).
173533965Sjdp	     2nd word: type of the function (plus any aux words needed).
173633965Sjdp	     Also, tie the external pointer back to the function begin symbol.  */
173733965Sjdp	  if (begin_type != st_File && begin_type != st_Block)
173833965Sjdp	    {
173933965Sjdp	      symint_t ty;
174033965Sjdp	      varray_t *svp = &cur_file_ptr->aux_syms;
174133965Sjdp
174233965Sjdp	      pscope->lsym->ecoff_sym.asym.index = add_aux_sym_symint (0);
174333965Sjdp	      pscope->lsym->index_ptr =
174433965Sjdp		&svp->last->datum->aux[svp->objects_last_page - 1];
174533965Sjdp	      ty = add_aux_sym_tir (&last_func_type_info,
174633965Sjdp				    hash_no,
174733965Sjdp				    &cur_file_ptr->thash_head[0]);
174833965Sjdp
174933965Sjdp/* This seems to be unnecessary.  I'm not even sure what it is
175033965Sjdp * intended to do.  It's from mips-tfile.
175133965Sjdp *	      if (last_func_sym_value != (symbolS *) NULL)
175233965Sjdp *		{
175333965Sjdp *		  last_func_sym_value->ifd = cur_file_ptr->file_index;
175433965Sjdp *		  last_func_sym_value->index = ty;
175533965Sjdp *		}
175633965Sjdp */
175733965Sjdp	    }
175833965Sjdp
175933965Sjdp	  free_scope (pscope);
176033965Sjdp	}
176133965Sjdp    }
176233965Sjdp
176333965Sjdp  cur_file_ptr->nested_scopes += scope_delta;
176433965Sjdp
176533965Sjdp#ifdef ECOFF_DEBUG
176633965Sjdp  if (debug && type != st_File
176733965Sjdp      && (debug > 2 || type == st_Block || type == st_End
176833965Sjdp	  || type == st_Proc || type == st_StaticProc))
176933965Sjdp    {
177033965Sjdp      char *sc_str = sc_to_string (storage);
177133965Sjdp      char *st_str = st_to_string (type);
177233965Sjdp      int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
177333965Sjdp
177433965Sjdp      fprintf (stderr,
177533965Sjdp	       "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
177633965Sjdp	       value, depth, sc_str);
177733965Sjdp
177833965Sjdp      if (str_start && str_end_p1 - str_start > 0)
177977298Sobrien	fprintf (stderr, " st= %-11s name= %.*s\n",
178077298Sobrien		 st_str, str_end_p1 - str_start, str_start);
178133965Sjdp      else
178233965Sjdp	{
178333965Sjdp	  unsigned long len = strlen (st_str);
178477298Sobrien	  fprintf (stderr, " st= %.*s\n", len - 1, st_str);
178533965Sjdp	}
178633965Sjdp    }
178733965Sjdp#endif
178833965Sjdp
178933965Sjdp  return psym;
179033965Sjdp}
179133965Sjdp
179233965Sjdp/* Add an auxiliary symbol (passing a symint).  This is actually used
179333965Sjdp   for integral aux types, not just symints.  */
179433965Sjdp
179533965Sjdpstatic symint_t
1796130561Sobrienadd_aux_sym_symint (symint_t aux_word /* auxiliary information word */)
179733965Sjdp{
179833965Sjdp  register varray_t *vp;
179933965Sjdp  register aux_t *aux_ptr;
180033965Sjdp
180133965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
180260484Sobrien    as_fatal (_("no current file pointer"));
180333965Sjdp
180433965Sjdp  vp = &cur_file_ptr->aux_syms;
180533965Sjdp
180633965Sjdp  if (vp->objects_last_page == vp->objects_per_page)
180733965Sjdp    add_varray_page (vp);
180833965Sjdp
180933965Sjdp  aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
181033965Sjdp  aux_ptr->type = aux_isym;
181133965Sjdp  aux_ptr->data.isym = aux_word;
181233965Sjdp
181333965Sjdp  return vp->num_allocated++;
181433965Sjdp}
181533965Sjdp
181633965Sjdp/* Add an auxiliary symbol (passing a file/symbol index combo).  */
181733965Sjdp
181833965Sjdpstatic symint_t
1819130561Sobrienadd_aux_sym_rndx (int file_index, symint_t sym_index)
182033965Sjdp{
182133965Sjdp  register varray_t *vp;
182233965Sjdp  register aux_t *aux_ptr;
182333965Sjdp
182433965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
182560484Sobrien    as_fatal (_("no current file pointer"));
182633965Sjdp
182733965Sjdp  vp = &cur_file_ptr->aux_syms;
182833965Sjdp
182933965Sjdp  if (vp->objects_last_page == vp->objects_per_page)
183033965Sjdp    add_varray_page (vp);
183133965Sjdp
183233965Sjdp  aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
183333965Sjdp  aux_ptr->type = aux_rndx;
183433965Sjdp  aux_ptr->data.rndx.rfd   = file_index;
183533965Sjdp  aux_ptr->data.rndx.index = sym_index;
183633965Sjdp
183733965Sjdp  return vp->num_allocated++;
183833965Sjdp}
183933965Sjdp
184033965Sjdp/* Add an auxiliary symbol (passing the basic type and possibly
184133965Sjdp   type qualifiers).  */
184233965Sjdp
184333965Sjdpstatic symint_t
1844130561Sobrienadd_aux_sym_tir (type_info_t *t,	/* current type information */
1845130561Sobrien		 hash_state_t state,	/* whether to hash type or not */
1846130561Sobrien		 thash_t **hash_tbl	/* pointer to hash table to use */)
184733965Sjdp{
184833965Sjdp  register varray_t *vp;
184933965Sjdp  register aux_t *aux_ptr;
185033965Sjdp  static AUXU init_aux;
185133965Sjdp  symint_t ret;
185233965Sjdp  int i;
185333965Sjdp  AUXU aux;
185433965Sjdp
185533965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
185660484Sobrien    as_fatal (_("no current file pointer"));
185733965Sjdp
185833965Sjdp  vp = &cur_file_ptr->aux_syms;
185933965Sjdp
186033965Sjdp  aux = init_aux;
186133965Sjdp  aux.ti.bt = (int) t->basic_type;
186233965Sjdp  aux.ti.continued = 0;
186333965Sjdp  aux.ti.fBitfield = t->bitfield;
186433965Sjdp
186533965Sjdp  aux.ti.tq0 = (int) t->type_qualifiers[0];
186633965Sjdp  aux.ti.tq1 = (int) t->type_qualifiers[1];
186733965Sjdp  aux.ti.tq2 = (int) t->type_qualifiers[2];
186833965Sjdp  aux.ti.tq3 = (int) t->type_qualifiers[3];
186933965Sjdp  aux.ti.tq4 = (int) t->type_qualifiers[4];
187033965Sjdp  aux.ti.tq5 = (int) t->type_qualifiers[5];
187133965Sjdp
187233965Sjdp  /* For anything that adds additional information, we must not hash,
187377298Sobrien     so check here, and reset our state.  */
187433965Sjdp
187533965Sjdp  if (state != hash_no
187633965Sjdp      && (t->type_qualifiers[0] == tq_Array
187733965Sjdp	  || t->type_qualifiers[1] == tq_Array
187833965Sjdp	  || t->type_qualifiers[2] == tq_Array
187933965Sjdp	  || t->type_qualifiers[3] == tq_Array
188033965Sjdp	  || t->type_qualifiers[4] == tq_Array
188133965Sjdp	  || t->type_qualifiers[5] == tq_Array
188233965Sjdp	  || t->basic_type == bt_Struct
188333965Sjdp	  || t->basic_type == bt_Union
188433965Sjdp	  || t->basic_type == bt_Enum
188533965Sjdp	  || t->bitfield
188633965Sjdp	  || t->num_dims > 0))
188733965Sjdp    state = hash_no;
188833965Sjdp
188933965Sjdp  /* See if we can hash this type, and save some space, but some types
189033965Sjdp     can't be hashed (because they contain arrays or continuations),
189133965Sjdp     and others can be put into the hash list, but cannot use existing
189233965Sjdp     types because other aux entries precede this one.  */
189333965Sjdp
189433965Sjdp  if (state != hash_no)
189533965Sjdp    {
189633965Sjdp      register thash_t *hash_ptr;
189733965Sjdp      register symint_t hi;
189833965Sjdp
189933965Sjdp      hi = aux.isym & ((1 << HASHBITS) - 1);
190033965Sjdp      hi %= THASH_SIZE;
190133965Sjdp
190233965Sjdp      for (hash_ptr = hash_tbl[hi];
190333965Sjdp	   hash_ptr != (thash_t *)0;
190433965Sjdp	   hash_ptr = hash_ptr->next)
190533965Sjdp	{
190633965Sjdp	  if (aux.isym == hash_ptr->type.isym)
190733965Sjdp	    break;
190833965Sjdp	}
190933965Sjdp
191033965Sjdp      if (hash_ptr != (thash_t *) NULL && state == hash_yes)
191133965Sjdp	return hash_ptr->indx;
191233965Sjdp
191333965Sjdp      if (hash_ptr == (thash_t *) NULL)
191433965Sjdp	{
191533965Sjdp	  hash_ptr = allocate_thash ();
191633965Sjdp	  hash_ptr->next = hash_tbl[hi];
191733965Sjdp	  hash_ptr->type = aux;
191833965Sjdp	  hash_ptr->indx = vp->num_allocated;
191933965Sjdp	  hash_tbl[hi] = hash_ptr;
192033965Sjdp	}
192133965Sjdp    }
192233965Sjdp
192377298Sobrien  /* Everything is set up, add the aux symbol.  */
192433965Sjdp  if (vp->objects_last_page == vp->objects_per_page)
192533965Sjdp    add_varray_page (vp);
192633965Sjdp
192777298Sobrien  aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
192833965Sjdp  aux_ptr->type = aux_tir;
192933965Sjdp  aux_ptr->data = aux;
193033965Sjdp
193133965Sjdp  ret = vp->num_allocated++;
193233965Sjdp
193333965Sjdp  /* Add bitfield length if it exists.
193433965Sjdp
193533965Sjdp     NOTE:  Mips documentation claims bitfield goes at the end of the
193633965Sjdp     AUX record, but the DECstation compiler emits it here.
193733965Sjdp     (This would only make a difference for enum bitfields.)
193833965Sjdp
193933965Sjdp     Also note:  We use the last size given since gcc may emit 2
194033965Sjdp     for an enum bitfield.  */
194133965Sjdp
194233965Sjdp  if (t->bitfield)
194377298Sobrien    (void) add_aux_sym_symint ((symint_t) t->sizes[t->num_sizes - 1]);
194433965Sjdp
194533965Sjdp  /* Add tag information if needed.  Structure, union, and enum
194633965Sjdp     references add 2 aux symbols: a [file index, symbol index]
194733965Sjdp     pointer to the structure type, and the current file index.  */
194833965Sjdp
194933965Sjdp  if (t->basic_type == bt_Struct
195033965Sjdp      || t->basic_type == bt_Union
195133965Sjdp      || t->basic_type == bt_Enum)
195233965Sjdp    {
195333965Sjdp      register symint_t file_index = t->tag_ptr->ifd;
195477298Sobrien      register localsym_t *sym = t->tag_ptr->sym;
195533965Sjdp      register forward_t *forward_ref = allocate_forward ();
195633965Sjdp
195733965Sjdp      if (sym != (localsym_t *) NULL)
195833965Sjdp	{
195933965Sjdp	  forward_ref->next = sym->forward_ref;
196033965Sjdp	  sym->forward_ref = forward_ref;
196133965Sjdp	}
196233965Sjdp      else
196333965Sjdp	{
196433965Sjdp	  forward_ref->next = t->tag_ptr->forward_ref;
196533965Sjdp	  t->tag_ptr->forward_ref = forward_ref;
196633965Sjdp	}
196733965Sjdp
196833965Sjdp      (void) add_aux_sym_rndx (ST_RFDESCAPE, indexNil);
196933965Sjdp      forward_ref->index_ptr
197077298Sobrien	= &vp->last->datum->aux[vp->objects_last_page - 1];
197133965Sjdp
197233965Sjdp      (void) add_aux_sym_symint (file_index);
197333965Sjdp      forward_ref->ifd_ptr
197477298Sobrien	= &vp->last->datum->aux[vp->objects_last_page - 1];
197533965Sjdp    }
197633965Sjdp
197733965Sjdp  /* Add information about array bounds if they exist.  */
197833965Sjdp  for (i = 0; i < t->num_dims; i++)
197933965Sjdp    {
198033965Sjdp      (void) add_aux_sym_rndx (ST_RFDESCAPE,
198133965Sjdp			       cur_file_ptr->int_type);
198233965Sjdp
198333965Sjdp      (void) add_aux_sym_symint (cur_file_ptr->file_index);	/* file index*/
198433965Sjdp      (void) add_aux_sym_symint ((symint_t) 0);			/* low bound */
198533965Sjdp      (void) add_aux_sym_symint (t->dimensions[i] - 1);		/* high bound*/
198633965Sjdp      (void) add_aux_sym_symint ((t->dimensions[i] == 0)	/* stride */
198733965Sjdp				 ? 0
198833965Sjdp				 : (t->sizes[i] * 8) / t->dimensions[i]);
198933965Sjdp    };
199033965Sjdp
199133965Sjdp  /* NOTE:  Mips documentation claims that the bitfield width goes here.
199277298Sobrien     But it needs to be emitted earlier.  */
199333965Sjdp
199433965Sjdp  return ret;
199533965Sjdp}
199633965Sjdp
199733965Sjdp/* Add a tag to the tag table (unless it already exists).  */
199833965Sjdp
199933965Sjdpstatic tag_t *
2000130561Sobrienget_tag (const char *tag,	/* tag name */
2001130561Sobrien	 localsym_t *sym,	/* tag start block */
2002130561Sobrien	 bt_t basic_type	/* bt_Struct, bt_Union, or bt_Enum */)
200333965Sjdp{
200433965Sjdp  shash_t *hash_ptr;
200533965Sjdp  const char *err;
200633965Sjdp  tag_t *tag_ptr;
200733965Sjdp
200833965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
200960484Sobrien    as_fatal (_("no current file pointer"));
201033965Sjdp
201133965Sjdp  hash_ptr = (shash_t *) hash_find (tag_hash, tag);
201233965Sjdp
201333965Sjdp  if (hash_ptr != (shash_t *) NULL
201433965Sjdp      && hash_ptr->tag_ptr != (tag_t *) NULL)
201577298Sobrien    {
201677298Sobrien      tag_ptr = hash_ptr->tag_ptr;
201777298Sobrien      if (sym != (localsym_t *) NULL)
201877298Sobrien	{
201977298Sobrien	  tag_ptr->basic_type = basic_type;
202077298Sobrien	  tag_ptr->ifd        = cur_file_ptr->file_index;
202177298Sobrien	  tag_ptr->sym        = sym;
202277298Sobrien	}
202377298Sobrien      return tag_ptr;
202477298Sobrien    }
202533965Sjdp
202633965Sjdp  if (hash_ptr == (shash_t *) NULL)
202733965Sjdp    {
202833965Sjdp      char *perm;
202933965Sjdp
2030104834Sobrien      perm = xstrdup (tag);
203133965Sjdp      hash_ptr = allocate_shash ();
203233965Sjdp      err = hash_insert (tag_hash, perm, (char *) hash_ptr);
203333965Sjdp      if (err)
203489857Sobrien	as_fatal (_("inserting \"%s\" into tag hash table: %s"),
203533965Sjdp		  tag, err);
203633965Sjdp      hash_ptr->string = perm;
203733965Sjdp    }
203833965Sjdp
203933965Sjdp  tag_ptr = allocate_tag ();
204033965Sjdp  tag_ptr->forward_ref	= (forward_t *) NULL;
204133965Sjdp  tag_ptr->hash_ptr	= hash_ptr;
204233965Sjdp  tag_ptr->same_name	= hash_ptr->tag_ptr;
204333965Sjdp  tag_ptr->basic_type	= basic_type;
204433965Sjdp  tag_ptr->sym		= sym;
204533965Sjdp  tag_ptr->ifd		= ((sym == (localsym_t *) NULL)
204633965Sjdp			   ? (symint_t) -1
204733965Sjdp			   : cur_file_ptr->file_index);
204833965Sjdp  tag_ptr->same_block	= cur_tag_head->first_tag;
204933965Sjdp
205033965Sjdp  cur_tag_head->first_tag = tag_ptr;
205133965Sjdp  hash_ptr->tag_ptr	  = tag_ptr;
205233965Sjdp
205333965Sjdp  return tag_ptr;
205433965Sjdp}
205533965Sjdp
205633965Sjdp/* Add an unknown {struct, union, enum} tag.  */
205733965Sjdp
205833965Sjdpstatic void
2059130561Sobrienadd_unknown_tag (tag_t *ptag /* pointer to tag information */)
206033965Sjdp{
206133965Sjdp  shash_t *hash_ptr	= ptag->hash_ptr;
206233965Sjdp  char *name		= hash_ptr->string;
206333965Sjdp  localsym_t *sym;
206433965Sjdp  forward_t **pf;
206533965Sjdp
206633965Sjdp#ifdef ECOFF_DEBUG
206733965Sjdp  if (debug > 1)
206833965Sjdp    {
206977298Sobrien      char *agg_type = "{unknown aggregate type}";
207033965Sjdp      switch (ptag->basic_type)
207133965Sjdp	{
207233965Sjdp	case bt_Struct:	agg_type = "struct";	break;
207333965Sjdp	case bt_Union:	agg_type = "union";	break;
207433965Sjdp	case bt_Enum:	agg_type = "enum";	break;
207533965Sjdp	default:				break;
207633965Sjdp	}
207733965Sjdp
207833965Sjdp      fprintf (stderr, "unknown %s %.*s found\n", agg_type,
207933965Sjdp	       hash_ptr->len, name_start);
208033965Sjdp    }
208133965Sjdp#endif
208233965Sjdp
208333965Sjdp  sym = add_ecoff_symbol (name,
208433965Sjdp			  st_Block,
208533965Sjdp			  sc_Info,
208633965Sjdp			  (symbolS *) NULL,
208733965Sjdp			  (bfd_vma) 0,
208833965Sjdp			  (symint_t) 0,
208933965Sjdp			  (symint_t) 0);
209033965Sjdp
209133965Sjdp  (void) add_ecoff_symbol (name,
209233965Sjdp			   st_End,
209333965Sjdp			   sc_Info,
209433965Sjdp			   (symbolS *) NULL,
209533965Sjdp			   (bfd_vma) 0,
209633965Sjdp			   (symint_t) 0,
209733965Sjdp			   (symint_t) 0);
209833965Sjdp
209933965Sjdp  for (pf = &sym->forward_ref; *pf != (forward_t *) NULL; pf = &(*pf)->next)
210033965Sjdp    ;
210133965Sjdp  *pf = ptag->forward_ref;
210233965Sjdp}
210333965Sjdp
210433965Sjdp/* Add a procedure to the current file's list of procedures, and record
210533965Sjdp   this is the current procedure.  */
210633965Sjdp
210733965Sjdpstatic void
2108130561Sobrienadd_procedure (char *func /* func name */)
210933965Sjdp{
211033965Sjdp  register varray_t *vp;
211133965Sjdp  register proc_t *new_proc_ptr;
211233965Sjdp  symbolS *sym;
211333965Sjdp
211433965Sjdp#ifdef ECOFF_DEBUG
211533965Sjdp  if (debug)
211633965Sjdp    fputc ('\n', stderr);
211733965Sjdp#endif
211833965Sjdp
211933965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
212060484Sobrien    as_fatal (_("no current file pointer"));
212133965Sjdp
212233965Sjdp  vp = &cur_file_ptr->procs;
212333965Sjdp
212433965Sjdp  if (vp->objects_last_page == vp->objects_per_page)
212533965Sjdp    add_varray_page (vp);
212633965Sjdp
212733965Sjdp  cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[vp->objects_last_page++];
212833965Sjdp
212933965Sjdp  if (first_proc_ptr == (proc_t *) NULL)
213033965Sjdp    first_proc_ptr = new_proc_ptr;
213133965Sjdp
213233965Sjdp  vp->num_allocated++;
213333965Sjdp
213433965Sjdp  new_proc_ptr->pdr.isym = -1;
213533965Sjdp  new_proc_ptr->pdr.iline = -1;
213633965Sjdp  new_proc_ptr->pdr.lnLow = -1;
213733965Sjdp  new_proc_ptr->pdr.lnHigh = -1;
213833965Sjdp
213933965Sjdp  /* Set the BSF_FUNCTION flag for the symbol.  */
214033965Sjdp  sym = symbol_find_or_make (func);
214160484Sobrien  symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
214233965Sjdp
214333965Sjdp  /* Push the start of the function.  */
214433965Sjdp  new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
214533965Sjdp					sym, (bfd_vma) 0, (symint_t) 0,
214633965Sjdp					(symint_t) 0);
214733965Sjdp
214833965Sjdp  ++proc_cnt;
214933965Sjdp
215033965Sjdp  /* Fill in the linenos preceding the .ent, if any.  */
215133965Sjdp  if (noproc_lineno != (lineno_list_t *) NULL)
215233965Sjdp    {
215333965Sjdp      lineno_list_t *l;
215433965Sjdp
215533965Sjdp      for (l = noproc_lineno; l != (lineno_list_t *) NULL; l = l->next)
215633965Sjdp	l->proc = new_proc_ptr;
215733965Sjdp      *last_lineno_ptr = noproc_lineno;
215833965Sjdp      while (*last_lineno_ptr != NULL)
215933965Sjdp	{
216033965Sjdp	  last_lineno = *last_lineno_ptr;
216133965Sjdp	  last_lineno_ptr = &last_lineno->next;
216233965Sjdp	}
216333965Sjdp      noproc_lineno = (lineno_list_t *) NULL;
216433965Sjdp    }
216533965Sjdp}
216660484Sobrien
216760484SobriensymbolS *
2168130561Sobrienecoff_get_cur_proc_sym (void)
216960484Sobrien{
217060484Sobrien  return (cur_proc_ptr ? cur_proc_ptr->sym->as_sym : NULL);
217160484Sobrien}
217233965Sjdp
217333965Sjdp/* Add a new filename, and set up all of the file relative
217433965Sjdp   virtual arrays (strings, symbols, aux syms, etc.).  Record
217533965Sjdp   where the current file structure lives.  */
217633965Sjdp
217733965Sjdpstatic void
2178130561Sobrienadd_file (const char *file_name, int indx ATTRIBUTE_UNUSED, int fake)
217933965Sjdp{
218033965Sjdp  register int first_ch;
218133965Sjdp  register efdr_t *fil_ptr;
218233965Sjdp
218333965Sjdp#ifdef ECOFF_DEBUG
218433965Sjdp  if (debug)
218533965Sjdp    fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
218633965Sjdp#endif
218733965Sjdp
218833965Sjdp  /* If the file name is NULL, then no .file symbol appeared, and we
218933965Sjdp     want to use the actual file name.  */
219033965Sjdp  if (file_name == (const char *) NULL)
219133965Sjdp    {
219233965Sjdp      char *file;
219333965Sjdp
219433965Sjdp      if (first_file != (efdr_t *) NULL)
219560484Sobrien	as_fatal (_("fake .file after real one"));
219633965Sjdp      as_where (&file, (unsigned int *) NULL);
219733965Sjdp      file_name = (const char *) file;
219833965Sjdp
219938889Sjdp      /* Automatically generate ECOFF debugging information, since I
220038889Sjdp         think that's what other ECOFF assemblers do.  We don't do
220138889Sjdp         this if we see a .file directive with a string, since that
220238889Sjdp         implies that some sort of debugging information is being
220338889Sjdp         provided.  */
220477298Sobrien      if (! symbol_table_frozen && debug_type == DEBUG_UNSPECIFIED)
220538889Sjdp	debug_type = DEBUG_ECOFF;
220633965Sjdp    }
220780016Sobrien  else if (debug_type == DEBUG_UNSPECIFIED)
220877298Sobrien    debug_type = DEBUG_NONE;
220933965Sjdp
221033965Sjdp#ifndef NO_LISTING
221133965Sjdp  if (listing)
221233965Sjdp    listing_source_file (file_name);
221333965Sjdp#endif
221433965Sjdp
221533965Sjdp  current_stabs_filename = file_name;
221633965Sjdp
221733965Sjdp  /* If we're creating stabs, then we don't actually make a new FDR.
221833965Sjdp     Instead, we just create a stabs symbol.  */
221933965Sjdp  if (stabs_seen)
222033965Sjdp    {
222133965Sjdp      (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil,
222233965Sjdp			       symbol_new ("L0\001", now_seg,
222333965Sjdp					   (valueT) frag_now_fix (),
222433965Sjdp					   frag_now),
222533965Sjdp			       (bfd_vma) 0, 0, ECOFF_MARK_STAB (N_SOL));
222633965Sjdp      return;
222733965Sjdp    }
222833965Sjdp
222933965Sjdp  first_ch = *file_name;
223033965Sjdp
223133965Sjdp  /* FIXME: We can't safely merge files which have line number
223233965Sjdp     information (fMerge will be zero in this case).  Otherwise, we
223333965Sjdp     get incorrect line number debugging info.  See for instance
223433965Sjdp     ecoff_build_lineno, which will end up setting all file->fdr.*
223533965Sjdp     fields multiple times, resulting in incorrect debug info.  In
223633965Sjdp     order to make this work right, all line number and symbol info
223733965Sjdp     for the same source file has to be adjacent in the object file,
223833965Sjdp     so that a single file descriptor can be used to point to them.
223933965Sjdp     This would require maintaining file specific lists of line
224033965Sjdp     numbers and symbols for each file, so that they can be merged
224133965Sjdp     together (or output together) when two .file pseudo-ops are
224233965Sjdp     merged into one file descriptor.  */
224333965Sjdp
224433965Sjdp  /* See if the file has already been created.  */
224533965Sjdp  for (fil_ptr = first_file;
224633965Sjdp       fil_ptr != (efdr_t *) NULL;
224733965Sjdp       fil_ptr = fil_ptr->next_file)
224833965Sjdp    {
224933965Sjdp      if (first_ch == fil_ptr->name[0]
225033965Sjdp	  && strcmp (file_name, fil_ptr->name) == 0
225133965Sjdp	  && fil_ptr->fdr.fMerge)
225233965Sjdp	{
225333965Sjdp	  cur_file_ptr = fil_ptr;
225433965Sjdp	  if (! fake)
225533965Sjdp	    cur_file_ptr->fake = 0;
225633965Sjdp	  break;
225733965Sjdp	}
225833965Sjdp    }
225933965Sjdp
226077298Sobrien  /* If this is a new file, create it.  */
226133965Sjdp  if (fil_ptr == (efdr_t *) NULL)
226233965Sjdp    {
226333965Sjdp      if (file_desc.objects_last_page == file_desc.objects_per_page)
226433965Sjdp	add_varray_page (&file_desc);
226533965Sjdp
226633965Sjdp      fil_ptr = cur_file_ptr =
226733965Sjdp	&file_desc.last->datum->file[file_desc.objects_last_page++];
226833965Sjdp      *fil_ptr = init_file;
226933965Sjdp
227033965Sjdp      fil_ptr->file_index = current_file_idx++;
227133965Sjdp      ++file_desc.num_allocated;
227233965Sjdp
227333965Sjdp      fil_ptr->fake = fake;
227433965Sjdp
227533965Sjdp      /* Allocate the string hash table.  */
227633965Sjdp      fil_ptr->str_hash = hash_new ();
227733965Sjdp
227833965Sjdp      /* Make sure 0 byte in string table is null  */
227933965Sjdp      add_string (&fil_ptr->strings,
228033965Sjdp		  fil_ptr->str_hash,
228133965Sjdp		  "",
228233965Sjdp		  (shash_t **)0);
228333965Sjdp
228433965Sjdp      if (strlen (file_name) > PAGE_USIZE - 2)
228589857Sobrien	as_fatal (_("filename goes over one page boundary"));
228633965Sjdp
228733965Sjdp      /* Push the start of the filename. We assume that the filename
228833965Sjdp         will be stored at string offset 1.  */
228933965Sjdp      (void) add_ecoff_symbol (file_name, st_File, sc_Text,
229033965Sjdp			       (symbolS *) NULL, (bfd_vma) 0,
229133965Sjdp			       (symint_t) 0, (symint_t) 0);
229233965Sjdp      fil_ptr->fdr.rss = 1;
229333965Sjdp      fil_ptr->name = &fil_ptr->strings.last->datum->byte[1];
229433965Sjdp
229533965Sjdp      /* Update the linked list of file descriptors.  */
229633965Sjdp      *last_file_ptr = fil_ptr;
229733965Sjdp      last_file_ptr = &fil_ptr->next_file;
229833965Sjdp
229933965Sjdp      /* Add void & int types to the file (void should be first to catch
230077298Sobrien         errant 0's within the index fields).  */
230133965Sjdp      fil_ptr->void_type = add_aux_sym_tir (&void_type_info,
230233965Sjdp					    hash_yes,
230333965Sjdp					    &cur_file_ptr->thash_head[0]);
230433965Sjdp
230533965Sjdp      fil_ptr->int_type = add_aux_sym_tir (&int_type_info,
230633965Sjdp					   hash_yes,
230733965Sjdp					   &cur_file_ptr->thash_head[0]);
230833965Sjdp    }
230933965Sjdp}
231033965Sjdp
231133965Sjdp/* This function is called when the assembler notices a preprocessor
231233965Sjdp   directive switching to a new file.  This will not happen in
231333965Sjdp   compiler output, only in hand coded assembler.  */
231433965Sjdp
231533965Sjdpvoid
2316218822Sdimecoff_new_file (const char *name, int appfile ATTRIBUTE_UNUSED)
231733965Sjdp{
231833965Sjdp  if (cur_file_ptr != NULL && strcmp (cur_file_ptr->name, name) == 0)
231933965Sjdp    return;
232033965Sjdp  add_file (name, 0, 0);
232138889Sjdp
232238889Sjdp  /* This is a hand coded assembler file, so automatically turn on
232338889Sjdp     debugging information.  */
232477298Sobrien  if (debug_type == DEBUG_UNSPECIFIED)
232538889Sjdp    debug_type = DEBUG_ECOFF;
232633965Sjdp}
232733965Sjdp
232833965Sjdp#ifdef ECOFF_DEBUG
232933965Sjdp
233033965Sjdp/* Convert storage class to string.  */
233133965Sjdp
233233965Sjdpstatic char *
233377298Sobriensc_to_string (storage_class)
233433965Sjdp     sc_t storage_class;
233533965Sjdp{
233677298Sobrien  switch (storage_class)
233733965Sjdp    {
233833965Sjdp    case sc_Nil:	 return "Nil,";
233933965Sjdp    case sc_Text:	 return "Text,";
234033965Sjdp    case sc_Data:	 return "Data,";
234133965Sjdp    case sc_Bss:	 return "Bss,";
234233965Sjdp    case sc_Register:	 return "Register,";
234333965Sjdp    case sc_Abs:	 return "Abs,";
234433965Sjdp    case sc_Undefined:	 return "Undefined,";
234533965Sjdp    case sc_CdbLocal:	 return "CdbLocal,";
234633965Sjdp    case sc_Bits:	 return "Bits,";
234733965Sjdp    case sc_CdbSystem:	 return "CdbSystem,";
234833965Sjdp    case sc_RegImage:	 return "RegImage,";
234933965Sjdp    case sc_Info:	 return "Info,";
235033965Sjdp    case sc_UserStruct:	 return "UserStruct,";
235133965Sjdp    case sc_SData:	 return "SData,";
235233965Sjdp    case sc_SBss:	 return "SBss,";
235333965Sjdp    case sc_RData:	 return "RData,";
235433965Sjdp    case sc_Var:	 return "Var,";
235533965Sjdp    case sc_Common:	 return "Common,";
235633965Sjdp    case sc_SCommon:	 return "SCommon,";
235733965Sjdp    case sc_VarRegister: return "VarRegister,";
235833965Sjdp    case sc_Variant:	 return "Variant,";
235933965Sjdp    case sc_SUndefined:	 return "SUndefined,";
236033965Sjdp    case sc_Init:	 return "Init,";
236133965Sjdp    case sc_Max:	 return "Max,";
236233965Sjdp    }
236333965Sjdp
236433965Sjdp  return "???,";
236533965Sjdp}
236633965Sjdp
236733965Sjdp#endif /* DEBUG */
236833965Sjdp
236933965Sjdp#ifdef ECOFF_DEBUG
237033965Sjdp
237133965Sjdp/* Convert symbol type to string.  */
237233965Sjdp
237333965Sjdpstatic char *
237477298Sobrienst_to_string (symbol_type)
237533965Sjdp     st_t symbol_type;
237633965Sjdp{
237777298Sobrien  switch (symbol_type)
237833965Sjdp    {
237933965Sjdp    case st_Nil:	return "Nil,";
238033965Sjdp    case st_Global:	return "Global,";
238133965Sjdp    case st_Static:	return "Static,";
238233965Sjdp    case st_Param:	return "Param,";
238333965Sjdp    case st_Local:	return "Local,";
238433965Sjdp    case st_Label:	return "Label,";
238533965Sjdp    case st_Proc:	return "Proc,";
238633965Sjdp    case st_Block:	return "Block,";
238733965Sjdp    case st_End:	return "End,";
238833965Sjdp    case st_Member:	return "Member,";
238933965Sjdp    case st_Typedef:	return "Typedef,";
239033965Sjdp    case st_File:	return "File,";
239133965Sjdp    case st_RegReloc:	return "RegReloc,";
239233965Sjdp    case st_Forward:	return "Forward,";
239333965Sjdp    case st_StaticProc:	return "StaticProc,";
239433965Sjdp    case st_Constant:	return "Constant,";
239533965Sjdp    case st_Str:	return "String,";
239633965Sjdp    case st_Number:	return "Number,";
239733965Sjdp    case st_Expr:	return "Expr,";
239833965Sjdp    case st_Type:	return "Type,";
239933965Sjdp    case st_Max:	return "Max,";
240033965Sjdp    }
240133965Sjdp
240233965Sjdp  return "???,";
240333965Sjdp}
240433965Sjdp
240533965Sjdp#endif /* DEBUG */
240633965Sjdp
240733965Sjdp/* Parse .begin directives which have a label as the first argument
240833965Sjdp   which gives the location of the start of the block.  */
240933965Sjdp
241033965Sjdpvoid
2411130561Sobrienecoff_directive_begin (int ignore ATTRIBUTE_UNUSED)
241233965Sjdp{
241333965Sjdp  char *name;
241433965Sjdp  char name_end;
241533965Sjdp
241633965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
241733965Sjdp    {
241860484Sobrien      as_warn (_(".begin directive without a preceding .file directive"));
241933965Sjdp      demand_empty_rest_of_line ();
242033965Sjdp      return;
242133965Sjdp    }
242233965Sjdp
242333965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
242433965Sjdp    {
242560484Sobrien      as_warn (_(".begin directive without a preceding .ent directive"));
242633965Sjdp      demand_empty_rest_of_line ();
242733965Sjdp      return;
242833965Sjdp    }
242933965Sjdp
243033965Sjdp  name = input_line_pointer;
243133965Sjdp  name_end = get_symbol_end ();
243233965Sjdp
243333965Sjdp  (void) add_ecoff_symbol ((const char *) NULL, st_Block, sc_Text,
243433965Sjdp			   symbol_find_or_make (name),
243533965Sjdp			   (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
243633965Sjdp
243733965Sjdp  *input_line_pointer = name_end;
243833965Sjdp
243933965Sjdp  /* The line number follows, but we don't use it.  */
244033965Sjdp  (void) get_absolute_expression ();
244133965Sjdp  demand_empty_rest_of_line ();
244233965Sjdp}
244333965Sjdp
244433965Sjdp/* Parse .bend directives which have a label as the first argument
244533965Sjdp   which gives the location of the end of the block.  */
244633965Sjdp
244733965Sjdpvoid
2448130561Sobrienecoff_directive_bend (int ignore ATTRIBUTE_UNUSED)
244933965Sjdp{
245033965Sjdp  char *name;
245133965Sjdp  char name_end;
245233965Sjdp  symbolS *endsym;
245333965Sjdp
245433965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
245533965Sjdp    {
245660484Sobrien      as_warn (_(".bend directive without a preceding .file directive"));
245733965Sjdp      demand_empty_rest_of_line ();
245833965Sjdp      return;
245933965Sjdp    }
246033965Sjdp
246133965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
246233965Sjdp    {
246360484Sobrien      as_warn (_(".bend directive without a preceding .ent directive"));
246433965Sjdp      demand_empty_rest_of_line ();
246533965Sjdp      return;
246633965Sjdp    }
246733965Sjdp
246833965Sjdp  name = input_line_pointer;
246933965Sjdp  name_end = get_symbol_end ();
247033965Sjdp
247133965Sjdp  /* The value is the distance between the .bend directive and the
247233965Sjdp     corresponding symbol.  We fill in the offset when we write out
247333965Sjdp     the symbol.  */
247433965Sjdp  endsym = symbol_find (name);
247533965Sjdp  if (endsym == (symbolS *) NULL)
247660484Sobrien    as_warn (_(".bend directive names unknown symbol"));
247733965Sjdp  else
247833965Sjdp    (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym,
247933965Sjdp			     (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
248033965Sjdp
248133965Sjdp  *input_line_pointer = name_end;
248233965Sjdp
248333965Sjdp  /* The line number follows, but we don't use it.  */
248433965Sjdp  (void) get_absolute_expression ();
248533965Sjdp  demand_empty_rest_of_line ();
248633965Sjdp}
248733965Sjdp
248833965Sjdp/* COFF debugging information is provided as a series of directives
248933965Sjdp   (.def, .scl, etc.).  We build up information as we read the
249033965Sjdp   directives in the following static variables, and file it away when
249133965Sjdp   we reach the .endef directive.  */
249233965Sjdpstatic char *coff_sym_name;
249333965Sjdpstatic type_info_t coff_type;
249433965Sjdpstatic sc_t coff_storage_class;
249533965Sjdpstatic st_t coff_symbol_typ;
249633965Sjdpstatic int coff_is_function;
249733965Sjdpstatic char *coff_tag;
249833965Sjdpstatic valueT coff_value;
249933965Sjdpstatic symbolS *coff_sym_value;
250033965Sjdpstatic bfd_vma coff_sym_addend;
250133965Sjdpstatic int coff_inside_enumeration;
250233965Sjdp
250333965Sjdp/* Handle a .def directive: start defining a symbol.  */
250433965Sjdp
250533965Sjdpvoid
2506130561Sobrienecoff_directive_def (int ignore ATTRIBUTE_UNUSED)
250733965Sjdp{
250833965Sjdp  char *name;
250933965Sjdp  char name_end;
251033965Sjdp
251133965Sjdp  ecoff_debugging_seen = 1;
251233965Sjdp
251333965Sjdp  SKIP_WHITESPACE ();
251433965Sjdp
251533965Sjdp  name = input_line_pointer;
251633965Sjdp  name_end = get_symbol_end ();
251733965Sjdp
251833965Sjdp  if (coff_sym_name != (char *) NULL)
251960484Sobrien    as_warn (_(".def pseudo-op used inside of .def/.endef; ignored"));
252033965Sjdp  else if (*name == '\0')
252189857Sobrien    as_warn (_("empty symbol name in .def; ignored"));
252233965Sjdp  else
252333965Sjdp    {
252433965Sjdp      if (coff_sym_name != (char *) NULL)
252533965Sjdp	free (coff_sym_name);
252633965Sjdp      if (coff_tag != (char *) NULL)
252733965Sjdp	free (coff_tag);
2528104834Sobrien
2529104834Sobrien      coff_sym_name = xstrdup (name);
253033965Sjdp      coff_type = type_info_init;
253133965Sjdp      coff_storage_class = sc_Nil;
253233965Sjdp      coff_symbol_typ = st_Nil;
253333965Sjdp      coff_is_function = 0;
253433965Sjdp      coff_tag = (char *) NULL;
253533965Sjdp      coff_value = 0;
253633965Sjdp      coff_sym_value = (symbolS *) NULL;
253733965Sjdp      coff_sym_addend = 0;
253833965Sjdp    }
253933965Sjdp
254033965Sjdp  *input_line_pointer = name_end;
254133965Sjdp
254233965Sjdp  demand_empty_rest_of_line ();
254333965Sjdp}
254433965Sjdp
254533965Sjdp/* Handle a .dim directive, used to give dimensions for an array.  The
254633965Sjdp   arguments are comma separated numbers.  mips-tfile assumes that
254733965Sjdp   there will not be more than 6 dimensions, and gdb won't read any
254833965Sjdp   more than that anyhow, so I will also make that assumption.  */
254933965Sjdp
255033965Sjdpvoid
2551130561Sobrienecoff_directive_dim (int ignore ATTRIBUTE_UNUSED)
255233965Sjdp{
255333965Sjdp  int dimens[N_TQ];
255433965Sjdp  int i;
255533965Sjdp
255633965Sjdp  if (coff_sym_name == (char *) NULL)
255733965Sjdp    {
255860484Sobrien      as_warn (_(".dim pseudo-op used outside of .def/.endef; ignored"));
255933965Sjdp      demand_empty_rest_of_line ();
256033965Sjdp      return;
256133965Sjdp    }
256233965Sjdp
256333965Sjdp  for (i = 0; i < N_TQ; i++)
256433965Sjdp    {
256533965Sjdp      SKIP_WHITESPACE ();
256633965Sjdp      dimens[i] = get_absolute_expression ();
256733965Sjdp      if (*input_line_pointer == ',')
256833965Sjdp	++input_line_pointer;
256933965Sjdp      else
257033965Sjdp	{
257133965Sjdp	  if (*input_line_pointer != '\n'
257233965Sjdp	      && *input_line_pointer != ';')
257389857Sobrien	    as_warn (_("badly formed .dim directive"));
257433965Sjdp	  break;
257533965Sjdp	}
257633965Sjdp    }
257733965Sjdp
257833965Sjdp  if (i == N_TQ)
257933965Sjdp    --i;
258033965Sjdp
258133965Sjdp  /* The dimensions are stored away in reverse order.  */
258233965Sjdp  for (; i >= 0; i--)
258333965Sjdp    {
258433965Sjdp      if (coff_type.num_dims >= N_TQ)
258533965Sjdp	{
258689857Sobrien	  as_warn (_("too many .dim entries"));
258733965Sjdp	  break;
258833965Sjdp	}
258933965Sjdp      coff_type.dimensions[coff_type.num_dims] = dimens[i];
259033965Sjdp      ++coff_type.num_dims;
259133965Sjdp    }
259233965Sjdp
259333965Sjdp  demand_empty_rest_of_line ();
259433965Sjdp}
259533965Sjdp
259633965Sjdp/* Handle a .scl directive, which sets the COFF storage class of the
259733965Sjdp   symbol.  */
259833965Sjdp
259933965Sjdpvoid
2600130561Sobrienecoff_directive_scl (int ignore ATTRIBUTE_UNUSED)
260133965Sjdp{
260233965Sjdp  long val;
260333965Sjdp
260433965Sjdp  if (coff_sym_name == (char *) NULL)
260533965Sjdp    {
260660484Sobrien      as_warn (_(".scl pseudo-op used outside of .def/.endef; ignored"));
260733965Sjdp      demand_empty_rest_of_line ();
260833965Sjdp      return;
260933965Sjdp    }
261033965Sjdp
261133965Sjdp  val = get_absolute_expression ();
261233965Sjdp
261333965Sjdp  coff_symbol_typ = map_coff_sym_type[val];
261433965Sjdp  coff_storage_class = map_coff_storage[val];
261533965Sjdp
261633965Sjdp  demand_empty_rest_of_line ();
261733965Sjdp}
261833965Sjdp
261933965Sjdp/* Handle a .size directive.  For some reason mips-tfile.c thinks that
262033965Sjdp   .size can have multiple arguments.  We humor it, although gcc will
262133965Sjdp   never generate more than one argument.  */
262233965Sjdp
262333965Sjdpvoid
2624130561Sobrienecoff_directive_size (int ignore ATTRIBUTE_UNUSED)
262533965Sjdp{
262633965Sjdp  int sizes[N_TQ];
262733965Sjdp  int i;
262833965Sjdp
262933965Sjdp  if (coff_sym_name == (char *) NULL)
263033965Sjdp    {
263160484Sobrien      as_warn (_(".size pseudo-op used outside of .def/.endef; ignored"));
263233965Sjdp      demand_empty_rest_of_line ();
263333965Sjdp      return;
263433965Sjdp    }
263533965Sjdp
263633965Sjdp  for (i = 0; i < N_TQ; i++)
263733965Sjdp    {
263833965Sjdp      SKIP_WHITESPACE ();
263933965Sjdp      sizes[i] = get_absolute_expression ();
264033965Sjdp      if (*input_line_pointer == ',')
264133965Sjdp	++input_line_pointer;
264233965Sjdp      else
264333965Sjdp	{
264433965Sjdp	  if (*input_line_pointer != '\n'
264533965Sjdp	      && *input_line_pointer != ';')
264689857Sobrien	    as_warn (_("badly formed .size directive"));
264733965Sjdp	  break;
264833965Sjdp	}
264933965Sjdp    }
265033965Sjdp
265133965Sjdp  if (i == N_TQ)
265233965Sjdp    --i;
265333965Sjdp
265433965Sjdp  /* The sizes are stored away in reverse order.  */
265533965Sjdp  for (; i >= 0; i--)
265633965Sjdp    {
265733965Sjdp      if (coff_type.num_sizes >= N_TQ)
265833965Sjdp	{
265989857Sobrien	  as_warn (_("too many .size entries"));
266033965Sjdp	  break;
266133965Sjdp	}
266233965Sjdp      coff_type.sizes[coff_type.num_sizes] = sizes[i];
266333965Sjdp      ++coff_type.num_sizes;
266433965Sjdp    }
266533965Sjdp
266633965Sjdp  demand_empty_rest_of_line ();
266733965Sjdp}
266833965Sjdp
266933965Sjdp/* Handle the .type directive, which gives the COFF type of the
267033965Sjdp   symbol.  */
267133965Sjdp
267233965Sjdpvoid
2673130561Sobrienecoff_directive_type (int ignore ATTRIBUTE_UNUSED)
267433965Sjdp{
267533965Sjdp  long val;
267633965Sjdp  tq_t *tq_ptr;
267733965Sjdp  tq_t *tq_shft;
267833965Sjdp
267933965Sjdp  if (coff_sym_name == (char *) NULL)
268033965Sjdp    {
268160484Sobrien      as_warn (_(".type pseudo-op used outside of .def/.endef; ignored"));
268233965Sjdp      demand_empty_rest_of_line ();
268333965Sjdp      return;
268433965Sjdp    }
268533965Sjdp
268633965Sjdp  val = get_absolute_expression ();
268733965Sjdp
268833965Sjdp  coff_type.orig_type = BTYPE (val);
268933965Sjdp  coff_type.basic_type = map_coff_types[coff_type.orig_type];
269033965Sjdp
269133965Sjdp  tq_ptr = &coff_type.type_qualifiers[N_TQ];
269277298Sobrien  while (val & ~N_BTMASK)
269333965Sjdp    {
269433965Sjdp      if (tq_ptr == &coff_type.type_qualifiers[0])
269533965Sjdp	{
269633965Sjdp	  /* FIXME: We could handle this by setting the continued bit.
269777298Sobrien	     There would still be a limit: the .type argument can not
269877298Sobrien	     be infinite.  */
269989857Sobrien	  as_warn (_("the type of %s is too complex; it will be simplified"),
270033965Sjdp		   coff_sym_name);
270133965Sjdp	  break;
270233965Sjdp	}
270333965Sjdp      if (ISPTR (val))
270433965Sjdp	*--tq_ptr = tq_Ptr;
270533965Sjdp      else if (ISFCN (val))
270633965Sjdp	*--tq_ptr = tq_Proc;
270733965Sjdp      else if (ISARY (val))
270833965Sjdp	*--tq_ptr = tq_Array;
270933965Sjdp      else
271060484Sobrien	as_fatal (_("Unrecognized .type argument"));
271133965Sjdp
271233965Sjdp      val = DECREF (val);
271333965Sjdp    }
271433965Sjdp
271533965Sjdp  tq_shft = &coff_type.type_qualifiers[0];
271633965Sjdp  while (tq_ptr != &coff_type.type_qualifiers[N_TQ])
271733965Sjdp    *tq_shft++ = *tq_ptr++;
271833965Sjdp
271933965Sjdp  if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc)
272033965Sjdp    {
272133965Sjdp      /* If this is a function, ignore it, so that we don't get two
272277298Sobrien         entries (one from the .ent, and one for the .def that
272377298Sobrien         precedes it).  Save the type information so that the end
272477298Sobrien         block can properly add it after the begin block index.  For
272577298Sobrien         MIPS knows what reason, we must strip off the function type
272677298Sobrien         at this point.  */
272733965Sjdp      coff_is_function = 1;
272833965Sjdp      tq_shft[-1] = tq_Nil;
272933965Sjdp    }
273033965Sjdp
273133965Sjdp  while (tq_shft != &coff_type.type_qualifiers[N_TQ])
273233965Sjdp    *tq_shft++ = tq_Nil;
273333965Sjdp
273433965Sjdp  demand_empty_rest_of_line ();
273533965Sjdp}
273633965Sjdp
273733965Sjdp/* Handle the .tag directive, which gives the name of a structure,
273833965Sjdp   union or enum.  */
273933965Sjdp
274033965Sjdpvoid
2741130561Sobrienecoff_directive_tag (int ignore ATTRIBUTE_UNUSED)
274233965Sjdp{
274333965Sjdp  char *name;
274433965Sjdp  char name_end;
274533965Sjdp
274633965Sjdp  if (coff_sym_name == (char *) NULL)
274733965Sjdp    {
274860484Sobrien      as_warn (_(".tag pseudo-op used outside of .def/.endef; ignored"));
274933965Sjdp      demand_empty_rest_of_line ();
275033965Sjdp      return;
275133965Sjdp    }
275233965Sjdp
275333965Sjdp  name = input_line_pointer;
275433965Sjdp  name_end = get_symbol_end ();
275533965Sjdp
2756104834Sobrien  coff_tag = xstrdup (name);
275733965Sjdp
275833965Sjdp  *input_line_pointer = name_end;
275933965Sjdp
276033965Sjdp  demand_empty_rest_of_line ();
276133965Sjdp}
276233965Sjdp
276333965Sjdp/* Handle the .val directive, which gives the value of the symbol.  It
276433965Sjdp   may be the name of a static or global symbol.  */
276533965Sjdp
276633965Sjdpvoid
2767130561Sobrienecoff_directive_val (int ignore ATTRIBUTE_UNUSED)
276833965Sjdp{
276933965Sjdp  expressionS exp;
277033965Sjdp
277133965Sjdp  if (coff_sym_name == (char *) NULL)
277233965Sjdp    {
277360484Sobrien      as_warn (_(".val pseudo-op used outside of .def/.endef; ignored"));
277433965Sjdp      demand_empty_rest_of_line ();
277533965Sjdp      return;
277633965Sjdp    }
277733965Sjdp
277833965Sjdp  expression (&exp);
277933965Sjdp  if (exp.X_op != O_constant && exp.X_op != O_symbol)
278033965Sjdp    {
2781218822Sdim      as_bad (_(".val expression is too complex"));
278233965Sjdp      demand_empty_rest_of_line ();
278333965Sjdp      return;
278433965Sjdp    }
278533965Sjdp
278633965Sjdp  if (exp.X_op == O_constant)
278733965Sjdp    coff_value = exp.X_add_number;
278833965Sjdp  else
278933965Sjdp    {
279033965Sjdp      coff_sym_value = exp.X_add_symbol;
279133965Sjdp      coff_sym_addend = exp.X_add_number;
279233965Sjdp    }
279333965Sjdp
279433965Sjdp  demand_empty_rest_of_line ();
279533965Sjdp}
279633965Sjdp
279733965Sjdp/* Handle the .endef directive, which terminates processing of COFF
279833965Sjdp   debugging information for a symbol.  */
279933965Sjdp
280033965Sjdpvoid
2801130561Sobrienecoff_directive_endef (int ignore ATTRIBUTE_UNUSED)
280233965Sjdp{
280333965Sjdp  char *name;
280433965Sjdp  symint_t indx;
280533965Sjdp  localsym_t *sym;
280633965Sjdp
280733965Sjdp  demand_empty_rest_of_line ();
280833965Sjdp
280933965Sjdp  if (coff_sym_name == (char *) NULL)
281033965Sjdp    {
281160484Sobrien      as_warn (_(".endef pseudo-op used before .def; ignored"));
281233965Sjdp      return;
281333965Sjdp    }
281433965Sjdp
281533965Sjdp  name = coff_sym_name;
281633965Sjdp  coff_sym_name = (char *) NULL;
281733965Sjdp
281833965Sjdp  /* If the symbol is a static or external, we have already gotten the
281933965Sjdp     appropriate type and class, so make sure we don't override those
282033965Sjdp     values.  This is needed because there are some type and classes
282133965Sjdp     that are not in COFF, such as short data, etc.  */
282233965Sjdp  if (coff_sym_value != (symbolS *) NULL)
282333965Sjdp    {
282433965Sjdp      coff_symbol_typ = st_Nil;
282533965Sjdp      coff_storage_class = sc_Nil;
282633965Sjdp    }
282733965Sjdp
282833965Sjdp  coff_type.extra_sizes = coff_tag != (char *) NULL;
282933965Sjdp  if (coff_type.num_dims > 0)
283033965Sjdp    {
283133965Sjdp      int diff = coff_type.num_dims - coff_type.num_sizes;
283233965Sjdp      int i = coff_type.num_dims - 1;
283333965Sjdp      int j;
283433965Sjdp
283533965Sjdp      if (coff_type.num_sizes != 1 || diff < 0)
283633965Sjdp	{
283789857Sobrien	  as_warn (_("bad COFF debugging information"));
283833965Sjdp	  return;
283933965Sjdp	}
284033965Sjdp
284133965Sjdp      /* If this is an array, make sure the same number of dimensions
284277298Sobrien         and sizes were passed, creating extra sizes for multiply
284377298Sobrien         dimensioned arrays if not passed.  */
284433965Sjdp      coff_type.extra_sizes = 0;
284533965Sjdp      if (diff)
284633965Sjdp	{
284733965Sjdp	  j = (sizeof (coff_type.sizes) / sizeof (coff_type.sizes[0])) - 1;
284833965Sjdp	  while (j >= 0)
284933965Sjdp	    {
285033965Sjdp	      coff_type.sizes[j] = (((j - diff) >= 0)
285133965Sjdp				    ? coff_type.sizes[j - diff]
285233965Sjdp				    : 0);
285333965Sjdp	      j--;
285433965Sjdp	    }
285533965Sjdp
285633965Sjdp	  coff_type.num_sizes = i + 1;
285733965Sjdp	  for (i--; i >= 0; i--)
285833965Sjdp	    coff_type.sizes[i] = (coff_type.dimensions[i + 1] == 0
285933965Sjdp				  ? 0
286033965Sjdp				  : (coff_type.sizes[i + 1]
286133965Sjdp				     / coff_type.dimensions[i + 1]));
286233965Sjdp	}
286333965Sjdp    }
286433965Sjdp  else if (coff_symbol_typ == st_Member
286533965Sjdp	   && coff_type.num_sizes - coff_type.extra_sizes == 1)
286633965Sjdp    {
2867130561Sobrien      /* Is this a bitfield?  This is indicated by a structure member
286877298Sobrien         having a size field that isn't an array.  */
286933965Sjdp      coff_type.bitfield = 1;
287033965Sjdp    }
287133965Sjdp
287233965Sjdp  /* Except for enumeration members & begin/ending of scopes, put the
287333965Sjdp     type word in the aux. symbol table.  */
287433965Sjdp  if (coff_symbol_typ == st_Block || coff_symbol_typ == st_End)
287533965Sjdp    indx = 0;
287633965Sjdp  else if (coff_inside_enumeration)
287733965Sjdp    indx = cur_file_ptr->void_type;
287833965Sjdp  else
287933965Sjdp    {
288033965Sjdp      if (coff_type.basic_type == bt_Struct
288133965Sjdp	  || coff_type.basic_type == bt_Union
288233965Sjdp	  || coff_type.basic_type == bt_Enum)
288333965Sjdp	{
288433965Sjdp	  if (coff_tag == (char *) NULL)
288533965Sjdp	    {
288689857Sobrien	      as_warn (_("no tag specified for %s"), name);
288733965Sjdp	      return;
288833965Sjdp	    }
288933965Sjdp
289033965Sjdp	  coff_type.tag_ptr = get_tag (coff_tag, (localsym_t *) NULL,
289133965Sjdp				       coff_type.basic_type);
289233965Sjdp	}
289333965Sjdp
289433965Sjdp      if (coff_is_function)
289533965Sjdp	{
289633965Sjdp	  last_func_type_info = coff_type;
289733965Sjdp	  last_func_sym_value = coff_sym_value;
289833965Sjdp	  return;
289933965Sjdp	}
290033965Sjdp
290133965Sjdp      indx = add_aux_sym_tir (&coff_type,
290233965Sjdp			      hash_yes,
290333965Sjdp			      &cur_file_ptr->thash_head[0]);
290433965Sjdp    }
290533965Sjdp
290633965Sjdp  /* Do any last minute adjustments that are necessary.  */
290733965Sjdp  switch (coff_symbol_typ)
290833965Sjdp    {
290933965Sjdp    default:
291033965Sjdp      break;
291133965Sjdp
291233965Sjdp      /* For the beginning of structs, unions, and enumerations, the
291377298Sobrien         size info needs to be passed in the value field.  */
291433965Sjdp    case st_Block:
291533965Sjdp      if (coff_type.num_sizes - coff_type.num_dims - coff_type.extra_sizes
291633965Sjdp	  != 1)
291733965Sjdp	{
291889857Sobrien	  as_warn (_("bad COFF debugging information"));
291933965Sjdp	  return;
292033965Sjdp	}
292133965Sjdp      else
292233965Sjdp	coff_value = coff_type.sizes[0];
292333965Sjdp
292433965Sjdp      coff_inside_enumeration = (coff_type.orig_type == T_ENUM);
292533965Sjdp      break;
292633965Sjdp
292733965Sjdp      /* For the end of structs, unions, and enumerations, omit the
292877298Sobrien         name which is always ".eos".  This needs to be done last, so
292977298Sobrien         that any error reporting above gives the correct name.  */
293033965Sjdp    case st_End:
293133965Sjdp      free (name);
293233965Sjdp      name = (char *) NULL;
293333965Sjdp      coff_value = 0;
293433965Sjdp      coff_inside_enumeration = 0;
293533965Sjdp      break;
293633965Sjdp
293733965Sjdp      /* Members of structures and unions that aren't bitfields, need
293877298Sobrien         to adjust the value from a byte offset to a bit offset.
293977298Sobrien         Members of enumerations do not have the value adjusted, and
294077298Sobrien         can be distinguished by indx == indexNil.  For enumerations,
294177298Sobrien         update the maximum enumeration value.  */
294233965Sjdp    case st_Member:
294333965Sjdp      if (! coff_type.bitfield && ! coff_inside_enumeration)
294433965Sjdp	coff_value *= 8;
294533965Sjdp
294633965Sjdp      break;
294733965Sjdp    }
294833965Sjdp
294933965Sjdp  /* Add the symbol.  */
295033965Sjdp  sym = add_ecoff_symbol (name,
295133965Sjdp			  coff_symbol_typ,
295233965Sjdp			  coff_storage_class,
295333965Sjdp			  coff_sym_value,
295433965Sjdp			  coff_sym_addend,
295533965Sjdp			  (symint_t) coff_value,
295633965Sjdp			  indx);
295733965Sjdp
295833965Sjdp  /* deal with struct, union, and enum tags.  */
295933965Sjdp  if (coff_symbol_typ == st_Block)
296033965Sjdp    {
296133965Sjdp      /* Create or update the tag information.  */
296233965Sjdp      tag_t *tag_ptr = get_tag (name,
296333965Sjdp				sym,
296433965Sjdp				coff_type.basic_type);
296533965Sjdp      forward_t **pf;
296633965Sjdp
296733965Sjdp      /* Remember any forward references.  */
296833965Sjdp      for (pf = &sym->forward_ref;
296933965Sjdp	   *pf != (forward_t *) NULL;
297033965Sjdp	   pf = &(*pf)->next)
297133965Sjdp	;
297233965Sjdp      *pf = tag_ptr->forward_ref;
297333965Sjdp      tag_ptr->forward_ref = (forward_t *) NULL;
297433965Sjdp    }
297533965Sjdp}
297633965Sjdp
297733965Sjdp/* Parse .end directives.  */
297833965Sjdp
297933965Sjdpvoid
2980130561Sobrienecoff_directive_end (int ignore ATTRIBUTE_UNUSED)
298133965Sjdp{
298233965Sjdp  char *name;
298333965Sjdp  char name_end;
298433965Sjdp  symbolS *ent;
298533965Sjdp
298633965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
298733965Sjdp    {
298860484Sobrien      as_warn (_(".end directive without a preceding .file directive"));
298933965Sjdp      demand_empty_rest_of_line ();
299033965Sjdp      return;
299133965Sjdp    }
299233965Sjdp
299333965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
299433965Sjdp    {
299560484Sobrien      as_warn (_(".end directive without a preceding .ent directive"));
299633965Sjdp      demand_empty_rest_of_line ();
299733965Sjdp      return;
299833965Sjdp    }
299933965Sjdp
300033965Sjdp  name = input_line_pointer;
300133965Sjdp  name_end = get_symbol_end ();
300233965Sjdp
300389857Sobrien  if (name == input_line_pointer)
300433965Sjdp    {
300560484Sobrien      as_warn (_(".end directive has no name"));
300633965Sjdp      *input_line_pointer = name_end;
300733965Sjdp      demand_empty_rest_of_line ();
300833965Sjdp      return;
300933965Sjdp    }
301033965Sjdp
301133965Sjdp  /* The value is the distance between the .end directive and the
301233965Sjdp     corresponding symbol.  We create a fake symbol to hold the
301333965Sjdp     current location, and put in the offset when we write out the
301433965Sjdp     symbol.  */
301533965Sjdp  ent = symbol_find (name);
301633965Sjdp  if (ent == (symbolS *) NULL)
301760484Sobrien    as_warn (_(".end directive names unknown symbol"));
301833965Sjdp  else
301938889Sjdp    (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
302038889Sjdp			     symbol_new ("L0\001", now_seg,
302138889Sjdp					 (valueT) frag_now_fix (),
302238889Sjdp					 frag_now),
302338889Sjdp			     (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
302433965Sjdp
302533965Sjdp  cur_proc_ptr = (proc_t *) NULL;
302633965Sjdp
302733965Sjdp  *input_line_pointer = name_end;
302833965Sjdp  demand_empty_rest_of_line ();
302933965Sjdp}
303033965Sjdp
303133965Sjdp/* Parse .ent directives.  */
303233965Sjdp
303333965Sjdpvoid
3034130561Sobrienecoff_directive_ent (int ignore ATTRIBUTE_UNUSED)
303533965Sjdp{
303633965Sjdp  char *name;
303733965Sjdp  char name_end;
303833965Sjdp
303933965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
304033965Sjdp    add_file ((const char *) NULL, 0, 1);
304133965Sjdp
304233965Sjdp  if (cur_proc_ptr != (proc_t *) NULL)
304333965Sjdp    {
304460484Sobrien      as_warn (_("second .ent directive found before .end directive"));
304533965Sjdp      demand_empty_rest_of_line ();
304633965Sjdp      return;
304733965Sjdp    }
304833965Sjdp
304933965Sjdp  name = input_line_pointer;
305033965Sjdp  name_end = get_symbol_end ();
305133965Sjdp
305289857Sobrien  if (name == input_line_pointer)
305333965Sjdp    {
305460484Sobrien      as_warn (_(".ent directive has no name"));
305533965Sjdp      *input_line_pointer = name_end;
305633965Sjdp      demand_empty_rest_of_line ();
305733965Sjdp      return;
305833965Sjdp    }
305933965Sjdp
306033965Sjdp  add_procedure (name);
306133965Sjdp
306233965Sjdp  *input_line_pointer = name_end;
306333965Sjdp
306433965Sjdp  /* The .ent directive is sometimes followed by a number.  I'm not
306533965Sjdp     really sure what the number means.  I don't see any way to store
306633965Sjdp     the information in the PDR.  The Irix 4 assembler seems to ignore
306733965Sjdp     the information.  */
306833965Sjdp  SKIP_WHITESPACE ();
306933965Sjdp  if (*input_line_pointer == ',')
307033965Sjdp    {
307133965Sjdp      ++input_line_pointer;
307233965Sjdp      SKIP_WHITESPACE ();
307333965Sjdp    }
307489857Sobrien  if (ISDIGIT (*input_line_pointer)
307560484Sobrien      || *input_line_pointer == '-')
307633965Sjdp    (void) get_absolute_expression ();
307733965Sjdp
307833965Sjdp  demand_empty_rest_of_line ();
307933965Sjdp}
308033965Sjdp
308133965Sjdp/* Parse .extern directives.  */
308233965Sjdp
308333965Sjdpvoid
3084130561Sobrienecoff_directive_extern (int ignore ATTRIBUTE_UNUSED)
308533965Sjdp{
308633965Sjdp  char *name;
308733965Sjdp  int c;
308833965Sjdp  symbolS *symbolp;
308933965Sjdp  valueT size;
309033965Sjdp
309133965Sjdp  name = input_line_pointer;
309233965Sjdp  c = get_symbol_end ();
309333965Sjdp  symbolp = symbol_find_or_make (name);
309433965Sjdp  *input_line_pointer = c;
309533965Sjdp
309633965Sjdp  S_SET_EXTERNAL (symbolp);
309733965Sjdp
309833965Sjdp  if (*input_line_pointer == ',')
309933965Sjdp    ++input_line_pointer;
310033965Sjdp  size = get_absolute_expression ();
310133965Sjdp
310260484Sobrien  symbol_get_obj (symbolp)->ecoff_extern_size = size;
310333965Sjdp}
310433965Sjdp
310533965Sjdp/* Parse .file directives.  */
310633965Sjdp
310733965Sjdpvoid
3108130561Sobrienecoff_directive_file (int ignore ATTRIBUTE_UNUSED)
310933965Sjdp{
311033965Sjdp  int indx;
311133965Sjdp  char *name;
311233965Sjdp  int len;
311333965Sjdp
311433965Sjdp  if (cur_proc_ptr != (proc_t *) NULL)
311533965Sjdp    {
311689857Sobrien      as_warn (_("no way to handle .file within .ent/.end section"));
311733965Sjdp      demand_empty_rest_of_line ();
311833965Sjdp      return;
311933965Sjdp    }
312033965Sjdp
312133965Sjdp  indx = (int) get_absolute_expression ();
312233965Sjdp
312333965Sjdp  /* FIXME: we don't have to save the name here.  */
312433965Sjdp  name = demand_copy_C_string (&len);
312533965Sjdp
312633965Sjdp  add_file (name, indx - 1, 0);
312733965Sjdp
312833965Sjdp  demand_empty_rest_of_line ();
312933965Sjdp}
313033965Sjdp
313133965Sjdp/* Parse .fmask directives.  */
313233965Sjdp
313333965Sjdpvoid
3134130561Sobrienecoff_directive_fmask (int ignore ATTRIBUTE_UNUSED)
313533965Sjdp{
313633965Sjdp  long val;
313733965Sjdp
313833965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
313933965Sjdp    {
314060484Sobrien      as_warn (_(".fmask outside of .ent"));
314133965Sjdp      demand_empty_rest_of_line ();
314233965Sjdp      return;
314333965Sjdp    }
314433965Sjdp
314533965Sjdp  if (get_absolute_expression_and_terminator (&val) != ',')
314633965Sjdp    {
314789857Sobrien      as_warn (_("bad .fmask directive"));
314833965Sjdp      --input_line_pointer;
314933965Sjdp      demand_empty_rest_of_line ();
315033965Sjdp      return;
315133965Sjdp    }
315233965Sjdp
315333965Sjdp  cur_proc_ptr->pdr.fregmask = val;
315433965Sjdp  cur_proc_ptr->pdr.fregoffset = get_absolute_expression ();
315533965Sjdp
315633965Sjdp  demand_empty_rest_of_line ();
315733965Sjdp}
315833965Sjdp
315933965Sjdp/* Parse .frame directives.  */
316033965Sjdp
316133965Sjdpvoid
3162130561Sobrienecoff_directive_frame (int ignore ATTRIBUTE_UNUSED)
316333965Sjdp{
316433965Sjdp  long val;
316533965Sjdp
316633965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
316733965Sjdp    {
316860484Sobrien      as_warn (_(".frame outside of .ent"));
316933965Sjdp      demand_empty_rest_of_line ();
317033965Sjdp      return;
317133965Sjdp    }
317233965Sjdp
317333965Sjdp  cur_proc_ptr->pdr.framereg = tc_get_register (1);
317433965Sjdp
317533965Sjdp  SKIP_WHITESPACE ();
317633965Sjdp  if (*input_line_pointer++ != ','
317733965Sjdp      || get_absolute_expression_and_terminator (&val) != ',')
317833965Sjdp    {
317989857Sobrien      as_warn (_("bad .frame directive"));
318033965Sjdp      --input_line_pointer;
318133965Sjdp      demand_empty_rest_of_line ();
318233965Sjdp      return;
318333965Sjdp    }
318433965Sjdp
318533965Sjdp  cur_proc_ptr->pdr.frameoffset = val;
318633965Sjdp
318733965Sjdp  cur_proc_ptr->pdr.pcreg = tc_get_register (0);
318833965Sjdp
318977298Sobrien  /* Alpha-OSF1 adds "the offset of saved $a0 from $sp", according to
319077298Sobrien     Sandro.  I don't yet know where this value should be stored, if
3191218822Sdim     anywhere.  Don't call demand_empty_rest_of_line ().  */
319233965Sjdp  s_ignore (42);
319333965Sjdp}
319433965Sjdp
319533965Sjdp/* Parse .mask directives.  */
319633965Sjdp
319733965Sjdpvoid
3198130561Sobrienecoff_directive_mask (int ignore ATTRIBUTE_UNUSED)
319933965Sjdp{
320033965Sjdp  long val;
320133965Sjdp
320233965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
320333965Sjdp    {
320460484Sobrien      as_warn (_(".mask outside of .ent"));
320533965Sjdp      demand_empty_rest_of_line ();
320633965Sjdp      return;
320733965Sjdp    }
320833965Sjdp
320933965Sjdp  if (get_absolute_expression_and_terminator (&val) != ',')
321033965Sjdp    {
321189857Sobrien      as_warn (_("bad .mask directive"));
321233965Sjdp      --input_line_pointer;
321333965Sjdp      demand_empty_rest_of_line ();
321433965Sjdp      return;
321533965Sjdp    }
321633965Sjdp
321733965Sjdp  cur_proc_ptr->pdr.regmask = val;
321833965Sjdp  cur_proc_ptr->pdr.regoffset = get_absolute_expression ();
321933965Sjdp
322033965Sjdp  demand_empty_rest_of_line ();
322133965Sjdp}
322233965Sjdp
322333965Sjdp/* Parse .loc directives.  */
322433965Sjdp
322533965Sjdpvoid
3226130561Sobrienecoff_directive_loc (int ignore ATTRIBUTE_UNUSED)
322733965Sjdp{
322833965Sjdp  lineno_list_t *list;
322933965Sjdp  symint_t lineno;
323033965Sjdp
323133965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
323233965Sjdp    {
323360484Sobrien      as_warn (_(".loc before .file"));
323433965Sjdp      demand_empty_rest_of_line ();
323533965Sjdp      return;
323633965Sjdp    }
323733965Sjdp
323833965Sjdp  if (now_seg != text_section)
323933965Sjdp    {
324060484Sobrien      as_warn (_(".loc outside of .text"));
324133965Sjdp      demand_empty_rest_of_line ();
324233965Sjdp      return;
324333965Sjdp    }
324433965Sjdp
324533965Sjdp  /* Skip the file number.  */
324633965Sjdp  SKIP_WHITESPACE ();
324733965Sjdp  get_absolute_expression ();
324833965Sjdp  SKIP_WHITESPACE ();
324933965Sjdp
325033965Sjdp  lineno = get_absolute_expression ();
325133965Sjdp
325233965Sjdp#ifndef NO_LISTING
325333965Sjdp  if (listing)
325433965Sjdp    listing_source_line (lineno);
325533965Sjdp#endif
325633965Sjdp
325733965Sjdp  /* If we're building stabs, then output a special label rather than
325833965Sjdp     ECOFF line number info.  */
325933965Sjdp  if (stabs_seen)
326033965Sjdp    {
326133965Sjdp      (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text,
326233965Sjdp			       symbol_new ("L0\001", now_seg,
326333965Sjdp					   (valueT) frag_now_fix (),
326433965Sjdp					   frag_now),
326533965Sjdp			       (bfd_vma) 0, 0, lineno);
326633965Sjdp      return;
326733965Sjdp    }
326833965Sjdp
326933965Sjdp  list = allocate_lineno_list ();
327033965Sjdp
327133965Sjdp  list->next = (lineno_list_t *) NULL;
327233965Sjdp  list->file = cur_file_ptr;
327333965Sjdp  list->proc = cur_proc_ptr;
327433965Sjdp  list->frag = frag_now;
327533965Sjdp  list->paddr = frag_now_fix ();
327633965Sjdp  list->lineno = lineno;
327733965Sjdp
327833965Sjdp  /* We don't want to merge files which have line numbers.  */
327933965Sjdp  cur_file_ptr->fdr.fMerge = 0;
328033965Sjdp
328133965Sjdp  /* A .loc directive will sometimes appear before a .ent directive,
328233965Sjdp     which means that cur_proc_ptr will be NULL here.  Arrange to
328333965Sjdp     patch this up.  */
328433965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
328533965Sjdp    {
328633965Sjdp      lineno_list_t **pl;
328733965Sjdp
328833965Sjdp      pl = &noproc_lineno;
328933965Sjdp      while (*pl != (lineno_list_t *) NULL)
329033965Sjdp	pl = &(*pl)->next;
329133965Sjdp      *pl = list;
329233965Sjdp    }
329333965Sjdp  else
329433965Sjdp    {
329533965Sjdp      last_lineno = list;
329633965Sjdp      *last_lineno_ptr = list;
329733965Sjdp      last_lineno_ptr = &list->next;
329833965Sjdp    }
329933965Sjdp}
330033965Sjdp
330133965Sjdp/* The MIPS assembler sometimes inserts nop instructions in the
330233965Sjdp   instruction stream.  When this happens, we must patch up the .loc
330333965Sjdp   information so that it points to the instruction after the nop.  */
330433965Sjdp
330533965Sjdpvoid
3306130561Sobrienecoff_fix_loc (fragS *old_frag, unsigned long old_frag_offset)
330733965Sjdp{
330833965Sjdp  if (last_lineno != NULL
330933965Sjdp      && last_lineno->frag == old_frag
331033965Sjdp      && last_lineno->paddr == old_frag_offset)
331133965Sjdp    {
331233965Sjdp      last_lineno->frag = frag_now;
331333965Sjdp      last_lineno->paddr = frag_now_fix ();
331433965Sjdp    }
331533965Sjdp}
331633965Sjdp
331733965Sjdp/* Make sure the @stabs symbol is emitted.  */
331833965Sjdp
331933965Sjdpstatic void
3320130561Sobrienmark_stabs (int ignore ATTRIBUTE_UNUSED)
332133965Sjdp{
332233965Sjdp  if (! stabs_seen)
332333965Sjdp    {
332477298Sobrien      /* Add a dummy @stabs dymbol.  */
332533965Sjdp      stabs_seen = 1;
332633965Sjdp      (void) add_ecoff_symbol (stabs_symbol, stNil, scInfo,
332733965Sjdp			       (symbolS *) NULL,
332833965Sjdp			       (bfd_vma) 0, (symint_t) -1,
332933965Sjdp			       ECOFF_MARK_STAB (0));
333033965Sjdp    }
333133965Sjdp}
333233965Sjdp
333333965Sjdp/* Parse .weakext directives.  */
333460484Sobrien#ifndef TC_MIPS
333577298Sobrien/* For TC_MIPS use the version in tc-mips.c.  */
333633965Sjdpvoid
3337130561Sobrienecoff_directive_weakext (int ignore ATTRIBUTE_UNUSED)
333833965Sjdp{
333933965Sjdp  char *name;
334033965Sjdp  int c;
334133965Sjdp  symbolS *symbolP;
334233965Sjdp  expressionS exp;
334333965Sjdp
334433965Sjdp  name = input_line_pointer;
334533965Sjdp  c = get_symbol_end ();
334633965Sjdp  symbolP = symbol_find_or_make (name);
334733965Sjdp  *input_line_pointer = c;
334833965Sjdp
334933965Sjdp  SKIP_WHITESPACE ();
335033965Sjdp
335133965Sjdp  if (*input_line_pointer == ',')
335233965Sjdp    {
335333965Sjdp      if (S_IS_DEFINED (symbolP))
335433965Sjdp	{
335589857Sobrien	  as_bad (_("symbol `%s' is already defined"),
335633965Sjdp		  S_GET_NAME (symbolP));
335733965Sjdp	  ignore_rest_of_line ();
335833965Sjdp	  return;
335933965Sjdp	}
336033965Sjdp
336133965Sjdp      ++input_line_pointer;
336233965Sjdp      SKIP_WHITESPACE ();
336333965Sjdp      if (! is_end_of_line[(unsigned char) *input_line_pointer])
336433965Sjdp	{
336533965Sjdp	  expression (&exp);
336633965Sjdp	  if (exp.X_op != O_symbol)
336733965Sjdp	    {
336860484Sobrien	      as_bad (_("bad .weakext directive"));
336977298Sobrien	      ignore_rest_of_line ();
337033965Sjdp	      return;
337133965Sjdp	    }
337260484Sobrien	  symbol_set_value_expression (symbolP, &exp);
337333965Sjdp	}
337433965Sjdp    }
337533965Sjdp
337633965Sjdp  S_SET_WEAK (symbolP);
337733965Sjdp
337833965Sjdp  demand_empty_rest_of_line ();
337933965Sjdp}
338060484Sobrien#endif /* not TC_MIPS */
338133965Sjdp
338233965Sjdp/* Handle .stabs directives.  The actual parsing routine is done by a
338333965Sjdp   generic routine.  This routine is called via OBJ_PROCESS_STAB.
338433965Sjdp   When this is called, input_line_pointer will be pointing at the
338533965Sjdp   value field of the stab.
338633965Sjdp
338733965Sjdp   .stabs directives have five fields:
338833965Sjdp	"string"	a string, encoding the type information.
338933965Sjdp	code		a numeric code, defined in <stab.h>
339033965Sjdp	0		a zero
339133965Sjdp	desc		a zero or line number
339233965Sjdp	value		a numeric value or an address.
339333965Sjdp
339433965Sjdp    If the value is relocatable, we transform this into:
339533965Sjdp	iss		points as an index into string space
339633965Sjdp	value		value from lookup of the name
339733965Sjdp	st		st from lookup of the name
339833965Sjdp	sc		sc from lookup of the name
339933965Sjdp	index		code|CODE_MASK
340033965Sjdp
340133965Sjdp    If the value is not relocatable, we transform this into:
340233965Sjdp	iss		points as an index into string space
340333965Sjdp	value		value
340433965Sjdp	st		st_Nil
340533965Sjdp	sc		sc_Nil
340633965Sjdp	index		code|CODE_MASK
340733965Sjdp
340833965Sjdp    .stabn directives have four fields (string is null):
340933965Sjdp	code		a numeric code, defined in <stab.h>
341033965Sjdp	0		a zero
341133965Sjdp	desc		a zero or a line number
341233965Sjdp	value		a numeric value or an address.  */
341333965Sjdp
341433965Sjdpvoid
3415130561Sobrienecoff_stab (segT sec ATTRIBUTE_UNUSED,
3416130561Sobrien	    int what,
3417130561Sobrien	    const char *string,
3418130561Sobrien	    int type,
3419130561Sobrien	    int other,
3420130561Sobrien	    int desc)
342133965Sjdp{
342233965Sjdp  efdr_t *save_file_ptr = cur_file_ptr;
342333965Sjdp  symbolS *sym;
342433965Sjdp  symint_t value;
342533965Sjdp  bfd_vma addend;
342633965Sjdp  st_t st;
342733965Sjdp  sc_t sc;
342833965Sjdp  symint_t indx;
342933965Sjdp  localsym_t *hold = NULL;
343033965Sjdp
343133965Sjdp  ecoff_debugging_seen = 1;
343233965Sjdp
343333965Sjdp  /* We don't handle .stabd.  */
343433965Sjdp  if (what != 's' && what != 'n')
343533965Sjdp    {
343660484Sobrien      as_bad (_(".stab%c is not supported"), what);
343733965Sjdp      return;
343833965Sjdp    }
343933965Sjdp
344033965Sjdp  /* A .stabn uses a null name, not an empty string.  */
344133965Sjdp  if (what == 'n')
344233965Sjdp    string = NULL;
344333965Sjdp
344433965Sjdp  /* We ignore the other field.  */
344533965Sjdp  if (other != 0)
344660484Sobrien    as_warn (_(".stab%c: ignoring non-zero other field"), what);
344733965Sjdp
344833965Sjdp  /* Make sure we have a current file.  */
344933965Sjdp  if (cur_file_ptr == (efdr_t *) NULL)
345033965Sjdp    {
345133965Sjdp      add_file ((const char *) NULL, 0, 1);
345233965Sjdp      save_file_ptr = cur_file_ptr;
345333965Sjdp    }
345433965Sjdp
345533965Sjdp  /* For stabs in ECOFF, the first symbol must be @stabs.  This is a
345633965Sjdp     signal to gdb.  */
345733965Sjdp  if (stabs_seen == 0)
345833965Sjdp    mark_stabs (0);
345933965Sjdp
346033965Sjdp  /* Line number stabs are handled differently, since they have two
346133965Sjdp     values, the line number and the address of the label.  We use the
346233965Sjdp     index field (aka desc) to hold the line number, and the value
346333965Sjdp     field to hold the address.  The symbol type is st_Label, which
346433965Sjdp     should be different from the other stabs, so that gdb can
346533965Sjdp     recognize it.  */
346633965Sjdp  if (type == N_SLINE)
346733965Sjdp    {
346833965Sjdp      SYMR dummy_symr;
346933965Sjdp      char *name;
347033965Sjdp      char name_end;
347133965Sjdp
347233965Sjdp#ifndef NO_LISTING
347333965Sjdp      if (listing)
347433965Sjdp	listing_source_line ((unsigned int) desc);
347533965Sjdp#endif
347633965Sjdp
347733965Sjdp      dummy_symr.index = desc;
347833965Sjdp      if (dummy_symr.index != desc)
347933965Sjdp	{
348089857Sobrien	  as_warn (_("line number (%d) for .stab%c directive cannot fit in index field (20 bits)"),
348133965Sjdp		   desc, what);
348233965Sjdp	  return;
348333965Sjdp	}
348433965Sjdp
348533965Sjdp      name = input_line_pointer;
348633965Sjdp      name_end = get_symbol_end ();
348733965Sjdp
348833965Sjdp      sym = symbol_find_or_make (name);
348933965Sjdp      *input_line_pointer = name_end;
349033965Sjdp
349133965Sjdp      value = 0;
349233965Sjdp      addend = 0;
349333965Sjdp      st = st_Label;
349433965Sjdp      sc = sc_Text;
349533965Sjdp      indx = desc;
349633965Sjdp    }
349733965Sjdp  else
349833965Sjdp    {
349933965Sjdp#ifndef NO_LISTING
350033965Sjdp      if (listing && (type == N_SO || type == N_SOL))
350133965Sjdp	listing_source_file (string);
350233965Sjdp#endif
350333965Sjdp
350489857Sobrien      if (ISDIGIT (*input_line_pointer)
350533965Sjdp	  || *input_line_pointer == '-'
350633965Sjdp	  || *input_line_pointer == '+')
350733965Sjdp	{
350833965Sjdp	  st = st_Nil;
350933965Sjdp	  sc = sc_Nil;
351033965Sjdp	  sym = (symbolS *) NULL;
351133965Sjdp	  value = get_absolute_expression ();
351233965Sjdp	  addend = 0;
351333965Sjdp	}
351433965Sjdp      else if (! is_name_beginner ((unsigned char) *input_line_pointer))
351533965Sjdp	{
351689857Sobrien	  as_warn (_("illegal .stab%c directive, bad character"), what);
351733965Sjdp	  return;
351833965Sjdp	}
351933965Sjdp      else
352033965Sjdp	{
352133965Sjdp	  expressionS exp;
352233965Sjdp
352333965Sjdp	  sc = sc_Nil;
352433965Sjdp	  st = st_Nil;
352533965Sjdp
352633965Sjdp	  expression (&exp);
352733965Sjdp	  if (exp.X_op == O_constant)
352833965Sjdp	    {
352933965Sjdp	      sym = NULL;
353033965Sjdp	      value = exp.X_add_number;
353133965Sjdp	      addend = 0;
353233965Sjdp	    }
353333965Sjdp	  else if (exp.X_op == O_symbol)
353433965Sjdp	    {
353533965Sjdp	      sym = exp.X_add_symbol;
353633965Sjdp	      value = 0;
353733965Sjdp	      addend = exp.X_add_number;
353833965Sjdp	    }
353933965Sjdp	  else
354033965Sjdp	    {
354133965Sjdp	      sym = make_expr_symbol (&exp);
354233965Sjdp	      value = 0;
354333965Sjdp	      addend = 0;
354433965Sjdp	    }
354533965Sjdp	}
354633965Sjdp
354733965Sjdp      indx = ECOFF_MARK_STAB (type);
354833965Sjdp    }
354933965Sjdp
355033965Sjdp  /* Don't store the stabs symbol we are creating as the type of the
355133965Sjdp     ECOFF symbol.  We want to compute the type of the ECOFF symbol
355233965Sjdp     independently.  */
355333965Sjdp  if (sym != (symbolS *) NULL)
355460484Sobrien    hold = symbol_get_obj (sym)->ecoff_symbol;
355533965Sjdp
355633965Sjdp  (void) add_ecoff_symbol (string, st, sc, sym, addend, value, indx);
355733965Sjdp
355833965Sjdp  if (sym != (symbolS *) NULL)
355960484Sobrien    symbol_get_obj (sym)->ecoff_symbol = hold;
356033965Sjdp
356133965Sjdp  /* Restore normal file type.  */
356233965Sjdp  cur_file_ptr = save_file_ptr;
356333965Sjdp}
356433965Sjdp
356533965Sjdp/* Frob an ECOFF symbol.  Small common symbols go into a special
356633965Sjdp   .scommon section rather than bfd_com_section.  */
356733965Sjdp
356833965Sjdpvoid
3569130561Sobrienecoff_frob_symbol (symbolS *sym)
357033965Sjdp{
357133965Sjdp  if (S_IS_COMMON (sym)
357233965Sjdp      && S_GET_VALUE (sym) > 0
357389857Sobrien      && S_GET_VALUE (sym) <= bfd_get_gp_size (stdoutput))
357433965Sjdp    {
357533965Sjdp      static asection scom_section;
357633965Sjdp      static asymbol scom_symbol;
357733965Sjdp
357833965Sjdp      /* We must construct a fake section similar to bfd_com_section
357977298Sobrien         but with the name .scommon.  */
358033965Sjdp      if (scom_section.name == NULL)
358133965Sjdp	{
358233965Sjdp	  scom_section = bfd_com_section;
358333965Sjdp	  scom_section.name = ".scommon";
358433965Sjdp	  scom_section.output_section = &scom_section;
358533965Sjdp	  scom_section.symbol = &scom_symbol;
358633965Sjdp	  scom_section.symbol_ptr_ptr = &scom_section.symbol;
358733965Sjdp	  scom_symbol = *bfd_com_section.symbol;
358833965Sjdp	  scom_symbol.name = ".scommon";
358933965Sjdp	  scom_symbol.section = &scom_section;
359033965Sjdp	}
359133965Sjdp      S_SET_SEGMENT (sym, &scom_section);
359233965Sjdp    }
359333965Sjdp
359433965Sjdp  /* Double check weak symbols.  */
359560484Sobrien  if (S_IS_WEAK (sym))
359633965Sjdp    {
359733965Sjdp      if (S_IS_COMMON (sym))
359889857Sobrien	as_bad (_("symbol `%s' can not be both weak and common"),
359933965Sjdp		S_GET_NAME (sym));
360033965Sjdp    }
360133965Sjdp}
360233965Sjdp
360333965Sjdp/* Add bytes to the symbolic information buffer.  */
360433965Sjdp
360533965Sjdpstatic char *
3606130561Sobrienecoff_add_bytes (char **buf,
3607130561Sobrien		 char **bufend,
3608130561Sobrien		 char *bufptr,
3609130561Sobrien		 unsigned long need)
361033965Sjdp{
361133965Sjdp  unsigned long at;
361233965Sjdp  unsigned long want;
361333965Sjdp
361433965Sjdp  at = bufptr - *buf;
361533965Sjdp  need -= *bufend - bufptr;
361633965Sjdp  if (need < PAGE_SIZE)
361733965Sjdp    need = PAGE_SIZE;
361833965Sjdp  want = (*bufend - *buf) + need;
361933965Sjdp  *buf = xrealloc (*buf, want);
362033965Sjdp  *bufend = *buf + want;
362133965Sjdp  return *buf + at;
362233965Sjdp}
362333965Sjdp
362433965Sjdp/* Adjust the symbolic information buffer to the alignment required
362533965Sjdp   for the ECOFF target debugging information.  */
362633965Sjdp
362733965Sjdpstatic unsigned long
3628130561Sobrienecoff_padding_adjust (const struct ecoff_debug_swap *backend,
3629130561Sobrien		      char **buf,
3630130561Sobrien		      char **bufend,
3631130561Sobrien		      unsigned long offset,
3632130561Sobrien		      char **bufptrptr)
363333965Sjdp{
363433965Sjdp  bfd_size_type align;
363533965Sjdp
363633965Sjdp  align = backend->debug_align;
363733965Sjdp  if ((offset & (align - 1)) != 0)
363833965Sjdp    {
363933965Sjdp      unsigned long add;
364033965Sjdp
364133965Sjdp      add = align - (offset & (align - 1));
364278828Sobrien      if ((unsigned long) (*bufend - (*buf + offset)) < add)
364333965Sjdp	(void) ecoff_add_bytes (buf, bufend, *buf + offset, add);
364433965Sjdp      memset (*buf + offset, 0, add);
364533965Sjdp      offset += add;
364633965Sjdp      if (bufptrptr != (char **) NULL)
364733965Sjdp	*bufptrptr = *buf + offset;
364833965Sjdp    }
364933965Sjdp
365033965Sjdp  return offset;
365133965Sjdp}
365233965Sjdp
365333965Sjdp/* Build the line number information.  */
365433965Sjdp
365533965Sjdpstatic unsigned long
3656130561Sobrienecoff_build_lineno (const struct ecoff_debug_swap *backend,
3657130561Sobrien		    char **buf,
3658130561Sobrien		    char **bufend,
3659130561Sobrien		    unsigned long offset,
3660130561Sobrien		    long *linecntptr)
366133965Sjdp{
366233965Sjdp  char *bufptr;
366333965Sjdp  register lineno_list_t *l;
366433965Sjdp  lineno_list_t *last;
366533965Sjdp  efdr_t *file;
366633965Sjdp  proc_t *proc;
366733965Sjdp  unsigned long c;
366833965Sjdp  long iline;
366933965Sjdp  long totcount;
367033965Sjdp  lineno_list_t first;
367160484Sobrien  lineno_list_t *local_first_lineno = first_lineno;
367233965Sjdp
367333965Sjdp  if (linecntptr != (long *) NULL)
367433965Sjdp    *linecntptr = 0;
367533965Sjdp
367633965Sjdp  bufptr = *buf + offset;
367733965Sjdp
367833965Sjdp  file = (efdr_t *) NULL;
367933965Sjdp  proc = (proc_t *) NULL;
368033965Sjdp  last = (lineno_list_t *) NULL;
368133965Sjdp  c = offset;
368233965Sjdp  iline = 0;
368333965Sjdp  totcount = 0;
368433965Sjdp
3685218822Sdim  /* FIXME?  Now that MIPS embedded-PIC is gone, it may be safe to
3686218822Sdim     remove this code.  */
368733965Sjdp  /* For some reason the address of the first procedure is ignored
368833965Sjdp     when reading line numbers.  This doesn't matter if the address of
368933965Sjdp     the first procedure is 0, but when gcc is generating MIPS
369033965Sjdp     embedded PIC code, it will put strings in the .text section
369133965Sjdp     before the first procedure.  We cope by inserting a dummy line if
369233965Sjdp     the address of the first procedure is not 0.  Hopefully this
369377298Sobrien     won't screw things up too badly.
369460484Sobrien
369560484Sobrien     Don't do this for ECOFF assembly source line numbers.  They work
369660484Sobrien     without this extra attention.  */
369760484Sobrien  if (debug_type != DEBUG_ECOFF
369860484Sobrien      && first_proc_ptr != (proc_t *) NULL
369960484Sobrien      && local_first_lineno != (lineno_list_t *) NULL
370033965Sjdp      && ((S_GET_VALUE (first_proc_ptr->sym->as_sym)
370133965Sjdp	   + bfd_get_section_vma (stdoutput,
370233965Sjdp				  S_GET_SEGMENT (first_proc_ptr->sym->as_sym)))
370333965Sjdp	  != 0))
370433965Sjdp    {
370560484Sobrien      first.file = local_first_lineno->file;
370660484Sobrien      first.proc = local_first_lineno->proc;
370733965Sjdp      first.frag = &zero_address_frag;
370833965Sjdp      first.paddr = 0;
370933965Sjdp      first.lineno = 0;
371033965Sjdp
371160484Sobrien      first.next = local_first_lineno;
371260484Sobrien      local_first_lineno = &first;
371333965Sjdp    }
371433965Sjdp
371560484Sobrien  for (l = local_first_lineno; l != (lineno_list_t *) NULL; l = l->next)
371633965Sjdp    {
371733965Sjdp      long count;
371833965Sjdp      long delta;
371933965Sjdp
372033965Sjdp      /* Get the offset to the memory address of the next line number
372177298Sobrien         (in words).  Do this first, so that we can skip ahead to the
372277298Sobrien         next useful line number entry.  */
372333965Sjdp      if (l->next == (lineno_list_t *) NULL)
372433965Sjdp	{
372533965Sjdp	  /* We want a count of zero, but it will be decremented
372633965Sjdp	     before it is used.  */
372733965Sjdp	  count = 1;
372833965Sjdp	}
372933965Sjdp      else if (l->next->frag->fr_address + l->next->paddr
373033965Sjdp	       > l->frag->fr_address + l->paddr)
373133965Sjdp	{
373233965Sjdp	  count = ((l->next->frag->fr_address + l->next->paddr
373333965Sjdp		    - (l->frag->fr_address + l->paddr))
373433965Sjdp		   >> 2);
373533965Sjdp	}
373633965Sjdp      else
373733965Sjdp	{
373833965Sjdp	  /* Don't change last, so we still get the right delta.  */
373933965Sjdp	  continue;
374033965Sjdp	}
374133965Sjdp
374233965Sjdp      if (l->file != file || l->proc != proc)
374333965Sjdp	{
374433965Sjdp	  if (l->proc != proc && proc != (proc_t *) NULL)
374533965Sjdp	    proc->pdr.lnHigh = last->lineno;
374633965Sjdp	  if (l->file != file && file != (efdr_t *) NULL)
374733965Sjdp	    {
374833965Sjdp	      file->fdr.cbLine = c - file->fdr.cbLineOffset;
374933965Sjdp	      file->fdr.cline = totcount + count;
375033965Sjdp	      if (linecntptr != (long *) NULL)
375133965Sjdp		*linecntptr += totcount + count;
375233965Sjdp	      totcount = 0;
375333965Sjdp	    }
375433965Sjdp
375533965Sjdp	  if (l->file != file)
375633965Sjdp	    {
375733965Sjdp	      efdr_t *last_file = file;
375833965Sjdp
375933965Sjdp	      file = l->file;
376033965Sjdp	      if (last_file != (efdr_t *) NULL)
376133965Sjdp		file->fdr.ilineBase
376233965Sjdp		  = last_file->fdr.ilineBase + last_file->fdr.cline;
376333965Sjdp	      else
376433965Sjdp		file->fdr.ilineBase = 0;
376533965Sjdp	      file->fdr.cbLineOffset = c;
376633965Sjdp	    }
376733965Sjdp	  if (l->proc != proc)
376833965Sjdp	    {
376933965Sjdp	      proc = l->proc;
377033965Sjdp	      if (proc != (proc_t *) NULL)
377133965Sjdp		{
377233965Sjdp		  proc->pdr.lnLow = l->lineno;
377333965Sjdp		  proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset;
377433965Sjdp		  proc->pdr.iline = totcount;
377533965Sjdp		}
377633965Sjdp	    }
377733965Sjdp
377833965Sjdp	  last = (lineno_list_t *) NULL;
377933965Sjdp	}
378033965Sjdp
378133965Sjdp      totcount += count;
378233965Sjdp
378333965Sjdp      /* Get the offset to this line number.  */
378433965Sjdp      if (last == (lineno_list_t *) NULL)
378533965Sjdp	delta = 0;
378633965Sjdp      else
378733965Sjdp	delta = l->lineno - last->lineno;
378833965Sjdp
378933965Sjdp      /* Put in the offset to this line number.  */
379033965Sjdp      while (delta != 0)
379133965Sjdp	{
379233965Sjdp	  int setcount;
379333965Sjdp
379433965Sjdp	  /* 1 is added to each count read.  */
379533965Sjdp	  --count;
379633965Sjdp	  /* We can only adjust the word count by up to 15 words at a
379733965Sjdp	     time.  */
379833965Sjdp	  if (count <= 0x0f)
379933965Sjdp	    {
380033965Sjdp	      setcount = count;
380133965Sjdp	      count = 0;
380233965Sjdp	    }
380333965Sjdp	  else
380433965Sjdp	    {
380533965Sjdp	      setcount = 0x0f;
380633965Sjdp	      count -= 0x0f;
380733965Sjdp	    }
380833965Sjdp	  if (delta >= -7 && delta <= 7)
380933965Sjdp	    {
381033965Sjdp	      if (bufptr >= *bufend)
381133965Sjdp		bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
381233965Sjdp	      *bufptr++ = setcount + (delta << 4);
381333965Sjdp	      delta = 0;
381433965Sjdp	      ++c;
381533965Sjdp	    }
381633965Sjdp	  else
381733965Sjdp	    {
381833965Sjdp	      int set;
381933965Sjdp
382033965Sjdp	      if (*bufend - bufptr < 3)
382133965Sjdp		bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3);
382233965Sjdp	      *bufptr++ = setcount + (8 << 4);
382333965Sjdp	      if (delta < -0x8000)
382433965Sjdp		{
382533965Sjdp		  set = -0x8000;
382633965Sjdp		  delta += 0x8000;
382733965Sjdp		}
382833965Sjdp	      else if (delta > 0x7fff)
382933965Sjdp		{
383033965Sjdp		  set = 0x7fff;
383133965Sjdp		  delta -= 0x7fff;
383233965Sjdp		}
383333965Sjdp	      else
383433965Sjdp		{
383533965Sjdp		  set = delta;
383633965Sjdp		  delta = 0;
383733965Sjdp		}
383833965Sjdp	      *bufptr++ = set >> 8;
383933965Sjdp	      *bufptr++ = set & 0xffff;
384033965Sjdp	      c += 3;
384133965Sjdp	    }
384233965Sjdp	}
384333965Sjdp
384433965Sjdp      /* Finish adjusting the count.  */
384533965Sjdp      while (count > 0)
384633965Sjdp	{
384733965Sjdp	  if (bufptr >= *bufend)
384833965Sjdp	    bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
384933965Sjdp	  /* 1 is added to each count read.  */
385033965Sjdp	  --count;
385133965Sjdp	  if (count > 0x0f)
385233965Sjdp	    {
385333965Sjdp	      *bufptr++ = 0x0f;
385433965Sjdp	      count -= 0x0f;
385533965Sjdp	    }
385633965Sjdp	  else
385733965Sjdp	    {
385833965Sjdp	      *bufptr++ = count;
385933965Sjdp	      count = 0;
386033965Sjdp	    }
386133965Sjdp	  ++c;
386233965Sjdp	}
386333965Sjdp
386433965Sjdp      ++iline;
386533965Sjdp      last = l;
386633965Sjdp    }
386733965Sjdp
386833965Sjdp  if (proc != (proc_t *) NULL)
386933965Sjdp    proc->pdr.lnHigh = last->lineno;
387033965Sjdp  if (file != (efdr_t *) NULL)
387133965Sjdp    {
387233965Sjdp      file->fdr.cbLine = c - file->fdr.cbLineOffset;
387333965Sjdp      file->fdr.cline = totcount;
387433965Sjdp    }
387533965Sjdp
387633965Sjdp  if (linecntptr != (long *) NULL)
387733965Sjdp    *linecntptr += totcount;
387833965Sjdp
387933965Sjdp  c = ecoff_padding_adjust (backend, buf, bufend, c, &bufptr);
388033965Sjdp
388133965Sjdp  return c;
388233965Sjdp}
388333965Sjdp
388433965Sjdp/* Build and swap out the symbols.  */
388533965Sjdp
388633965Sjdpstatic unsigned long
3887130561Sobrienecoff_build_symbols (const struct ecoff_debug_swap *backend,
3888130561Sobrien		     char **buf,
3889130561Sobrien		     char **bufend,
3890130561Sobrien		     unsigned long offset)
389133965Sjdp{
389233965Sjdp  const bfd_size_type external_sym_size = backend->external_sym_size;
3893130561Sobrien  void (* const swap_sym_out) (bfd *, const SYMR *, PTR)
389433965Sjdp    = backend->swap_sym_out;
389533965Sjdp  char *sym_out;
389633965Sjdp  long isym;
389733965Sjdp  vlinks_t *file_link;
389833965Sjdp
389933965Sjdp  sym_out = *buf + offset;
390033965Sjdp
390133965Sjdp  isym = 0;
390233965Sjdp
390333965Sjdp  /* The symbols are stored by file.  */
390433965Sjdp  for (file_link = file_desc.first;
390533965Sjdp       file_link != (vlinks_t *) NULL;
390633965Sjdp       file_link = file_link->next)
390733965Sjdp    {
390833965Sjdp      int ifilesym;
390933965Sjdp      int fil_cnt;
391033965Sjdp      efdr_t *fil_ptr;
391133965Sjdp      efdr_t *fil_end;
391233965Sjdp
391333965Sjdp      if (file_link->next == (vlinks_t *) NULL)
391433965Sjdp	fil_cnt = file_desc.objects_last_page;
391533965Sjdp      else
391633965Sjdp	fil_cnt = file_desc.objects_per_page;
391733965Sjdp      fil_ptr = file_link->datum->file;
391833965Sjdp      fil_end = fil_ptr + fil_cnt;
391933965Sjdp      for (; fil_ptr < fil_end; fil_ptr++)
392033965Sjdp	{
392133965Sjdp	  vlinks_t *sym_link;
392233965Sjdp
392333965Sjdp	  fil_ptr->fdr.isymBase = isym;
392433965Sjdp	  ifilesym = isym;
392533965Sjdp	  for (sym_link = fil_ptr->symbols.first;
392633965Sjdp	       sym_link != (vlinks_t *) NULL;
392733965Sjdp	       sym_link = sym_link->next)
392833965Sjdp	    {
392933965Sjdp	      int sym_cnt;
393033965Sjdp	      localsym_t *sym_ptr;
393133965Sjdp	      localsym_t *sym_end;
393233965Sjdp
393333965Sjdp	      if (sym_link->next == (vlinks_t *) NULL)
393433965Sjdp		sym_cnt = fil_ptr->symbols.objects_last_page;
393533965Sjdp	      else
393633965Sjdp		sym_cnt = fil_ptr->symbols.objects_per_page;
393733965Sjdp	      sym_ptr = sym_link->datum->sym;
393833965Sjdp	      sym_end = sym_ptr + sym_cnt;
393933965Sjdp	      for (; sym_ptr < sym_end; sym_ptr++)
394033965Sjdp		{
394133965Sjdp		  int local;
394233965Sjdp		  symbolS *as_sym;
394333965Sjdp		  forward_t *f;
394433965Sjdp
394533965Sjdp		  know (sym_ptr->file_ptr == fil_ptr);
394633965Sjdp
394733965Sjdp		  /* If there is no associated gas symbol, then this
394833965Sjdp		     is a pure debugging symbol.  We have already
394933965Sjdp		     added the name (if any) to fil_ptr->strings.
395033965Sjdp		     Otherwise we must decide whether this is an
395133965Sjdp		     external or a local symbol (actually, it may be
395233965Sjdp		     both if the local provides additional debugging
395333965Sjdp		     information for the external).  */
395433965Sjdp		  local = 1;
395533965Sjdp		  as_sym = sym_ptr->as_sym;
395633965Sjdp		  if (as_sym != (symbolS *) NULL)
395733965Sjdp		    {
395833965Sjdp		      symint_t indx;
395933965Sjdp
396033965Sjdp		      /* The value of a block start symbol is the
396177298Sobrien		         offset from the start of the procedure.  For
396277298Sobrien		         other symbols we just use the gas value (but
396377298Sobrien		         we must offset it by the vma of the section,
396477298Sobrien		         just as BFD does, because BFD will not see
396577298Sobrien		         this value).  */
396633965Sjdp		      if (sym_ptr->ecoff_sym.asym.st == (int) st_Block
396733965Sjdp			  && sym_ptr->ecoff_sym.asym.sc == (int) sc_Text)
396833965Sjdp			{
396933965Sjdp			  symbolS *begin_sym;
397033965Sjdp
397133965Sjdp			  know (sym_ptr->proc_ptr != (proc_t *) NULL);
397233965Sjdp			  begin_sym = sym_ptr->proc_ptr->sym->as_sym;
397333965Sjdp			  if (S_GET_SEGMENT (as_sym)
397433965Sjdp			      != S_GET_SEGMENT (begin_sym))
397560484Sobrien			    as_warn (_(".begin/.bend in different segments"));
397633965Sjdp			  sym_ptr->ecoff_sym.asym.value =
397733965Sjdp			    S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
397833965Sjdp			}
397933965Sjdp		      else
398033965Sjdp			sym_ptr->ecoff_sym.asym.value =
398133965Sjdp			  (S_GET_VALUE (as_sym)
398233965Sjdp			   + bfd_get_section_vma (stdoutput,
398333965Sjdp						  S_GET_SEGMENT (as_sym))
398433965Sjdp			   + sym_ptr->addend);
398533965Sjdp
398633965Sjdp		      sym_ptr->ecoff_sym.weakext = S_IS_WEAK (as_sym);
398733965Sjdp
398833965Sjdp		      /* Set st_Proc to st_StaticProc for local
398933965Sjdp			 functions.  */
399033965Sjdp		      if (sym_ptr->ecoff_sym.asym.st == st_Proc
399133965Sjdp			  && S_IS_DEFINED (as_sym)
399233965Sjdp			  && ! S_IS_EXTERNAL (as_sym)
399333965Sjdp			  && ! S_IS_WEAK (as_sym))
399433965Sjdp			sym_ptr->ecoff_sym.asym.st = st_StaticProc;
399533965Sjdp
399633965Sjdp		      /* Get the type and storage class based on where
399777298Sobrien		         the symbol actually wound up.  Traditionally,
399877298Sobrien		         N_LBRAC and N_RBRAC are *not* relocated.  */
399933965Sjdp		      indx = sym_ptr->ecoff_sym.asym.index;
400033965Sjdp		      if (sym_ptr->ecoff_sym.asym.st == st_Nil
400133965Sjdp			  && sym_ptr->ecoff_sym.asym.sc == sc_Nil
400233965Sjdp			  && (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
400333965Sjdp			      || ((ECOFF_UNMARK_STAB (indx) != N_LBRAC)
400433965Sjdp				  && (ECOFF_UNMARK_STAB (indx) != N_RBRAC))))
400533965Sjdp			{
400633965Sjdp			  segT seg;
400733965Sjdp			  const char *segname;
400833965Sjdp			  st_t st;
400933965Sjdp			  sc_t sc;
401033965Sjdp
401133965Sjdp			  seg = S_GET_SEGMENT (as_sym);
401233965Sjdp			  segname = segment_name (seg);
401333965Sjdp
401433965Sjdp			  if (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
401533965Sjdp			      && (S_IS_EXTERNAL (as_sym)
401633965Sjdp				  || S_IS_WEAK (as_sym)
401733965Sjdp				  || ! S_IS_DEFINED (as_sym)))
401833965Sjdp			    {
401960484Sobrien			      if ((symbol_get_bfdsym (as_sym)->flags
402060484Sobrien				   & BSF_FUNCTION) != 0)
402133965Sjdp				st = st_Proc;
402233965Sjdp			      else
402333965Sjdp				st = st_Global;
402433965Sjdp			    }
402533965Sjdp			  else if (seg == text_section)
402633965Sjdp			    st = st_Label;
402733965Sjdp			  else
402833965Sjdp			    st = st_Static;
402933965Sjdp
403033965Sjdp			  if (! S_IS_DEFINED (as_sym))
403133965Sjdp			    {
403260484Sobrien			      valueT s;
403360484Sobrien
403460484Sobrien			      s = symbol_get_obj (as_sym)->ecoff_extern_size;
403560484Sobrien			      if (s == 0
403689857Sobrien				  || s > bfd_get_gp_size (stdoutput))
403733965Sjdp				sc = sc_Undefined;
403833965Sjdp			      else
403933965Sjdp				{
404033965Sjdp				  sc = sc_SUndefined;
404160484Sobrien				  sym_ptr->ecoff_sym.asym.value = s;
404233965Sjdp				}
404333965Sjdp#ifdef S_SET_SIZE
404460484Sobrien			      S_SET_SIZE (as_sym, s);
404533965Sjdp#endif
404633965Sjdp			    }
404733965Sjdp			  else if (S_IS_COMMON (as_sym))
404833965Sjdp			    {
404933965Sjdp			      if (S_GET_VALUE (as_sym) > 0
405033965Sjdp				  && (S_GET_VALUE (as_sym)
405189857Sobrien				      <= bfd_get_gp_size (stdoutput)))
405233965Sjdp				sc = sc_SCommon;
405333965Sjdp			      else
405433965Sjdp				sc = sc_Common;
405533965Sjdp			    }
405633965Sjdp			  else if (seg == text_section)
405733965Sjdp			    sc = sc_Text;
405833965Sjdp			  else if (seg == data_section)
405933965Sjdp			    sc = sc_Data;
406033965Sjdp			  else if (strcmp (segname, ".rdata") == 0
406133965Sjdp				   || strcmp (segname, ".rodata") == 0)
406233965Sjdp			    sc = sc_RData;
406333965Sjdp			  else if (strcmp (segname, ".sdata") == 0)
406433965Sjdp			    sc = sc_SData;
406533965Sjdp			  else if (seg == bss_section)
406633965Sjdp			    sc = sc_Bss;
406733965Sjdp			  else if (strcmp (segname, ".sbss") == 0)
406833965Sjdp			    sc = sc_SBss;
406933965Sjdp			  else if (seg == &bfd_abs_section)
407033965Sjdp			    sc = sc_Abs;
407133965Sjdp			  else
407233965Sjdp			    {
407333965Sjdp			      /* This must be a user named section.
407477298Sobrien			         This is not possible in ECOFF, but it
407577298Sobrien			         is in ELF.  */
407633965Sjdp			      sc = sc_Data;
407733965Sjdp			    }
407833965Sjdp
407933965Sjdp			  sym_ptr->ecoff_sym.asym.st = (int) st;
408033965Sjdp			  sym_ptr->ecoff_sym.asym.sc = (int) sc;
408133965Sjdp			}
408233965Sjdp
408333965Sjdp		      /* This is just an external symbol if it is
408477298Sobrien		         outside a procedure and it has a type.
408577298Sobrien		         FIXME: g++ will generate symbols which have
408677298Sobrien		         different names in the debugging information
408777298Sobrien		         than the actual symbol.  Should we handle
408877298Sobrien		         them here?  */
408933965Sjdp		      if ((S_IS_EXTERNAL (as_sym)
409033965Sjdp			   || S_IS_WEAK (as_sym)
409133965Sjdp			   || ! S_IS_DEFINED (as_sym))
409233965Sjdp			  && sym_ptr->proc_ptr == (proc_t *) NULL
409333965Sjdp			  && sym_ptr->ecoff_sym.asym.st != (int) st_Nil
409433965Sjdp			  && ! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym))
409533965Sjdp			local = 0;
409633965Sjdp
409733965Sjdp		      /* This is just an external symbol if it is a
409877298Sobrien		         common symbol.  */
409933965Sjdp		      if (S_IS_COMMON (as_sym))
410033965Sjdp			local = 0;
410133965Sjdp
410233965Sjdp		      /* If an st_end symbol has an associated gas
410377298Sobrien		         symbol, then it is a local label created for
410477298Sobrien		         a .bend or .end directive.  Stabs line
410577298Sobrien		         numbers will have \001 in the names.  */
410633965Sjdp		      if (local
410733965Sjdp			  && sym_ptr->ecoff_sym.asym.st != st_End
410833965Sjdp			  && strchr (sym_ptr->name, '\001') == 0)
410933965Sjdp			sym_ptr->ecoff_sym.asym.iss =
411033965Sjdp			  add_string (&fil_ptr->strings,
411133965Sjdp				      fil_ptr->str_hash,
411233965Sjdp				      sym_ptr->name,
411333965Sjdp				      (shash_t **) NULL);
411433965Sjdp		    }
411533965Sjdp
411633965Sjdp		  /* We now know the index of this symbol; fill in
411733965Sjdp		     locations that have been waiting for that
411833965Sjdp		     information.  */
411933965Sjdp		  if (sym_ptr->begin_ptr != (localsym_t *) NULL)
412033965Sjdp		    {
412133965Sjdp		      localsym_t *begin_ptr;
412233965Sjdp		      st_t begin_type;
412333965Sjdp
412433965Sjdp		      know (local);
412533965Sjdp		      begin_ptr = sym_ptr->begin_ptr;
412633965Sjdp		      know (begin_ptr->sym_index != -1);
412733965Sjdp		      sym_ptr->ecoff_sym.asym.index = begin_ptr->sym_index;
412833965Sjdp		      if (sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
412933965Sjdp			sym_ptr->ecoff_sym.asym.iss =
413033965Sjdp			  begin_ptr->ecoff_sym.asym.iss;
413133965Sjdp
413233965Sjdp		      begin_type = begin_ptr->ecoff_sym.asym.st;
413333965Sjdp		      if (begin_type == st_File
413433965Sjdp			  || begin_type == st_Block)
413533965Sjdp			{
413633965Sjdp			  begin_ptr->ecoff_sym.asym.index =
413733965Sjdp			    isym - ifilesym + 1;
413833965Sjdp			  (*swap_sym_out) (stdoutput,
413933965Sjdp					   &begin_ptr->ecoff_sym.asym,
414033965Sjdp					   (*buf
414133965Sjdp					    + offset
414233965Sjdp					    + (begin_ptr->sym_index
414333965Sjdp					       * external_sym_size)));
414433965Sjdp			}
414533965Sjdp		      else
414633965Sjdp			{
414733965Sjdp			  know (begin_ptr->index_ptr != (aux_t *) NULL);
414833965Sjdp			  begin_ptr->index_ptr->data.isym =
414933965Sjdp			    isym - ifilesym + 1;
415033965Sjdp			}
415133965Sjdp
415233965Sjdp		      /* The value of the symbol marking the end of a
415377298Sobrien		         procedure is the size of the procedure.  The
415477298Sobrien		         value of the symbol marking the end of a
415577298Sobrien		         block is the offset from the start of the
415677298Sobrien		         procedure to the block.  */
415733965Sjdp		      if (begin_type == st_Proc
415833965Sjdp			  || begin_type == st_StaticProc)
415933965Sjdp			{
416033965Sjdp			  know (as_sym != (symbolS *) NULL);
416133965Sjdp			  know (begin_ptr->as_sym != (symbolS *) NULL);
416233965Sjdp			  if (S_GET_SEGMENT (as_sym)
416333965Sjdp			      != S_GET_SEGMENT (begin_ptr->as_sym))
416460484Sobrien			    as_warn (_(".begin/.bend in different segments"));
416533965Sjdp			  sym_ptr->ecoff_sym.asym.value =
416633965Sjdp			    (S_GET_VALUE (as_sym)
416733965Sjdp			     - S_GET_VALUE (begin_ptr->as_sym));
416833965Sjdp
416933965Sjdp			  /* If the size is odd, this is probably a
417077298Sobrien			     mips16 function; force it to be even.  */
417133965Sjdp			  if ((sym_ptr->ecoff_sym.asym.value & 1) != 0)
417233965Sjdp			    ++sym_ptr->ecoff_sym.asym.value;
417333965Sjdp
417433965Sjdp#ifdef S_SET_SIZE
417533965Sjdp			  S_SET_SIZE (begin_ptr->as_sym,
417633965Sjdp				      sym_ptr->ecoff_sym.asym.value);
417733965Sjdp#endif
417833965Sjdp			}
417933965Sjdp		      else if (begin_type == st_Block
418033965Sjdp			       && sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
418133965Sjdp			{
418233965Sjdp			  symbolS *begin_sym;
418333965Sjdp
418433965Sjdp			  know (as_sym != (symbolS *) NULL);
418533965Sjdp			  know (sym_ptr->proc_ptr != (proc_t *) NULL);
418633965Sjdp			  begin_sym = sym_ptr->proc_ptr->sym->as_sym;
418733965Sjdp			  if (S_GET_SEGMENT (as_sym)
418833965Sjdp			      != S_GET_SEGMENT (begin_sym))
418960484Sobrien			    as_warn (_(".begin/.bend in different segments"));
419033965Sjdp			  sym_ptr->ecoff_sym.asym.value =
419133965Sjdp			    S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
419233965Sjdp			}
419333965Sjdp		    }
419433965Sjdp
419533965Sjdp		  for (f = sym_ptr->forward_ref;
419633965Sjdp		       f != (forward_t *) NULL;
419733965Sjdp		       f = f->next)
419833965Sjdp		    {
419933965Sjdp		      know (local);
420033965Sjdp		      f->ifd_ptr->data.isym = fil_ptr->file_index;
420133965Sjdp		      f->index_ptr->data.rndx.index = isym - ifilesym;
420233965Sjdp		    }
420333965Sjdp
420433965Sjdp		  if (local)
420533965Sjdp		    {
420678828Sobrien		      if ((bfd_size_type)(*bufend - sym_out) < external_sym_size)
420733965Sjdp			sym_out = ecoff_add_bytes (buf, bufend,
420833965Sjdp						   sym_out,
420933965Sjdp						   external_sym_size);
421033965Sjdp		      (*swap_sym_out) (stdoutput, &sym_ptr->ecoff_sym.asym,
421133965Sjdp				       sym_out);
421233965Sjdp		      sym_out += external_sym_size;
421333965Sjdp
421433965Sjdp		      sym_ptr->sym_index = isym;
421533965Sjdp
421633965Sjdp		      if (sym_ptr->proc_ptr != (proc_t *) NULL
421733965Sjdp			  && sym_ptr->proc_ptr->sym == sym_ptr)
421833965Sjdp			sym_ptr->proc_ptr->pdr.isym = isym - ifilesym;
421933965Sjdp
422033965Sjdp		      ++isym;
422133965Sjdp		    }
422233965Sjdp
422333965Sjdp		  /* Record the local symbol index and file number in
422433965Sjdp		     case this is an external symbol.  Note that this
422533965Sjdp		     destroys the asym.index field.  */
422633965Sjdp		  if (as_sym != (symbolS *) NULL
422760484Sobrien		      && symbol_get_obj (as_sym)->ecoff_symbol == sym_ptr)
422833965Sjdp		    {
422933965Sjdp		      if ((sym_ptr->ecoff_sym.asym.st == st_Proc
423033965Sjdp			   || sym_ptr->ecoff_sym.asym.st == st_StaticProc)
423133965Sjdp			  && local)
423233965Sjdp			sym_ptr->ecoff_sym.asym.index = isym - ifilesym - 1;
423333965Sjdp		      sym_ptr->ecoff_sym.ifd = fil_ptr->file_index;
423438889Sjdp
423538889Sjdp		      /* Don't try to merge an FDR which has an
423677298Sobrien		         external symbol attached to it.  */
423738889Sjdp		      if (S_IS_EXTERNAL (as_sym) || S_IS_WEAK (as_sym))
423838889Sjdp			fil_ptr->fdr.fMerge = 0;
423933965Sjdp		    }
424033965Sjdp		}
424133965Sjdp	    }
424233965Sjdp	  fil_ptr->fdr.csym = isym - fil_ptr->fdr.isymBase;
424333965Sjdp	}
424433965Sjdp    }
424533965Sjdp
424633965Sjdp  return offset + isym * external_sym_size;
424733965Sjdp}
424833965Sjdp
424933965Sjdp/* Swap out the procedure information.  */
425033965Sjdp
425133965Sjdpstatic unsigned long
4252130561Sobrienecoff_build_procs (const struct ecoff_debug_swap *backend,
4253130561Sobrien		   char **buf,
4254130561Sobrien		   char **bufend,
4255130561Sobrien		   unsigned long offset)
425633965Sjdp{
425733965Sjdp  const bfd_size_type external_pdr_size = backend->external_pdr_size;
4258130561Sobrien  void (* const swap_pdr_out) (bfd *, const PDR *, PTR)
425933965Sjdp    = backend->swap_pdr_out;
426033965Sjdp  char *pdr_out;
426133965Sjdp  long iproc;
426233965Sjdp  vlinks_t *file_link;
426333965Sjdp
426433965Sjdp  pdr_out = *buf + offset;
426533965Sjdp
426633965Sjdp  iproc = 0;
426733965Sjdp
426833965Sjdp  /* The procedures are stored by file.  */
426933965Sjdp  for (file_link = file_desc.first;
427033965Sjdp       file_link != (vlinks_t *) NULL;
427133965Sjdp       file_link = file_link->next)
427233965Sjdp    {
427333965Sjdp      int fil_cnt;
427433965Sjdp      efdr_t *fil_ptr;
427533965Sjdp      efdr_t *fil_end;
427633965Sjdp
427733965Sjdp      if (file_link->next == (vlinks_t *) NULL)
427833965Sjdp	fil_cnt = file_desc.objects_last_page;
427933965Sjdp      else
428033965Sjdp	fil_cnt = file_desc.objects_per_page;
428133965Sjdp      fil_ptr = file_link->datum->file;
428233965Sjdp      fil_end = fil_ptr + fil_cnt;
428333965Sjdp      for (; fil_ptr < fil_end; fil_ptr++)
428433965Sjdp	{
428533965Sjdp	  vlinks_t *proc_link;
428633965Sjdp	  int first;
428733965Sjdp
428833965Sjdp	  fil_ptr->fdr.ipdFirst = iproc;
428933965Sjdp	  first = 1;
429033965Sjdp	  for (proc_link = fil_ptr->procs.first;
429133965Sjdp	       proc_link != (vlinks_t *) NULL;
429233965Sjdp	       proc_link = proc_link->next)
429333965Sjdp	    {
429433965Sjdp	      int prc_cnt;
429533965Sjdp	      proc_t *proc_ptr;
429633965Sjdp	      proc_t *proc_end;
429733965Sjdp
429833965Sjdp	      if (proc_link->next == (vlinks_t *) NULL)
429933965Sjdp		prc_cnt = fil_ptr->procs.objects_last_page;
430033965Sjdp	      else
430133965Sjdp		prc_cnt = fil_ptr->procs.objects_per_page;
430233965Sjdp	      proc_ptr = proc_link->datum->proc;
430333965Sjdp	      proc_end = proc_ptr + prc_cnt;
430433965Sjdp	      for (; proc_ptr < proc_end; proc_ptr++)
430533965Sjdp		{
430633965Sjdp		  symbolS *adr_sym;
430733965Sjdp		  unsigned long adr;
430833965Sjdp
430933965Sjdp		  adr_sym = proc_ptr->sym->as_sym;
431033965Sjdp		  adr = (S_GET_VALUE (adr_sym)
431133965Sjdp			 + bfd_get_section_vma (stdoutput,
431233965Sjdp						S_GET_SEGMENT (adr_sym)));
431333965Sjdp		  if (first)
431433965Sjdp		    {
431533965Sjdp		      /* This code used to force the adr of the very
431677298Sobrien		         first fdr to be 0.  However, the native tools
431777298Sobrien		         don't do that, and I can't remember why it
431877298Sobrien		         used to work that way, so I took it out.  */
431933965Sjdp		      fil_ptr->fdr.adr = adr;
432033965Sjdp		      first = 0;
432133965Sjdp		    }
432233965Sjdp		  proc_ptr->pdr.adr = adr - fil_ptr->fdr.adr;
432378828Sobrien		  if ((bfd_size_type)(*bufend - pdr_out) < external_pdr_size)
432433965Sjdp		    pdr_out = ecoff_add_bytes (buf, bufend,
432533965Sjdp					       pdr_out,
432633965Sjdp					       external_pdr_size);
432733965Sjdp		  (*swap_pdr_out) (stdoutput, &proc_ptr->pdr, pdr_out);
432833965Sjdp		  pdr_out += external_pdr_size;
432933965Sjdp		  ++iproc;
433033965Sjdp		}
433133965Sjdp	    }
433233965Sjdp	  fil_ptr->fdr.cpd = iproc - fil_ptr->fdr.ipdFirst;
433333965Sjdp	}
433433965Sjdp    }
433533965Sjdp
433633965Sjdp  return offset + iproc * external_pdr_size;
433733965Sjdp}
433833965Sjdp
433933965Sjdp/* Swap out the aux information.  */
434033965Sjdp
434133965Sjdpstatic unsigned long
4342130561Sobrienecoff_build_aux (const struct ecoff_debug_swap *backend,
4343130561Sobrien		 char **buf,
4344130561Sobrien		 char **bufend,
4345130561Sobrien		 unsigned long offset)
434633965Sjdp{
434733965Sjdp  int bigendian;
434833965Sjdp  union aux_ext *aux_out;
434933965Sjdp  long iaux;
435033965Sjdp  vlinks_t *file_link;
435133965Sjdp
435233965Sjdp  bigendian = bfd_big_endian (stdoutput);
435333965Sjdp
435433965Sjdp  aux_out = (union aux_ext *) (*buf + offset);
435533965Sjdp
435633965Sjdp  iaux = 0;
435733965Sjdp
435833965Sjdp  /* The aux entries are stored by file.  */
435933965Sjdp  for (file_link = file_desc.first;
436033965Sjdp       file_link != (vlinks_t *) NULL;
436133965Sjdp       file_link = file_link->next)
436233965Sjdp    {
436333965Sjdp      int fil_cnt;
436433965Sjdp      efdr_t *fil_ptr;
436533965Sjdp      efdr_t *fil_end;
436633965Sjdp
436733965Sjdp      if (file_link->next == (vlinks_t *) NULL)
436833965Sjdp	fil_cnt = file_desc.objects_last_page;
436933965Sjdp      else
437033965Sjdp	fil_cnt = file_desc.objects_per_page;
437133965Sjdp      fil_ptr = file_link->datum->file;
437233965Sjdp      fil_end = fil_ptr + fil_cnt;
437333965Sjdp      for (; fil_ptr < fil_end; fil_ptr++)
437433965Sjdp	{
437533965Sjdp	  vlinks_t *aux_link;
437633965Sjdp
437733965Sjdp	  fil_ptr->fdr.fBigendian = bigendian;
437833965Sjdp	  fil_ptr->fdr.iauxBase = iaux;
437933965Sjdp	  for (aux_link = fil_ptr->aux_syms.first;
438033965Sjdp	       aux_link != (vlinks_t *) NULL;
438133965Sjdp	       aux_link = aux_link->next)
438233965Sjdp	    {
438333965Sjdp	      int aux_cnt;
438433965Sjdp	      aux_t *aux_ptr;
438533965Sjdp	      aux_t *aux_end;
438633965Sjdp
438733965Sjdp	      if (aux_link->next == (vlinks_t *) NULL)
438833965Sjdp		aux_cnt = fil_ptr->aux_syms.objects_last_page;
438933965Sjdp	      else
439033965Sjdp		aux_cnt = fil_ptr->aux_syms.objects_per_page;
439133965Sjdp	      aux_ptr = aux_link->datum->aux;
439233965Sjdp	      aux_end = aux_ptr + aux_cnt;
439333965Sjdp	      for (; aux_ptr < aux_end; aux_ptr++)
439433965Sjdp		{
439578828Sobrien		  if ((unsigned long) (*bufend - (char *) aux_out)
439678828Sobrien		      < sizeof (union aux_ext))
439733965Sjdp		    aux_out = ((union aux_ext *)
439833965Sjdp			       ecoff_add_bytes (buf, bufend,
439933965Sjdp						(char *) aux_out,
440033965Sjdp						sizeof (union aux_ext)));
440133965Sjdp		  switch (aux_ptr->type)
440233965Sjdp		    {
440333965Sjdp		    case aux_tir:
440433965Sjdp		      (*backend->swap_tir_out) (bigendian,
440533965Sjdp						&aux_ptr->data.ti,
440633965Sjdp						&aux_out->a_ti);
440733965Sjdp		      break;
440833965Sjdp		    case aux_rndx:
440933965Sjdp		      (*backend->swap_rndx_out) (bigendian,
441033965Sjdp						 &aux_ptr->data.rndx,
441133965Sjdp						 &aux_out->a_rndx);
441233965Sjdp		      break;
441333965Sjdp		    case aux_dnLow:
441433965Sjdp		      AUX_PUT_DNLOW (bigendian, aux_ptr->data.dnLow,
441533965Sjdp				     aux_out);
441633965Sjdp		      break;
441733965Sjdp		    case aux_dnHigh:
441833965Sjdp		      AUX_PUT_DNHIGH (bigendian, aux_ptr->data.dnHigh,
441933965Sjdp				      aux_out);
442033965Sjdp		      break;
442133965Sjdp		    case aux_isym:
442233965Sjdp		      AUX_PUT_ISYM (bigendian, aux_ptr->data.isym,
442333965Sjdp				    aux_out);
442433965Sjdp		      break;
442533965Sjdp		    case aux_iss:
442633965Sjdp		      AUX_PUT_ISS (bigendian, aux_ptr->data.iss,
442733965Sjdp				   aux_out);
442833965Sjdp		      break;
442933965Sjdp		    case aux_width:
443033965Sjdp		      AUX_PUT_WIDTH (bigendian, aux_ptr->data.width,
443133965Sjdp				     aux_out);
443233965Sjdp		      break;
443333965Sjdp		    case aux_count:
443433965Sjdp		      AUX_PUT_COUNT (bigendian, aux_ptr->data.count,
443533965Sjdp				     aux_out);
443633965Sjdp		      break;
443733965Sjdp		    }
443833965Sjdp
443933965Sjdp		  ++aux_out;
444033965Sjdp		  ++iaux;
444133965Sjdp		}
444233965Sjdp	    }
444333965Sjdp	  fil_ptr->fdr.caux = iaux - fil_ptr->fdr.iauxBase;
444433965Sjdp	}
444533965Sjdp    }
444633965Sjdp
444733965Sjdp  return ecoff_padding_adjust (backend, buf, bufend,
444833965Sjdp			       offset + iaux * sizeof (union aux_ext),
444933965Sjdp			       (char **) NULL);
445033965Sjdp}
445133965Sjdp
445233965Sjdp/* Copy out the strings from a varray_t.  This returns the number of
445333965Sjdp   bytes copied, rather than the new offset.  */
445433965Sjdp
445533965Sjdpstatic unsigned long
4456130561Sobrienecoff_build_strings (char **buf,
4457130561Sobrien		     char **bufend,
4458130561Sobrien		     unsigned long offset,
4459130561Sobrien		     varray_t *vp)
446033965Sjdp{
446133965Sjdp  unsigned long istr;
446233965Sjdp  char *str_out;
446333965Sjdp  vlinks_t *str_link;
446433965Sjdp
446533965Sjdp  str_out = *buf + offset;
446633965Sjdp
446733965Sjdp  istr = 0;
446833965Sjdp
446933965Sjdp  for (str_link = vp->first;
447033965Sjdp       str_link != (vlinks_t *) NULL;
447133965Sjdp       str_link = str_link->next)
447233965Sjdp    {
447333965Sjdp      unsigned long str_cnt;
447433965Sjdp
447533965Sjdp      if (str_link->next == (vlinks_t *) NULL)
447633965Sjdp	str_cnt = vp->objects_last_page;
447733965Sjdp      else
447833965Sjdp	str_cnt = vp->objects_per_page;
447933965Sjdp
448078828Sobrien      if ((unsigned long)(*bufend - str_out) < str_cnt)
448133965Sjdp	str_out = ecoff_add_bytes (buf, bufend, str_out, str_cnt);
448233965Sjdp
448333965Sjdp      memcpy (str_out, str_link->datum->byte, str_cnt);
448433965Sjdp      str_out += str_cnt;
448533965Sjdp      istr += str_cnt;
448633965Sjdp    }
448733965Sjdp
448833965Sjdp  return istr;
448933965Sjdp}
449033965Sjdp
449133965Sjdp/* Dump out the local strings.  */
449233965Sjdp
449333965Sjdpstatic unsigned long
4494130561Sobrienecoff_build_ss (const struct ecoff_debug_swap *backend,
4495130561Sobrien		char **buf,
4496130561Sobrien		char **bufend,
4497130561Sobrien		unsigned long offset)
449833965Sjdp{
449933965Sjdp  long iss;
450033965Sjdp  vlinks_t *file_link;
450133965Sjdp
450233965Sjdp  iss = 0;
450333965Sjdp
450433965Sjdp  for (file_link = file_desc.first;
450533965Sjdp       file_link != (vlinks_t *) NULL;
450633965Sjdp       file_link = file_link->next)
450733965Sjdp    {
450833965Sjdp      int fil_cnt;
450933965Sjdp      efdr_t *fil_ptr;
451033965Sjdp      efdr_t *fil_end;
451133965Sjdp
451233965Sjdp      if (file_link->next == (vlinks_t *) NULL)
451333965Sjdp	fil_cnt = file_desc.objects_last_page;
451433965Sjdp      else
451533965Sjdp	fil_cnt = file_desc.objects_per_page;
451633965Sjdp      fil_ptr = file_link->datum->file;
451733965Sjdp      fil_end = fil_ptr + fil_cnt;
451833965Sjdp      for (; fil_ptr < fil_end; fil_ptr++)
451933965Sjdp	{
452033965Sjdp	  long ss_cnt;
452133965Sjdp
452233965Sjdp	  fil_ptr->fdr.issBase = iss;
452333965Sjdp	  ss_cnt = ecoff_build_strings (buf, bufend, offset + iss,
452433965Sjdp					&fil_ptr->strings);
452533965Sjdp	  fil_ptr->fdr.cbSs = ss_cnt;
452633965Sjdp	  iss += ss_cnt;
452733965Sjdp	}
452833965Sjdp    }
452933965Sjdp
453033965Sjdp  return ecoff_padding_adjust (backend, buf, bufend, offset + iss,
453133965Sjdp			       (char **) NULL);
453233965Sjdp}
453333965Sjdp
453433965Sjdp/* Swap out the file descriptors.  */
453533965Sjdp
453633965Sjdpstatic unsigned long
4537130561Sobrienecoff_build_fdr (const struct ecoff_debug_swap *backend,
4538130561Sobrien		 char **buf,
4539130561Sobrien		 char **bufend,
4540130561Sobrien		 unsigned long offset)
454133965Sjdp{
454233965Sjdp  const bfd_size_type external_fdr_size = backend->external_fdr_size;
4543130561Sobrien  void (* const swap_fdr_out) (bfd *, const FDR *, PTR)
454433965Sjdp    = backend->swap_fdr_out;
454533965Sjdp  long ifile;
454633965Sjdp  char *fdr_out;
454733965Sjdp  vlinks_t *file_link;
454833965Sjdp
454933965Sjdp  ifile = 0;
455033965Sjdp
455133965Sjdp  fdr_out = *buf + offset;
455233965Sjdp
455333965Sjdp  for (file_link = file_desc.first;
455433965Sjdp       file_link != (vlinks_t *) NULL;
455533965Sjdp       file_link = file_link->next)
455633965Sjdp    {
455733965Sjdp      int fil_cnt;
455833965Sjdp      efdr_t *fil_ptr;
455933965Sjdp      efdr_t *fil_end;
456033965Sjdp
456133965Sjdp      if (file_link->next == (vlinks_t *) NULL)
456233965Sjdp	fil_cnt = file_desc.objects_last_page;
456333965Sjdp      else
456433965Sjdp	fil_cnt = file_desc.objects_per_page;
456533965Sjdp      fil_ptr = file_link->datum->file;
456633965Sjdp      fil_end = fil_ptr + fil_cnt;
456733965Sjdp      for (; fil_ptr < fil_end; fil_ptr++)
456833965Sjdp	{
456978828Sobrien	  if ((bfd_size_type)(*bufend - fdr_out) < external_fdr_size)
457033965Sjdp	    fdr_out = ecoff_add_bytes (buf, bufend, fdr_out,
457133965Sjdp				       external_fdr_size);
457233965Sjdp	  (*swap_fdr_out) (stdoutput, &fil_ptr->fdr, fdr_out);
457333965Sjdp	  fdr_out += external_fdr_size;
457433965Sjdp	  ++ifile;
457533965Sjdp	}
457633965Sjdp    }
457733965Sjdp
457833965Sjdp  return offset + ifile * external_fdr_size;
457933965Sjdp}
458033965Sjdp
458133965Sjdp/* Set up the external symbols.  These are supposed to be handled by
458233965Sjdp   the backend.  This routine just gets the right information and
458333965Sjdp   calls a backend function to deal with it.  */
458433965Sjdp
458533965Sjdpstatic void
4586130561Sobrienecoff_setup_ext (void)
458733965Sjdp{
458833965Sjdp  register symbolS *sym;
458933965Sjdp
459033965Sjdp  for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
459133965Sjdp    {
459260484Sobrien      if (symbol_get_obj (sym)->ecoff_symbol == NULL)
459333965Sjdp	continue;
459433965Sjdp
459533965Sjdp      /* If this is a local symbol, then force the fields to zero.  */
459633965Sjdp      if (! S_IS_EXTERNAL (sym)
459733965Sjdp	  && ! S_IS_WEAK (sym)
459833965Sjdp	  && S_IS_DEFINED (sym))
459933965Sjdp	{
460060484Sobrien	  struct localsym *lsym;
460160484Sobrien
460260484Sobrien	  lsym = symbol_get_obj (sym)->ecoff_symbol;
460360484Sobrien	  lsym->ecoff_sym.asym.value = 0;
460460484Sobrien	  lsym->ecoff_sym.asym.st = (int) st_Nil;
460560484Sobrien	  lsym->ecoff_sym.asym.sc = (int) sc_Nil;
460660484Sobrien	  lsym->ecoff_sym.asym.index = indexNil;
460733965Sjdp	}
460833965Sjdp
460960484Sobrien      obj_ecoff_set_ext (sym, &symbol_get_obj (sym)->ecoff_symbol->ecoff_sym);
461033965Sjdp    }
461133965Sjdp}
461233965Sjdp
461333965Sjdp/* Build the ECOFF debugging information.  */
461433965Sjdp
461533965Sjdpunsigned long
4616130561Sobrienecoff_build_debug (HDRR *hdr,
4617130561Sobrien		   char **bufp,
4618130561Sobrien		   const struct ecoff_debug_swap *backend)
461933965Sjdp{
462033965Sjdp  const bfd_size_type external_pdr_size = backend->external_pdr_size;
462133965Sjdp  tag_t *ptag;
462233965Sjdp  tag_t *ptag_next;
462333965Sjdp  efdr_t *fil_ptr;
462433965Sjdp  int end_warning;
462533965Sjdp  efdr_t *hold_file_ptr;
462677298Sobrien  proc_t *hold_proc_ptr;
462733965Sjdp  symbolS *sym;
462833965Sjdp  char *buf;
462933965Sjdp  char *bufend;
463033965Sjdp  unsigned long offset;
463133965Sjdp
463233965Sjdp  /* Make sure we have a file.  */
463333965Sjdp  if (first_file == (efdr_t *) NULL)
463433965Sjdp    add_file ((const char *) NULL, 0, 1);
463533965Sjdp
463633965Sjdp  /* Handle any top level tags.  */
463733965Sjdp  for (ptag = top_tag_head->first_tag;
463833965Sjdp       ptag != (tag_t *) NULL;
463933965Sjdp       ptag = ptag_next)
464033965Sjdp    {
464133965Sjdp      if (ptag->forward_ref != (forward_t *) NULL)
464233965Sjdp	add_unknown_tag (ptag);
464333965Sjdp
464433965Sjdp      ptag_next = ptag->same_block;
464533965Sjdp      ptag->hash_ptr->tag_ptr = ptag->same_name;
464633965Sjdp      free_tag (ptag);
464733965Sjdp    }
464833965Sjdp
464933965Sjdp  free_thead (top_tag_head);
465033965Sjdp
465133965Sjdp  /* Look through the symbols.  Add debugging information for each
465233965Sjdp     symbol that has not already received it.  */
465333965Sjdp  hold_file_ptr = cur_file_ptr;
465433965Sjdp  hold_proc_ptr = cur_proc_ptr;
465533965Sjdp  cur_proc_ptr = (proc_t *) NULL;
465633965Sjdp  for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
465733965Sjdp    {
465860484Sobrien      if (symbol_get_obj (sym)->ecoff_symbol != NULL
465960484Sobrien	  || symbol_get_obj (sym)->ecoff_file == (efdr_t *) NULL
466060484Sobrien	  || (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0)
466133965Sjdp	continue;
466233965Sjdp
466360484Sobrien      cur_file_ptr = symbol_get_obj (sym)->ecoff_file;
466433965Sjdp      add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym,
466533965Sjdp			(bfd_vma) 0, S_GET_VALUE (sym), indexNil);
466633965Sjdp    }
466733965Sjdp  cur_proc_ptr = hold_proc_ptr;
466833965Sjdp  cur_file_ptr = hold_file_ptr;
466933965Sjdp
467033965Sjdp  /* Output an ending symbol for all the files.  We have to do this
467133965Sjdp     here for the last file, so we may as well do it for all of the
467233965Sjdp     files.  */
467333965Sjdp  end_warning = 0;
467433965Sjdp  for (fil_ptr = first_file;
467533965Sjdp       fil_ptr != (efdr_t *) NULL;
467633965Sjdp       fil_ptr = fil_ptr->next_file)
467733965Sjdp    {
467833965Sjdp      cur_file_ptr = fil_ptr;
467933965Sjdp      while (cur_file_ptr->cur_scope != (scope_t *) NULL
468033965Sjdp	     && cur_file_ptr->cur_scope->prev != (scope_t *) NULL)
468133965Sjdp	{
468233965Sjdp	  cur_file_ptr->cur_scope = cur_file_ptr->cur_scope->prev;
468333965Sjdp	  if (! end_warning && ! cur_file_ptr->fake)
468433965Sjdp	    {
468589857Sobrien	      as_warn (_("missing .end or .bend at end of file"));
468633965Sjdp	      end_warning = 1;
468733965Sjdp	    }
468833965Sjdp	}
468933965Sjdp      if (cur_file_ptr->cur_scope != (scope_t *) NULL)
469033965Sjdp	(void) add_ecoff_symbol ((const char *) NULL,
469133965Sjdp				 st_End, sc_Text,
469233965Sjdp				 (symbolS *) NULL,
469333965Sjdp				 (bfd_vma) 0,
469433965Sjdp				 (symint_t) 0,
469533965Sjdp				 (symint_t) 0);
469633965Sjdp    }
469733965Sjdp
469833965Sjdp  /* Build the symbolic information.  */
469933965Sjdp  offset = 0;
470033965Sjdp  buf = xmalloc (PAGE_SIZE);
470133965Sjdp  bufend = buf + PAGE_SIZE;
470233965Sjdp
470333965Sjdp  /* Build the line number information.  */
470433965Sjdp  hdr->cbLineOffset = offset;
470533965Sjdp  offset = ecoff_build_lineno (backend, &buf, &bufend, offset,
470633965Sjdp			       &hdr->ilineMax);
470733965Sjdp  hdr->cbLine = offset - hdr->cbLineOffset;
470833965Sjdp
470933965Sjdp  /* We don't use dense numbers at all.  */
471033965Sjdp  hdr->idnMax = 0;
471133965Sjdp  hdr->cbDnOffset = 0;
471233965Sjdp
471333965Sjdp  /* We can't build the PDR table until we have built the symbols,
471433965Sjdp     because a PDR contains a symbol index.  However, we set aside
471533965Sjdp     space at this point.  */
471633965Sjdp  hdr->ipdMax = proc_cnt;
471733965Sjdp  hdr->cbPdOffset = offset;
471878828Sobrien  if ((bfd_size_type)(bufend - (buf + offset)) < proc_cnt * external_pdr_size)
471933965Sjdp    (void) ecoff_add_bytes (&buf, &bufend, buf + offset,
472033965Sjdp			    proc_cnt * external_pdr_size);
472133965Sjdp  offset += proc_cnt * external_pdr_size;
472233965Sjdp
472333965Sjdp  /* Build the local symbols.  */
472433965Sjdp  hdr->cbSymOffset = offset;
472533965Sjdp  offset = ecoff_build_symbols (backend, &buf, &bufend, offset);
472633965Sjdp  hdr->isymMax = (offset - hdr->cbSymOffset) / backend->external_sym_size;
472733965Sjdp
472833965Sjdp  /* Building the symbols initializes the symbol index in the PDR's.
472933965Sjdp     Now we can swap out the PDR's.  */
473033965Sjdp  (void) ecoff_build_procs (backend, &buf, &bufend, hdr->cbPdOffset);
473133965Sjdp
473233965Sjdp  /* We don't use optimization symbols.  */
473333965Sjdp  hdr->ioptMax = 0;
473433965Sjdp  hdr->cbOptOffset = 0;
473533965Sjdp
473633965Sjdp  /* Swap out the auxiliary type information.  */
473733965Sjdp  hdr->cbAuxOffset = offset;
473833965Sjdp  offset = ecoff_build_aux (backend, &buf, &bufend, offset);
473933965Sjdp  hdr->iauxMax = (offset - hdr->cbAuxOffset) / sizeof (union aux_ext);
474033965Sjdp
474133965Sjdp  /* Copy out the local strings.  */
474233965Sjdp  hdr->cbSsOffset = offset;
474333965Sjdp  offset = ecoff_build_ss (backend, &buf, &bufend, offset);
474433965Sjdp  hdr->issMax = offset - hdr->cbSsOffset;
474533965Sjdp
474633965Sjdp  /* We don't use relative file descriptors.  */
474733965Sjdp  hdr->crfd = 0;
474833965Sjdp  hdr->cbRfdOffset = 0;
474933965Sjdp
475033965Sjdp  /* Swap out the file descriptors.  */
475133965Sjdp  hdr->cbFdOffset = offset;
475233965Sjdp  offset = ecoff_build_fdr (backend, &buf, &bufend, offset);
475333965Sjdp  hdr->ifdMax = (offset - hdr->cbFdOffset) / backend->external_fdr_size;
475433965Sjdp
475533965Sjdp  /* Set up the external symbols, which are handled by the BFD back
475633965Sjdp     end.  */
475733965Sjdp  hdr->issExtMax = 0;
475833965Sjdp  hdr->cbSsExtOffset = 0;
475933965Sjdp  hdr->iextMax = 0;
476033965Sjdp  hdr->cbExtOffset = 0;
476133965Sjdp  ecoff_setup_ext ();
476233965Sjdp
476333965Sjdp  know ((offset & (backend->debug_align - 1)) == 0);
476433965Sjdp
476533965Sjdp  /* FIXME: This value should be determined from the .verstamp directive,
476633965Sjdp     with reasonable defaults in config files.  */
476733965Sjdp#ifdef TC_ALPHA
476833965Sjdp  hdr->vstamp = 0x030b;
476933965Sjdp#else
477033965Sjdp  hdr->vstamp = 0x020b;
477133965Sjdp#endif
477233965Sjdp
477333965Sjdp  *bufp = buf;
477433965Sjdp  return offset;
477533965Sjdp}
477633965Sjdp
477733965Sjdp/* Allocate a cluster of pages.  */
477833965Sjdp
477933965Sjdp#ifndef MALLOC_CHECK
478033965Sjdp
478138889Sjdpstatic page_type *
4782130561Sobrienallocate_cluster (unsigned long npages)
478333965Sjdp{
478438889Sjdp  register page_type *value = (page_type *) xmalloc (npages * PAGE_USIZE);
478533965Sjdp
478633965Sjdp#ifdef ECOFF_DEBUG
478733965Sjdp  if (debug > 3)
478833965Sjdp    fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
478933965Sjdp#endif
479033965Sjdp
479133965Sjdp  memset (value, 0, npages * PAGE_USIZE);
479233965Sjdp
479333965Sjdp  return value;
479433965Sjdp}
479533965Sjdp
479638889Sjdpstatic page_type *cluster_ptr = NULL;
479733965Sjdpstatic unsigned long pages_left = 0;
479833965Sjdp
479933965Sjdp#endif /* MALLOC_CHECK */
480033965Sjdp
480133965Sjdp/* Allocate one page (which is initialized to 0).  */
480233965Sjdp
480338889Sjdpstatic page_type *
4804130561Sobrienallocate_page (void)
480533965Sjdp{
480633965Sjdp#ifndef MALLOC_CHECK
480733965Sjdp
480833965Sjdp  if (pages_left == 0)
480933965Sjdp    {
481033965Sjdp      pages_left = MAX_CLUSTER_PAGES;
481133965Sjdp      cluster_ptr = allocate_cluster (pages_left);
481233965Sjdp    }
481333965Sjdp
481433965Sjdp  pages_left--;
481533965Sjdp  return cluster_ptr++;
481633965Sjdp
481777298Sobrien#else /* MALLOC_CHECK */
481833965Sjdp
481938889Sjdp  page_type *ptr;
482033965Sjdp
482133965Sjdp  ptr = xmalloc (PAGE_USIZE);
482233965Sjdp  memset (ptr, 0, PAGE_USIZE);
482333965Sjdp  return ptr;
482433965Sjdp
482577298Sobrien#endif /* MALLOC_CHECK */
482633965Sjdp}
482733965Sjdp
482833965Sjdp/* Allocate scoping information.  */
482933965Sjdp
483033965Sjdpstatic scope_t *
4831130561Sobrienallocate_scope (void)
483233965Sjdp{
483333965Sjdp  register scope_t *ptr;
483433965Sjdp  static scope_t initial_scope;
483533965Sjdp
483633965Sjdp#ifndef MALLOC_CHECK
483733965Sjdp
483877298Sobrien  ptr = alloc_counts[(int) alloc_type_scope].free_list.f_scope;
483933965Sjdp  if (ptr != (scope_t *) NULL)
484077298Sobrien    alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr->free;
484133965Sjdp  else
484233965Sjdp    {
484377298Sobrien      register int unallocated	= alloc_counts[(int) alloc_type_scope].unallocated;
484477298Sobrien      register page_type *cur_page	= alloc_counts[(int) alloc_type_scope].cur_page;
484533965Sjdp
484633965Sjdp      if (unallocated == 0)
484733965Sjdp	{
484833965Sjdp	  unallocated = PAGE_SIZE / sizeof (scope_t);
484977298Sobrien	  alloc_counts[(int) alloc_type_scope].cur_page = cur_page = allocate_page ();
485077298Sobrien	  alloc_counts[(int) alloc_type_scope].total_pages++;
485133965Sjdp	}
485233965Sjdp
485333965Sjdp      ptr = &cur_page->scope[--unallocated];
485477298Sobrien      alloc_counts[(int) alloc_type_scope].unallocated = unallocated;
485533965Sjdp    }
485633965Sjdp
485733965Sjdp#else
485833965Sjdp
485933965Sjdp  ptr = (scope_t *) xmalloc (sizeof (scope_t));
486033965Sjdp
486133965Sjdp#endif
486233965Sjdp
486377298Sobrien  alloc_counts[(int) alloc_type_scope].total_alloc++;
486433965Sjdp  *ptr = initial_scope;
486533965Sjdp  return ptr;
486633965Sjdp}
486733965Sjdp
486833965Sjdp/* Free scoping information.  */
486933965Sjdp
487033965Sjdpstatic void
4871130561Sobrienfree_scope (scope_t *ptr)
487233965Sjdp{
487377298Sobrien  alloc_counts[(int) alloc_type_scope].total_free++;
487433965Sjdp
487533965Sjdp#ifndef MALLOC_CHECK
487677298Sobrien  ptr->free = alloc_counts[(int) alloc_type_scope].free_list.f_scope;
487777298Sobrien  alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr;
487833965Sjdp#else
487933965Sjdp  free ((PTR) ptr);
488033965Sjdp#endif
488133965Sjdp}
488233965Sjdp
488333965Sjdp/* Allocate links for pages in a virtual array.  */
488433965Sjdp
488533965Sjdpstatic vlinks_t *
4886130561Sobrienallocate_vlinks (void)
488733965Sjdp{
488833965Sjdp  register vlinks_t *ptr;
488933965Sjdp  static vlinks_t initial_vlinks;
489033965Sjdp
489133965Sjdp#ifndef MALLOC_CHECK
489233965Sjdp
489377298Sobrien  register int unallocated = alloc_counts[(int) alloc_type_vlinks].unallocated;
489477298Sobrien  register page_type *cur_page = alloc_counts[(int) alloc_type_vlinks].cur_page;
489533965Sjdp
489633965Sjdp  if (unallocated == 0)
489733965Sjdp    {
489833965Sjdp      unallocated = PAGE_SIZE / sizeof (vlinks_t);
489977298Sobrien      alloc_counts[(int) alloc_type_vlinks].cur_page = cur_page = allocate_page ();
490077298Sobrien      alloc_counts[(int) alloc_type_vlinks].total_pages++;
490133965Sjdp    }
490233965Sjdp
490333965Sjdp  ptr = &cur_page->vlinks[--unallocated];
490477298Sobrien  alloc_counts[(int) alloc_type_vlinks].unallocated = unallocated;
490533965Sjdp
490633965Sjdp#else
490733965Sjdp
490833965Sjdp  ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t));
490933965Sjdp
491033965Sjdp#endif
491133965Sjdp
491277298Sobrien  alloc_counts[(int) alloc_type_vlinks].total_alloc++;
491333965Sjdp  *ptr = initial_vlinks;
491433965Sjdp  return ptr;
491533965Sjdp}
491633965Sjdp
491733965Sjdp/* Allocate string hash buckets.  */
491833965Sjdp
491933965Sjdpstatic shash_t *
4920130561Sobrienallocate_shash (void)
492133965Sjdp{
492233965Sjdp  register shash_t *ptr;
492333965Sjdp  static shash_t initial_shash;
492433965Sjdp
492533965Sjdp#ifndef MALLOC_CHECK
492633965Sjdp
492777298Sobrien  register int unallocated = alloc_counts[(int) alloc_type_shash].unallocated;
492877298Sobrien  register page_type *cur_page = alloc_counts[(int) alloc_type_shash].cur_page;
492933965Sjdp
493033965Sjdp  if (unallocated == 0)
493133965Sjdp    {
493233965Sjdp      unallocated = PAGE_SIZE / sizeof (shash_t);
493377298Sobrien      alloc_counts[(int) alloc_type_shash].cur_page = cur_page = allocate_page ();
493477298Sobrien      alloc_counts[(int) alloc_type_shash].total_pages++;
493533965Sjdp    }
493633965Sjdp
493733965Sjdp  ptr = &cur_page->shash[--unallocated];
493877298Sobrien  alloc_counts[(int) alloc_type_shash].unallocated = unallocated;
493933965Sjdp
494033965Sjdp#else
494133965Sjdp
494233965Sjdp  ptr = (shash_t *) xmalloc (sizeof (shash_t));
494333965Sjdp
494433965Sjdp#endif
494533965Sjdp
494677298Sobrien  alloc_counts[(int) alloc_type_shash].total_alloc++;
494733965Sjdp  *ptr = initial_shash;
494833965Sjdp  return ptr;
494933965Sjdp}
495033965Sjdp
495133965Sjdp/* Allocate type hash buckets.  */
495233965Sjdp
495333965Sjdpstatic thash_t *
4954130561Sobrienallocate_thash (void)
495533965Sjdp{
495633965Sjdp  register thash_t *ptr;
495733965Sjdp  static thash_t initial_thash;
495833965Sjdp
495933965Sjdp#ifndef MALLOC_CHECK
496033965Sjdp
496177298Sobrien  register int unallocated = alloc_counts[(int) alloc_type_thash].unallocated;
496277298Sobrien  register page_type *cur_page = alloc_counts[(int) alloc_type_thash].cur_page;
496333965Sjdp
496433965Sjdp  if (unallocated == 0)
496533965Sjdp    {
496633965Sjdp      unallocated = PAGE_SIZE / sizeof (thash_t);
496777298Sobrien      alloc_counts[(int) alloc_type_thash].cur_page = cur_page = allocate_page ();
496877298Sobrien      alloc_counts[(int) alloc_type_thash].total_pages++;
496933965Sjdp    }
497033965Sjdp
497133965Sjdp  ptr = &cur_page->thash[--unallocated];
497277298Sobrien  alloc_counts[(int) alloc_type_thash].unallocated = unallocated;
497333965Sjdp
497433965Sjdp#else
497533965Sjdp
497633965Sjdp  ptr = (thash_t *) xmalloc (sizeof (thash_t));
497733965Sjdp
497833965Sjdp#endif
497933965Sjdp
498077298Sobrien  alloc_counts[(int) alloc_type_thash].total_alloc++;
498133965Sjdp  *ptr = initial_thash;
498233965Sjdp  return ptr;
498333965Sjdp}
498433965Sjdp
498533965Sjdp/* Allocate structure, union, or enum tag information.  */
498633965Sjdp
498733965Sjdpstatic tag_t *
4988130561Sobrienallocate_tag (void)
498933965Sjdp{
499033965Sjdp  register tag_t *ptr;
499133965Sjdp  static tag_t initial_tag;
499233965Sjdp
499333965Sjdp#ifndef MALLOC_CHECK
499433965Sjdp
499577298Sobrien  ptr = alloc_counts[(int) alloc_type_tag].free_list.f_tag;
499633965Sjdp  if (ptr != (tag_t *) NULL)
499777298Sobrien    alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr->free;
499833965Sjdp  else
499933965Sjdp    {
500077298Sobrien      register int unallocated = alloc_counts[(int) alloc_type_tag].unallocated;
500177298Sobrien      register page_type *cur_page = alloc_counts[(int) alloc_type_tag].cur_page;
500233965Sjdp
500333965Sjdp      if (unallocated == 0)
500433965Sjdp	{
500533965Sjdp	  unallocated = PAGE_SIZE / sizeof (tag_t);
500677298Sobrien	  alloc_counts[(int) alloc_type_tag].cur_page = cur_page = allocate_page ();
500777298Sobrien	  alloc_counts[(int) alloc_type_tag].total_pages++;
500833965Sjdp	}
500933965Sjdp
501033965Sjdp      ptr = &cur_page->tag[--unallocated];
501177298Sobrien      alloc_counts[(int) alloc_type_tag].unallocated = unallocated;
501233965Sjdp    }
501333965Sjdp
501433965Sjdp#else
501533965Sjdp
501633965Sjdp  ptr = (tag_t *) xmalloc (sizeof (tag_t));
501733965Sjdp
501833965Sjdp#endif
501933965Sjdp
502077298Sobrien  alloc_counts[(int) alloc_type_tag].total_alloc++;
502133965Sjdp  *ptr = initial_tag;
502233965Sjdp  return ptr;
502333965Sjdp}
502433965Sjdp
502533965Sjdp/* Free scoping information.  */
502633965Sjdp
502733965Sjdpstatic void
5028130561Sobrienfree_tag (tag_t *ptr)
502933965Sjdp{
503077298Sobrien  alloc_counts[(int) alloc_type_tag].total_free++;
503133965Sjdp
503233965Sjdp#ifndef MALLOC_CHECK
503377298Sobrien  ptr->free = alloc_counts[(int) alloc_type_tag].free_list.f_tag;
503477298Sobrien  alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr;
503533965Sjdp#else
503633965Sjdp  free ((PTR_T) ptr);
503733965Sjdp#endif
503833965Sjdp}
503933965Sjdp
504033965Sjdp/* Allocate forward reference to a yet unknown tag.  */
504133965Sjdp
504233965Sjdpstatic forward_t *
5043130561Sobrienallocate_forward (void)
504433965Sjdp{
504533965Sjdp  register forward_t *ptr;
504633965Sjdp  static forward_t initial_forward;
504733965Sjdp
504833965Sjdp#ifndef MALLOC_CHECK
504933965Sjdp
505077298Sobrien  register int unallocated = alloc_counts[(int) alloc_type_forward].unallocated;
505177298Sobrien  register page_type *cur_page = alloc_counts[(int) alloc_type_forward].cur_page;
505233965Sjdp
505333965Sjdp  if (unallocated == 0)
505433965Sjdp    {
505533965Sjdp      unallocated = PAGE_SIZE / sizeof (forward_t);
505677298Sobrien      alloc_counts[(int) alloc_type_forward].cur_page = cur_page = allocate_page ();
505777298Sobrien      alloc_counts[(int) alloc_type_forward].total_pages++;
505833965Sjdp    }
505933965Sjdp
506033965Sjdp  ptr = &cur_page->forward[--unallocated];
506177298Sobrien  alloc_counts[(int) alloc_type_forward].unallocated = unallocated;
506233965Sjdp
506333965Sjdp#else
506433965Sjdp
506533965Sjdp  ptr = (forward_t *) xmalloc (sizeof (forward_t));
506633965Sjdp
506733965Sjdp#endif
506833965Sjdp
506977298Sobrien  alloc_counts[(int) alloc_type_forward].total_alloc++;
507033965Sjdp  *ptr = initial_forward;
507133965Sjdp  return ptr;
507233965Sjdp}
507333965Sjdp
507433965Sjdp/* Allocate head of type hash list.  */
507533965Sjdp
507633965Sjdpstatic thead_t *
5077130561Sobrienallocate_thead (void)
507833965Sjdp{
507933965Sjdp  register thead_t *ptr;
508033965Sjdp  static thead_t initial_thead;
508133965Sjdp
508233965Sjdp#ifndef MALLOC_CHECK
508333965Sjdp
508477298Sobrien  ptr = alloc_counts[(int) alloc_type_thead].free_list.f_thead;
508533965Sjdp  if (ptr != (thead_t *) NULL)
508677298Sobrien    alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr->free;
508733965Sjdp  else
508833965Sjdp    {
508977298Sobrien      register int unallocated = alloc_counts[(int) alloc_type_thead].unallocated;
509077298Sobrien      register page_type *cur_page = alloc_counts[(int) alloc_type_thead].cur_page;
509133965Sjdp
509233965Sjdp      if (unallocated == 0)
509333965Sjdp	{
509433965Sjdp	  unallocated = PAGE_SIZE / sizeof (thead_t);
509577298Sobrien	  alloc_counts[(int) alloc_type_thead].cur_page = cur_page = allocate_page ();
509677298Sobrien	  alloc_counts[(int) alloc_type_thead].total_pages++;
509733965Sjdp	}
509833965Sjdp
509933965Sjdp      ptr = &cur_page->thead[--unallocated];
510077298Sobrien      alloc_counts[(int) alloc_type_thead].unallocated = unallocated;
510133965Sjdp    }
510233965Sjdp
510333965Sjdp#else
510433965Sjdp
510533965Sjdp  ptr = (thead_t *) xmalloc (sizeof (thead_t));
510633965Sjdp
510733965Sjdp#endif
510833965Sjdp
510977298Sobrien  alloc_counts[(int) alloc_type_thead].total_alloc++;
511033965Sjdp  *ptr = initial_thead;
511133965Sjdp  return ptr;
511233965Sjdp}
511333965Sjdp
511433965Sjdp/* Free scoping information.  */
511533965Sjdp
511633965Sjdpstatic void
5117130561Sobrienfree_thead (thead_t *ptr)
511833965Sjdp{
511977298Sobrien  alloc_counts[(int) alloc_type_thead].total_free++;
512033965Sjdp
512133965Sjdp#ifndef MALLOC_CHECK
512277298Sobrien  ptr->free = (thead_t *) alloc_counts[(int) alloc_type_thead].free_list.f_thead;
512377298Sobrien  alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr;
512433965Sjdp#else
512533965Sjdp  free ((PTR_T) ptr);
512633965Sjdp#endif
512733965Sjdp}
512833965Sjdp
512933965Sjdpstatic lineno_list_t *
5130130561Sobrienallocate_lineno_list (void)
513133965Sjdp{
513233965Sjdp  register lineno_list_t *ptr;
513333965Sjdp  static lineno_list_t initial_lineno_list;
513433965Sjdp
513533965Sjdp#ifndef MALLOC_CHECK
513633965Sjdp
513777298Sobrien  register int unallocated = alloc_counts[(int) alloc_type_lineno].unallocated;
513877298Sobrien  register page_type *cur_page = alloc_counts[(int) alloc_type_lineno].cur_page;
513933965Sjdp
514033965Sjdp  if (unallocated == 0)
514133965Sjdp    {
514233965Sjdp      unallocated = PAGE_SIZE / sizeof (lineno_list_t);
514377298Sobrien      alloc_counts[(int) alloc_type_lineno].cur_page = cur_page = allocate_page ();
514477298Sobrien      alloc_counts[(int) alloc_type_lineno].total_pages++;
514533965Sjdp    }
514633965Sjdp
514733965Sjdp  ptr = &cur_page->lineno[--unallocated];
514877298Sobrien  alloc_counts[(int) alloc_type_lineno].unallocated = unallocated;
514933965Sjdp
515033965Sjdp#else
515133965Sjdp
515233965Sjdp  ptr = (lineno_list_t *) xmalloc (sizeof (lineno_list_t));
515333965Sjdp
515433965Sjdp#endif
515533965Sjdp
515677298Sobrien  alloc_counts[(int) alloc_type_lineno].total_alloc++;
515733965Sjdp  *ptr = initial_lineno_list;
515833965Sjdp  return ptr;
515933965Sjdp}
516033965Sjdp
516133965Sjdpvoid
5162130561Sobrienecoff_set_gp_prolog_size (int sz)
516333965Sjdp{
516433965Sjdp  if (cur_proc_ptr == 0)
516533965Sjdp    return;
516633965Sjdp
516733965Sjdp  cur_proc_ptr->pdr.gp_prologue = sz;
516833965Sjdp  if (cur_proc_ptr->pdr.gp_prologue != sz)
516933965Sjdp    {
517060484Sobrien      as_warn (_("GP prologue size exceeds field size, using 0 instead"));
517133965Sjdp      cur_proc_ptr->pdr.gp_prologue = 0;
517233965Sjdp    }
517333965Sjdp
517433965Sjdp  cur_proc_ptr->pdr.gp_used = 1;
517533965Sjdp}
517633965Sjdp
517777298Sobrienint
5178130561Sobrienecoff_no_current_file (void)
517933965Sjdp{
518033965Sjdp  return cur_file_ptr == (efdr_t *) NULL;
518133965Sjdp}
518233965Sjdp
518333965Sjdpvoid
5184130561Sobrienecoff_generate_asm_lineno (void)
518533965Sjdp{
518660484Sobrien  unsigned int lineno;
518760484Sobrien  char *filename;
518833965Sjdp  lineno_list_t *list;
518933965Sjdp
519060484Sobrien  as_where (&filename, &lineno);
519160484Sobrien
519277298Sobrien  if (current_stabs_filename == (char *) NULL
519338889Sjdp      || strcmp (current_stabs_filename, filename))
519438889Sjdp    add_file (filename, 0, 1);
519533965Sjdp
519633965Sjdp  list = allocate_lineno_list ();
519733965Sjdp
519833965Sjdp  list->next = (lineno_list_t *) NULL;
519933965Sjdp  list->file = cur_file_ptr;
520033965Sjdp  list->proc = cur_proc_ptr;
520133965Sjdp  list->frag = frag_now;
520233965Sjdp  list->paddr = frag_now_fix ();
520333965Sjdp  list->lineno = lineno;
520433965Sjdp
520533965Sjdp  /* We don't want to merge files which have line numbers.  */
520633965Sjdp  cur_file_ptr->fdr.fMerge = 0;
520733965Sjdp
520833965Sjdp  /* A .loc directive will sometimes appear before a .ent directive,
520933965Sjdp     which means that cur_proc_ptr will be NULL here.  Arrange to
521033965Sjdp     patch this up.  */
521133965Sjdp  if (cur_proc_ptr == (proc_t *) NULL)
521233965Sjdp    {
521333965Sjdp      lineno_list_t **pl;
521433965Sjdp
521533965Sjdp      pl = &noproc_lineno;
521633965Sjdp      while (*pl != (lineno_list_t *) NULL)
521777298Sobrien	pl = &(*pl)->next;
521833965Sjdp      *pl = list;
521933965Sjdp    }
522033965Sjdp  else
522133965Sjdp    {
522233965Sjdp      last_lineno = list;
522333965Sjdp      *last_lineno_ptr = list;
522433965Sjdp      last_lineno_ptr = &list->next;
522533965Sjdp    }
522633965Sjdp}
522733965Sjdp
522860484Sobrien#else
522960484Sobrien
523060484Sobrienvoid
5231130561Sobrienecoff_generate_asm_lineno (void)
523260484Sobrien{
523360484Sobrien}
523460484Sobrien
523533965Sjdp#endif /* ECOFF_DEBUGGING */
5236