xref: /openbsd/gnu/usr.bin/binutils/gas/ecoff.c (revision 007c2a45)
12159047fSniklas /* ECOFF debugging support.
2c074d1c9Sdrahn    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
3b55d4692Sfgsch    Free Software Foundation, Inc.
42159047fSniklas    Contributed by Cygnus Support.
52159047fSniklas    This file was put together by Ian Lance Taylor <ian@cygnus.com>.  A
62159047fSniklas    good deal of it comes directly from mips-tfile.c, by Michael
72159047fSniklas    Meissner <meissner@osf.org>.
82159047fSniklas 
92159047fSniklas    This file is part of GAS.
102159047fSniklas 
112159047fSniklas    GAS is free software; you can redistribute it and/or modify
122159047fSniklas    it under the terms of the GNU General Public License as published by
132159047fSniklas    the Free Software Foundation; either version 2, or (at your option)
142159047fSniklas    any later version.
152159047fSniklas 
162159047fSniklas    GAS is distributed in the hope that it will be useful,
172159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
182159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
192159047fSniklas    GNU General Public License for more details.
202159047fSniklas 
212159047fSniklas    You should have received a copy of the GNU General Public License
22191aa565Sniklas    along with GAS; see the file COPYING.  If not, write to the Free
23191aa565Sniklas    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24191aa565Sniklas    02111-1307, USA.  */
252159047fSniklas 
262159047fSniklas #include "as.h"
272159047fSniklas 
282159047fSniklas /* This file is compiled conditionally for those targets which use
292159047fSniklas    ECOFF debugging information (e.g., MIPS ECOFF, MIPS ELF, Alpha
302159047fSniklas    ECOFF).  */
312159047fSniklas 
32b305b0f1Sespie #include "ecoff.h"
33b305b0f1Sespie 
342159047fSniklas #ifdef ECOFF_DEBUGGING
352159047fSniklas 
362159047fSniklas #include "coff/internal.h"
372159047fSniklas #include "coff/symconst.h"
382159047fSniklas #include "aout/stab_gnu.h"
392159047fSniklas 
40c074d1c9Sdrahn #include "safe-ctype.h"
412159047fSniklas 
422159047fSniklas /* Why isn't this in coff/sym.h?  */
432159047fSniklas #define ST_RFDESCAPE 0xfff
442159047fSniklas 
452159047fSniklas /* This file constructs the information used by the ECOFF debugging
462159047fSniklas    format.  It just builds a large block of data.
472159047fSniklas 
482159047fSniklas    We support both ECOFF style debugging and stabs debugging (the
492159047fSniklas    stabs symbols are encapsulated in ECOFF symbols).  This should let
502159047fSniklas    us handle anything the compiler might throw at us.  */
512159047fSniklas 
522159047fSniklas /* Here is a brief description of the MIPS ECOFF symbol table, by
532159047fSniklas    Michael Meissner.  The MIPS symbol table has the following pieces:
542159047fSniklas 
552159047fSniklas 	Symbolic Header
562159047fSniklas 	    |
572159047fSniklas 	    +--	Auxiliary Symbols
582159047fSniklas 	    |
592159047fSniklas 	    +--	Dense number table
602159047fSniklas 	    |
612159047fSniklas 	    +--	Optimizer Symbols
622159047fSniklas 	    |
632159047fSniklas 	    +--	External Strings
642159047fSniklas 	    |
652159047fSniklas 	    +--	External Symbols
662159047fSniklas 	    |
672159047fSniklas 	    +--	Relative file descriptors
682159047fSniklas 	    |
692159047fSniklas 	    +--	File table
702159047fSniklas 		    |
712159047fSniklas 		    +--	Procedure table
722159047fSniklas 		    |
732159047fSniklas 		    +--	Line number table
742159047fSniklas 		    |
752159047fSniklas 		    +--	Local Strings
762159047fSniklas 		    |
772159047fSniklas 		    +--	Local Symbols
782159047fSniklas 
792159047fSniklas    The symbolic header points to each of the other tables, and also
802159047fSniklas    contains the number of entries.  It also contains a magic number
812159047fSniklas    and MIPS compiler version number, such as 2.0.
822159047fSniklas 
832159047fSniklas    The auxiliary table is a series of 32 bit integers, that are
842159047fSniklas    referenced as needed from the local symbol table.  Unlike standard
852159047fSniklas    COFF, the aux.  information does not follow the symbol that uses
862159047fSniklas    it, but rather is a separate table.  In theory, this would allow
872159047fSniklas    the MIPS compilers to collapse duplicate aux. entries, but I've not
882159047fSniklas    noticed this happening with the 1.31 compiler suite.  The different
892159047fSniklas    types of aux. entries are:
902159047fSniklas 
912159047fSniklas     1)	dnLow: Low bound on array dimension.
922159047fSniklas 
932159047fSniklas     2)	dnHigh: High bound on array dimension.
942159047fSniklas 
952159047fSniklas     3)	isym: Index to the local symbol which is the start of the
962159047fSniklas 	function for the end of function first aux. entry.
972159047fSniklas 
982159047fSniklas     4)	width: Width of structures and bitfields.
992159047fSniklas 
1002159047fSniklas     5)	count: Count of ranges for variant part.
1012159047fSniklas 
1022159047fSniklas     6)	rndx: A relative index into the symbol table.  The relative
1032159047fSniklas 	index field has two parts: rfd which is a pointer into the
1042159047fSniklas 	relative file index table or ST_RFDESCAPE which says the next
1052159047fSniklas 	aux. entry is the file number, and index: which is the pointer
1062159047fSniklas 	into the local symbol within a given file table.  This is for
1072159047fSniklas 	things like references to types defined in another file.
1082159047fSniklas 
1092159047fSniklas     7)	Type information: This is like the COFF type bits, except it
1102159047fSniklas 	is 32 bits instead of 16; they still have room to add new
1112159047fSniklas 	basic types; and they can handle more than 6 levels of array,
1122159047fSniklas 	pointer, function, etc.  Each type information field contains
1132159047fSniklas 	the following structure members:
1142159047fSniklas 
1152159047fSniklas 	    a)	fBitfield: a bit that says this is a bitfield, and the
1162159047fSniklas 		size in bits follows as the next aux. entry.
1172159047fSniklas 
1182159047fSniklas 	    b)	continued: a bit that says the next aux. entry is a
1192159047fSniklas 		continuation of the current type information (in case
1202159047fSniklas 		there are more than 6 levels of array/ptr/function).
1212159047fSniklas 
1222159047fSniklas 	    c)	bt: an integer containing the base type before adding
1232159047fSniklas 		array, pointer, function, etc. qualifiers.  The
1242159047fSniklas 		current base types that I have documentation for are:
1252159047fSniklas 
1262159047fSniklas 			btNil		-- undefined
1272159047fSniklas 			btAdr		-- address - integer same size as ptr
1282159047fSniklas 			btChar		-- character
1292159047fSniklas 			btUChar		-- unsigned character
1302159047fSniklas 			btShort		-- short
1312159047fSniklas 			btUShort	-- unsigned short
1322159047fSniklas 			btInt		-- int
1332159047fSniklas 			btUInt		-- unsigned int
1342159047fSniklas 			btLong		-- long
1352159047fSniklas 			btULong		-- unsigned long
1362159047fSniklas 			btFloat		-- float (real)
1372159047fSniklas 			btDouble	-- Double (real)
1382159047fSniklas 			btStruct	-- Structure (Record)
1392159047fSniklas 			btUnion		-- Union (variant)
1402159047fSniklas 			btEnum		-- Enumerated
1412159047fSniklas 			btTypedef	-- defined via a typedef isymRef
1422159047fSniklas 			btRange		-- subrange of int
1432159047fSniklas 			btSet		-- pascal sets
1442159047fSniklas 			btComplex	-- fortran complex
1452159047fSniklas 			btDComplex	-- fortran double complex
1462159047fSniklas 			btIndirect	-- forward or unnamed typedef
1472159047fSniklas 			btFixedDec	-- Fixed Decimal
1482159047fSniklas 			btFloatDec	-- Float Decimal
1492159047fSniklas 			btString	-- Varying Length Character String
1502159047fSniklas 			btBit		-- Aligned Bit String
1512159047fSniklas 			btPicture	-- Picture
1522159047fSniklas 			btVoid		-- Void (MIPS cc revision >= 2.00)
1532159047fSniklas 
1542159047fSniklas 	    d)	tq0 - tq5: type qualifier fields as needed.  The
1552159047fSniklas 		current type qualifier fields I have documentation for
1562159047fSniklas 		are:
1572159047fSniklas 
1582159047fSniklas 			tqNil		-- no more qualifiers
1592159047fSniklas 			tqPtr		-- pointer
1602159047fSniklas 			tqProc		-- procedure
1612159047fSniklas 			tqArray		-- array
1622159047fSniklas 			tqFar		-- 8086 far pointers
1632159047fSniklas 			tqVol		-- volatile
1642159047fSniklas 
1652159047fSniklas    The dense number table is used in the front ends, and disappears by
1662159047fSniklas    the time the .o is created.
1672159047fSniklas 
1682159047fSniklas    With the 1.31 compiler suite, the optimization symbols don't seem
1692159047fSniklas    to be used as far as I can tell.
1702159047fSniklas 
1712159047fSniklas    The linker is the first entity that creates the relative file
1722159047fSniklas    descriptor table, and I believe it is used so that the individual
1732159047fSniklas    file table pointers don't have to be rewritten when the objects are
1742159047fSniklas    merged together into the program file.
1752159047fSniklas 
1762159047fSniklas    Unlike COFF, the basic symbol & string tables are split into
1772159047fSniklas    external and local symbols/strings.  The relocation information
1782159047fSniklas    only goes off of the external symbol table, and the debug
1792159047fSniklas    information only goes off of the internal symbol table.  The
1802159047fSniklas    external symbols can have links to an appropriate file index and
1812159047fSniklas    symbol within the file to give it the appropriate type information.
1822159047fSniklas    Because of this, the external symbols are actually larger than the
1832159047fSniklas    internal symbols (to contain the link information), and contain the
1842159047fSniklas    local symbol structure as a member, though this member is not the
1852159047fSniklas    first member of the external symbol structure (!).  I suspect this
1862159047fSniklas    split is to make strip easier to deal with.
1872159047fSniklas 
1882159047fSniklas    Each file table has offsets for where the line numbers, local
1892159047fSniklas    strings, local symbols, and procedure table starts from within the
1902159047fSniklas    global tables, and the indexs are reset to 0 for each of those
1912159047fSniklas    tables for the file.
1922159047fSniklas 
1932159047fSniklas    The procedure table contains the binary equivalents of the .ent
1942159047fSniklas    (start of the function address), .frame (what register is the
1952159047fSniklas    virtual frame pointer, constant offset from the register to obtain
1962159047fSniklas    the VFP, and what register holds the return address), .mask/.fmask
1972159047fSniklas    (bitmask of saved registers, and where the first register is stored
1982159047fSniklas    relative to the VFP) assembler directives.  It also contains the
1992159047fSniklas    low and high bounds of the line numbers if debugging is turned on.
2002159047fSniklas 
2012159047fSniklas    The line number table is a compressed form of the normal COFF line
2022159047fSniklas    table.  Each line number entry is either 1 or 3 bytes long, and
2032159047fSniklas    contains a signed delta from the previous line, and an unsigned
2042159047fSniklas    count of the number of instructions this statement takes.
2052159047fSniklas 
2062159047fSniklas    The local symbol table contains the following fields:
2072159047fSniklas 
2082159047fSniklas     1)	iss: index to the local string table giving the name of the
2092159047fSniklas 	symbol.
2102159047fSniklas 
2112159047fSniklas     2)	value: value of the symbol (address, register number, etc.).
2122159047fSniklas 
2132159047fSniklas     3)	st: symbol type.  The current symbol types are:
2142159047fSniklas 
2152159047fSniklas 	    stNil	  -- Nuthin' special
2162159047fSniklas 	    stGlobal	  -- external symbol
2172159047fSniklas 	    stStatic	  -- static
2182159047fSniklas 	    stParam	  -- procedure argument
2192159047fSniklas 	    stLocal	  -- local variable
2202159047fSniklas 	    stLabel	  -- label
2212159047fSniklas 	    stProc	  -- External Procedure
2222159047fSniklas 	    stBlock	  -- beginning of block
2232159047fSniklas 	    stEnd	  -- end (of anything)
2242159047fSniklas 	    stMember	  -- member (of anything)
2252159047fSniklas 	    stTypedef	  -- type definition
2262159047fSniklas 	    stFile	  -- file name
2272159047fSniklas 	    stRegReloc	  -- register relocation
2282159047fSniklas 	    stForward	  -- forwarding address
2292159047fSniklas 	    stStaticProc  -- Static procedure
2302159047fSniklas 	    stConstant	  -- const
2312159047fSniklas 
2322159047fSniklas     4)	sc: storage class.  The current storage classes are:
2332159047fSniklas 
2342159047fSniklas 	    scText	  -- text symbol
2352159047fSniklas 	    scData	  -- initialized data symbol
2362159047fSniklas 	    scBss	  -- un-initialized data symbol
2372159047fSniklas 	    scRegister	  -- value of symbol is register number
2382159047fSniklas 	    scAbs	  -- value of symbol is absolute
2392159047fSniklas 	    scUndefined   -- who knows?
2402159047fSniklas 	    scCdbLocal	  -- variable's value is IN se->va.??
2412159047fSniklas 	    scBits	  -- this is a bit field
2422159047fSniklas 	    scCdbSystem	  -- value is IN debugger's address space
2432159047fSniklas 	    scRegImage	  -- register value saved on stack
2442159047fSniklas 	    scInfo	  -- symbol contains debugger information
2452159047fSniklas 	    scUserStruct  -- addr in struct user for current process
2462159047fSniklas 	    scSData	  -- load time only small data
2472159047fSniklas 	    scSBss	  -- load time only small common
2482159047fSniklas 	    scRData	  -- load time only read only data
2492159047fSniklas 	    scVar	  -- Var parameter (fortranpascal)
2502159047fSniklas 	    scCommon	  -- common variable
2512159047fSniklas 	    scSCommon	  -- small common
2522159047fSniklas 	    scVarRegister -- Var parameter in a register
2532159047fSniklas 	    scVariant	  -- Variant record
2542159047fSniklas 	    scSUndefined  -- small undefined(external) data
2552159047fSniklas 	    scInit	  -- .init section symbol
2562159047fSniklas 
2572159047fSniklas     5)	index: pointer to a local symbol or aux. entry.
2582159047fSniklas 
2592159047fSniklas    For the following program:
2602159047fSniklas 
2612159047fSniklas 	#include <stdio.h>
2622159047fSniklas 
2632159047fSniklas 	main(){
2642159047fSniklas 		printf("Hello World!\n");
2652159047fSniklas 		return 0;
2662159047fSniklas 	}
2672159047fSniklas 
2682159047fSniklas    Mips-tdump produces the following information:
2692159047fSniklas 
2702159047fSniklas    Global file header:
2712159047fSniklas        magic number             0x162
2722159047fSniklas        # sections               2
2732159047fSniklas        timestamp                645311799, Wed Jun 13 17:16:39 1990
2742159047fSniklas        symbolic header offset   284
2752159047fSniklas        symbolic header size     96
2762159047fSniklas        optional header          56
2772159047fSniklas        flags                    0x0
2782159047fSniklas 
2792159047fSniklas    Symbolic header, magic number = 0x7009, vstamp = 1.31:
2802159047fSniklas 
2812159047fSniklas        Info                      Offset      Number       Bytes
2822159047fSniklas        ====                      ======      ======      =====
2832159047fSniklas 
2842159047fSniklas        Line numbers                 380           4           4 [13]
2852159047fSniklas        Dense numbers                  0           0           0
2862159047fSniklas        Procedures Tables            384           1          52
2872159047fSniklas        Local Symbols                436          16         192
2882159047fSniklas        Optimization Symbols           0           0           0
2892159047fSniklas        Auxiliary Symbols            628          39         156
2902159047fSniklas        Local Strings                784          80          80
2912159047fSniklas        External Strings             864         144         144
2922159047fSniklas        File Tables                 1008           2         144
2932159047fSniklas        Relative Files                 0           0           0
2942159047fSniklas        External Symbols            1152          20         320
2952159047fSniklas 
2962159047fSniklas    File #0, "hello2.c"
2972159047fSniklas 
2982159047fSniklas        Name index  = 1          Readin      = No
2992159047fSniklas        Merge       = No         Endian      = LITTLE
3002159047fSniklas        Debug level = G2         Language    = C
3012159047fSniklas        Adr         = 0x00000000
3022159047fSniklas 
3032159047fSniklas        Info                       Start      Number        Size      Offset
3042159047fSniklas        ====                       =====      ======        ====      ======
3052159047fSniklas        Local strings                  0          15          15         784
3062159047fSniklas        Local symbols                  0           6          72         436
3072159047fSniklas        Line numbers                   0          13          13         380
3082159047fSniklas        Optimization symbols           0           0           0           0
3092159047fSniklas        Procedures                     0           1          52         384
3102159047fSniklas        Auxiliary symbols              0          14          56         628
3112159047fSniklas        Relative Files                 0           0           0           0
3122159047fSniklas 
3132159047fSniklas     There are 6 local symbols, starting at 436
3142159047fSniklas 
3152159047fSniklas 	Symbol# 0: "hello2.c"
3162159047fSniklas 	    End+1 symbol  = 6
3172159047fSniklas 	    String index  = 1
3182159047fSniklas 	    Storage class = Text        Index  = 6
3192159047fSniklas 	    Symbol type   = File        Value  = 0
3202159047fSniklas 
3212159047fSniklas 	Symbol# 1: "main"
3222159047fSniklas 	    End+1 symbol  = 5
3232159047fSniklas 	    Type          = int
3242159047fSniklas 	    String index  = 10
3252159047fSniklas 	    Storage class = Text        Index  = 12
3262159047fSniklas 	    Symbol type   = Proc        Value  = 0
3272159047fSniklas 
3282159047fSniklas 	Symbol# 2: ""
3292159047fSniklas 	    End+1 symbol  = 4
3302159047fSniklas 	    String index  = 0
3312159047fSniklas 	    Storage class = Text        Index  = 4
3322159047fSniklas 	    Symbol type   = Block       Value  = 8
3332159047fSniklas 
3342159047fSniklas 	Symbol# 3: ""
3352159047fSniklas 	    First symbol  = 2
3362159047fSniklas 	    String index  = 0
3372159047fSniklas 	    Storage class = Text        Index  = 2
3382159047fSniklas 	    Symbol type   = End         Value  = 28
3392159047fSniklas 
3402159047fSniklas 	Symbol# 4: "main"
3412159047fSniklas 	    First symbol  = 1
3422159047fSniklas 	    String index  = 10
3432159047fSniklas 	    Storage class = Text        Index  = 1
3442159047fSniklas 	    Symbol type   = End         Value  = 52
3452159047fSniklas 
3462159047fSniklas 	Symbol# 5: "hello2.c"
3472159047fSniklas 	    First symbol  = 0
3482159047fSniklas 	    String index  = 1
3492159047fSniklas 	    Storage class = Text        Index  = 0
3502159047fSniklas 	    Symbol type   = End         Value  = 0
3512159047fSniklas 
3522159047fSniklas     There are 14 auxiliary table entries, starting at 628.
3532159047fSniklas 
3542159047fSniklas 	* #0               0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
3552159047fSniklas 	* #1              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
3562159047fSniklas 	* #2               8, [   8/      0], [ 2 0:0 0:0:0:0:0:0]
3572159047fSniklas 	* #3              16, [  16/      0], [ 4 0:0 0:0:0:0:0:0]
3582159047fSniklas 	* #4              24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
3592159047fSniklas 	* #5              32, [  32/      0], [ 8 0:0 0:0:0:0:0:0]
3602159047fSniklas 	* #6              40, [  40/      0], [10 0:0 0:0:0:0:0:0]
3612159047fSniklas 	* #7              44, [  44/      0], [11 0:0 0:0:0:0:0:0]
3622159047fSniklas 	* #8              12, [  12/      0], [ 3 0:0 0:0:0:0:0:0]
3632159047fSniklas 	* #9              20, [  20/      0], [ 5 0:0 0:0:0:0:0:0]
3642159047fSniklas 	* #10             28, [  28/      0], [ 7 0:0 0:0:0:0:0:0]
3652159047fSniklas 	* #11             36, [  36/      0], [ 9 0:0 0:0:0:0:0:0]
3662159047fSniklas 	  #12              5, [   5/      0], [ 1 1:0 0:0:0:0:0:0]
3672159047fSniklas 	  #13             24, [  24/      0], [ 6 0:0 0:0:0:0:0:0]
3682159047fSniklas 
3692159047fSniklas     There are 1 procedure descriptor entries, starting at 0.
3702159047fSniklas 
3712159047fSniklas 	Procedure descriptor 0:
3722159047fSniklas 	    Name index   = 10          Name          = "main"
3732159047fSniklas 	    .mask 0x80000000,-4        .fmask 0x00000000,0
3742159047fSniklas 	    .frame $29,24,$31
3752159047fSniklas 	    Opt. start   = -1          Symbols start = 1
3762159047fSniklas 	    First line # = 3           Last line #   = 6
3772159047fSniklas 	    Line Offset  = 0           Address       = 0x00000000
3782159047fSniklas 
3792159047fSniklas 	There are 4 bytes holding line numbers, starting at 380.
3802159047fSniklas 	    Line           3,   delta     0,   count  2
3812159047fSniklas 	    Line           4,   delta     1,   count  3
3822159047fSniklas 	    Line           5,   delta     1,   count  2
3832159047fSniklas 	    Line           6,   delta     1,   count  6
3842159047fSniklas 
3852159047fSniklas    File #1, "/usr/include/stdio.h"
3862159047fSniklas 
3872159047fSniklas     Name index  = 1          Readin      = No
3882159047fSniklas     Merge       = Yes        Endian      = LITTLE
3892159047fSniklas     Debug level = G2         Language    = C
3902159047fSniklas     Adr         = 0x00000000
3912159047fSniklas 
3922159047fSniklas     Info                       Start      Number        Size      Offset
3932159047fSniklas     ====                       =====      ======        ====      ======
3942159047fSniklas     Local strings                 15          65          65         799
3952159047fSniklas     Local symbols                  6          10         120         508
3962159047fSniklas     Line numbers                   0           0           0         380
3972159047fSniklas     Optimization symbols           0           0           0           0
3982159047fSniklas     Procedures                     1           0           0         436
3992159047fSniklas     Auxiliary symbols             14          25         100         684
4002159047fSniklas     Relative Files                 0           0           0           0
4012159047fSniklas 
4022159047fSniklas     There are 10 local symbols, starting at 442
4032159047fSniklas 
4042159047fSniklas 	Symbol# 0: "/usr/include/stdio.h"
4052159047fSniklas 	    End+1 symbol  = 10
4062159047fSniklas 	    String index  = 1
4072159047fSniklas 	    Storage class = Text        Index  = 10
4082159047fSniklas 	    Symbol type   = File        Value  = 0
4092159047fSniklas 
4102159047fSniklas 	Symbol# 1: "_iobuf"
4112159047fSniklas 	    End+1 symbol  = 9
4122159047fSniklas 	    String index  = 22
4132159047fSniklas 	    Storage class = Info        Index  = 9
4142159047fSniklas 	    Symbol type   = Block       Value  = 20
4152159047fSniklas 
4162159047fSniklas 	Symbol# 2: "_cnt"
4172159047fSniklas 	    Type          = int
4182159047fSniklas 	    String index  = 29
4192159047fSniklas 	    Storage class = Info        Index  = 4
4202159047fSniklas 	    Symbol type   = Member      Value  = 0
4212159047fSniklas 
4222159047fSniklas 	Symbol# 3: "_ptr"
4232159047fSniklas 	    Type          = ptr to char
4242159047fSniklas 	    String index  = 34
4252159047fSniklas 	    Storage class = Info        Index  = 15
4262159047fSniklas 	    Symbol type   = Member      Value  = 32
4272159047fSniklas 
4282159047fSniklas 	Symbol# 4: "_base"
4292159047fSniklas 	    Type          = ptr to char
4302159047fSniklas 	    String index  = 39
4312159047fSniklas 	    Storage class = Info        Index  = 16
4322159047fSniklas 	    Symbol type   = Member      Value  = 64
4332159047fSniklas 
4342159047fSniklas 	Symbol# 5: "_bufsiz"
4352159047fSniklas 	    Type          = int
4362159047fSniklas 	    String index  = 45
4372159047fSniklas 	    Storage class = Info        Index  = 4
4382159047fSniklas 	    Symbol type   = Member      Value  = 96
4392159047fSniklas 
4402159047fSniklas 	Symbol# 6: "_flag"
4412159047fSniklas 	    Type          = short
4422159047fSniklas 	    String index  = 53
4432159047fSniklas 	    Storage class = Info        Index  = 3
4442159047fSniklas 	    Symbol type   = Member      Value  = 128
4452159047fSniklas 
4462159047fSniklas 	Symbol# 7: "_file"
4472159047fSniklas 	    Type          = char
4482159047fSniklas 	    String index  = 59
4492159047fSniklas 	    Storage class = Info        Index  = 2
4502159047fSniklas 	    Symbol type   = Member      Value  = 144
4512159047fSniklas 
4522159047fSniklas 	Symbol# 8: ""
4532159047fSniklas 	    First symbol  = 1
4542159047fSniklas 	    String index  = 0
4552159047fSniklas 	    Storage class = Info        Index  = 1
4562159047fSniklas 	    Symbol type   = End         Value  = 0
4572159047fSniklas 
4582159047fSniklas 	Symbol# 9: "/usr/include/stdio.h"
4592159047fSniklas 	    First symbol  = 0
4602159047fSniklas 	    String index  = 1
4612159047fSniklas 	    Storage class = Text        Index  = 0
4622159047fSniklas 	    Symbol type   = End         Value  = 0
4632159047fSniklas 
4642159047fSniklas     There are 25 auxiliary table entries, starting at 642.
4652159047fSniklas 
4662159047fSniklas 	* #14             -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
4672159047fSniklas 	  #15          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
4682159047fSniklas 	  #16          65544, [   8/     16], [ 2 0:0 1:0:0:0:0:0]
4692159047fSniklas 	* #17         196656, [  48/     48], [12 0:0 3:0:0:0:0:0]
4702159047fSniklas 	* #18           8191, [4095/      1], [63 1:1 0:0:0:0:f:1]
4712159047fSniklas 	* #19              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
4722159047fSniklas 	* #20          20479, [4095/      4], [63 1:1 0:0:0:0:f:4]
4732159047fSniklas 	* #21              1, [   1/      0], [ 0 1:0 0:0:0:0:0:0]
4742159047fSniklas 	* #22              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4752159047fSniklas 	* #23              2, [   2/      0], [ 0 0:1 0:0:0:0:0:0]
4762159047fSniklas 	* #24            160, [ 160/      0], [40 0:0 0:0:0:0:0:0]
4772159047fSniklas 	* #25              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4782159047fSniklas 	* #26              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4792159047fSniklas 	* #27              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4802159047fSniklas 	* #28              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4812159047fSniklas 	* #29              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4822159047fSniklas 	* #30              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4832159047fSniklas 	* #31              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4842159047fSniklas 	* #32              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4852159047fSniklas 	* #33              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4862159047fSniklas 	* #34              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4872159047fSniklas 	* #35              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4882159047fSniklas 	* #36              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4892159047fSniklas 	* #37              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4902159047fSniklas 	* #38              0, [   0/      0], [ 0 0:0 0:0:0:0:0:0]
4912159047fSniklas 
4922159047fSniklas     There are 0 procedure descriptor entries, starting at 1.
4932159047fSniklas 
4942159047fSniklas    There are 20 external symbols, starting at 1152
4952159047fSniklas 
4962159047fSniklas 	Symbol# 0: "_iob"
4972159047fSniklas 	    Type          = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
4982159047fSniklas 	    String index  = 0           Ifd    = 1
4992159047fSniklas 	    Storage class = Nil         Index  = 17
5002159047fSniklas 	    Symbol type   = Global      Value  = 60
5012159047fSniklas 
5022159047fSniklas 	Symbol# 1: "fopen"
5032159047fSniklas 	    String index  = 5           Ifd    = 1
5042159047fSniklas 	    Storage class = Nil         Index  = 1048575
5052159047fSniklas 	    Symbol type   = Proc        Value  = 0
5062159047fSniklas 
5072159047fSniklas 	Symbol# 2: "fdopen"
5082159047fSniklas 	    String index  = 11          Ifd    = 1
5092159047fSniklas 	    Storage class = Nil         Index  = 1048575
5102159047fSniklas 	    Symbol type   = Proc        Value  = 0
5112159047fSniklas 
5122159047fSniklas 	Symbol# 3: "freopen"
5132159047fSniklas 	    String index  = 18          Ifd    = 1
5142159047fSniklas 	    Storage class = Nil         Index  = 1048575
5152159047fSniklas 	    Symbol type   = Proc        Value  = 0
5162159047fSniklas 
5172159047fSniklas 	Symbol# 4: "popen"
5182159047fSniklas 	    String index  = 26          Ifd    = 1
5192159047fSniklas 	    Storage class = Nil         Index  = 1048575
5202159047fSniklas 	    Symbol type   = Proc        Value  = 0
5212159047fSniklas 
5222159047fSniklas 	Symbol# 5: "tmpfile"
5232159047fSniklas 	    String index  = 32          Ifd    = 1
5242159047fSniklas 	    Storage class = Nil         Index  = 1048575
5252159047fSniklas 	    Symbol type   = Proc        Value  = 0
5262159047fSniklas 
5272159047fSniklas 	Symbol# 6: "ftell"
5282159047fSniklas 	    String index  = 40          Ifd    = 1
5292159047fSniklas 	    Storage class = Nil         Index  = 1048575
5302159047fSniklas 	    Symbol type   = Proc        Value  = 0
5312159047fSniklas 
5322159047fSniklas 	Symbol# 7: "rewind"
5332159047fSniklas 	    String index  = 46          Ifd    = 1
5342159047fSniklas 	    Storage class = Nil         Index  = 1048575
5352159047fSniklas 	    Symbol type   = Proc        Value  = 0
5362159047fSniklas 
5372159047fSniklas 	Symbol# 8: "setbuf"
5382159047fSniklas 	    String index  = 53          Ifd    = 1
5392159047fSniklas 	    Storage class = Nil         Index  = 1048575
5402159047fSniklas 	    Symbol type   = Proc        Value  = 0
5412159047fSniklas 
5422159047fSniklas 	Symbol# 9: "setbuffer"
5432159047fSniklas 	    String index  = 60          Ifd    = 1
5442159047fSniklas 	    Storage class = Nil         Index  = 1048575
5452159047fSniklas 	    Symbol type   = Proc        Value  = 0
5462159047fSniklas 
5472159047fSniklas 	Symbol# 10: "setlinebuf"
5482159047fSniklas 	    String index  = 70          Ifd    = 1
5492159047fSniklas 	    Storage class = Nil         Index  = 1048575
5502159047fSniklas 	    Symbol type   = Proc        Value  = 0
5512159047fSniklas 
5522159047fSniklas 	Symbol# 11: "fgets"
5532159047fSniklas 	    String index  = 81          Ifd    = 1
5542159047fSniklas 	    Storage class = Nil         Index  = 1048575
5552159047fSniklas 	    Symbol type   = Proc        Value  = 0
5562159047fSniklas 
5572159047fSniklas 	Symbol# 12: "gets"
5582159047fSniklas 	    String index  = 87          Ifd    = 1
5592159047fSniklas 	    Storage class = Nil         Index  = 1048575
5602159047fSniklas 	    Symbol type   = Proc        Value  = 0
5612159047fSniklas 
5622159047fSniklas 	Symbol# 13: "ctermid"
5632159047fSniklas 	    String index  = 92          Ifd    = 1
5642159047fSniklas 	    Storage class = Nil         Index  = 1048575
5652159047fSniklas 	    Symbol type   = Proc        Value  = 0
5662159047fSniklas 
5672159047fSniklas 	Symbol# 14: "cuserid"
5682159047fSniklas 	    String index  = 100         Ifd    = 1
5692159047fSniklas 	    Storage class = Nil         Index  = 1048575
5702159047fSniklas 	    Symbol type   = Proc        Value  = 0
5712159047fSniklas 
5722159047fSniklas 	Symbol# 15: "tempnam"
5732159047fSniklas 	    String index  = 108         Ifd    = 1
5742159047fSniklas 	    Storage class = Nil         Index  = 1048575
5752159047fSniklas 	    Symbol type   = Proc        Value  = 0
5762159047fSniklas 
5772159047fSniklas 	Symbol# 16: "tmpnam"
5782159047fSniklas 	    String index  = 116         Ifd    = 1
5792159047fSniklas 	    Storage class = Nil         Index  = 1048575
5802159047fSniklas 	    Symbol type   = Proc        Value  = 0
5812159047fSniklas 
5822159047fSniklas 	Symbol# 17: "sprintf"
5832159047fSniklas 	    String index  = 123         Ifd    = 1
5842159047fSniklas 	    Storage class = Nil         Index  = 1048575
5852159047fSniklas 	    Symbol type   = Proc        Value  = 0
5862159047fSniklas 
5872159047fSniklas 	Symbol# 18: "main"
5882159047fSniklas 	    Type          = int
5892159047fSniklas 	    String index  = 131         Ifd    = 0
5902159047fSniklas 	    Storage class = Text        Index  = 1
5912159047fSniklas 	    Symbol type   = Proc        Value  = 0
5922159047fSniklas 
5932159047fSniklas 	Symbol# 19: "printf"
5942159047fSniklas 	    String index  = 136         Ifd    = 0
5952159047fSniklas 	    Storage class = Undefined   Index  = 1048575
5962159047fSniklas 	    Symbol type   = Proc        Value  = 0
5972159047fSniklas 
5982159047fSniklas    The following auxiliary table entries were unused:
5992159047fSniklas 
6002159047fSniklas     #0               0  0x00000000  void
6012159047fSniklas     #2               8  0x00000008  char
6022159047fSniklas     #3              16  0x00000010  short
6032159047fSniklas     #4              24  0x00000018  int
6042159047fSniklas     #5              32  0x00000020  long
6052159047fSniklas     #6              40  0x00000028  float
6062159047fSniklas     #7              44  0x0000002c  double
6072159047fSniklas     #8              12  0x0000000c  unsigned char
6082159047fSniklas     #9              20  0x00000014  unsigned short
6092159047fSniklas     #10             28  0x0000001c  unsigned int
6102159047fSniklas     #11             36  0x00000024  unsigned long
6112159047fSniklas     #14              0  0x00000000  void
6122159047fSniklas     #15             24  0x00000018  int
6132159047fSniklas     #19             32  0x00000020  long
6142159047fSniklas     #20             40  0x00000028  float
6152159047fSniklas     #21             44  0x0000002c  double
6162159047fSniklas     #22             12  0x0000000c  unsigned char
6172159047fSniklas     #23             20  0x00000014  unsigned short
6182159047fSniklas     #24             28  0x0000001c  unsigned int
6192159047fSniklas     #25             36  0x00000024  unsigned long
6202159047fSniklas     #26             48  0x00000030  struct no name { ifd = -1, index = 1048575 }
6212159047fSniklas */
6222159047fSniklas 
6232159047fSniklas /* Redefinition of of storage classes as an enumeration for better
6242159047fSniklas    debugging.  */
6252159047fSniklas 
6262159047fSniklas typedef enum sc {
6272159047fSniklas   sc_Nil	 = scNil,	  /* no storage class */
6282159047fSniklas   sc_Text	 = scText,	  /* text symbol */
6292159047fSniklas   sc_Data	 = scData,	  /* initialized data symbol */
6302159047fSniklas   sc_Bss	 = scBss,	  /* un-initialized data symbol */
6312159047fSniklas   sc_Register	 = scRegister,	  /* value of symbol is register number */
6322159047fSniklas   sc_Abs	 = scAbs,	  /* value of symbol is absolute */
6332159047fSniklas   sc_Undefined	 = scUndefined,	  /* who knows? */
6342159047fSniklas   sc_CdbLocal	 = scCdbLocal,	  /* variable's value is IN se->va.?? */
6352159047fSniklas   sc_Bits	 = scBits,	  /* this is a bit field */
6362159047fSniklas   sc_CdbSystem	 = scCdbSystem,	  /* value is IN CDB's address space */
6372159047fSniklas   sc_RegImage	 = scRegImage,	  /* register value saved on stack */
6382159047fSniklas   sc_Info	 = scInfo,	  /* symbol contains debugger information */
6392159047fSniklas   sc_UserStruct	 = scUserStruct,  /* addr in struct user for current process */
6402159047fSniklas   sc_SData	 = scSData,	  /* load time only small data */
6412159047fSniklas   sc_SBss	 = scSBss,	  /* load time only small common */
6422159047fSniklas   sc_RData	 = scRData,	  /* load time only read only data */
6432159047fSniklas   sc_Var	 = scVar,	  /* Var parameter (fortran,pascal) */
6442159047fSniklas   sc_Common	 = scCommon,	  /* common variable */
6452159047fSniklas   sc_SCommon	 = scSCommon,	  /* small common */
6462159047fSniklas   sc_VarRegister = scVarRegister, /* Var parameter in a register */
6472159047fSniklas   sc_Variant	 = scVariant,	  /* Variant record */
6482159047fSniklas   sc_SUndefined	 = scSUndefined,  /* small undefined(external) data */
6492159047fSniklas   sc_Init	 = scInit,	  /* .init section symbol */
6502159047fSniklas   sc_Max	 = scMax	  /* Max storage class+1 */
6512159047fSniklas } sc_t;
6522159047fSniklas 
6532159047fSniklas /* Redefinition of symbol type.  */
6542159047fSniklas 
6552159047fSniklas typedef enum st {
6562159047fSniklas   st_Nil	= stNil,	/* Nuthin' special */
6572159047fSniklas   st_Global	= stGlobal,	/* external symbol */
6582159047fSniklas   st_Static	= stStatic,	/* static */
6592159047fSniklas   st_Param	= stParam,	/* procedure argument */
6602159047fSniklas   st_Local	= stLocal,	/* local variable */
6612159047fSniklas   st_Label	= stLabel,	/* label */
6622159047fSniklas   st_Proc	= stProc,	/*     "      "	 Procedure */
6632159047fSniklas   st_Block	= stBlock,	/* beginning of block */
6642159047fSniklas   st_End	= stEnd,	/* end (of anything) */
6652159047fSniklas   st_Member	= stMember,	/* member (of anything	- struct/union/enum */
6662159047fSniklas   st_Typedef	= stTypedef,	/* type definition */
6672159047fSniklas   st_File	= stFile,	/* file name */
6682159047fSniklas   st_RegReloc	= stRegReloc,	/* register relocation */
6692159047fSniklas   st_Forward	= stForward,	/* forwarding address */
6702159047fSniklas   st_StaticProc	= stStaticProc,	/* load time only static procs */
6712159047fSniklas   st_Constant	= stConstant,	/* const */
6722159047fSniklas   st_Str	= stStr,	/* string */
6732159047fSniklas   st_Number	= stNumber,	/* pure number (ie. 4 NOR 2+2) */
6742159047fSniklas   st_Expr	= stExpr,	/* 2+2 vs. 4 */
6752159047fSniklas   st_Type	= stType,	/* post-coercion SER */
6762159047fSniklas   st_Max	= stMax		/* max type+1 */
6772159047fSniklas } st_t;
6782159047fSniklas 
6792159047fSniklas /* Redefinition of type qualifiers.  */
6802159047fSniklas 
6812159047fSniklas typedef enum tq {
6822159047fSniklas   tq_Nil	= tqNil,	/* bt is what you see */
6832159047fSniklas   tq_Ptr	= tqPtr,	/* pointer */
6842159047fSniklas   tq_Proc	= tqProc,	/* procedure */
6852159047fSniklas   tq_Array	= tqArray,	/* duh */
6862159047fSniklas   tq_Far	= tqFar,	/* longer addressing - 8086/8 land */
6872159047fSniklas   tq_Vol	= tqVol,	/* volatile */
6882159047fSniklas   tq_Max	= tqMax		/* Max type qualifier+1 */
6892159047fSniklas } tq_t;
6902159047fSniklas 
6912159047fSniklas /* Redefinition of basic types.  */
6922159047fSniklas 
6932159047fSniklas typedef enum bt {
6942159047fSniklas   bt_Nil	= btNil,	/* undefined */
6952159047fSniklas   bt_Adr	= btAdr,	/* address - integer same size as pointer */
6962159047fSniklas   bt_Char	= btChar,	/* character */
6972159047fSniklas   bt_UChar	= btUChar,	/* unsigned character */
6982159047fSniklas   bt_Short	= btShort,	/* short */
6992159047fSniklas   bt_UShort	= btUShort,	/* unsigned short */
7002159047fSniklas   bt_Int	= btInt,	/* int */
7012159047fSniklas   bt_UInt	= btUInt,	/* unsigned int */
7022159047fSniklas   bt_Long	= btLong,	/* long */
7032159047fSniklas   bt_ULong	= btULong,	/* unsigned long */
7042159047fSniklas   bt_Float	= btFloat,	/* float (real) */
7052159047fSniklas   bt_Double	= btDouble,	/* Double (real) */
7062159047fSniklas   bt_Struct	= btStruct,	/* Structure (Record) */
7072159047fSniklas   bt_Union	= btUnion,	/* Union (variant) */
7082159047fSniklas   bt_Enum	= btEnum,	/* Enumerated */
7092159047fSniklas   bt_Typedef	= btTypedef,	/* defined via a typedef, isymRef points */
7102159047fSniklas   bt_Range	= btRange,	/* subrange of int */
7112159047fSniklas   bt_Set	= btSet,	/* pascal sets */
7122159047fSniklas   bt_Complex	= btComplex,	/* fortran complex */
7132159047fSniklas   bt_DComplex	= btDComplex,	/* fortran double complex */
7142159047fSniklas   bt_Indirect	= btIndirect,	/* forward or unnamed typedef */
7152159047fSniklas   bt_FixedDec	= btFixedDec,	/* Fixed Decimal */
7162159047fSniklas   bt_FloatDec	= btFloatDec,	/* Float Decimal */
7172159047fSniklas   bt_String	= btString,	/* Varying Length Character String */
7182159047fSniklas   bt_Bit	= btBit,	/* Aligned Bit String */
7192159047fSniklas   bt_Picture	= btPicture,	/* Picture */
7202159047fSniklas   bt_Void	= btVoid,	/* Void */
7212159047fSniklas   bt_Max	= btMax		/* Max basic type+1 */
7222159047fSniklas } bt_t;
7232159047fSniklas 
7242159047fSniklas #define N_TQ itqMax
7252159047fSniklas 
7262159047fSniklas /* States for whether to hash type or not.  */
7272159047fSniklas typedef enum hash_state {
728b55d4692Sfgsch   hash_no	= 0,		/* Don't hash type */
729b55d4692Sfgsch   hash_yes	= 1,		/* OK to hash type, or use previous hash */
730b55d4692Sfgsch   hash_record	= 2		/* OK to record hash, but don't use prev.  */
7312159047fSniklas } hash_state_t;
7322159047fSniklas 
7332159047fSniklas /* Types of different sized allocation requests.  */
7342159047fSniklas enum alloc_type {
7352159047fSniklas   alloc_type_none,		/* dummy value */
7362159047fSniklas   alloc_type_scope,		/* nested scopes linked list */
7372159047fSniklas   alloc_type_vlinks,		/* glue linking pages in varray */
7382159047fSniklas   alloc_type_shash,		/* string hash element */
7392159047fSniklas   alloc_type_thash,		/* type hash element */
7402159047fSniklas   alloc_type_tag,		/* struct/union/tag element */
7412159047fSniklas   alloc_type_forward,		/* element to hold unknown tag */
7422159047fSniklas   alloc_type_thead,		/* head of type hash list */
7432159047fSniklas   alloc_type_varray,		/* general varray allocation */
7442159047fSniklas   alloc_type_lineno,		/* line number list */
7452159047fSniklas   alloc_type_last		/* last+1 element for array bounds */
7462159047fSniklas };
7472159047fSniklas 
7482159047fSniklas /* Types of auxiliary type information.  */
7492159047fSniklas enum aux_type {
7502159047fSniklas   aux_tir,			/* TIR type information */
7512159047fSniklas   aux_rndx,			/* relative index into symbol table */
7522159047fSniklas   aux_dnLow,			/* low dimension */
7532159047fSniklas   aux_dnHigh,			/* high dimension */
7542159047fSniklas   aux_isym,			/* symbol table index (end of proc) */
7552159047fSniklas   aux_iss,			/* index into string space (not used) */
7562159047fSniklas   aux_width,			/* width for non-default sized struc fields */
7572159047fSniklas   aux_count			/* count of ranges for variant arm */
7582159047fSniklas };
7592159047fSniklas 
7602159047fSniklas /* Structures to provide n-number of virtual arrays, each of which can
7612159047fSniklas    grow linearly, and which are written in the object file as
7622159047fSniklas    sequential pages.  On systems with a BSD malloc, the
7632159047fSniklas    MAX_CLUSTER_PAGES should be 1 less than a power of two, since
7642159047fSniklas    malloc adds it's overhead, and rounds up to the next power of 2.
7652159047fSniklas    Pages are linked together via a linked list.
7662159047fSniklas 
7672159047fSniklas    If PAGE_SIZE is > 4096, the string length in the shash_t structure
7682159047fSniklas    can't be represented (assuming there are strings > 4096 bytes).  */
7692159047fSniklas 
770b305b0f1Sespie /* FIXME: Yes, there can be such strings while emitting C++ class debug
771b305b0f1Sespie    info.  Templates are the offender here, the test case in question
772b305b0f1Sespie    having a mangled class name of
773b305b0f1Sespie 
774b305b0f1Sespie      t7rb_tree4Z4xkeyZt4pair2ZC4xkeyZt7xsocket1Z4UserZt9select1st2Zt4pair\
775b305b0f1Sespie      2ZC4xkeyZt7xsocket1Z4UserZ4xkeyZt4less1Z4xkey
776b305b0f1Sespie 
777b305b0f1Sespie    Repeat that a couple dozen times while listing the class members and
778b305b0f1Sespie    you've got strings over 4k.  Hack around this for now by increasing
779b305b0f1Sespie    the page size.  A proper solution would abandon this structure scheme
780b305b0f1Sespie    certainly for very large strings, and possibly entirely.  */
781b305b0f1Sespie 
7822159047fSniklas #ifndef PAGE_SIZE
783b305b0f1Sespie #define PAGE_SIZE (8*1024)	/* size of varray pages */
7842159047fSniklas #endif
7852159047fSniklas 
7862159047fSniklas #define PAGE_USIZE ((unsigned long) PAGE_SIZE)
7872159047fSniklas 
7882159047fSniklas #ifndef MAX_CLUSTER_PAGES	/* # pages to get from system */
7892159047fSniklas #define MAX_CLUSTER_PAGES 63
7902159047fSniklas #endif
7912159047fSniklas 
7922159047fSniklas /* Linked list connecting separate page allocations.  */
7932159047fSniklas typedef struct vlinks {
7942159047fSniklas   struct vlinks	*prev;		/* previous set of pages */
7952159047fSniklas   struct vlinks *next;		/* next set of pages */
7962159047fSniklas   union  page   *datum;		/* start of page */
7972159047fSniklas   unsigned long	 start_index;	/* starting index # of page */
7982159047fSniklas } vlinks_t;
7992159047fSniklas 
8002159047fSniklas /* Virtual array header.  */
8012159047fSniklas typedef struct varray {
8022159047fSniklas   vlinks_t	*first;			/* first page link */
8032159047fSniklas   vlinks_t	*last;			/* last page link */
8042159047fSniklas   unsigned long	 num_allocated;		/* # objects allocated */
8052159047fSniklas   unsigned short object_size;		/* size in bytes of each object */
8062159047fSniklas   unsigned short objects_per_page;	/* # objects that can fit on a page */
8072159047fSniklas   unsigned short objects_last_page;	/* # objects allocated on last page */
8082159047fSniklas } varray_t;
8092159047fSniklas 
8102159047fSniklas #ifndef MALLOC_CHECK
8112159047fSniklas #define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
8122159047fSniklas #else
8132159047fSniklas #define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
8142159047fSniklas #endif
8152159047fSniklas 
8162159047fSniklas #define INIT_VARRAY(type) {	/* macro to initialize a varray */	\
8172159047fSniklas   (vlinks_t *)0,		/* first */				\
8182159047fSniklas   (vlinks_t *)0,		/* last */				\
8192159047fSniklas   0,				/* num_allocated */			\
8202159047fSniklas   sizeof (type),		/* object_size */			\
8212159047fSniklas   OBJECTS_PER_PAGE (type),	/* objects_per_page */			\
8222159047fSniklas   OBJECTS_PER_PAGE (type),	/* objects_last_page */			\
8232159047fSniklas }
8242159047fSniklas 
8252159047fSniklas /* Master type for indexes within the symbol table.  */
8262159047fSniklas typedef unsigned long symint_t;
8272159047fSniklas 
8282159047fSniklas /* Linked list support for nested scopes (file, block, structure, etc.).  */
8292159047fSniklas typedef struct scope {
8302159047fSniklas   struct scope	*prev;		/* previous scope level */
8312159047fSniklas   struct scope	*free;		/* free list pointer */
8322159047fSniklas   struct localsym *lsym;	/* pointer to local symbol node */
8332159047fSniklas   st_t		 type;		/* type of the node */
8342159047fSniklas } scope_t;
8352159047fSniklas 
8362159047fSniklas /* For a local symbol we store a gas symbol as well as the debugging
8372159047fSniklas    information we generate.  The gas symbol will be NULL if this is
8382159047fSniklas    only a debugging symbol.  */
8392159047fSniklas typedef struct localsym {
8402159047fSniklas   const char *name;		/* symbol name */
8412159047fSniklas   symbolS *as_sym;		/* symbol as seen by gas */
842191aa565Sniklas   bfd_vma addend;		/* addend to as_sym value */
8432159047fSniklas   struct efdr *file_ptr;	/* file pointer */
8442159047fSniklas   struct ecoff_proc *proc_ptr;	/* proc pointer */
8452159047fSniklas   struct localsym *begin_ptr;	/* symbol at start of block */
8462159047fSniklas   struct ecoff_aux *index_ptr;	/* index value to be filled in */
8472159047fSniklas   struct forward *forward_ref;	/* forward references to this symbol */
8482159047fSniklas   long sym_index;		/* final symbol index */
8492159047fSniklas   EXTR ecoff_sym;		/* ECOFF debugging symbol */
8502159047fSniklas } localsym_t;
8512159047fSniklas 
8522159047fSniklas /* For aux information we keep the type and the data.  */
8532159047fSniklas typedef struct ecoff_aux {
8542159047fSniklas   enum aux_type type;		/* aux type */
8552159047fSniklas   AUXU data;			/* aux data */
8562159047fSniklas } aux_t;
8572159047fSniklas 
8582159047fSniklas /* For a procedure we store the gas symbol as well as the PDR
8592159047fSniklas    debugging information.  */
8602159047fSniklas typedef struct ecoff_proc {
8612159047fSniklas   localsym_t *sym;		/* associated symbol */
8622159047fSniklas   PDR pdr;			/* ECOFF debugging info */
8632159047fSniklas } proc_t;
8642159047fSniklas 
8652159047fSniklas /* Number of proc_t structures allocated.  */
8662159047fSniklas static unsigned long proc_cnt;
8672159047fSniklas 
8682159047fSniklas /* Forward reference list for tags referenced, but not yet defined.  */
8692159047fSniklas typedef struct forward {
8702159047fSniklas   struct forward *next;		/* next forward reference */
8712159047fSniklas   struct forward *free;		/* free list pointer */
8722159047fSniklas   aux_t		 *ifd_ptr;	/* pointer to store file index */
8732159047fSniklas   aux_t		 *index_ptr;	/* pointer to store symbol index */
8742159047fSniklas } forward_t;
8752159047fSniklas 
8762159047fSniklas /* Linked list support for tags.  The first tag in the list is always
8772159047fSniklas    the current tag for that block.  */
8782159047fSniklas typedef struct tag {
8792159047fSniklas   struct tag	 *free;		/* free list pointer */
8802159047fSniklas   struct shash	 *hash_ptr;	/* pointer to the hash table head */
8812159047fSniklas   struct tag	 *same_name;	/* tag with same name in outer scope */
8822159047fSniklas   struct tag	 *same_block;	/* next tag defined in the same block.  */
8832159047fSniklas   struct forward *forward_ref;	/* list of forward references */
8842159047fSniklas   bt_t		  basic_type;	/* bt_Struct, bt_Union, or bt_Enum */
8852159047fSniklas   symint_t	  ifd;		/* file # tag defined in */
8862159047fSniklas   localsym_t	 *sym;		/* file's local symbols */
8872159047fSniklas } tag_t;
8882159047fSniklas 
8892159047fSniklas /* Head of a block's linked list of tags.  */
8902159047fSniklas typedef struct thead {
8912159047fSniklas   struct thead	*prev;		/* previous block */
8922159047fSniklas   struct thead	*free;		/* free list pointer */
8932159047fSniklas   struct tag	*first_tag;	/* first tag in block defined */
8942159047fSniklas } thead_t;
8952159047fSniklas 
8962159047fSniklas /* Union containing pointers to each the small structures which are freed up.  */
8972159047fSniklas typedef union small_free {
8982159047fSniklas   scope_t	*f_scope;	/* scope structure */
8992159047fSniklas   thead_t	*f_thead;	/* tag head structure */
9002159047fSniklas   tag_t		*f_tag;		/* tag element structure */
9012159047fSniklas   forward_t	*f_forward;	/* forward tag reference */
9022159047fSniklas } small_free_t;
9032159047fSniklas 
9042159047fSniklas /* String hash table entry.  */
9052159047fSniklas 
9062159047fSniklas typedef struct shash {
9072159047fSniklas   char		*string;	/* string we are hashing */
9082159047fSniklas   symint_t	 indx;		/* index within string table */
9092159047fSniklas   EXTR		*esym_ptr;	/* global symbol pointer */
9102159047fSniklas   localsym_t	*sym_ptr;	/* local symbol pointer */
9112159047fSniklas   localsym_t	*end_ptr;	/* symbol pointer to end block */
9122159047fSniklas   tag_t		*tag_ptr;	/* tag pointer */
9132159047fSniklas   proc_t	*proc_ptr;	/* procedure descriptor pointer */
9142159047fSniklas } shash_t;
9152159047fSniklas 
9162159047fSniklas /* Type hash table support.  The size of the hash table must fit
9172159047fSniklas    within a page with the other extended file descriptor information.
9182159047fSniklas    Because unique types which are hashed are fewer in number than
9192159047fSniklas    strings, we use a smaller hash value.  */
9202159047fSniklas 
9212159047fSniklas #define HASHBITS 30
9222159047fSniklas 
9232159047fSniklas #ifndef THASH_SIZE
9242159047fSniklas #define THASH_SIZE 113
9252159047fSniklas #endif
9262159047fSniklas 
9272159047fSniklas typedef struct thash {
9282159047fSniklas   struct thash	*next;		/* next hash value */
9292159047fSniklas   AUXU		 type;		/* type we are hashing */
9302159047fSniklas   symint_t	 indx;		/* index within string table */
9312159047fSniklas } thash_t;
9322159047fSniklas 
9332159047fSniklas /* Extended file descriptor that contains all of the support necessary
9342159047fSniklas    to add things to each file separately.  */
9352159047fSniklas typedef struct efdr {
9362159047fSniklas   FDR		 fdr;		/* File header to be written out */
9372159047fSniklas   FDR		*orig_fdr;	/* original file header */
9382159047fSniklas   char		*name;		/* filename */
9392159047fSniklas   int		 fake;		/* whether this is faked .file */
9402159047fSniklas   symint_t	 void_type;	/* aux. pointer to 'void' type */
9412159047fSniklas   symint_t	 int_type;	/* aux. pointer to 'int' type */
9422159047fSniklas   scope_t	*cur_scope;	/* current nested scopes */
9432159047fSniklas   symint_t	 file_index;	/* current file number */
9442159047fSniklas   int		 nested_scopes;	/* # nested scopes */
9452159047fSniklas   varray_t	 strings;	/* local strings */
9462159047fSniklas   varray_t	 symbols;	/* local symbols */
9472159047fSniklas   varray_t	 procs;		/* procedures */
9482159047fSniklas   varray_t	 aux_syms;	/* auxiliary symbols */
9492159047fSniklas   struct efdr	*next_file;	/* next file descriptor */
9502159047fSniklas 				/* string/type hash tables */
9512159047fSniklas   struct hash_control *str_hash;	/* string hash table */
9522159047fSniklas   thash_t	*thash_head[THASH_SIZE];
9532159047fSniklas } efdr_t;
9542159047fSniklas 
9552159047fSniklas /* Pre-initialized extended file structure.  */
956b55d4692Sfgsch static const efdr_t init_file = {
9572159047fSniklas   {			/* FDR structure */
9582159047fSniklas     0,			/* adr:		memory address of beginning of file */
9592159047fSniklas     0,			/* rss:		file name (of source, if known) */
9602159047fSniklas     0,			/* issBase:	file's string space */
9612159047fSniklas     0,			/* cbSs:	number of bytes in the ss */
9622159047fSniklas     0,			/* isymBase:	beginning of symbols */
9632159047fSniklas     0,			/* csym:	count file's of symbols */
9642159047fSniklas     0,			/* ilineBase:	file's line symbols */
9652159047fSniklas     0,			/* cline:	count of file's line symbols */
9662159047fSniklas     0,			/* ioptBase:	file's optimization entries */
9672159047fSniklas     0,			/* copt:	count of file's optimization entries */
9682159047fSniklas     0,			/* ipdFirst:	start of procedures for this file */
9692159047fSniklas     0,			/* cpd:		count of procedures for this file */
9702159047fSniklas     0,			/* iauxBase:	file's auxiliary entries */
9712159047fSniklas     0,			/* caux:	count of file's auxiliary entries */
9722159047fSniklas     0,			/* rfdBase:	index into the file indirect table */
9732159047fSniklas     0,			/* crfd:	count file indirect entries */
9742159047fSniklas     langC,		/* lang:	language for this file */
9750c6d0228Sniklas     1,			/* fMerge:	whether this file can be merged */
9762159047fSniklas     0,			/* fReadin:	true if read in (not just created) */
9776a4c786fSespie     TARGET_BYTES_BIG_ENDIAN,  /* fBigendian:	if 1, compiled on big endian machine */
9782159047fSniklas     GLEVEL_2,		/* glevel:	level this file was compiled with */
9792159047fSniklas     0,			/* reserved:	reserved for future use */
9802159047fSniklas     0,			/* cbLineOffset: byte offset from header for this file ln's */
9812159047fSniklas     0,			/* cbLine:	size of lines for this file */
9822159047fSniklas   },
9832159047fSniklas 
9842159047fSniklas   (FDR *)0,		/* orig_fdr:	original file header pointer */
9852159047fSniklas   (char *)0,		/* name:	pointer to filename */
9862159047fSniklas   0,			/* fake:	whether this is a faked .file */
9872159047fSniklas   0,			/* void_type:	ptr to aux node for void type */
9882159047fSniklas   0,			/* int_type:	ptr to aux node for int type */
9892159047fSniklas   (scope_t *)0,		/* cur_scope:	current scope being processed */
9902159047fSniklas   0,			/* file_index:	current file # */
9912159047fSniklas   0,			/* nested_scopes: # nested scopes */
9922159047fSniklas   INIT_VARRAY (char),	/* strings:	local string varray */
9932159047fSniklas   INIT_VARRAY (localsym_t),	/* symbols:	local symbols varray */
9942159047fSniklas   INIT_VARRAY (proc_t),	/* procs:	procedure varray */
9952159047fSniklas   INIT_VARRAY (aux_t),	/* aux_syms:	auxiliary symbols varray */
9962159047fSniklas 
9972159047fSniklas   (struct efdr *)0,	/* next_file:	next file structure */
9982159047fSniklas 
9992159047fSniklas   (struct hash_control *)0,	/* str_hash:	string hash table */
10002159047fSniklas   { 0 },		/* thash_head:	type hash table */
10012159047fSniklas };
10022159047fSniklas 
10032159047fSniklas static efdr_t *first_file;			/* first file descriptor */
10042159047fSniklas static efdr_t **last_file_ptr = &first_file;	/* file descriptor tail */
10052159047fSniklas 
10062159047fSniklas /* Line number information is kept in a list until the assembly is
10072159047fSniklas    finished.  */
10082159047fSniklas typedef struct lineno_list {
10092159047fSniklas   struct lineno_list *next;	/* next element in list */
10102159047fSniklas   efdr_t *file;			/* file this line is in */
10112159047fSniklas   proc_t *proc;			/* procedure this line is in */
10122159047fSniklas   fragS *frag;			/* fragment this line number is in */
10132159047fSniklas   unsigned long paddr;		/* offset within fragment */
10142159047fSniklas   long lineno;			/* actual line number */
10152159047fSniklas } lineno_list_t;
10162159047fSniklas 
10172159047fSniklas static lineno_list_t *first_lineno;
10180c6d0228Sniklas static lineno_list_t *last_lineno;
10192159047fSniklas static lineno_list_t **last_lineno_ptr = &first_lineno;
10202159047fSniklas 
10212159047fSniklas /* Sometimes there will be some .loc statements before a .ent.  We
10222159047fSniklas    keep them in this list so that we can fill in the procedure pointer
10232159047fSniklas    after we see the .ent.  */
10242159047fSniklas static lineno_list_t *noproc_lineno;
10252159047fSniklas 
10262159047fSniklas /* Union of various things that are held in pages.  */
10272159047fSniklas typedef union page {
10282159047fSniklas   char		byte	[ PAGE_SIZE ];
10292159047fSniklas   unsigned char	ubyte	[ PAGE_SIZE ];
10302159047fSniklas   efdr_t	file	[ PAGE_SIZE / sizeof (efdr_t)	     ];
10312159047fSniklas   FDR		ofile	[ PAGE_SIZE / sizeof (FDR)	     ];
10322159047fSniklas   proc_t	proc	[ PAGE_SIZE / sizeof (proc_t)	     ];
10332159047fSniklas   localsym_t	sym	[ PAGE_SIZE / sizeof (localsym_t)    ];
10342159047fSniklas   aux_t		aux	[ PAGE_SIZE / sizeof (aux_t)	     ];
10352159047fSniklas   DNR		dense	[ PAGE_SIZE / sizeof (DNR)	     ];
10362159047fSniklas   scope_t	scope	[ PAGE_SIZE / sizeof (scope_t)	     ];
10372159047fSniklas   vlinks_t	vlinks	[ PAGE_SIZE / sizeof (vlinks_t)	     ];
10382159047fSniklas   shash_t	shash	[ PAGE_SIZE / sizeof (shash_t)	     ];
10392159047fSniklas   thash_t	thash	[ PAGE_SIZE / sizeof (thash_t)	     ];
10402159047fSniklas   tag_t		tag	[ PAGE_SIZE / sizeof (tag_t)	     ];
10412159047fSniklas   forward_t	forward	[ PAGE_SIZE / sizeof (forward_t)     ];
10422159047fSniklas   thead_t	thead	[ PAGE_SIZE / sizeof (thead_t)	     ];
10432159047fSniklas   lineno_list_t	lineno	[ PAGE_SIZE / sizeof (lineno_list_t) ];
1044b305b0f1Sespie } page_type;
10452159047fSniklas 
10462159047fSniklas /* Structure holding allocation information for small sized structures.  */
10472159047fSniklas typedef struct alloc_info {
10482159047fSniklas   char		*alloc_name;	/* name of this allocation type (must be first) */
1049b305b0f1Sespie   page_type	*cur_page;	/* current page being allocated from */
10502159047fSniklas   small_free_t	 free_list;	/* current free list if any */
10512159047fSniklas   int		 unallocated;	/* number of elements unallocated on page */
10522159047fSniklas   int		 total_alloc;	/* total number of allocations */
10532159047fSniklas   int		 total_free;	/* total number of frees */
10542159047fSniklas   int		 total_pages;	/* total number of pages allocated */
10552159047fSniklas } alloc_info_t;
10562159047fSniklas 
10572159047fSniklas /* Type information collected together.  */
10582159047fSniklas typedef struct type_info {
10592159047fSniklas   bt_t	      basic_type;		/* basic type */
10602159047fSniklas   int	      orig_type;		/* original COFF-based type */
10612159047fSniklas   int	      num_tq;			/* # type qualifiers */
10622159047fSniklas   int	      num_dims;			/* # dimensions */
10632159047fSniklas   int	      num_sizes;		/* # sizes */
10642159047fSniklas   int	      extra_sizes;		/* # extra sizes not tied with dims */
10652159047fSniklas   tag_t *     tag_ptr;			/* tag pointer */
10662159047fSniklas   int	      bitfield;			/* symbol is a bitfield */
10672159047fSniklas   tq_t	      type_qualifiers[N_TQ];	/* type qualifiers (ptr, func, array)*/
10682159047fSniklas   symint_t    dimensions     [N_TQ];	/* dimensions for each array */
10692159047fSniklas   symint_t    sizes	     [N_TQ+2];	/* sizes of each array slice + size of
10702159047fSniklas 					   struct/union/enum + bitfield size */
10712159047fSniklas } type_info_t;
10722159047fSniklas 
10732159047fSniklas /* Pre-initialized type_info struct.  */
10742159047fSniklas static const type_info_t type_info_init = {
10752159047fSniklas   bt_Nil,				/* basic type */
10762159047fSniklas   T_NULL,				/* original COFF-based type */
10772159047fSniklas   0,					/* # type qualifiers */
10782159047fSniklas   0,					/* # dimensions */
10792159047fSniklas   0,					/* # sizes */
10802159047fSniklas   0,					/* sizes not tied with dims */
10812159047fSniklas   NULL,					/* ptr to tag */
10822159047fSniklas   0,					/* bitfield */
10832159047fSniklas   {					/* type qualifiers */
10842159047fSniklas     tq_Nil,
10852159047fSniklas     tq_Nil,
10862159047fSniklas     tq_Nil,
10872159047fSniklas     tq_Nil,
10882159047fSniklas     tq_Nil,
10892159047fSniklas     tq_Nil,
10902159047fSniklas   },
10912159047fSniklas   {					/* dimensions */
10922159047fSniklas     0,
10932159047fSniklas     0,
10942159047fSniklas     0,
10952159047fSniklas     0,
10962159047fSniklas     0,
10972159047fSniklas     0
10982159047fSniklas   },
10992159047fSniklas   {					/* sizes */
11002159047fSniklas     0,
11012159047fSniklas     0,
11022159047fSniklas     0,
11032159047fSniklas     0,
11042159047fSniklas     0,
11052159047fSniklas     0,
11062159047fSniklas     0,
11072159047fSniklas     0,
11082159047fSniklas   },
11092159047fSniklas };
11102159047fSniklas 
11112159047fSniklas /* Global hash table for the tags table and global table for file
11122159047fSniklas    descriptors.  */
11132159047fSniklas 
11142159047fSniklas static varray_t file_desc = INIT_VARRAY (efdr_t);
11152159047fSniklas 
11162159047fSniklas static struct hash_control *tag_hash;
11172159047fSniklas 
11182159047fSniklas /* Static types for int and void.  Also, remember the last function's
11192159047fSniklas    type (which is set up when we encounter the declaration for the
11202159047fSniklas    function, and used when the end block for the function is emitted.  */
11212159047fSniklas 
11222159047fSniklas static type_info_t int_type_info;
11232159047fSniklas static type_info_t void_type_info;
11242159047fSniklas static type_info_t last_func_type_info;
11252159047fSniklas static symbolS *last_func_sym_value;
11262159047fSniklas 
11272159047fSniklas /* Convert COFF basic type to ECOFF basic type.  The T_NULL type
11282159047fSniklas    really should use bt_Void, but this causes the current ecoff GDB to
11292159047fSniklas    issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
11302159047fSniklas    2.0) doesn't understand it, even though the compiler generates it.
11312159047fSniklas    Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
11322159047fSniklas    suite, but for now go with what works.
11332159047fSniklas 
11342159047fSniklas    It would make sense for the .type and .scl directives to use the
11352159047fSniklas    ECOFF numbers directly, rather than using the COFF numbers and
11362159047fSniklas    mapping them.  Unfortunately, this is historically what mips-tfile
11372159047fSniklas    expects, and changing gcc now would be a considerable pain (the
11382159047fSniklas    native compiler generates debugging information internally, rather
11392159047fSniklas    than via the assembler, so it will never use .type or .scl).  */
11402159047fSniklas 
11412159047fSniklas static const bt_t map_coff_types[] = {
11422159047fSniklas   bt_Nil,			/* T_NULL */
11432159047fSniklas   bt_Nil,			/* T_ARG */
11442159047fSniklas   bt_Char,			/* T_CHAR */
11452159047fSniklas   bt_Short,			/* T_SHORT */
11462159047fSniklas   bt_Int,			/* T_INT */
11472159047fSniklas   bt_Long,			/* T_LONG */
11482159047fSniklas   bt_Float,			/* T_FLOAT */
11492159047fSniklas   bt_Double,			/* T_DOUBLE */
11502159047fSniklas   bt_Struct,			/* T_STRUCT */
11512159047fSniklas   bt_Union,			/* T_UNION */
11522159047fSniklas   bt_Enum,			/* T_ENUM */
11532159047fSniklas   bt_Enum,			/* T_MOE */
11542159047fSniklas   bt_UChar,			/* T_UCHAR */
11552159047fSniklas   bt_UShort,			/* T_USHORT */
11562159047fSniklas   bt_UInt,			/* T_UINT */
11572159047fSniklas   bt_ULong			/* T_ULONG */
11582159047fSniklas };
11592159047fSniklas 
11602159047fSniklas /* Convert COFF storage class to ECOFF storage class.  */
11612159047fSniklas static const sc_t map_coff_storage[] = {
11622159047fSniklas   sc_Nil,			/*   0: C_NULL */
11632159047fSniklas   sc_Abs,			/*   1: C_AUTO	  auto var */
11642159047fSniklas   sc_Undefined,			/*   2: C_EXT	  external */
11652159047fSniklas   sc_Data,			/*   3: C_STAT	  static */
11662159047fSniklas   sc_Register,			/*   4: C_REG	  register */
11672159047fSniklas   sc_Undefined,			/*   5: C_EXTDEF  ??? */
11682159047fSniklas   sc_Text,			/*   6: C_LABEL	  label */
11692159047fSniklas   sc_Text,			/*   7: C_ULABEL  user label */
11702159047fSniklas   sc_Info,			/*   8: C_MOS	  member of struct */
11712159047fSniklas   sc_Abs,			/*   9: C_ARG	  argument */
11722159047fSniklas   sc_Info,			/*  10: C_STRTAG  struct tag */
11732159047fSniklas   sc_Info,			/*  11: C_MOU	  member of union */
11742159047fSniklas   sc_Info,			/*  12: C_UNTAG   union tag */
11752159047fSniklas   sc_Info,			/*  13: C_TPDEF	  typedef */
11762159047fSniklas   sc_Data,			/*  14: C_USTATIC ??? */
11772159047fSniklas   sc_Info,			/*  15: C_ENTAG	  enum tag */
11782159047fSniklas   sc_Info,			/*  16: C_MOE	  member of enum */
11792159047fSniklas   sc_Register,			/*  17: C_REGPARM register parameter */
11802159047fSniklas   sc_Bits,			/*  18; C_FIELD	  bitfield */
11812159047fSniklas   sc_Nil,			/*  19 */
11822159047fSniklas   sc_Nil,			/*  20 */
11832159047fSniklas   sc_Nil,			/*  21 */
11842159047fSniklas   sc_Nil,			/*  22 */
11852159047fSniklas   sc_Nil,			/*  23 */
11862159047fSniklas   sc_Nil,			/*  24 */
11872159047fSniklas   sc_Nil,			/*  25 */
11882159047fSniklas   sc_Nil,			/*  26 */
11892159047fSniklas   sc_Nil,			/*  27 */
11902159047fSniklas   sc_Nil,			/*  28 */
11912159047fSniklas   sc_Nil,			/*  29 */
11922159047fSniklas   sc_Nil,			/*  30 */
11932159047fSniklas   sc_Nil,			/*  31 */
11942159047fSniklas   sc_Nil,			/*  32 */
11952159047fSniklas   sc_Nil,			/*  33 */
11962159047fSniklas   sc_Nil,			/*  34 */
11972159047fSniklas   sc_Nil,			/*  35 */
11982159047fSniklas   sc_Nil,			/*  36 */
11992159047fSniklas   sc_Nil,			/*  37 */
12002159047fSniklas   sc_Nil,			/*  38 */
12012159047fSniklas   sc_Nil,			/*  39 */
12022159047fSniklas   sc_Nil,			/*  40 */
12032159047fSniklas   sc_Nil,			/*  41 */
12042159047fSniklas   sc_Nil,			/*  42 */
12052159047fSniklas   sc_Nil,			/*  43 */
12062159047fSniklas   sc_Nil,			/*  44 */
12072159047fSniklas   sc_Nil,			/*  45 */
12082159047fSniklas   sc_Nil,			/*  46 */
12092159047fSniklas   sc_Nil,			/*  47 */
12102159047fSniklas   sc_Nil,			/*  48 */
12112159047fSniklas   sc_Nil,			/*  49 */
12122159047fSniklas   sc_Nil,			/*  50 */
12132159047fSniklas   sc_Nil,			/*  51 */
12142159047fSniklas   sc_Nil,			/*  52 */
12152159047fSniklas   sc_Nil,			/*  53 */
12162159047fSniklas   sc_Nil,			/*  54 */
12172159047fSniklas   sc_Nil,			/*  55 */
12182159047fSniklas   sc_Nil,			/*  56 */
12192159047fSniklas   sc_Nil,			/*  57 */
12202159047fSniklas   sc_Nil,			/*  58 */
12212159047fSniklas   sc_Nil,			/*  59 */
12222159047fSniklas   sc_Nil,			/*  60 */
12232159047fSniklas   sc_Nil,			/*  61 */
12242159047fSniklas   sc_Nil,			/*  62 */
12252159047fSniklas   sc_Nil,			/*  63 */
12262159047fSniklas   sc_Nil,			/*  64 */
12272159047fSniklas   sc_Nil,			/*  65 */
12282159047fSniklas   sc_Nil,			/*  66 */
12292159047fSniklas   sc_Nil,			/*  67 */
12302159047fSniklas   sc_Nil,			/*  68 */
12312159047fSniklas   sc_Nil,			/*  69 */
12322159047fSniklas   sc_Nil,			/*  70 */
12332159047fSniklas   sc_Nil,			/*  71 */
12342159047fSniklas   sc_Nil,			/*  72 */
12352159047fSniklas   sc_Nil,			/*  73 */
12362159047fSniklas   sc_Nil,			/*  74 */
12372159047fSniklas   sc_Nil,			/*  75 */
12382159047fSniklas   sc_Nil,			/*  76 */
12392159047fSniklas   sc_Nil,			/*  77 */
12402159047fSniklas   sc_Nil,			/*  78 */
12412159047fSniklas   sc_Nil,			/*  79 */
12422159047fSniklas   sc_Nil,			/*  80 */
12432159047fSniklas   sc_Nil,			/*  81 */
12442159047fSniklas   sc_Nil,			/*  82 */
12452159047fSniklas   sc_Nil,			/*  83 */
12462159047fSniklas   sc_Nil,			/*  84 */
12472159047fSniklas   sc_Nil,			/*  85 */
12482159047fSniklas   sc_Nil,			/*  86 */
12492159047fSniklas   sc_Nil,			/*  87 */
12502159047fSniklas   sc_Nil,			/*  88 */
12512159047fSniklas   sc_Nil,			/*  89 */
12522159047fSniklas   sc_Nil,			/*  90 */
12532159047fSniklas   sc_Nil,			/*  91 */
12542159047fSniklas   sc_Nil,			/*  92 */
12552159047fSniklas   sc_Nil,			/*  93 */
12562159047fSniklas   sc_Nil,			/*  94 */
12572159047fSniklas   sc_Nil,			/*  95 */
12582159047fSniklas   sc_Nil,			/*  96 */
12592159047fSniklas   sc_Nil,			/*  97 */
12602159047fSniklas   sc_Nil,			/*  98 */
12612159047fSniklas   sc_Nil,			/*  99 */
12622159047fSniklas   sc_Text,			/* 100: C_BLOCK  block start/end */
12632159047fSniklas   sc_Text,			/* 101: C_FCN	 function start/end */
12642159047fSniklas   sc_Info,			/* 102: C_EOS	 end of struct/union/enum */
12652159047fSniklas   sc_Nil,			/* 103: C_FILE	 file start */
12662159047fSniklas   sc_Nil,			/* 104: C_LINE	 line number */
12672159047fSniklas   sc_Nil,			/* 105: C_ALIAS	 combined type info */
12682159047fSniklas   sc_Nil,			/* 106: C_HIDDEN ??? */
12692159047fSniklas };
12702159047fSniklas 
12712159047fSniklas /* Convert COFF storage class to ECOFF symbol type.  */
12722159047fSniklas static const st_t map_coff_sym_type[] = {
12732159047fSniklas   st_Nil,			/*   0: C_NULL */
12742159047fSniklas   st_Local,			/*   1: C_AUTO	  auto var */
12752159047fSniklas   st_Global,			/*   2: C_EXT	  external */
12762159047fSniklas   st_Static,			/*   3: C_STAT	  static */
12772159047fSniklas   st_Local,			/*   4: C_REG	  register */
12782159047fSniklas   st_Global,			/*   5: C_EXTDEF  ??? */
12792159047fSniklas   st_Label,			/*   6: C_LABEL	  label */
12802159047fSniklas   st_Label,			/*   7: C_ULABEL  user label */
12812159047fSniklas   st_Member,			/*   8: C_MOS	  member of struct */
12822159047fSniklas   st_Param,			/*   9: C_ARG	  argument */
12832159047fSniklas   st_Block,			/*  10: C_STRTAG  struct tag */
12842159047fSniklas   st_Member,			/*  11: C_MOU	  member of union */
12852159047fSniklas   st_Block,			/*  12: C_UNTAG   union tag */
12862159047fSniklas   st_Typedef,			/*  13: C_TPDEF	  typedef */
12872159047fSniklas   st_Static,			/*  14: C_USTATIC ??? */
12882159047fSniklas   st_Block,			/*  15: C_ENTAG	  enum tag */
12892159047fSniklas   st_Member,			/*  16: C_MOE	  member of enum */
12902159047fSniklas   st_Param,			/*  17: C_REGPARM register parameter */
12912159047fSniklas   st_Member,			/*  18; C_FIELD	  bitfield */
12922159047fSniklas   st_Nil,			/*  19 */
12932159047fSniklas   st_Nil,			/*  20 */
12942159047fSniklas   st_Nil,			/*  21 */
12952159047fSniklas   st_Nil,			/*  22 */
12962159047fSniklas   st_Nil,			/*  23 */
12972159047fSniklas   st_Nil,			/*  24 */
12982159047fSniklas   st_Nil,			/*  25 */
12992159047fSniklas   st_Nil,			/*  26 */
13002159047fSniklas   st_Nil,			/*  27 */
13012159047fSniklas   st_Nil,			/*  28 */
13022159047fSniklas   st_Nil,			/*  29 */
13032159047fSniklas   st_Nil,			/*  30 */
13042159047fSniklas   st_Nil,			/*  31 */
13052159047fSniklas   st_Nil,			/*  32 */
13062159047fSniklas   st_Nil,			/*  33 */
13072159047fSniklas   st_Nil,			/*  34 */
13082159047fSniklas   st_Nil,			/*  35 */
13092159047fSniklas   st_Nil,			/*  36 */
13102159047fSniklas   st_Nil,			/*  37 */
13112159047fSniklas   st_Nil,			/*  38 */
13122159047fSniklas   st_Nil,			/*  39 */
13132159047fSniklas   st_Nil,			/*  40 */
13142159047fSniklas   st_Nil,			/*  41 */
13152159047fSniklas   st_Nil,			/*  42 */
13162159047fSniklas   st_Nil,			/*  43 */
13172159047fSniklas   st_Nil,			/*  44 */
13182159047fSniklas   st_Nil,			/*  45 */
13192159047fSniklas   st_Nil,			/*  46 */
13202159047fSniklas   st_Nil,			/*  47 */
13212159047fSniklas   st_Nil,			/*  48 */
13222159047fSniklas   st_Nil,			/*  49 */
13232159047fSniklas   st_Nil,			/*  50 */
13242159047fSniklas   st_Nil,			/*  51 */
13252159047fSniklas   st_Nil,			/*  52 */
13262159047fSniklas   st_Nil,			/*  53 */
13272159047fSniklas   st_Nil,			/*  54 */
13282159047fSniklas   st_Nil,			/*  55 */
13292159047fSniklas   st_Nil,			/*  56 */
13302159047fSniklas   st_Nil,			/*  57 */
13312159047fSniklas   st_Nil,			/*  58 */
13322159047fSniklas   st_Nil,			/*  59 */
13332159047fSniklas   st_Nil,			/*  60 */
13342159047fSniklas   st_Nil,			/*  61 */
13352159047fSniklas   st_Nil,			/*  62 */
13362159047fSniklas   st_Nil,			/*  63 */
13372159047fSniklas   st_Nil,			/*  64 */
13382159047fSniklas   st_Nil,			/*  65 */
13392159047fSniklas   st_Nil,			/*  66 */
13402159047fSniklas   st_Nil,			/*  67 */
13412159047fSniklas   st_Nil,			/*  68 */
13422159047fSniklas   st_Nil,			/*  69 */
13432159047fSniklas   st_Nil,			/*  70 */
13442159047fSniklas   st_Nil,			/*  71 */
13452159047fSniklas   st_Nil,			/*  72 */
13462159047fSniklas   st_Nil,			/*  73 */
13472159047fSniklas   st_Nil,			/*  74 */
13482159047fSniklas   st_Nil,			/*  75 */
13492159047fSniklas   st_Nil,			/*  76 */
13502159047fSniklas   st_Nil,			/*  77 */
13512159047fSniklas   st_Nil,			/*  78 */
13522159047fSniklas   st_Nil,			/*  79 */
13532159047fSniklas   st_Nil,			/*  80 */
13542159047fSniklas   st_Nil,			/*  81 */
13552159047fSniklas   st_Nil,			/*  82 */
13562159047fSniklas   st_Nil,			/*  83 */
13572159047fSniklas   st_Nil,			/*  84 */
13582159047fSniklas   st_Nil,			/*  85 */
13592159047fSniklas   st_Nil,			/*  86 */
13602159047fSniklas   st_Nil,			/*  87 */
13612159047fSniklas   st_Nil,			/*  88 */
13622159047fSniklas   st_Nil,			/*  89 */
13632159047fSniklas   st_Nil,			/*  90 */
13642159047fSniklas   st_Nil,			/*  91 */
13652159047fSniklas   st_Nil,			/*  92 */
13662159047fSniklas   st_Nil,			/*  93 */
13672159047fSniklas   st_Nil,			/*  94 */
13682159047fSniklas   st_Nil,			/*  95 */
13692159047fSniklas   st_Nil,			/*  96 */
13702159047fSniklas   st_Nil,			/*  97 */
13712159047fSniklas   st_Nil,			/*  98 */
13722159047fSniklas   st_Nil,			/*  99 */
13732159047fSniklas   st_Block,			/* 100: C_BLOCK  block start/end */
13742159047fSniklas   st_Proc,			/* 101: C_FCN	 function start/end */
13752159047fSniklas   st_End,			/* 102: C_EOS	 end of struct/union/enum */
13762159047fSniklas   st_File,			/* 103: C_FILE	 file start */
13772159047fSniklas   st_Nil,			/* 104: C_LINE	 line number */
13782159047fSniklas   st_Nil,			/* 105: C_ALIAS	 combined type info */
13792159047fSniklas   st_Nil,			/* 106: C_HIDDEN ??? */
13802159047fSniklas };
13812159047fSniklas 
13822159047fSniklas /* Keep track of different sized allocation requests.  */
13832159047fSniklas static alloc_info_t alloc_counts[(int) alloc_type_last];
13842159047fSniklas 
13852159047fSniklas /* Record whether we have seen any debugging information.  */
13862159047fSniklas int ecoff_debugging_seen = 0;
13872159047fSniklas 
13882159047fSniklas /* Various statics.  */
13892159047fSniklas static efdr_t  *cur_file_ptr	= (efdr_t *) 0;	/* current file desc. header */
13902159047fSniklas static proc_t  *cur_proc_ptr	= (proc_t *) 0;	/* current procedure header */
13912159047fSniklas static proc_t  *first_proc_ptr  = (proc_t *) 0; /* first procedure header */
13922159047fSniklas static thead_t *top_tag_head	= (thead_t *) 0; /* top level tag head */
13932159047fSniklas static thead_t *cur_tag_head	= (thead_t *) 0; /* current tag head */
13942159047fSniklas #ifdef ECOFF_DEBUG
13952159047fSniklas static int	debug		= 0; 		/* trace functions */
13962159047fSniklas #endif
13972159047fSniklas static int	stabs_seen	= 0;		/* != 0 if stabs have been seen */
13982159047fSniklas 
13992159047fSniklas static int current_file_idx;
14002159047fSniklas static const char *current_stabs_filename;
14012159047fSniklas 
14022159047fSniklas /* Pseudo symbol to use when putting stabs into the symbol table.  */
14032159047fSniklas #ifndef STABS_SYMBOL
14042159047fSniklas #define STABS_SYMBOL "@stabs"
14052159047fSniklas #endif
14062159047fSniklas 
14072159047fSniklas static char stabs_symbol[] = STABS_SYMBOL;
14082159047fSniklas 
14092159047fSniklas /* Prototypes for functions defined in this file.  */
14102159047fSniklas 
1411*007c2a45Smiod static void add_varray_page (varray_t *vp);
1412*007c2a45Smiod static symint_t add_string (varray_t *vp,
14132159047fSniklas 			    struct hash_control *hash_tbl,
14142159047fSniklas 			    const char *str,
1415*007c2a45Smiod 			    shash_t **ret_hash);
1416*007c2a45Smiod static localsym_t *add_ecoff_symbol (const char *str, st_t type,
14172159047fSniklas 				     sc_t storage, symbolS *sym,
1418191aa565Sniklas 				     bfd_vma addend, symint_t value,
1419*007c2a45Smiod 				     symint_t indx);
1420*007c2a45Smiod static symint_t add_aux_sym_symint (symint_t aux_word);
1421*007c2a45Smiod static symint_t add_aux_sym_rndx (int file_index, symint_t sym_index);
1422*007c2a45Smiod static symint_t add_aux_sym_tir (type_info_t *t,
14232159047fSniklas 				 hash_state_t state,
1424*007c2a45Smiod 				 thash_t **hash_tbl);
1425*007c2a45Smiod static tag_t *get_tag (const char *tag, localsym_t *sym, bt_t basic_type);
1426*007c2a45Smiod static void add_unknown_tag (tag_t *ptag);
1427*007c2a45Smiod static void add_procedure (char *func);
1428*007c2a45Smiod static void add_file (const char *file_name, int indx, int fake);
14292159047fSniklas #ifdef ECOFF_DEBUG
1430*007c2a45Smiod static char *sc_to_string (sc_t storage_class);
1431*007c2a45Smiod static char *st_to_string (st_t symbol_type);
14322159047fSniklas #endif
1433*007c2a45Smiod static void mark_stabs (int);
1434*007c2a45Smiod static char *ecoff_add_bytes (char **buf, char **bufend,
1435*007c2a45Smiod 			      char *bufptr, unsigned long need);
14362159047fSniklas static unsigned long ecoff_padding_adjust
1437*007c2a45Smiod   (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1438*007c2a45Smiod    unsigned long offset, char **bufptrptr);
14392159047fSniklas static unsigned long ecoff_build_lineno
1440*007c2a45Smiod   (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1441*007c2a45Smiod    unsigned long offset, long *linecntptr);
14422159047fSniklas static unsigned long ecoff_build_symbols
1443*007c2a45Smiod   (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1444*007c2a45Smiod    unsigned long offset);
14452159047fSniklas static unsigned long ecoff_build_procs
1446*007c2a45Smiod   (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1447*007c2a45Smiod    unsigned long offset);
14482159047fSniklas static unsigned long ecoff_build_aux
1449*007c2a45Smiod   (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1450*007c2a45Smiod    unsigned long offset);
1451*007c2a45Smiod static unsigned long ecoff_build_strings (char **buf, char **bufend,
14522159047fSniklas 					  unsigned long offset,
1453*007c2a45Smiod 					  varray_t *vp);
14542159047fSniklas static unsigned long ecoff_build_ss
1455*007c2a45Smiod   (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1456*007c2a45Smiod    unsigned long offset);
14572159047fSniklas static unsigned long ecoff_build_fdr
1458*007c2a45Smiod   (const struct ecoff_debug_swap *backend, char **buf, char **bufend,
1459*007c2a45Smiod    unsigned long offset);
1460*007c2a45Smiod static void ecoff_setup_ext (void);
1461*007c2a45Smiod static page_type *allocate_cluster (unsigned long npages);
1462*007c2a45Smiod static page_type *allocate_page (void);
1463*007c2a45Smiod static scope_t *allocate_scope (void);
1464*007c2a45Smiod static void free_scope (scope_t *ptr);
1465*007c2a45Smiod static vlinks_t *allocate_vlinks (void);
1466*007c2a45Smiod static shash_t *allocate_shash (void);
1467*007c2a45Smiod static thash_t *allocate_thash (void);
1468*007c2a45Smiod static tag_t *allocate_tag (void);
1469*007c2a45Smiod static void free_tag (tag_t *ptr);
1470*007c2a45Smiod static forward_t *allocate_forward (void);
1471*007c2a45Smiod static thead_t *allocate_thead (void);
1472*007c2a45Smiod static void free_thead (thead_t *ptr);
1473*007c2a45Smiod static lineno_list_t *allocate_lineno_list (void);
14742159047fSniklas 
14752159047fSniklas /* This function should be called when the assembler starts up.  */
14762159047fSniklas 
14772159047fSniklas void
ecoff_read_begin_hook(void)1478*007c2a45Smiod ecoff_read_begin_hook (void)
14792159047fSniklas {
14802159047fSniklas   tag_hash = hash_new ();
14812159047fSniklas   top_tag_head = allocate_thead ();
14822159047fSniklas   top_tag_head->first_tag = (tag_t *) NULL;
14832159047fSniklas   top_tag_head->free = (thead_t *) NULL;
14842159047fSniklas   top_tag_head->prev = cur_tag_head;
14852159047fSniklas   cur_tag_head = top_tag_head;
14862159047fSniklas }
14872159047fSniklas 
14882159047fSniklas /* This function should be called when a symbol is created.  */
14892159047fSniklas 
14902159047fSniklas void
ecoff_symbol_new_hook(symbolS * symbolP)1491*007c2a45Smiod ecoff_symbol_new_hook (symbolS *symbolP)
14922159047fSniklas {
1493b305b0f1Sespie   OBJ_SYMFIELD_TYPE *obj;
1494b305b0f1Sespie 
14952159047fSniklas   /* Make sure that we have a file pointer, but only if we have seen a
14962159047fSniklas      file.  If we haven't seen a file, then this is a probably special
14972159047fSniklas      symbol created by md_begin which may required special handling at
14982159047fSniklas      some point.  Creating a dummy file with a dummy name is certainly
14992159047fSniklas      wrong.  */
15002159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL
15012159047fSniklas       && seen_at_least_1_file ())
15022159047fSniklas     add_file ((const char *) NULL, 0, 1);
1503b305b0f1Sespie   obj = symbol_get_obj (symbolP);
1504b305b0f1Sespie   obj->ecoff_file = cur_file_ptr;
1505b305b0f1Sespie   obj->ecoff_symbol = NULL;
1506b305b0f1Sespie   obj->ecoff_extern_size = 0;
15072159047fSniklas }
15082159047fSniklas 
15092159047fSniklas /* Add a page to a varray object.  */
15102159047fSniklas 
15112159047fSniklas static void
add_varray_page(varray_t * vp)1512*007c2a45Smiod add_varray_page (varray_t *vp /* varray to add page to */)
15132159047fSniklas {
15142159047fSniklas   vlinks_t *new_links = allocate_vlinks ();
15152159047fSniklas 
15162159047fSniklas #ifdef MALLOC_CHECK
15172159047fSniklas   if (vp->object_size > 1)
1518b305b0f1Sespie     new_links->datum = (page_type *) xcalloc (1, vp->object_size);
15192159047fSniklas   else
15202159047fSniklas #endif
15212159047fSniklas     new_links->datum = allocate_page ();
15222159047fSniklas 
15232159047fSniklas   alloc_counts[(int) alloc_type_varray].total_alloc++;
15242159047fSniklas   alloc_counts[(int) alloc_type_varray].total_pages++;
15252159047fSniklas 
15262159047fSniklas   new_links->start_index = vp->num_allocated;
15272159047fSniklas   vp->objects_last_page = 0;
15282159047fSniklas 
15292159047fSniklas   if (vp->first == (vlinks_t *) NULL)		/* first allocation? */
15302159047fSniklas     vp->first = vp->last = new_links;
15312159047fSniklas   else
15322159047fSniklas     {						/* 2nd or greater allocation */
15332159047fSniklas       new_links->prev = vp->last;
15342159047fSniklas       vp->last->next = new_links;
15352159047fSniklas       vp->last = new_links;
15362159047fSniklas     }
15372159047fSniklas }
15382159047fSniklas 
15392159047fSniklas /* Add a string (and null pad) to one of the string tables.  */
15402159047fSniklas 
15412159047fSniklas static symint_t
add_string(varray_t * vp,struct hash_control * hash_tbl,const char * str,shash_t ** ret_hash)1542*007c2a45Smiod add_string (varray_t *vp,			/* string obstack */
1543*007c2a45Smiod 	    struct hash_control *hash_tbl,	/* ptr to hash table */
1544*007c2a45Smiod 	    const char *str,			/* string */
1545*007c2a45Smiod 	    shash_t **ret_hash			/* return hash pointer */)
15462159047fSniklas {
15472159047fSniklas   register unsigned long len = strlen (str);
15482159047fSniklas   register shash_t *hash_ptr;
15492159047fSniklas 
15502159047fSniklas   if (len >= PAGE_USIZE)
1551c074d1c9Sdrahn     as_fatal (_("string too big (%lu bytes)"), len);
15522159047fSniklas 
15532159047fSniklas   hash_ptr = (shash_t *) hash_find (hash_tbl, str);
15542159047fSniklas   if (hash_ptr == (shash_t *) NULL)
15552159047fSniklas     {
15562159047fSniklas       register const char *err;
15572159047fSniklas 
15582159047fSniklas       if (vp->objects_last_page + len >= PAGE_USIZE)
15592159047fSniklas 	{
15602159047fSniklas 	  vp->num_allocated =
15612159047fSniklas 	    ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
15622159047fSniklas 	  add_varray_page (vp);
15632159047fSniklas 	}
15642159047fSniklas 
15652159047fSniklas       hash_ptr = allocate_shash ();
15662159047fSniklas       hash_ptr->indx = vp->num_allocated;
15672159047fSniklas 
15682159047fSniklas       hash_ptr->string = &vp->last->datum->byte[vp->objects_last_page];
15692159047fSniklas 
15702159047fSniklas       vp->objects_last_page += len + 1;
15712159047fSniklas       vp->num_allocated += len + 1;
15722159047fSniklas 
15732159047fSniklas       strcpy (hash_ptr->string, str);
15742159047fSniklas 
15752159047fSniklas       err = hash_insert (hash_tbl, str, (char *) hash_ptr);
15762159047fSniklas       if (err)
1577c074d1c9Sdrahn 	as_fatal (_("inserting \"%s\" into string hash table: %s"),
15782159047fSniklas 		  str, err);
15792159047fSniklas     }
15802159047fSniklas 
15812159047fSniklas   if (ret_hash != (shash_t **) NULL)
15822159047fSniklas     *ret_hash = hash_ptr;
15832159047fSniklas 
15842159047fSniklas   return hash_ptr->indx;
15852159047fSniklas }
15862159047fSniklas 
15872159047fSniklas /* Add debugging information for a symbol.  */
15882159047fSniklas 
15892159047fSniklas static localsym_t *
add_ecoff_symbol(const char * str,st_t type,sc_t storage,symbolS * sym_value,bfd_vma addend,symint_t value,symint_t indx)1590*007c2a45Smiod add_ecoff_symbol (const char *str,	/* symbol name */
1591*007c2a45Smiod 		  st_t type,		/* symbol type */
1592*007c2a45Smiod 		  sc_t storage,		/* storage class */
1593*007c2a45Smiod 		  symbolS *sym_value,	/* associated symbol.  */
1594*007c2a45Smiod 		  bfd_vma addend,	/* addend to sym_value.  */
1595*007c2a45Smiod 		  symint_t value,	/* value of symbol */
1596*007c2a45Smiod 		  symint_t indx		/* index to local/aux. syms */)
15972159047fSniklas {
15982159047fSniklas   localsym_t *psym;
15992159047fSniklas   register scope_t *pscope;
16002159047fSniklas   register thead_t *ptag_head;
16012159047fSniklas   register tag_t *ptag;
16022159047fSniklas   register tag_t *ptag_next;
16032159047fSniklas   register varray_t *vp;
16042159047fSniklas   register int scope_delta = 0;
16052159047fSniklas   shash_t *hash_ptr = (shash_t *) NULL;
16062159047fSniklas 
16072159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
1608b305b0f1Sespie     as_fatal (_("no current file pointer"));
16092159047fSniklas 
16102159047fSniklas   vp = &cur_file_ptr->symbols;
16112159047fSniklas 
16122159047fSniklas   if (vp->objects_last_page == vp->objects_per_page)
16132159047fSniklas     add_varray_page (vp);
16142159047fSniklas 
16152159047fSniklas   psym = &vp->last->datum->sym[vp->objects_last_page++];
16162159047fSniklas 
16172159047fSniklas   if (str == (const char *) NULL && sym_value != (symbolS *) NULL)
16182159047fSniklas     psym->name = S_GET_NAME (sym_value);
16192159047fSniklas   else
16202159047fSniklas     psym->name = str;
16212159047fSniklas   psym->as_sym = sym_value;
16222159047fSniklas   if (sym_value != (symbolS *) NULL)
1623b305b0f1Sespie     symbol_get_obj (sym_value)->ecoff_symbol = psym;
1624191aa565Sniklas   psym->addend = addend;
16252159047fSniklas   psym->file_ptr = cur_file_ptr;
16262159047fSniklas   psym->proc_ptr = cur_proc_ptr;
16272159047fSniklas   psym->begin_ptr = (localsym_t *) NULL;
16282159047fSniklas   psym->index_ptr = (aux_t *) NULL;
16292159047fSniklas   psym->forward_ref = (forward_t *) NULL;
16302159047fSniklas   psym->sym_index = -1;
16312159047fSniklas   memset (&psym->ecoff_sym, 0, sizeof (EXTR));
16322159047fSniklas   psym->ecoff_sym.asym.value = value;
16332159047fSniklas   psym->ecoff_sym.asym.st = (unsigned) type;
16342159047fSniklas   psym->ecoff_sym.asym.sc = (unsigned) storage;
16352159047fSniklas   psym->ecoff_sym.asym.index = indx;
16362159047fSniklas 
16372159047fSniklas   /* If there is an associated symbol, we wait until the end of the
16382159047fSniklas      assembly before deciding where to put the name (it may be just an
16392159047fSniklas      external symbol).  Otherwise, this is just a debugging symbol and
16402159047fSniklas      the name should go with the current file.  */
16412159047fSniklas   if (sym_value == (symbolS *) NULL)
16422159047fSniklas     psym->ecoff_sym.asym.iss = ((str == (const char *) NULL)
16432159047fSniklas 				? 0
16442159047fSniklas 				: add_string (&cur_file_ptr->strings,
16452159047fSniklas 					      cur_file_ptr->str_hash,
16462159047fSniklas 					      str,
16472159047fSniklas 					      &hash_ptr));
16482159047fSniklas 
16492159047fSniklas   ++vp->num_allocated;
16502159047fSniklas 
16512159047fSniklas   if (ECOFF_IS_STAB (&psym->ecoff_sym.asym))
16522159047fSniklas     return psym;
16532159047fSniklas 
16542159047fSniklas   /* Save the symbol within the hash table if this is a static
16552159047fSniklas      item, and it has a name.  */
16562159047fSniklas   if (hash_ptr != (shash_t *) NULL
16572159047fSniklas       && (type == st_Global || type == st_Static || type == st_Label
16582159047fSniklas 	  || type == st_Proc || type == st_StaticProc))
16592159047fSniklas     hash_ptr->sym_ptr = psym;
16602159047fSniklas 
16612159047fSniklas   /* push or pop a scope if appropriate.  */
16622159047fSniklas   switch (type)
16632159047fSniklas     {
16642159047fSniklas     default:
16652159047fSniklas       break;
16662159047fSniklas 
16672159047fSniklas     case st_File:			/* beginning of file */
16682159047fSniklas     case st_Proc:			/* procedure */
16692159047fSniklas     case st_StaticProc:			/* static procedure */
16702159047fSniklas     case st_Block:			/* begin scope */
16712159047fSniklas       pscope = allocate_scope ();
16722159047fSniklas       pscope->prev = cur_file_ptr->cur_scope;
16732159047fSniklas       pscope->lsym = psym;
16742159047fSniklas       pscope->type = type;
16752159047fSniklas       cur_file_ptr->cur_scope = pscope;
16762159047fSniklas 
16772159047fSniklas       if (type != st_File)
16782159047fSniklas 	scope_delta = 1;
16792159047fSniklas 
16802159047fSniklas       /* For every block type except file, struct, union, or
16812159047fSniklas          enumeration blocks, push a level on the tag stack.  We omit
16822159047fSniklas          file types, so that tags can span file boundaries.  */
16832159047fSniklas       if (type != st_File && storage != sc_Info)
16842159047fSniklas 	{
16852159047fSniklas 	  ptag_head = allocate_thead ();
16862159047fSniklas 	  ptag_head->first_tag = 0;
16872159047fSniklas 	  ptag_head->prev = cur_tag_head;
16882159047fSniklas 	  cur_tag_head = ptag_head;
16892159047fSniklas 	}
16902159047fSniklas       break;
16912159047fSniklas 
16922159047fSniklas     case st_End:
16932159047fSniklas       pscope = cur_file_ptr->cur_scope;
16942159047fSniklas       if (pscope == (scope_t *) NULL)
1695b305b0f1Sespie 	as_fatal (_("too many st_End's"));
16962159047fSniklas       else
16972159047fSniklas 	{
16982159047fSniklas 	  st_t begin_type = (st_t) pscope->lsym->ecoff_sym.asym.st;
16992159047fSniklas 
17002159047fSniklas 	  psym->begin_ptr = pscope->lsym;
17012159047fSniklas 
17022159047fSniklas 	  if (begin_type != st_File)
17032159047fSniklas 	    scope_delta = -1;
17042159047fSniklas 
17052159047fSniklas 	  /* Except for file, structure, union, or enumeration end
17062159047fSniklas 	     blocks remove all tags created within this scope.  */
17072159047fSniklas 	  if (begin_type != st_File && storage != sc_Info)
17082159047fSniklas 	    {
17092159047fSniklas 	      ptag_head = cur_tag_head;
17102159047fSniklas 	      cur_tag_head = ptag_head->prev;
17112159047fSniklas 
17122159047fSniklas 	      for (ptag = ptag_head->first_tag;
17132159047fSniklas 		   ptag != (tag_t *) NULL;
17142159047fSniklas 		   ptag = ptag_next)
17152159047fSniklas 		{
17162159047fSniklas 		  if (ptag->forward_ref != (forward_t *) NULL)
17172159047fSniklas 		    add_unknown_tag (ptag);
17182159047fSniklas 
17192159047fSniklas 		  ptag_next = ptag->same_block;
17202159047fSniklas 		  ptag->hash_ptr->tag_ptr = ptag->same_name;
17212159047fSniklas 		  free_tag (ptag);
17222159047fSniklas 		}
17232159047fSniklas 
17242159047fSniklas 	      free_thead (ptag_head);
17252159047fSniklas 	    }
17262159047fSniklas 
17272159047fSniklas 	  cur_file_ptr->cur_scope = pscope->prev;
17282159047fSniklas 
17292159047fSniklas 	  /* block begin gets next sym #.  This is set when we know
17302159047fSniklas 	     the symbol index value.  */
17312159047fSniklas 
17322159047fSniklas 	  /* Functions push two or more aux words as follows:
17332159047fSniklas 	     1st word: index+1 of the end symbol (filled in later).
17342159047fSniklas 	     2nd word: type of the function (plus any aux words needed).
17352159047fSniklas 	     Also, tie the external pointer back to the function begin symbol.  */
17362159047fSniklas 	  if (begin_type != st_File && begin_type != st_Block)
17372159047fSniklas 	    {
17382159047fSniklas 	      symint_t ty;
17392159047fSniklas 	      varray_t *svp = &cur_file_ptr->aux_syms;
17402159047fSniklas 
17412159047fSniklas 	      pscope->lsym->ecoff_sym.asym.index = add_aux_sym_symint (0);
17422159047fSniklas 	      pscope->lsym->index_ptr =
17432159047fSniklas 		&svp->last->datum->aux[svp->objects_last_page - 1];
17442159047fSniklas 	      ty = add_aux_sym_tir (&last_func_type_info,
17452159047fSniklas 				    hash_no,
17462159047fSniklas 				    &cur_file_ptr->thash_head[0]);
17472159047fSniklas 
17482159047fSniklas /* This seems to be unnecessary.  I'm not even sure what it is
17492159047fSniklas  * intended to do.  It's from mips-tfile.
17502159047fSniklas  *	      if (last_func_sym_value != (symbolS *) NULL)
17512159047fSniklas  *		{
17522159047fSniklas  *		  last_func_sym_value->ifd = cur_file_ptr->file_index;
17532159047fSniklas  *		  last_func_sym_value->index = ty;
17542159047fSniklas  *		}
17552159047fSniklas  */
17562159047fSniklas 	    }
17572159047fSniklas 
17582159047fSniklas 	  free_scope (pscope);
17592159047fSniklas 	}
17602159047fSniklas     }
17612159047fSniklas 
17622159047fSniklas   cur_file_ptr->nested_scopes += scope_delta;
17632159047fSniklas 
17642159047fSniklas #ifdef ECOFF_DEBUG
17652159047fSniklas   if (debug && type != st_File
17662159047fSniklas       && (debug > 2 || type == st_Block || type == st_End
17672159047fSniklas 	  || type == st_Proc || type == st_StaticProc))
17682159047fSniklas     {
17692159047fSniklas       char *sc_str = sc_to_string (storage);
17702159047fSniklas       char *st_str = st_to_string (type);
17712159047fSniklas       int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
17722159047fSniklas 
17732159047fSniklas       fprintf (stderr,
17742159047fSniklas 	       "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
17752159047fSniklas 	       value, depth, sc_str);
17762159047fSniklas 
17772159047fSniklas       if (str_start && str_end_p1 - str_start > 0)
1778b55d4692Sfgsch 	fprintf (stderr, " st= %-11s name= %.*s\n",
1779b55d4692Sfgsch 		 st_str, str_end_p1 - str_start, str_start);
17802159047fSniklas       else
17812159047fSniklas 	{
17822159047fSniklas 	  unsigned long len = strlen (st_str);
17832159047fSniklas 	  fprintf (stderr, " st= %.*s\n", len - 1, st_str);
17842159047fSniklas 	}
17852159047fSniklas     }
17862159047fSniklas #endif
17872159047fSniklas 
17882159047fSniklas   return psym;
17892159047fSniklas }
17902159047fSniklas 
17912159047fSniklas /* Add an auxiliary symbol (passing a symint).  This is actually used
17922159047fSniklas    for integral aux types, not just symints.  */
17932159047fSniklas 
17942159047fSniklas static symint_t
add_aux_sym_symint(symint_t aux_word)1795*007c2a45Smiod add_aux_sym_symint (symint_t aux_word /* auxiliary information word */)
17962159047fSniklas {
17972159047fSniklas   register varray_t *vp;
17982159047fSniklas   register aux_t *aux_ptr;
17992159047fSniklas 
18002159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
1801b305b0f1Sespie     as_fatal (_("no current file pointer"));
18022159047fSniklas 
18032159047fSniklas   vp = &cur_file_ptr->aux_syms;
18042159047fSniklas 
18052159047fSniklas   if (vp->objects_last_page == vp->objects_per_page)
18062159047fSniklas     add_varray_page (vp);
18072159047fSniklas 
18082159047fSniklas   aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
18092159047fSniklas   aux_ptr->type = aux_isym;
18102159047fSniklas   aux_ptr->data.isym = aux_word;
18112159047fSniklas 
18122159047fSniklas   return vp->num_allocated++;
18132159047fSniklas }
18142159047fSniklas 
18152159047fSniklas /* Add an auxiliary symbol (passing a file/symbol index combo).  */
18162159047fSniklas 
18172159047fSniklas static symint_t
add_aux_sym_rndx(int file_index,symint_t sym_index)1818*007c2a45Smiod add_aux_sym_rndx (int file_index, symint_t sym_index)
18192159047fSniklas {
18202159047fSniklas   register varray_t *vp;
18212159047fSniklas   register aux_t *aux_ptr;
18222159047fSniklas 
18232159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
1824b305b0f1Sespie     as_fatal (_("no current file pointer"));
18252159047fSniklas 
18262159047fSniklas   vp = &cur_file_ptr->aux_syms;
18272159047fSniklas 
18282159047fSniklas   if (vp->objects_last_page == vp->objects_per_page)
18292159047fSniklas     add_varray_page (vp);
18302159047fSniklas 
18312159047fSniklas   aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
18322159047fSniklas   aux_ptr->type = aux_rndx;
18332159047fSniklas   aux_ptr->data.rndx.rfd   = file_index;
18342159047fSniklas   aux_ptr->data.rndx.index = sym_index;
18352159047fSniklas 
18362159047fSniklas   return vp->num_allocated++;
18372159047fSniklas }
18382159047fSniklas 
18392159047fSniklas /* Add an auxiliary symbol (passing the basic type and possibly
18402159047fSniklas    type qualifiers).  */
18412159047fSniklas 
18422159047fSniklas static symint_t
add_aux_sym_tir(type_info_t * t,hash_state_t state,thash_t ** hash_tbl)1843*007c2a45Smiod add_aux_sym_tir (type_info_t *t,	/* current type information */
1844*007c2a45Smiod 		 hash_state_t state,	/* whether to hash type or not */
1845*007c2a45Smiod 		 thash_t **hash_tbl	/* pointer to hash table to use */)
18462159047fSniklas {
18472159047fSniklas   register varray_t *vp;
18482159047fSniklas   register aux_t *aux_ptr;
18492159047fSniklas   static AUXU init_aux;
18502159047fSniklas   symint_t ret;
18512159047fSniklas   int i;
18522159047fSniklas   AUXU aux;
18532159047fSniklas 
18542159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
1855b305b0f1Sespie     as_fatal (_("no current file pointer"));
18562159047fSniklas 
18572159047fSniklas   vp = &cur_file_ptr->aux_syms;
18582159047fSniklas 
18592159047fSniklas   aux = init_aux;
18602159047fSniklas   aux.ti.bt = (int) t->basic_type;
18612159047fSniklas   aux.ti.continued = 0;
18622159047fSniklas   aux.ti.fBitfield = t->bitfield;
18632159047fSniklas 
18642159047fSniklas   aux.ti.tq0 = (int) t->type_qualifiers[0];
18652159047fSniklas   aux.ti.tq1 = (int) t->type_qualifiers[1];
18662159047fSniklas   aux.ti.tq2 = (int) t->type_qualifiers[2];
18672159047fSniklas   aux.ti.tq3 = (int) t->type_qualifiers[3];
18682159047fSniklas   aux.ti.tq4 = (int) t->type_qualifiers[4];
18692159047fSniklas   aux.ti.tq5 = (int) t->type_qualifiers[5];
18702159047fSniklas 
18712159047fSniklas   /* For anything that adds additional information, we must not hash,
18722159047fSniklas      so check here, and reset our state.  */
18732159047fSniklas 
18742159047fSniklas   if (state != hash_no
18752159047fSniklas       && (t->type_qualifiers[0] == tq_Array
18762159047fSniklas 	  || t->type_qualifiers[1] == tq_Array
18772159047fSniklas 	  || t->type_qualifiers[2] == tq_Array
18782159047fSniklas 	  || t->type_qualifiers[3] == tq_Array
18792159047fSniklas 	  || t->type_qualifiers[4] == tq_Array
18802159047fSniklas 	  || t->type_qualifiers[5] == tq_Array
18812159047fSniklas 	  || t->basic_type == bt_Struct
18822159047fSniklas 	  || t->basic_type == bt_Union
18832159047fSniklas 	  || t->basic_type == bt_Enum
18842159047fSniklas 	  || t->bitfield
18852159047fSniklas 	  || t->num_dims > 0))
18862159047fSniklas     state = hash_no;
18872159047fSniklas 
18882159047fSniklas   /* See if we can hash this type, and save some space, but some types
18892159047fSniklas      can't be hashed (because they contain arrays or continuations),
18902159047fSniklas      and others can be put into the hash list, but cannot use existing
18912159047fSniklas      types because other aux entries precede this one.  */
18922159047fSniklas 
18932159047fSniklas   if (state != hash_no)
18942159047fSniklas     {
18952159047fSniklas       register thash_t *hash_ptr;
18962159047fSniklas       register symint_t hi;
18972159047fSniklas 
18982159047fSniklas       hi = aux.isym & ((1 << HASHBITS) - 1);
18992159047fSniklas       hi %= THASH_SIZE;
19002159047fSniklas 
19012159047fSniklas       for (hash_ptr = hash_tbl[hi];
19022159047fSniklas 	   hash_ptr != (thash_t *)0;
19032159047fSniklas 	   hash_ptr = hash_ptr->next)
19042159047fSniklas 	{
19052159047fSniklas 	  if (aux.isym == hash_ptr->type.isym)
19062159047fSniklas 	    break;
19072159047fSniklas 	}
19082159047fSniklas 
19092159047fSniklas       if (hash_ptr != (thash_t *) NULL && state == hash_yes)
19102159047fSniklas 	return hash_ptr->indx;
19112159047fSniklas 
19122159047fSniklas       if (hash_ptr == (thash_t *) NULL)
19132159047fSniklas 	{
19142159047fSniklas 	  hash_ptr = allocate_thash ();
19152159047fSniklas 	  hash_ptr->next = hash_tbl[hi];
19162159047fSniklas 	  hash_ptr->type = aux;
19172159047fSniklas 	  hash_ptr->indx = vp->num_allocated;
19182159047fSniklas 	  hash_tbl[hi] = hash_ptr;
19192159047fSniklas 	}
19202159047fSniklas     }
19212159047fSniklas 
19222159047fSniklas   /* Everything is set up, add the aux symbol.  */
19232159047fSniklas   if (vp->objects_last_page == vp->objects_per_page)
19242159047fSniklas     add_varray_page (vp);
19252159047fSniklas 
19262159047fSniklas   aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
19272159047fSniklas   aux_ptr->type = aux_tir;
19282159047fSniklas   aux_ptr->data = aux;
19292159047fSniklas 
19302159047fSniklas   ret = vp->num_allocated++;
19312159047fSniklas 
19322159047fSniklas   /* Add bitfield length if it exists.
19332159047fSniklas 
19342159047fSniklas      NOTE:  Mips documentation claims bitfield goes at the end of the
19352159047fSniklas      AUX record, but the DECstation compiler emits it here.
19362159047fSniklas      (This would only make a difference for enum bitfields.)
19372159047fSniklas 
19382159047fSniklas      Also note:  We use the last size given since gcc may emit 2
19392159047fSniklas      for an enum bitfield.  */
19402159047fSniklas 
19412159047fSniklas   if (t->bitfield)
19422159047fSniklas     (void) add_aux_sym_symint ((symint_t) t->sizes[t->num_sizes - 1]);
19432159047fSniklas 
19442159047fSniklas   /* Add tag information if needed.  Structure, union, and enum
19452159047fSniklas      references add 2 aux symbols: a [file index, symbol index]
19462159047fSniklas      pointer to the structure type, and the current file index.  */
19472159047fSniklas 
19482159047fSniklas   if (t->basic_type == bt_Struct
19492159047fSniklas       || t->basic_type == bt_Union
19502159047fSniklas       || t->basic_type == bt_Enum)
19512159047fSniklas     {
19522159047fSniklas       register symint_t file_index = t->tag_ptr->ifd;
19532159047fSniklas       register localsym_t *sym = t->tag_ptr->sym;
19542159047fSniklas       register forward_t *forward_ref = allocate_forward ();
19552159047fSniklas 
19562159047fSniklas       if (sym != (localsym_t *) NULL)
19572159047fSniklas 	{
19582159047fSniklas 	  forward_ref->next = sym->forward_ref;
19592159047fSniklas 	  sym->forward_ref = forward_ref;
19602159047fSniklas 	}
19612159047fSniklas       else
19622159047fSniklas 	{
19632159047fSniklas 	  forward_ref->next = t->tag_ptr->forward_ref;
19642159047fSniklas 	  t->tag_ptr->forward_ref = forward_ref;
19652159047fSniklas 	}
19662159047fSniklas 
19672159047fSniklas       (void) add_aux_sym_rndx (ST_RFDESCAPE, indexNil);
19682159047fSniklas       forward_ref->index_ptr
19692159047fSniklas 	= &vp->last->datum->aux[vp->objects_last_page - 1];
19702159047fSniklas 
19712159047fSniklas       (void) add_aux_sym_symint (file_index);
19722159047fSniklas       forward_ref->ifd_ptr
19732159047fSniklas 	= &vp->last->datum->aux[vp->objects_last_page - 1];
19742159047fSniklas     }
19752159047fSniklas 
19762159047fSniklas   /* Add information about array bounds if they exist.  */
19772159047fSniklas   for (i = 0; i < t->num_dims; i++)
19782159047fSniklas     {
19792159047fSniklas       (void) add_aux_sym_rndx (ST_RFDESCAPE,
19802159047fSniklas 			       cur_file_ptr->int_type);
19812159047fSniklas 
19822159047fSniklas       (void) add_aux_sym_symint (cur_file_ptr->file_index);	/* file index*/
19832159047fSniklas       (void) add_aux_sym_symint ((symint_t) 0);			/* low bound */
19842159047fSniklas       (void) add_aux_sym_symint (t->dimensions[i] - 1);		/* high bound*/
19852159047fSniklas       (void) add_aux_sym_symint ((t->dimensions[i] == 0)	/* stride */
19862159047fSniklas 				 ? 0
19872159047fSniklas 				 : (t->sizes[i] * 8) / t->dimensions[i]);
19882159047fSniklas     };
19892159047fSniklas 
19902159047fSniklas   /* NOTE:  Mips documentation claims that the bitfield width goes here.
19912159047fSniklas      But it needs to be emitted earlier.  */
19922159047fSniklas 
19932159047fSniklas   return ret;
19942159047fSniklas }
19952159047fSniklas 
19962159047fSniklas /* Add a tag to the tag table (unless it already exists).  */
19972159047fSniklas 
19982159047fSniklas static tag_t *
get_tag(const char * tag,localsym_t * sym,bt_t basic_type)1999*007c2a45Smiod get_tag (const char *tag,	/* tag name */
2000*007c2a45Smiod 	 localsym_t *sym,	/* tag start block */
2001*007c2a45Smiod 	 bt_t basic_type	/* bt_Struct, bt_Union, or bt_Enum */)
20022159047fSniklas {
20032159047fSniklas   shash_t *hash_ptr;
20042159047fSniklas   const char *err;
20052159047fSniklas   tag_t *tag_ptr;
20062159047fSniklas 
20072159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
2008b305b0f1Sespie     as_fatal (_("no current file pointer"));
20092159047fSniklas 
20102159047fSniklas   hash_ptr = (shash_t *) hash_find (tag_hash, tag);
20112159047fSniklas 
20122159047fSniklas   if (hash_ptr != (shash_t *) NULL
20132159047fSniklas       && hash_ptr->tag_ptr != (tag_t *) NULL)
20142159047fSniklas     {
20152159047fSniklas       tag_ptr = hash_ptr->tag_ptr;
20162159047fSniklas       if (sym != (localsym_t *) NULL)
20172159047fSniklas 	{
20182159047fSniklas 	  tag_ptr->basic_type = basic_type;
20192159047fSniklas 	  tag_ptr->ifd        = cur_file_ptr->file_index;
20202159047fSniklas 	  tag_ptr->sym        = sym;
20212159047fSniklas 	}
20222159047fSniklas       return tag_ptr;
20232159047fSniklas     }
20242159047fSniklas 
20252159047fSniklas   if (hash_ptr == (shash_t *) NULL)
20262159047fSniklas     {
20272159047fSniklas       char *perm;
20282159047fSniklas 
2029c074d1c9Sdrahn       perm = xstrdup (tag);
20302159047fSniklas       hash_ptr = allocate_shash ();
20312159047fSniklas       err = hash_insert (tag_hash, perm, (char *) hash_ptr);
20322159047fSniklas       if (err)
2033c074d1c9Sdrahn 	as_fatal (_("inserting \"%s\" into tag hash table: %s"),
20342159047fSniklas 		  tag, err);
20352159047fSniklas       hash_ptr->string = perm;
20362159047fSniklas     }
20372159047fSniklas 
20382159047fSniklas   tag_ptr = allocate_tag ();
20392159047fSniklas   tag_ptr->forward_ref	= (forward_t *) NULL;
20402159047fSniklas   tag_ptr->hash_ptr	= hash_ptr;
20412159047fSniklas   tag_ptr->same_name	= hash_ptr->tag_ptr;
20422159047fSniklas   tag_ptr->basic_type	= basic_type;
20432159047fSniklas   tag_ptr->sym		= sym;
20442159047fSniklas   tag_ptr->ifd		= ((sym == (localsym_t *) NULL)
20452159047fSniklas 			   ? (symint_t) -1
20462159047fSniklas 			   : cur_file_ptr->file_index);
20472159047fSniklas   tag_ptr->same_block	= cur_tag_head->first_tag;
20482159047fSniklas 
20492159047fSniklas   cur_tag_head->first_tag = tag_ptr;
20502159047fSniklas   hash_ptr->tag_ptr	  = tag_ptr;
20512159047fSniklas 
20522159047fSniklas   return tag_ptr;
20532159047fSniklas }
20542159047fSniklas 
20552159047fSniklas /* Add an unknown {struct, union, enum} tag.  */
20562159047fSniklas 
20572159047fSniklas static void
add_unknown_tag(tag_t * ptag)2058*007c2a45Smiod add_unknown_tag (tag_t *ptag /* pointer to tag information */)
20592159047fSniklas {
20602159047fSniklas   shash_t *hash_ptr	= ptag->hash_ptr;
20612159047fSniklas   char *name		= hash_ptr->string;
20622159047fSniklas   localsym_t *sym;
20632159047fSniklas   forward_t **pf;
20642159047fSniklas 
20652159047fSniklas #ifdef ECOFF_DEBUG
20662159047fSniklas   if (debug > 1)
20672159047fSniklas     {
20682159047fSniklas       char *agg_type = "{unknown aggregate type}";
20692159047fSniklas       switch (ptag->basic_type)
20702159047fSniklas 	{
20712159047fSniklas 	case bt_Struct:	agg_type = "struct";	break;
20722159047fSniklas 	case bt_Union:	agg_type = "union";	break;
20732159047fSniklas 	case bt_Enum:	agg_type = "enum";	break;
20742159047fSniklas 	default:				break;
20752159047fSniklas 	}
20762159047fSniklas 
20772159047fSniklas       fprintf (stderr, "unknown %s %.*s found\n", agg_type,
20782159047fSniklas 	       hash_ptr->len, name_start);
20792159047fSniklas     }
20802159047fSniklas #endif
20812159047fSniklas 
20822159047fSniklas   sym = add_ecoff_symbol (name,
20832159047fSniklas 			  st_Block,
20842159047fSniklas 			  sc_Info,
20852159047fSniklas 			  (symbolS *) NULL,
2086191aa565Sniklas 			  (bfd_vma) 0,
20872159047fSniklas 			  (symint_t) 0,
20882159047fSniklas 			  (symint_t) 0);
20892159047fSniklas 
20902159047fSniklas   (void) add_ecoff_symbol (name,
20912159047fSniklas 			   st_End,
20922159047fSniklas 			   sc_Info,
20932159047fSniklas 			   (symbolS *) NULL,
2094191aa565Sniklas 			   (bfd_vma) 0,
20952159047fSniklas 			   (symint_t) 0,
20962159047fSniklas 			   (symint_t) 0);
20972159047fSniklas 
20982159047fSniklas   for (pf = &sym->forward_ref; *pf != (forward_t *) NULL; pf = &(*pf)->next)
20992159047fSniklas     ;
21002159047fSniklas   *pf = ptag->forward_ref;
21012159047fSniklas }
21022159047fSniklas 
21032159047fSniklas /* Add a procedure to the current file's list of procedures, and record
21042159047fSniklas    this is the current procedure.  */
21052159047fSniklas 
21062159047fSniklas static void
add_procedure(char * func)2107*007c2a45Smiod add_procedure (char *func /* func name */)
21082159047fSniklas {
21092159047fSniklas   register varray_t *vp;
21102159047fSniklas   register proc_t *new_proc_ptr;
2111191aa565Sniklas   symbolS *sym;
21122159047fSniklas 
21132159047fSniklas #ifdef ECOFF_DEBUG
21142159047fSniklas   if (debug)
21152159047fSniklas     fputc ('\n', stderr);
21162159047fSniklas #endif
21172159047fSniklas 
21182159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
2119b305b0f1Sespie     as_fatal (_("no current file pointer"));
21202159047fSniklas 
21212159047fSniklas   vp = &cur_file_ptr->procs;
21222159047fSniklas 
21232159047fSniklas   if (vp->objects_last_page == vp->objects_per_page)
21242159047fSniklas     add_varray_page (vp);
21252159047fSniklas 
21262159047fSniklas   cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[vp->objects_last_page++];
21272159047fSniklas 
21282159047fSniklas   if (first_proc_ptr == (proc_t *) NULL)
21292159047fSniklas     first_proc_ptr = new_proc_ptr;
21302159047fSniklas 
21312159047fSniklas   vp->num_allocated++;
21322159047fSniklas 
21332159047fSniklas   new_proc_ptr->pdr.isym = -1;
21342159047fSniklas   new_proc_ptr->pdr.iline = -1;
21352159047fSniklas   new_proc_ptr->pdr.lnLow = -1;
21362159047fSniklas   new_proc_ptr->pdr.lnHigh = -1;
21372159047fSniklas 
2138191aa565Sniklas   /* Set the BSF_FUNCTION flag for the symbol.  */
2139191aa565Sniklas   sym = symbol_find_or_make (func);
2140b305b0f1Sespie   symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
2141191aa565Sniklas 
21422159047fSniklas   /* Push the start of the function.  */
21432159047fSniklas   new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
2144191aa565Sniklas 					sym, (bfd_vma) 0, (symint_t) 0,
2145191aa565Sniklas 					(symint_t) 0);
21462159047fSniklas 
21472159047fSniklas   ++proc_cnt;
21482159047fSniklas 
21492159047fSniklas   /* Fill in the linenos preceding the .ent, if any.  */
21502159047fSniklas   if (noproc_lineno != (lineno_list_t *) NULL)
21512159047fSniklas     {
21522159047fSniklas       lineno_list_t *l;
21532159047fSniklas 
21542159047fSniklas       for (l = noproc_lineno; l != (lineno_list_t *) NULL; l = l->next)
21552159047fSniklas 	l->proc = new_proc_ptr;
21562159047fSniklas       *last_lineno_ptr = noproc_lineno;
21572159047fSniklas       while (*last_lineno_ptr != NULL)
21580c6d0228Sniklas 	{
21590c6d0228Sniklas 	  last_lineno = *last_lineno_ptr;
21600c6d0228Sniklas 	  last_lineno_ptr = &last_lineno->next;
21610c6d0228Sniklas 	}
21622159047fSniklas       noproc_lineno = (lineno_list_t *) NULL;
21632159047fSniklas     }
21642159047fSniklas }
2165b305b0f1Sespie 
2166b305b0f1Sespie symbolS *
ecoff_get_cur_proc_sym(void)2167*007c2a45Smiod ecoff_get_cur_proc_sym (void)
2168b305b0f1Sespie {
2169b305b0f1Sespie   return (cur_proc_ptr ? cur_proc_ptr->sym->as_sym : NULL);
2170b305b0f1Sespie }
21712159047fSniklas 
21722159047fSniklas /* Add a new filename, and set up all of the file relative
21732159047fSniklas    virtual arrays (strings, symbols, aux syms, etc.).  Record
21742159047fSniklas    where the current file structure lives.  */
21752159047fSniklas 
21762159047fSniklas static void
add_file(const char * file_name,int indx ATTRIBUTE_UNUSED,int fake)2177*007c2a45Smiod add_file (const char *file_name, int indx ATTRIBUTE_UNUSED, int fake)
21782159047fSniklas {
21792159047fSniklas   register int first_ch;
21802159047fSniklas   register efdr_t *fil_ptr;
21812159047fSniklas 
21822159047fSniklas #ifdef ECOFF_DEBUG
21832159047fSniklas   if (debug)
21842159047fSniklas     fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
21852159047fSniklas #endif
21862159047fSniklas 
21872159047fSniklas   /* If the file name is NULL, then no .file symbol appeared, and we
21882159047fSniklas      want to use the actual file name.  */
21892159047fSniklas   if (file_name == (const char *) NULL)
21902159047fSniklas     {
21912159047fSniklas       char *file;
21922159047fSniklas 
21932159047fSniklas       if (first_file != (efdr_t *) NULL)
2194b305b0f1Sespie 	as_fatal (_("fake .file after real one"));
21952159047fSniklas       as_where (&file, (unsigned int *) NULL);
21962159047fSniklas       file_name = (const char *) file;
21972159047fSniklas 
2198b305b0f1Sespie       /* Automatically generate ECOFF debugging information, since I
2199b305b0f1Sespie          think that's what other ECOFF assemblers do.  We don't do
2200b305b0f1Sespie          this if we see a .file directive with a string, since that
2201b305b0f1Sespie          implies that some sort of debugging information is being
2202b305b0f1Sespie          provided.  */
2203b55d4692Sfgsch       if (! symbol_table_frozen && debug_type == DEBUG_UNSPECIFIED)
2204b305b0f1Sespie 	debug_type = DEBUG_ECOFF;
22052159047fSniklas     }
2206c074d1c9Sdrahn   else if (debug_type == DEBUG_UNSPECIFIED)
2207b55d4692Sfgsch     debug_type = DEBUG_NONE;
22082159047fSniklas 
22092159047fSniklas #ifndef NO_LISTING
22102159047fSniklas   if (listing)
22112159047fSniklas     listing_source_file (file_name);
22122159047fSniklas #endif
22132159047fSniklas 
22142159047fSniklas   current_stabs_filename = file_name;
22152159047fSniklas 
22162159047fSniklas   /* If we're creating stabs, then we don't actually make a new FDR.
22172159047fSniklas      Instead, we just create a stabs symbol.  */
22182159047fSniklas   if (stabs_seen)
22192159047fSniklas     {
22202159047fSniklas       (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil,
22212159047fSniklas 			       symbol_new ("L0\001", now_seg,
22222159047fSniklas 					   (valueT) frag_now_fix (),
22232159047fSniklas 					   frag_now),
2224191aa565Sniklas 			       (bfd_vma) 0, 0, ECOFF_MARK_STAB (N_SOL));
22252159047fSniklas       return;
22262159047fSniklas     }
22272159047fSniklas 
22282159047fSniklas   first_ch = *file_name;
22292159047fSniklas 
22300c6d0228Sniklas   /* FIXME: We can't safely merge files which have line number
22310c6d0228Sniklas      information (fMerge will be zero in this case).  Otherwise, we
22320c6d0228Sniklas      get incorrect line number debugging info.  See for instance
22330c6d0228Sniklas      ecoff_build_lineno, which will end up setting all file->fdr.*
22340c6d0228Sniklas      fields multiple times, resulting in incorrect debug info.  In
22350c6d0228Sniklas      order to make this work right, all line number and symbol info
22360c6d0228Sniklas      for the same source file has to be adjacent in the object file,
22370c6d0228Sniklas      so that a single file descriptor can be used to point to them.
22380c6d0228Sniklas      This would require maintaining file specific lists of line
22390c6d0228Sniklas      numbers and symbols for each file, so that they can be merged
22400c6d0228Sniklas      together (or output together) when two .file pseudo-ops are
22410c6d0228Sniklas      merged into one file descriptor.  */
22422159047fSniklas 
22432159047fSniklas   /* See if the file has already been created.  */
22442159047fSniklas   for (fil_ptr = first_file;
22452159047fSniklas        fil_ptr != (efdr_t *) NULL;
22462159047fSniklas        fil_ptr = fil_ptr->next_file)
22472159047fSniklas     {
22482159047fSniklas       if (first_ch == fil_ptr->name[0]
22490c6d0228Sniklas 	  && strcmp (file_name, fil_ptr->name) == 0
22500c6d0228Sniklas 	  && fil_ptr->fdr.fMerge)
22512159047fSniklas 	{
22522159047fSniklas 	  cur_file_ptr = fil_ptr;
22532159047fSniklas 	  if (! fake)
22542159047fSniklas 	    cur_file_ptr->fake = 0;
22552159047fSniklas 	  break;
22562159047fSniklas 	}
22572159047fSniklas     }
22582159047fSniklas 
22592159047fSniklas   /* If this is a new file, create it.  */
22602159047fSniklas   if (fil_ptr == (efdr_t *) NULL)
22612159047fSniklas     {
22622159047fSniklas       if (file_desc.objects_last_page == file_desc.objects_per_page)
22632159047fSniklas 	add_varray_page (&file_desc);
22642159047fSniklas 
22652159047fSniklas       fil_ptr = cur_file_ptr =
22662159047fSniklas 	&file_desc.last->datum->file[file_desc.objects_last_page++];
22672159047fSniklas       *fil_ptr = init_file;
22682159047fSniklas 
22692159047fSniklas       fil_ptr->file_index = current_file_idx++;
22702159047fSniklas       ++file_desc.num_allocated;
22712159047fSniklas 
22722159047fSniklas       fil_ptr->fake = fake;
22732159047fSniklas 
22742159047fSniklas       /* Allocate the string hash table.  */
22752159047fSniklas       fil_ptr->str_hash = hash_new ();
22762159047fSniklas 
22772159047fSniklas       /* Make sure 0 byte in string table is null  */
22782159047fSniklas       add_string (&fil_ptr->strings,
22792159047fSniklas 		  fil_ptr->str_hash,
22802159047fSniklas 		  "",
22812159047fSniklas 		  (shash_t **)0);
22822159047fSniklas 
22832159047fSniklas       if (strlen (file_name) > PAGE_USIZE - 2)
2284c074d1c9Sdrahn 	as_fatal (_("filename goes over one page boundary"));
22852159047fSniklas 
22862159047fSniklas       /* Push the start of the filename. We assume that the filename
22872159047fSniklas          will be stored at string offset 1.  */
22882159047fSniklas       (void) add_ecoff_symbol (file_name, st_File, sc_Text,
2289191aa565Sniklas 			       (symbolS *) NULL, (bfd_vma) 0,
22902159047fSniklas 			       (symint_t) 0, (symint_t) 0);
22912159047fSniklas       fil_ptr->fdr.rss = 1;
22922159047fSniklas       fil_ptr->name = &fil_ptr->strings.last->datum->byte[1];
22932159047fSniklas 
22942159047fSniklas       /* Update the linked list of file descriptors.  */
22952159047fSniklas       *last_file_ptr = fil_ptr;
22962159047fSniklas       last_file_ptr = &fil_ptr->next_file;
22972159047fSniklas 
22982159047fSniklas       /* Add void & int types to the file (void should be first to catch
22992159047fSniklas          errant 0's within the index fields).  */
23002159047fSniklas       fil_ptr->void_type = add_aux_sym_tir (&void_type_info,
23012159047fSniklas 					    hash_yes,
23022159047fSniklas 					    &cur_file_ptr->thash_head[0]);
23032159047fSniklas 
23042159047fSniklas       fil_ptr->int_type = add_aux_sym_tir (&int_type_info,
23052159047fSniklas 					   hash_yes,
23062159047fSniklas 					   &cur_file_ptr->thash_head[0]);
23072159047fSniklas     }
23082159047fSniklas }
2309e93f7393Sniklas 
2310e93f7393Sniklas /* This function is called when the assembler notices a preprocessor
2311e93f7393Sniklas    directive switching to a new file.  This will not happen in
2312e93f7393Sniklas    compiler output, only in hand coded assembler.  */
2313e93f7393Sniklas 
2314e93f7393Sniklas void
ecoff_new_file(const char * name)2315*007c2a45Smiod ecoff_new_file (const char *name)
2316e93f7393Sniklas {
2317e93f7393Sniklas   if (cur_file_ptr != NULL && strcmp (cur_file_ptr->name, name) == 0)
2318e93f7393Sniklas     return;
2319e93f7393Sniklas   add_file (name, 0, 0);
2320b305b0f1Sespie 
2321b305b0f1Sespie   /* This is a hand coded assembler file, so automatically turn on
2322b305b0f1Sespie      debugging information.  */
2323b55d4692Sfgsch   if (debug_type == DEBUG_UNSPECIFIED)
2324b305b0f1Sespie     debug_type = DEBUG_ECOFF;
2325e93f7393Sniklas }
23262159047fSniklas 
23272159047fSniklas #ifdef ECOFF_DEBUG
23282159047fSniklas 
23292159047fSniklas /* Convert storage class to string.  */
23302159047fSniklas 
23312159047fSniklas static char *
sc_to_string(storage_class)23322159047fSniklas sc_to_string (storage_class)
23332159047fSniklas      sc_t storage_class;
23342159047fSniklas {
23352159047fSniklas   switch (storage_class)
23362159047fSniklas     {
23372159047fSniklas     case sc_Nil:	 return "Nil,";
23382159047fSniklas     case sc_Text:	 return "Text,";
23392159047fSniklas     case sc_Data:	 return "Data,";
23402159047fSniklas     case sc_Bss:	 return "Bss,";
23412159047fSniklas     case sc_Register:	 return "Register,";
23422159047fSniklas     case sc_Abs:	 return "Abs,";
23432159047fSniklas     case sc_Undefined:	 return "Undefined,";
23442159047fSniklas     case sc_CdbLocal:	 return "CdbLocal,";
23452159047fSniklas     case sc_Bits:	 return "Bits,";
23462159047fSniklas     case sc_CdbSystem:	 return "CdbSystem,";
23472159047fSniklas     case sc_RegImage:	 return "RegImage,";
23482159047fSniklas     case sc_Info:	 return "Info,";
23492159047fSniklas     case sc_UserStruct:	 return "UserStruct,";
23502159047fSniklas     case sc_SData:	 return "SData,";
23512159047fSniklas     case sc_SBss:	 return "SBss,";
23522159047fSniklas     case sc_RData:	 return "RData,";
23532159047fSniklas     case sc_Var:	 return "Var,";
23542159047fSniklas     case sc_Common:	 return "Common,";
23552159047fSniklas     case sc_SCommon:	 return "SCommon,";
23562159047fSniklas     case sc_VarRegister: return "VarRegister,";
23572159047fSniklas     case sc_Variant:	 return "Variant,";
23582159047fSniklas     case sc_SUndefined:	 return "SUndefined,";
23592159047fSniklas     case sc_Init:	 return "Init,";
23602159047fSniklas     case sc_Max:	 return "Max,";
23612159047fSniklas     }
23622159047fSniklas 
23632159047fSniklas   return "???,";
23642159047fSniklas }
23652159047fSniklas 
23662159047fSniklas #endif /* DEBUG */
23672159047fSniklas 
23682159047fSniklas #ifdef ECOFF_DEBUG
23692159047fSniklas 
23702159047fSniklas /* Convert symbol type to string.  */
23712159047fSniklas 
23722159047fSniklas static char *
st_to_string(symbol_type)23732159047fSniklas st_to_string (symbol_type)
23742159047fSniklas      st_t symbol_type;
23752159047fSniklas {
23762159047fSniklas   switch (symbol_type)
23772159047fSniklas     {
23782159047fSniklas     case st_Nil:	return "Nil,";
23792159047fSniklas     case st_Global:	return "Global,";
23802159047fSniklas     case st_Static:	return "Static,";
23812159047fSniklas     case st_Param:	return "Param,";
23822159047fSniklas     case st_Local:	return "Local,";
23832159047fSniklas     case st_Label:	return "Label,";
23842159047fSniklas     case st_Proc:	return "Proc,";
23852159047fSniklas     case st_Block:	return "Block,";
23862159047fSniklas     case st_End:	return "End,";
23872159047fSniklas     case st_Member:	return "Member,";
23882159047fSniklas     case st_Typedef:	return "Typedef,";
23892159047fSniklas     case st_File:	return "File,";
23902159047fSniklas     case st_RegReloc:	return "RegReloc,";
23912159047fSniklas     case st_Forward:	return "Forward,";
23922159047fSniklas     case st_StaticProc:	return "StaticProc,";
23932159047fSniklas     case st_Constant:	return "Constant,";
23942159047fSniklas     case st_Str:	return "String,";
23952159047fSniklas     case st_Number:	return "Number,";
23962159047fSniklas     case st_Expr:	return "Expr,";
23972159047fSniklas     case st_Type:	return "Type,";
23982159047fSniklas     case st_Max:	return "Max,";
23992159047fSniklas     }
24002159047fSniklas 
24012159047fSniklas   return "???,";
24022159047fSniklas }
24032159047fSniklas 
24042159047fSniklas #endif /* DEBUG */
24052159047fSniklas 
24062159047fSniklas /* Parse .begin directives which have a label as the first argument
24072159047fSniklas    which gives the location of the start of the block.  */
24082159047fSniklas 
24092159047fSniklas void
ecoff_directive_begin(int ignore ATTRIBUTE_UNUSED)2410*007c2a45Smiod ecoff_directive_begin (int ignore ATTRIBUTE_UNUSED)
24112159047fSniklas {
24122159047fSniklas   char *name;
24132159047fSniklas   char name_end;
24142159047fSniklas 
24152159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
24162159047fSniklas     {
2417b305b0f1Sespie       as_warn (_(".begin directive without a preceding .file directive"));
24182159047fSniklas       demand_empty_rest_of_line ();
24192159047fSniklas       return;
24202159047fSniklas     }
24212159047fSniklas 
24222159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
24232159047fSniklas     {
2424b305b0f1Sespie       as_warn (_(".begin directive without a preceding .ent directive"));
24252159047fSniklas       demand_empty_rest_of_line ();
24262159047fSniklas       return;
24272159047fSniklas     }
24282159047fSniklas 
24292159047fSniklas   name = input_line_pointer;
24302159047fSniklas   name_end = get_symbol_end ();
24312159047fSniklas 
24322159047fSniklas   (void) add_ecoff_symbol ((const char *) NULL, st_Block, sc_Text,
24332159047fSniklas 			   symbol_find_or_make (name),
2434191aa565Sniklas 			   (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
24352159047fSniklas 
24362159047fSniklas   *input_line_pointer = name_end;
24372159047fSniklas 
24382159047fSniklas   /* The line number follows, but we don't use it.  */
24392159047fSniklas   (void) get_absolute_expression ();
24402159047fSniklas   demand_empty_rest_of_line ();
24412159047fSniklas }
24422159047fSniklas 
24432159047fSniklas /* Parse .bend directives which have a label as the first argument
24442159047fSniklas    which gives the location of the end of the block.  */
24452159047fSniklas 
24462159047fSniklas void
ecoff_directive_bend(int ignore ATTRIBUTE_UNUSED)2447*007c2a45Smiod ecoff_directive_bend (int ignore ATTRIBUTE_UNUSED)
24482159047fSniklas {
24492159047fSniklas   char *name;
24502159047fSniklas   char name_end;
24512159047fSniklas   symbolS *endsym;
24522159047fSniklas 
24532159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
24542159047fSniklas     {
2455b305b0f1Sespie       as_warn (_(".bend directive without a preceding .file directive"));
24562159047fSniklas       demand_empty_rest_of_line ();
24572159047fSniklas       return;
24582159047fSniklas     }
24592159047fSniklas 
24602159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
24612159047fSniklas     {
2462b305b0f1Sespie       as_warn (_(".bend directive without a preceding .ent directive"));
24632159047fSniklas       demand_empty_rest_of_line ();
24642159047fSniklas       return;
24652159047fSniklas     }
24662159047fSniklas 
24672159047fSniklas   name = input_line_pointer;
24682159047fSniklas   name_end = get_symbol_end ();
24692159047fSniklas 
24702159047fSniklas   /* The value is the distance between the .bend directive and the
24712159047fSniklas      corresponding symbol.  We fill in the offset when we write out
24722159047fSniklas      the symbol.  */
24732159047fSniklas   endsym = symbol_find (name);
24742159047fSniklas   if (endsym == (symbolS *) NULL)
2475b305b0f1Sespie     as_warn (_(".bend directive names unknown symbol"));
24762159047fSniklas   else
24772159047fSniklas     (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym,
2478191aa565Sniklas 			     (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
24792159047fSniklas 
24802159047fSniklas   *input_line_pointer = name_end;
24812159047fSniklas 
24822159047fSniklas   /* The line number follows, but we don't use it.  */
24832159047fSniklas   (void) get_absolute_expression ();
24842159047fSniklas   demand_empty_rest_of_line ();
24852159047fSniklas }
24862159047fSniklas 
24872159047fSniklas /* COFF debugging information is provided as a series of directives
24882159047fSniklas    (.def, .scl, etc.).  We build up information as we read the
24892159047fSniklas    directives in the following static variables, and file it away when
24902159047fSniklas    we reach the .endef directive.  */
24912159047fSniklas static char *coff_sym_name;
24922159047fSniklas static type_info_t coff_type;
24932159047fSniklas static sc_t coff_storage_class;
24942159047fSniklas static st_t coff_symbol_typ;
24952159047fSniklas static int coff_is_function;
24962159047fSniklas static char *coff_tag;
24972159047fSniklas static valueT coff_value;
2498191aa565Sniklas static symbolS *coff_sym_value;
2499191aa565Sniklas static bfd_vma coff_sym_addend;
25002159047fSniklas static int coff_inside_enumeration;
25012159047fSniklas 
25022159047fSniklas /* Handle a .def directive: start defining a symbol.  */
25032159047fSniklas 
25042159047fSniklas void
ecoff_directive_def(int ignore ATTRIBUTE_UNUSED)2505*007c2a45Smiod ecoff_directive_def (int ignore ATTRIBUTE_UNUSED)
25062159047fSniklas {
25072159047fSniklas   char *name;
25082159047fSniklas   char name_end;
25092159047fSniklas 
25102159047fSniklas   ecoff_debugging_seen = 1;
25112159047fSniklas 
25122159047fSniklas   SKIP_WHITESPACE ();
25132159047fSniklas 
25142159047fSniklas   name = input_line_pointer;
25152159047fSniklas   name_end = get_symbol_end ();
25162159047fSniklas 
25172159047fSniklas   if (coff_sym_name != (char *) NULL)
2518b305b0f1Sespie     as_warn (_(".def pseudo-op used inside of .def/.endef; ignored"));
25192159047fSniklas   else if (*name == '\0')
2520c074d1c9Sdrahn     as_warn (_("empty symbol name in .def; ignored"));
25212159047fSniklas   else
25222159047fSniklas     {
25232159047fSniklas       if (coff_sym_name != (char *) NULL)
25242159047fSniklas 	free (coff_sym_name);
25252159047fSniklas       if (coff_tag != (char *) NULL)
25262159047fSniklas 	free (coff_tag);
2527c074d1c9Sdrahn 
2528c074d1c9Sdrahn       coff_sym_name = xstrdup (name);
25292159047fSniklas       coff_type = type_info_init;
25302159047fSniklas       coff_storage_class = sc_Nil;
25312159047fSniklas       coff_symbol_typ = st_Nil;
25322159047fSniklas       coff_is_function = 0;
25332159047fSniklas       coff_tag = (char *) NULL;
25342159047fSniklas       coff_value = 0;
25352159047fSniklas       coff_sym_value = (symbolS *) NULL;
2536191aa565Sniklas       coff_sym_addend = 0;
25372159047fSniklas     }
25382159047fSniklas 
25392159047fSniklas   *input_line_pointer = name_end;
25402159047fSniklas 
25412159047fSniklas   demand_empty_rest_of_line ();
25422159047fSniklas }
25432159047fSniklas 
25442159047fSniklas /* Handle a .dim directive, used to give dimensions for an array.  The
25452159047fSniklas    arguments are comma separated numbers.  mips-tfile assumes that
25462159047fSniklas    there will not be more than 6 dimensions, and gdb won't read any
25472159047fSniklas    more than that anyhow, so I will also make that assumption.  */
25482159047fSniklas 
25492159047fSniklas void
ecoff_directive_dim(int ignore ATTRIBUTE_UNUSED)2550*007c2a45Smiod ecoff_directive_dim (int ignore ATTRIBUTE_UNUSED)
25512159047fSniklas {
25522159047fSniklas   int dimens[N_TQ];
25532159047fSniklas   int i;
25542159047fSniklas 
25552159047fSniklas   if (coff_sym_name == (char *) NULL)
25562159047fSniklas     {
2557b305b0f1Sespie       as_warn (_(".dim pseudo-op used outside of .def/.endef; ignored"));
25582159047fSniklas       demand_empty_rest_of_line ();
25592159047fSniklas       return;
25602159047fSniklas     }
25612159047fSniklas 
25622159047fSniklas   for (i = 0; i < N_TQ; i++)
25632159047fSniklas     {
25642159047fSniklas       SKIP_WHITESPACE ();
25652159047fSniklas       dimens[i] = get_absolute_expression ();
25662159047fSniklas       if (*input_line_pointer == ',')
25672159047fSniklas 	++input_line_pointer;
25682159047fSniklas       else
25692159047fSniklas 	{
25702159047fSniklas 	  if (*input_line_pointer != '\n'
25712159047fSniklas 	      && *input_line_pointer != ';')
2572c074d1c9Sdrahn 	    as_warn (_("badly formed .dim directive"));
25732159047fSniklas 	  break;
25742159047fSniklas 	}
25752159047fSniklas     }
25762159047fSniklas 
25772159047fSniklas   if (i == N_TQ)
25782159047fSniklas     --i;
25792159047fSniklas 
25802159047fSniklas   /* The dimensions are stored away in reverse order.  */
25812159047fSniklas   for (; i >= 0; i--)
25822159047fSniklas     {
25832159047fSniklas       if (coff_type.num_dims >= N_TQ)
25842159047fSniklas 	{
2585c074d1c9Sdrahn 	  as_warn (_("too many .dim entries"));
25862159047fSniklas 	  break;
25872159047fSniklas 	}
25882159047fSniklas       coff_type.dimensions[coff_type.num_dims] = dimens[i];
25892159047fSniklas       ++coff_type.num_dims;
25902159047fSniklas     }
25912159047fSniklas 
25922159047fSniklas   demand_empty_rest_of_line ();
25932159047fSniklas }
25942159047fSniklas 
25952159047fSniklas /* Handle a .scl directive, which sets the COFF storage class of the
25962159047fSniklas    symbol.  */
25972159047fSniklas 
25982159047fSniklas void
ecoff_directive_scl(int ignore ATTRIBUTE_UNUSED)2599*007c2a45Smiod ecoff_directive_scl (int ignore ATTRIBUTE_UNUSED)
26002159047fSniklas {
26012159047fSniklas   long val;
26022159047fSniklas 
26032159047fSniklas   if (coff_sym_name == (char *) NULL)
26042159047fSniklas     {
2605b305b0f1Sespie       as_warn (_(".scl pseudo-op used outside of .def/.endef; ignored"));
26062159047fSniklas       demand_empty_rest_of_line ();
26072159047fSniklas       return;
26082159047fSniklas     }
26092159047fSniklas 
26102159047fSniklas   val = get_absolute_expression ();
26112159047fSniklas 
26122159047fSniklas   coff_symbol_typ = map_coff_sym_type[val];
26132159047fSniklas   coff_storage_class = map_coff_storage[val];
26142159047fSniklas 
26152159047fSniklas   demand_empty_rest_of_line ();
26162159047fSniklas }
26172159047fSniklas 
26182159047fSniklas /* Handle a .size directive.  For some reason mips-tfile.c thinks that
26192159047fSniklas    .size can have multiple arguments.  We humor it, although gcc will
26202159047fSniklas    never generate more than one argument.  */
26212159047fSniklas 
26222159047fSniklas void
ecoff_directive_size(int ignore ATTRIBUTE_UNUSED)2623*007c2a45Smiod ecoff_directive_size (int ignore ATTRIBUTE_UNUSED)
26242159047fSniklas {
26252159047fSniklas   int sizes[N_TQ];
26262159047fSniklas   int i;
26272159047fSniklas 
26282159047fSniklas   if (coff_sym_name == (char *) NULL)
26292159047fSniklas     {
2630b305b0f1Sespie       as_warn (_(".size pseudo-op used outside of .def/.endef; ignored"));
26312159047fSniklas       demand_empty_rest_of_line ();
26322159047fSniklas       return;
26332159047fSniklas     }
26342159047fSniklas 
26352159047fSniklas   for (i = 0; i < N_TQ; i++)
26362159047fSniklas     {
26372159047fSniklas       SKIP_WHITESPACE ();
26382159047fSniklas       sizes[i] = get_absolute_expression ();
26392159047fSniklas       if (*input_line_pointer == ',')
26402159047fSniklas 	++input_line_pointer;
26412159047fSniklas       else
26422159047fSniklas 	{
26432159047fSniklas 	  if (*input_line_pointer != '\n'
26442159047fSniklas 	      && *input_line_pointer != ';')
2645c074d1c9Sdrahn 	    as_warn (_("badly formed .size directive"));
26462159047fSniklas 	  break;
26472159047fSniklas 	}
26482159047fSniklas     }
26492159047fSniklas 
26502159047fSniklas   if (i == N_TQ)
26512159047fSniklas     --i;
26522159047fSniklas 
26532159047fSniklas   /* The sizes are stored away in reverse order.  */
26542159047fSniklas   for (; i >= 0; i--)
26552159047fSniklas     {
26562159047fSniklas       if (coff_type.num_sizes >= N_TQ)
26572159047fSniklas 	{
2658c074d1c9Sdrahn 	  as_warn (_("too many .size entries"));
26592159047fSniklas 	  break;
26602159047fSniklas 	}
26612159047fSniklas       coff_type.sizes[coff_type.num_sizes] = sizes[i];
26622159047fSniklas       ++coff_type.num_sizes;
26632159047fSniklas     }
26642159047fSniklas 
26652159047fSniklas   demand_empty_rest_of_line ();
26662159047fSniklas }
26672159047fSniklas 
26682159047fSniklas /* Handle the .type directive, which gives the COFF type of the
26692159047fSniklas    symbol.  */
26702159047fSniklas 
26712159047fSniklas void
ecoff_directive_type(int ignore ATTRIBUTE_UNUSED)2672*007c2a45Smiod ecoff_directive_type (int ignore ATTRIBUTE_UNUSED)
26732159047fSniklas {
26742159047fSniklas   long val;
26752159047fSniklas   tq_t *tq_ptr;
26762159047fSniklas   tq_t *tq_shft;
26772159047fSniklas 
26782159047fSniklas   if (coff_sym_name == (char *) NULL)
26792159047fSniklas     {
2680b305b0f1Sespie       as_warn (_(".type pseudo-op used outside of .def/.endef; ignored"));
26812159047fSniklas       demand_empty_rest_of_line ();
26822159047fSniklas       return;
26832159047fSniklas     }
26842159047fSniklas 
26852159047fSniklas   val = get_absolute_expression ();
26862159047fSniklas 
26872159047fSniklas   coff_type.orig_type = BTYPE (val);
26882159047fSniklas   coff_type.basic_type = map_coff_types[coff_type.orig_type];
26892159047fSniklas 
26902159047fSniklas   tq_ptr = &coff_type.type_qualifiers[N_TQ];
26912159047fSniklas   while (val & ~N_BTMASK)
26922159047fSniklas     {
26932159047fSniklas       if (tq_ptr == &coff_type.type_qualifiers[0])
26942159047fSniklas 	{
26952159047fSniklas 	  /* FIXME: We could handle this by setting the continued bit.
26962159047fSniklas 	     There would still be a limit: the .type argument can not
26972159047fSniklas 	     be infinite.  */
2698c074d1c9Sdrahn 	  as_warn (_("the type of %s is too complex; it will be simplified"),
26992159047fSniklas 		   coff_sym_name);
27002159047fSniklas 	  break;
27012159047fSniklas 	}
27022159047fSniklas       if (ISPTR (val))
27032159047fSniklas 	*--tq_ptr = tq_Ptr;
27042159047fSniklas       else if (ISFCN (val))
27052159047fSniklas 	*--tq_ptr = tq_Proc;
27062159047fSniklas       else if (ISARY (val))
27072159047fSniklas 	*--tq_ptr = tq_Array;
27082159047fSniklas       else
2709b305b0f1Sespie 	as_fatal (_("Unrecognized .type argument"));
27102159047fSniklas 
27112159047fSniklas       val = DECREF (val);
27122159047fSniklas     }
27132159047fSniklas 
27142159047fSniklas   tq_shft = &coff_type.type_qualifiers[0];
27152159047fSniklas   while (tq_ptr != &coff_type.type_qualifiers[N_TQ])
27162159047fSniklas     *tq_shft++ = *tq_ptr++;
27172159047fSniklas 
27182159047fSniklas   if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc)
27192159047fSniklas     {
27202159047fSniklas       /* If this is a function, ignore it, so that we don't get two
27212159047fSniklas          entries (one from the .ent, and one for the .def that
27222159047fSniklas          precedes it).  Save the type information so that the end
27232159047fSniklas          block can properly add it after the begin block index.  For
27242159047fSniklas          MIPS knows what reason, we must strip off the function type
27252159047fSniklas          at this point.  */
27262159047fSniklas       coff_is_function = 1;
27272159047fSniklas       tq_shft[-1] = tq_Nil;
27282159047fSniklas     }
27292159047fSniklas 
27302159047fSniklas   while (tq_shft != &coff_type.type_qualifiers[N_TQ])
27312159047fSniklas     *tq_shft++ = tq_Nil;
27322159047fSniklas 
27332159047fSniklas   demand_empty_rest_of_line ();
27342159047fSniklas }
27352159047fSniklas 
27362159047fSniklas /* Handle the .tag directive, which gives the name of a structure,
27372159047fSniklas    union or enum.  */
27382159047fSniklas 
27392159047fSniklas void
ecoff_directive_tag(int ignore ATTRIBUTE_UNUSED)2740*007c2a45Smiod ecoff_directive_tag (int ignore ATTRIBUTE_UNUSED)
27412159047fSniklas {
27422159047fSniklas   char *name;
27432159047fSniklas   char name_end;
27442159047fSniklas 
27452159047fSniklas   if (coff_sym_name == (char *) NULL)
27462159047fSniklas     {
2747b305b0f1Sespie       as_warn (_(".tag pseudo-op used outside of .def/.endef; ignored"));
27482159047fSniklas       demand_empty_rest_of_line ();
27492159047fSniklas       return;
27502159047fSniklas     }
27512159047fSniklas 
27522159047fSniklas   name = input_line_pointer;
27532159047fSniklas   name_end = get_symbol_end ();
27542159047fSniklas 
2755c074d1c9Sdrahn   coff_tag = xstrdup (name);
27562159047fSniklas 
27572159047fSniklas   *input_line_pointer = name_end;
27582159047fSniklas 
27592159047fSniklas   demand_empty_rest_of_line ();
27602159047fSniklas }
27612159047fSniklas 
27622159047fSniklas /* Handle the .val directive, which gives the value of the symbol.  It
27632159047fSniklas    may be the name of a static or global symbol.  */
27642159047fSniklas 
27652159047fSniklas void
ecoff_directive_val(int ignore ATTRIBUTE_UNUSED)2766*007c2a45Smiod ecoff_directive_val (int ignore ATTRIBUTE_UNUSED)
27672159047fSniklas {
2768191aa565Sniklas   expressionS exp;
2769191aa565Sniklas 
27702159047fSniklas   if (coff_sym_name == (char *) NULL)
27712159047fSniklas     {
2772b305b0f1Sespie       as_warn (_(".val pseudo-op used outside of .def/.endef; ignored"));
27732159047fSniklas       demand_empty_rest_of_line ();
27742159047fSniklas       return;
27752159047fSniklas     }
27762159047fSniklas 
2777191aa565Sniklas   expression (&exp);
2778191aa565Sniklas   if (exp.X_op != O_constant && exp.X_op != O_symbol)
2779191aa565Sniklas     {
2780b305b0f1Sespie       as_bad (_(".val expression is too copmlex"));
2781191aa565Sniklas       demand_empty_rest_of_line ();
2782191aa565Sniklas       return;
2783191aa565Sniklas     }
2784191aa565Sniklas 
2785191aa565Sniklas   if (exp.X_op == O_constant)
2786191aa565Sniklas     coff_value = exp.X_add_number;
27872159047fSniklas   else
27882159047fSniklas     {
2789191aa565Sniklas       coff_sym_value = exp.X_add_symbol;
2790191aa565Sniklas       coff_sym_addend = exp.X_add_number;
27912159047fSniklas     }
27922159047fSniklas 
27932159047fSniklas   demand_empty_rest_of_line ();
27942159047fSniklas }
27952159047fSniklas 
27962159047fSniklas /* Handle the .endef directive, which terminates processing of COFF
27972159047fSniklas    debugging information for a symbol.  */
27982159047fSniklas 
27992159047fSniklas void
ecoff_directive_endef(int ignore ATTRIBUTE_UNUSED)2800*007c2a45Smiod ecoff_directive_endef (int ignore ATTRIBUTE_UNUSED)
28012159047fSniklas {
28022159047fSniklas   char *name;
28032159047fSniklas   symint_t indx;
28042159047fSniklas   localsym_t *sym;
28052159047fSniklas 
28062159047fSniklas   demand_empty_rest_of_line ();
28072159047fSniklas 
28082159047fSniklas   if (coff_sym_name == (char *) NULL)
28092159047fSniklas     {
2810b305b0f1Sespie       as_warn (_(".endef pseudo-op used before .def; ignored"));
28112159047fSniklas       return;
28122159047fSniklas     }
28132159047fSniklas 
28142159047fSniklas   name = coff_sym_name;
28152159047fSniklas   coff_sym_name = (char *) NULL;
28162159047fSniklas 
28172159047fSniklas   /* If the symbol is a static or external, we have already gotten the
28182159047fSniklas      appropriate type and class, so make sure we don't override those
28192159047fSniklas      values.  This is needed because there are some type and classes
28202159047fSniklas      that are not in COFF, such as short data, etc.  */
28212159047fSniklas   if (coff_sym_value != (symbolS *) NULL)
28222159047fSniklas     {
28232159047fSniklas       coff_symbol_typ = st_Nil;
28242159047fSniklas       coff_storage_class = sc_Nil;
28252159047fSniklas     }
28262159047fSniklas 
28272159047fSniklas   coff_type.extra_sizes = coff_tag != (char *) NULL;
28282159047fSniklas   if (coff_type.num_dims > 0)
28292159047fSniklas     {
28302159047fSniklas       int diff = coff_type.num_dims - coff_type.num_sizes;
28312159047fSniklas       int i = coff_type.num_dims - 1;
28322159047fSniklas       int j;
28332159047fSniklas 
28342159047fSniklas       if (coff_type.num_sizes != 1 || diff < 0)
28352159047fSniklas 	{
2836c074d1c9Sdrahn 	  as_warn (_("bad COFF debugging information"));
28372159047fSniklas 	  return;
28382159047fSniklas 	}
28392159047fSniklas 
28402159047fSniklas       /* If this is an array, make sure the same number of dimensions
28412159047fSniklas          and sizes were passed, creating extra sizes for multiply
28422159047fSniklas          dimensioned arrays if not passed.  */
28432159047fSniklas       coff_type.extra_sizes = 0;
28442159047fSniklas       if (diff)
28452159047fSniklas 	{
28462159047fSniklas 	  j = (sizeof (coff_type.sizes) / sizeof (coff_type.sizes[0])) - 1;
28472159047fSniklas 	  while (j >= 0)
28482159047fSniklas 	    {
28492159047fSniklas 	      coff_type.sizes[j] = (((j - diff) >= 0)
28502159047fSniklas 				    ? coff_type.sizes[j - diff]
28512159047fSniklas 				    : 0);
28522159047fSniklas 	      j--;
28532159047fSniklas 	    }
28542159047fSniklas 
28552159047fSniklas 	  coff_type.num_sizes = i + 1;
28562159047fSniklas 	  for (i--; i >= 0; i--)
28570c6d0228Sniklas 	    coff_type.sizes[i] = (coff_type.dimensions[i + 1] == 0
28580c6d0228Sniklas 				  ? 0
28590c6d0228Sniklas 				  : (coff_type.sizes[i + 1]
28600c6d0228Sniklas 				     / coff_type.dimensions[i + 1]));
28612159047fSniklas 	}
28622159047fSniklas     }
28632159047fSniklas   else if (coff_symbol_typ == st_Member
28642159047fSniklas 	   && coff_type.num_sizes - coff_type.extra_sizes == 1)
28652159047fSniklas     {
2866*007c2a45Smiod       /* Is this a bitfield?  This is indicated by a structure member
28672159047fSniklas          having a size field that isn't an array.  */
28682159047fSniklas       coff_type.bitfield = 1;
28692159047fSniklas     }
28702159047fSniklas 
28712159047fSniklas   /* Except for enumeration members & begin/ending of scopes, put the
28722159047fSniklas      type word in the aux. symbol table.  */
28732159047fSniklas   if (coff_symbol_typ == st_Block || coff_symbol_typ == st_End)
28742159047fSniklas     indx = 0;
28752159047fSniklas   else if (coff_inside_enumeration)
28762159047fSniklas     indx = cur_file_ptr->void_type;
28772159047fSniklas   else
28782159047fSniklas     {
28792159047fSniklas       if (coff_type.basic_type == bt_Struct
28802159047fSniklas 	  || coff_type.basic_type == bt_Union
28812159047fSniklas 	  || coff_type.basic_type == bt_Enum)
28822159047fSniklas 	{
28832159047fSniklas 	  if (coff_tag == (char *) NULL)
28842159047fSniklas 	    {
2885c074d1c9Sdrahn 	      as_warn (_("no tag specified for %s"), name);
28862159047fSniklas 	      return;
28872159047fSniklas 	    }
28882159047fSniklas 
28892159047fSniklas 	  coff_type.tag_ptr = get_tag (coff_tag, (localsym_t *) NULL,
28902159047fSniklas 				       coff_type.basic_type);
28912159047fSniklas 	}
28922159047fSniklas 
28932159047fSniklas       if (coff_is_function)
28942159047fSniklas 	{
28952159047fSniklas 	  last_func_type_info = coff_type;
28962159047fSniklas 	  last_func_sym_value = coff_sym_value;
28972159047fSniklas 	  return;
28982159047fSniklas 	}
28992159047fSniklas 
29002159047fSniklas       indx = add_aux_sym_tir (&coff_type,
29012159047fSniklas 			      hash_yes,
29022159047fSniklas 			      &cur_file_ptr->thash_head[0]);
29032159047fSniklas     }
29042159047fSniklas 
29052159047fSniklas   /* Do any last minute adjustments that are necessary.  */
29062159047fSniklas   switch (coff_symbol_typ)
29072159047fSniklas     {
29082159047fSniklas     default:
29092159047fSniklas       break;
29102159047fSniklas 
29112159047fSniklas       /* For the beginning of structs, unions, and enumerations, the
29122159047fSniklas          size info needs to be passed in the value field.  */
29132159047fSniklas     case st_Block:
29142159047fSniklas       if (coff_type.num_sizes - coff_type.num_dims - coff_type.extra_sizes
29152159047fSniklas 	  != 1)
29162159047fSniklas 	{
2917c074d1c9Sdrahn 	  as_warn (_("bad COFF debugging information"));
29182159047fSniklas 	  return;
29192159047fSniklas 	}
29202159047fSniklas       else
29212159047fSniklas 	coff_value = coff_type.sizes[0];
29222159047fSniklas 
29232159047fSniklas       coff_inside_enumeration = (coff_type.orig_type == T_ENUM);
29242159047fSniklas       break;
29252159047fSniklas 
29262159047fSniklas       /* For the end of structs, unions, and enumerations, omit the
29272159047fSniklas          name which is always ".eos".  This needs to be done last, so
29282159047fSniklas          that any error reporting above gives the correct name.  */
29292159047fSniklas     case st_End:
29302159047fSniklas       free (name);
29312159047fSniklas       name = (char *) NULL;
29322159047fSniklas       coff_value = 0;
29332159047fSniklas       coff_inside_enumeration = 0;
29342159047fSniklas       break;
29352159047fSniklas 
29362159047fSniklas       /* Members of structures and unions that aren't bitfields, need
29372159047fSniklas          to adjust the value from a byte offset to a bit offset.
29382159047fSniklas          Members of enumerations do not have the value adjusted, and
29392159047fSniklas          can be distinguished by indx == indexNil.  For enumerations,
29402159047fSniklas          update the maximum enumeration value.  */
29412159047fSniklas     case st_Member:
29422159047fSniklas       if (! coff_type.bitfield && ! coff_inside_enumeration)
29432159047fSniklas 	coff_value *= 8;
29442159047fSniklas 
29452159047fSniklas       break;
29462159047fSniklas     }
29472159047fSniklas 
29482159047fSniklas   /* Add the symbol.  */
29492159047fSniklas   sym = add_ecoff_symbol (name,
29502159047fSniklas 			  coff_symbol_typ,
29512159047fSniklas 			  coff_storage_class,
29522159047fSniklas 			  coff_sym_value,
2953191aa565Sniklas 			  coff_sym_addend,
29542159047fSniklas 			  (symint_t) coff_value,
29552159047fSniklas 			  indx);
29562159047fSniklas 
29572159047fSniklas   /* deal with struct, union, and enum tags.  */
29582159047fSniklas   if (coff_symbol_typ == st_Block)
29592159047fSniklas     {
29602159047fSniklas       /* Create or update the tag information.  */
29612159047fSniklas       tag_t *tag_ptr = get_tag (name,
29622159047fSniklas 				sym,
29632159047fSniklas 				coff_type.basic_type);
29642159047fSniklas       forward_t **pf;
29652159047fSniklas 
29662159047fSniklas       /* Remember any forward references.  */
29672159047fSniklas       for (pf = &sym->forward_ref;
29682159047fSniklas 	   *pf != (forward_t *) NULL;
29692159047fSniklas 	   pf = &(*pf)->next)
29702159047fSniklas 	;
29712159047fSniklas       *pf = tag_ptr->forward_ref;
29722159047fSniklas       tag_ptr->forward_ref = (forward_t *) NULL;
29732159047fSniklas     }
29742159047fSniklas }
29752159047fSniklas 
29762159047fSniklas /* Parse .end directives.  */
29772159047fSniklas 
29782159047fSniklas void
ecoff_directive_end(int ignore ATTRIBUTE_UNUSED)2979*007c2a45Smiod ecoff_directive_end (int ignore ATTRIBUTE_UNUSED)
29802159047fSniklas {
29812159047fSniklas   char *name;
29822159047fSniklas   char name_end;
29832159047fSniklas   symbolS *ent;
29842159047fSniklas 
29852159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
29862159047fSniklas     {
2987b305b0f1Sespie       as_warn (_(".end directive without a preceding .file directive"));
29882159047fSniklas       demand_empty_rest_of_line ();
29892159047fSniklas       return;
29902159047fSniklas     }
29912159047fSniklas 
29922159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
29932159047fSniklas     {
2994b305b0f1Sespie       as_warn (_(".end directive without a preceding .ent directive"));
29952159047fSniklas       demand_empty_rest_of_line ();
29962159047fSniklas       return;
29972159047fSniklas     }
29982159047fSniklas 
29992159047fSniklas   name = input_line_pointer;
30002159047fSniklas   name_end = get_symbol_end ();
30012159047fSniklas 
3002c074d1c9Sdrahn   if (name == input_line_pointer)
30032159047fSniklas     {
3004b305b0f1Sespie       as_warn (_(".end directive has no name"));
30052159047fSniklas       *input_line_pointer = name_end;
30062159047fSniklas       demand_empty_rest_of_line ();
30072159047fSniklas       return;
30082159047fSniklas     }
30092159047fSniklas 
30102159047fSniklas   /* The value is the distance between the .end directive and the
30112159047fSniklas      corresponding symbol.  We create a fake symbol to hold the
30122159047fSniklas      current location, and put in the offset when we write out the
30132159047fSniklas      symbol.  */
30142159047fSniklas   ent = symbol_find (name);
30152159047fSniklas   if (ent == (symbolS *) NULL)
3016b305b0f1Sespie     as_warn (_(".end directive names unknown symbol"));
30172159047fSniklas   else
30182159047fSniklas     (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
30192159047fSniklas 			     symbol_new ("L0\001", now_seg,
30202159047fSniklas 					 (valueT) frag_now_fix (),
30212159047fSniklas 					 frag_now),
3022191aa565Sniklas 			     (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
30232159047fSniklas 
30242159047fSniklas   cur_proc_ptr = (proc_t *) NULL;
30252159047fSniklas 
30262159047fSniklas   *input_line_pointer = name_end;
30272159047fSniklas   demand_empty_rest_of_line ();
30282159047fSniklas }
30292159047fSniklas 
30302159047fSniklas /* Parse .ent directives.  */
30312159047fSniklas 
30322159047fSniklas void
ecoff_directive_ent(int ignore ATTRIBUTE_UNUSED)3033*007c2a45Smiod ecoff_directive_ent (int ignore ATTRIBUTE_UNUSED)
30342159047fSniklas {
30352159047fSniklas   char *name;
30362159047fSniklas   char name_end;
30372159047fSniklas 
30382159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
30392159047fSniklas     add_file ((const char *) NULL, 0, 1);
30402159047fSniklas 
30412159047fSniklas   if (cur_proc_ptr != (proc_t *) NULL)
30422159047fSniklas     {
3043b305b0f1Sespie       as_warn (_("second .ent directive found before .end directive"));
30442159047fSniklas       demand_empty_rest_of_line ();
30452159047fSniklas       return;
30462159047fSniklas     }
30472159047fSniklas 
30482159047fSniklas   name = input_line_pointer;
30492159047fSniklas   name_end = get_symbol_end ();
30502159047fSniklas 
3051c074d1c9Sdrahn   if (name == input_line_pointer)
30522159047fSniklas     {
3053b305b0f1Sespie       as_warn (_(".ent directive has no name"));
30542159047fSniklas       *input_line_pointer = name_end;
30552159047fSniklas       demand_empty_rest_of_line ();
30562159047fSniklas       return;
30572159047fSniklas     }
30582159047fSniklas 
30592159047fSniklas   add_procedure (name);
30602159047fSniklas 
30612159047fSniklas   *input_line_pointer = name_end;
30622159047fSniklas 
30632159047fSniklas   /* The .ent directive is sometimes followed by a number.  I'm not
30642159047fSniklas      really sure what the number means.  I don't see any way to store
30652159047fSniklas      the information in the PDR.  The Irix 4 assembler seems to ignore
30662159047fSniklas      the information.  */
30672159047fSniklas   SKIP_WHITESPACE ();
30682159047fSniklas   if (*input_line_pointer == ',')
30692159047fSniklas     {
30702159047fSniklas       ++input_line_pointer;
30712159047fSniklas       SKIP_WHITESPACE ();
30722159047fSniklas     }
3073c074d1c9Sdrahn   if (ISDIGIT (*input_line_pointer)
3074b305b0f1Sespie       || *input_line_pointer == '-')
30752159047fSniklas     (void) get_absolute_expression ();
30762159047fSniklas 
30772159047fSniklas   demand_empty_rest_of_line ();
30782159047fSniklas }
30792159047fSniklas 
30802159047fSniklas /* Parse .extern directives.  */
30812159047fSniklas 
30822159047fSniklas void
ecoff_directive_extern(int ignore ATTRIBUTE_UNUSED)3083*007c2a45Smiod ecoff_directive_extern (int ignore ATTRIBUTE_UNUSED)
30842159047fSniklas {
30852159047fSniklas   char *name;
30862159047fSniklas   int c;
30872159047fSniklas   symbolS *symbolp;
30882159047fSniklas   valueT size;
30892159047fSniklas 
30902159047fSniklas   name = input_line_pointer;
30912159047fSniklas   c = get_symbol_end ();
30922159047fSniklas   symbolp = symbol_find_or_make (name);
30932159047fSniklas   *input_line_pointer = c;
30942159047fSniklas 
30952159047fSniklas   S_SET_EXTERNAL (symbolp);
30962159047fSniklas 
30972159047fSniklas   if (*input_line_pointer == ',')
30982159047fSniklas     ++input_line_pointer;
30992159047fSniklas   size = get_absolute_expression ();
31002159047fSniklas 
3101b305b0f1Sespie   symbol_get_obj (symbolp)->ecoff_extern_size = size;
31022159047fSniklas }
31032159047fSniklas 
31042159047fSniklas /* Parse .file directives.  */
31052159047fSniklas 
31062159047fSniklas void
ecoff_directive_file(int ignore ATTRIBUTE_UNUSED)3107*007c2a45Smiod ecoff_directive_file (int ignore ATTRIBUTE_UNUSED)
31082159047fSniklas {
31092159047fSniklas   int indx;
31102159047fSniklas   char *name;
31112159047fSniklas   int len;
31122159047fSniklas 
31132159047fSniklas   if (cur_proc_ptr != (proc_t *) NULL)
31142159047fSniklas     {
3115c074d1c9Sdrahn       as_warn (_("no way to handle .file within .ent/.end section"));
31162159047fSniklas       demand_empty_rest_of_line ();
31172159047fSniklas       return;
31182159047fSniklas     }
31192159047fSniklas 
31202159047fSniklas   indx = (int) get_absolute_expression ();
31212159047fSniklas 
31222159047fSniklas   /* FIXME: we don't have to save the name here.  */
31232159047fSniklas   name = demand_copy_C_string (&len);
31242159047fSniklas 
31252159047fSniklas   add_file (name, indx - 1, 0);
31262159047fSniklas 
31272159047fSniklas   demand_empty_rest_of_line ();
31282159047fSniklas }
31292159047fSniklas 
31302159047fSniklas /* Parse .fmask directives.  */
31312159047fSniklas 
31322159047fSniklas void
ecoff_directive_fmask(int ignore ATTRIBUTE_UNUSED)3133*007c2a45Smiod ecoff_directive_fmask (int ignore ATTRIBUTE_UNUSED)
31342159047fSniklas {
31352159047fSniklas   long val;
31362159047fSniklas 
31372159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
31382159047fSniklas     {
3139b305b0f1Sespie       as_warn (_(".fmask outside of .ent"));
31402159047fSniklas       demand_empty_rest_of_line ();
31412159047fSniklas       return;
31422159047fSniklas     }
31432159047fSniklas 
31442159047fSniklas   if (get_absolute_expression_and_terminator (&val) != ',')
31452159047fSniklas     {
3146c074d1c9Sdrahn       as_warn (_("bad .fmask directive"));
31472159047fSniklas       --input_line_pointer;
31482159047fSniklas       demand_empty_rest_of_line ();
31492159047fSniklas       return;
31502159047fSniklas     }
31512159047fSniklas 
31522159047fSniklas   cur_proc_ptr->pdr.fregmask = val;
31532159047fSniklas   cur_proc_ptr->pdr.fregoffset = get_absolute_expression ();
31542159047fSniklas 
31552159047fSniklas   demand_empty_rest_of_line ();
31562159047fSniklas }
31572159047fSniklas 
31582159047fSniklas /* Parse .frame directives.  */
31592159047fSniklas 
31602159047fSniklas void
ecoff_directive_frame(int ignore ATTRIBUTE_UNUSED)3161*007c2a45Smiod ecoff_directive_frame (int ignore ATTRIBUTE_UNUSED)
31622159047fSniklas {
31632159047fSniklas   long val;
31642159047fSniklas 
31652159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
31662159047fSniklas     {
3167b305b0f1Sespie       as_warn (_(".frame outside of .ent"));
31682159047fSniklas       demand_empty_rest_of_line ();
31692159047fSniklas       return;
31702159047fSniklas     }
31712159047fSniklas 
31722159047fSniklas   cur_proc_ptr->pdr.framereg = tc_get_register (1);
31732159047fSniklas 
31742159047fSniklas   SKIP_WHITESPACE ();
31752159047fSniklas   if (*input_line_pointer++ != ','
31762159047fSniklas       || get_absolute_expression_and_terminator (&val) != ',')
31772159047fSniklas     {
3178c074d1c9Sdrahn       as_warn (_("bad .frame directive"));
31792159047fSniklas       --input_line_pointer;
31802159047fSniklas       demand_empty_rest_of_line ();
31812159047fSniklas       return;
31822159047fSniklas     }
31832159047fSniklas 
31842159047fSniklas   cur_proc_ptr->pdr.frameoffset = val;
31852159047fSniklas 
31862159047fSniklas   cur_proc_ptr->pdr.pcreg = tc_get_register (0);
31872159047fSniklas 
3188b55d4692Sfgsch #if 0
3189b55d4692Sfgsch   /* Alpha-OSF1 adds "the offset of saved $a0 from $sp", according to
3190b55d4692Sfgsch      Sandro.  I don't yet know where this value should be stored, if
31912159047fSniklas      anywhere.  */
31922159047fSniklas   demand_empty_rest_of_line ();
31932159047fSniklas #else
31942159047fSniklas   s_ignore (42);
31952159047fSniklas #endif
31962159047fSniklas }
31972159047fSniklas 
31982159047fSniklas /* Parse .mask directives.  */
31992159047fSniklas 
32002159047fSniklas void
ecoff_directive_mask(int ignore ATTRIBUTE_UNUSED)3201*007c2a45Smiod ecoff_directive_mask (int ignore ATTRIBUTE_UNUSED)
32022159047fSniklas {
32032159047fSniklas   long val;
32042159047fSniklas 
32052159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
32062159047fSniklas     {
3207b305b0f1Sespie       as_warn (_(".mask outside of .ent"));
32082159047fSniklas       demand_empty_rest_of_line ();
32092159047fSniklas       return;
32102159047fSniklas     }
32112159047fSniklas 
32122159047fSniklas   if (get_absolute_expression_and_terminator (&val) != ',')
32132159047fSniklas     {
3214c074d1c9Sdrahn       as_warn (_("bad .mask directive"));
32152159047fSniklas       --input_line_pointer;
32162159047fSniklas       demand_empty_rest_of_line ();
32172159047fSniklas       return;
32182159047fSniklas     }
32192159047fSniklas 
32202159047fSniklas   cur_proc_ptr->pdr.regmask = val;
32212159047fSniklas   cur_proc_ptr->pdr.regoffset = get_absolute_expression ();
32222159047fSniklas 
32232159047fSniklas   demand_empty_rest_of_line ();
32242159047fSniklas }
32252159047fSniklas 
32262159047fSniklas /* Parse .loc directives.  */
32272159047fSniklas 
32282159047fSniklas void
ecoff_directive_loc(int ignore ATTRIBUTE_UNUSED)3229*007c2a45Smiod ecoff_directive_loc (int ignore ATTRIBUTE_UNUSED)
32302159047fSniklas {
32312159047fSniklas   lineno_list_t *list;
32322159047fSniklas   symint_t lineno;
32332159047fSniklas 
32342159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
32352159047fSniklas     {
3236b305b0f1Sespie       as_warn (_(".loc before .file"));
32372159047fSniklas       demand_empty_rest_of_line ();
32382159047fSniklas       return;
32392159047fSniklas     }
32402159047fSniklas 
32412159047fSniklas   if (now_seg != text_section)
32422159047fSniklas     {
3243b305b0f1Sespie       as_warn (_(".loc outside of .text"));
32442159047fSniklas       demand_empty_rest_of_line ();
32452159047fSniklas       return;
32462159047fSniklas     }
32472159047fSniklas 
32482159047fSniklas   /* Skip the file number.  */
32492159047fSniklas   SKIP_WHITESPACE ();
32502159047fSniklas   get_absolute_expression ();
32512159047fSniklas   SKIP_WHITESPACE ();
32522159047fSniklas 
32532159047fSniklas   lineno = get_absolute_expression ();
32542159047fSniklas 
32552159047fSniklas #ifndef NO_LISTING
32562159047fSniklas   if (listing)
32572159047fSniklas     listing_source_line (lineno);
32582159047fSniklas #endif
32592159047fSniklas 
32602159047fSniklas   /* If we're building stabs, then output a special label rather than
32612159047fSniklas      ECOFF line number info.  */
32622159047fSniklas   if (stabs_seen)
32632159047fSniklas     {
32642159047fSniklas       (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text,
32652159047fSniklas 			       symbol_new ("L0\001", now_seg,
32662159047fSniklas 					   (valueT) frag_now_fix (),
32672159047fSniklas 					   frag_now),
3268191aa565Sniklas 			       (bfd_vma) 0, 0, lineno);
32692159047fSniklas       return;
32702159047fSniklas     }
32712159047fSniklas 
32722159047fSniklas   list = allocate_lineno_list ();
32732159047fSniklas 
32742159047fSniklas   list->next = (lineno_list_t *) NULL;
32752159047fSniklas   list->file = cur_file_ptr;
32762159047fSniklas   list->proc = cur_proc_ptr;
32772159047fSniklas   list->frag = frag_now;
32782159047fSniklas   list->paddr = frag_now_fix ();
32792159047fSniklas   list->lineno = lineno;
32802159047fSniklas 
32810c6d0228Sniklas   /* We don't want to merge files which have line numbers.  */
32820c6d0228Sniklas   cur_file_ptr->fdr.fMerge = 0;
32830c6d0228Sniklas 
32842159047fSniklas   /* A .loc directive will sometimes appear before a .ent directive,
32852159047fSniklas      which means that cur_proc_ptr will be NULL here.  Arrange to
32862159047fSniklas      patch this up.  */
32872159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
32882159047fSniklas     {
32892159047fSniklas       lineno_list_t **pl;
32902159047fSniklas 
32912159047fSniklas       pl = &noproc_lineno;
32922159047fSniklas       while (*pl != (lineno_list_t *) NULL)
32932159047fSniklas 	pl = &(*pl)->next;
32942159047fSniklas       *pl = list;
32952159047fSniklas     }
32962159047fSniklas   else
32972159047fSniklas     {
32980c6d0228Sniklas       last_lineno = list;
32992159047fSniklas       *last_lineno_ptr = list;
33002159047fSniklas       last_lineno_ptr = &list->next;
33012159047fSniklas     }
33022159047fSniklas }
33030c6d0228Sniklas 
33040c6d0228Sniklas /* The MIPS assembler sometimes inserts nop instructions in the
33050c6d0228Sniklas    instruction stream.  When this happens, we must patch up the .loc
33060c6d0228Sniklas    information so that it points to the instruction after the nop.  */
33070c6d0228Sniklas 
33080c6d0228Sniklas void
ecoff_fix_loc(fragS * old_frag,unsigned long old_frag_offset)3309*007c2a45Smiod ecoff_fix_loc (fragS *old_frag, unsigned long old_frag_offset)
33100c6d0228Sniklas {
33110c6d0228Sniklas   if (last_lineno != NULL
33120c6d0228Sniklas       && last_lineno->frag == old_frag
33130c6d0228Sniklas       && last_lineno->paddr == old_frag_offset)
33140c6d0228Sniklas     {
33150c6d0228Sniklas       last_lineno->frag = frag_now;
33160c6d0228Sniklas       last_lineno->paddr = frag_now_fix ();
33170c6d0228Sniklas     }
33180c6d0228Sniklas }
33192159047fSniklas 
33202159047fSniklas /* Make sure the @stabs symbol is emitted.  */
33212159047fSniklas 
33222159047fSniklas static void
mark_stabs(int ignore ATTRIBUTE_UNUSED)3323*007c2a45Smiod mark_stabs (int ignore ATTRIBUTE_UNUSED)
33242159047fSniklas {
33252159047fSniklas   if (! stabs_seen)
33262159047fSniklas     {
33272159047fSniklas       /* Add a dummy @stabs dymbol.  */
33282159047fSniklas       stabs_seen = 1;
33292159047fSniklas       (void) add_ecoff_symbol (stabs_symbol, stNil, scInfo,
33302159047fSniklas 			       (symbolS *) NULL,
3331191aa565Sniklas 			       (bfd_vma) 0, (symint_t) -1,
3332191aa565Sniklas 			       ECOFF_MARK_STAB (0));
33332159047fSniklas     }
33342159047fSniklas }
33352159047fSniklas 
33362159047fSniklas /* Parse .weakext directives.  */
3337b305b0f1Sespie #ifndef TC_MIPS
3338b305b0f1Sespie /* For TC_MIPS use the version in tc-mips.c.  */
33392159047fSniklas void
ecoff_directive_weakext(int ignore ATTRIBUTE_UNUSED)3340*007c2a45Smiod ecoff_directive_weakext (int ignore ATTRIBUTE_UNUSED)
33412159047fSniklas {
33422159047fSniklas   char *name;
33432159047fSniklas   int c;
33442159047fSniklas   symbolS *symbolP;
33452159047fSniklas   expressionS exp;
33462159047fSniklas 
33472159047fSniklas   name = input_line_pointer;
33482159047fSniklas   c = get_symbol_end ();
33492159047fSniklas   symbolP = symbol_find_or_make (name);
33502159047fSniklas   *input_line_pointer = c;
33512159047fSniklas 
33522159047fSniklas   SKIP_WHITESPACE ();
33532159047fSniklas 
3354191aa565Sniklas   if (*input_line_pointer == ',')
33552159047fSniklas     {
33562159047fSniklas       if (S_IS_DEFINED (symbolP))
33572159047fSniklas 	{
3358c074d1c9Sdrahn 	  as_bad (_("symbol `%s' is already defined"),
33592159047fSniklas 		  S_GET_NAME (symbolP));
33602159047fSniklas 	  ignore_rest_of_line ();
33612159047fSniklas 	  return;
33622159047fSniklas 	}
33632159047fSniklas 
33642159047fSniklas       ++input_line_pointer;
33652159047fSniklas       SKIP_WHITESPACE ();
33662159047fSniklas       if (! is_end_of_line[(unsigned char) *input_line_pointer])
33672159047fSniklas 	{
33682159047fSniklas 	  expression (&exp);
33692159047fSniklas 	  if (exp.X_op != O_symbol)
33702159047fSniklas 	    {
3371b305b0f1Sespie 	      as_bad (_("bad .weakext directive"));
33722159047fSniklas 	      ignore_rest_of_line ();
33732159047fSniklas 	      return;
33742159047fSniklas 	    }
3375b305b0f1Sespie 	  symbol_set_value_expression (symbolP, &exp);
33762159047fSniklas 	}
33772159047fSniklas     }
33782159047fSniklas 
33792159047fSniklas   S_SET_WEAK (symbolP);
33802159047fSniklas 
33812159047fSniklas   demand_empty_rest_of_line ();
33822159047fSniklas }
3383b305b0f1Sespie #endif /* not TC_MIPS */
33842159047fSniklas 
33852159047fSniklas /* Handle .stabs directives.  The actual parsing routine is done by a
33862159047fSniklas    generic routine.  This routine is called via OBJ_PROCESS_STAB.
33872159047fSniklas    When this is called, input_line_pointer will be pointing at the
33882159047fSniklas    value field of the stab.
33892159047fSniklas 
33902159047fSniklas    .stabs directives have five fields:
33912159047fSniklas 	"string"	a string, encoding the type information.
33922159047fSniklas 	code		a numeric code, defined in <stab.h>
33932159047fSniklas 	0		a zero
33942159047fSniklas 	desc		a zero or line number
33952159047fSniklas 	value		a numeric value or an address.
33962159047fSniklas 
33972159047fSniklas     If the value is relocatable, we transform this into:
33982159047fSniklas 	iss		points as an index into string space
33992159047fSniklas 	value		value from lookup of the name
34002159047fSniklas 	st		st from lookup of the name
34012159047fSniklas 	sc		sc from lookup of the name
34022159047fSniklas 	index		code|CODE_MASK
34032159047fSniklas 
34042159047fSniklas     If the value is not relocatable, we transform this into:
34052159047fSniklas 	iss		points as an index into string space
34062159047fSniklas 	value		value
34072159047fSniklas 	st		st_Nil
34082159047fSniklas 	sc		sc_Nil
34092159047fSniklas 	index		code|CODE_MASK
34102159047fSniklas 
34112159047fSniklas     .stabn directives have four fields (string is null):
34122159047fSniklas 	code		a numeric code, defined in <stab.h>
34132159047fSniklas 	0		a zero
34142159047fSniklas 	desc		a zero or a line number
34152159047fSniklas 	value		a numeric value or an address.  */
34162159047fSniklas 
34172159047fSniklas void
ecoff_stab(segT sec ATTRIBUTE_UNUSED,int what,const char * string,int type,int other,int desc)3418*007c2a45Smiod ecoff_stab (segT sec ATTRIBUTE_UNUSED,
3419*007c2a45Smiod 	    int what,
3420*007c2a45Smiod 	    const char *string,
3421*007c2a45Smiod 	    int type,
3422*007c2a45Smiod 	    int other,
3423*007c2a45Smiod 	    int desc)
34242159047fSniklas {
34252159047fSniklas   efdr_t *save_file_ptr = cur_file_ptr;
34262159047fSniklas   symbolS *sym;
34272159047fSniklas   symint_t value;
3428191aa565Sniklas   bfd_vma addend;
34292159047fSniklas   st_t st;
34302159047fSniklas   sc_t sc;
34312159047fSniklas   symint_t indx;
34322159047fSniklas   localsym_t *hold = NULL;
34332159047fSniklas 
34342159047fSniklas   ecoff_debugging_seen = 1;
34352159047fSniklas 
34362159047fSniklas   /* We don't handle .stabd.  */
34372159047fSniklas   if (what != 's' && what != 'n')
34382159047fSniklas     {
3439b305b0f1Sespie       as_bad (_(".stab%c is not supported"), what);
34402159047fSniklas       return;
34412159047fSniklas     }
34422159047fSniklas 
34432159047fSniklas   /* A .stabn uses a null name, not an empty string.  */
34442159047fSniklas   if (what == 'n')
34452159047fSniklas     string = NULL;
34462159047fSniklas 
34472159047fSniklas   /* We ignore the other field.  */
34482159047fSniklas   if (other != 0)
3449b305b0f1Sespie     as_warn (_(".stab%c: ignoring non-zero other field"), what);
34502159047fSniklas 
34512159047fSniklas   /* Make sure we have a current file.  */
34522159047fSniklas   if (cur_file_ptr == (efdr_t *) NULL)
34532159047fSniklas     {
34542159047fSniklas       add_file ((const char *) NULL, 0, 1);
34552159047fSniklas       save_file_ptr = cur_file_ptr;
34562159047fSniklas     }
34572159047fSniklas 
34582159047fSniklas   /* For stabs in ECOFF, the first symbol must be @stabs.  This is a
34592159047fSniklas      signal to gdb.  */
34602159047fSniklas   if (stabs_seen == 0)
34612159047fSniklas     mark_stabs (0);
34622159047fSniklas 
34632159047fSniklas   /* Line number stabs are handled differently, since they have two
34642159047fSniklas      values, the line number and the address of the label.  We use the
34652159047fSniklas      index field (aka desc) to hold the line number, and the value
34662159047fSniklas      field to hold the address.  The symbol type is st_Label, which
34672159047fSniklas      should be different from the other stabs, so that gdb can
34682159047fSniklas      recognize it.  */
34692159047fSniklas   if (type == N_SLINE)
34702159047fSniklas     {
34712159047fSniklas       SYMR dummy_symr;
34722159047fSniklas       char *name;
34732159047fSniklas       char name_end;
34742159047fSniklas 
34752159047fSniklas #ifndef NO_LISTING
34762159047fSniklas       if (listing)
34772159047fSniklas 	listing_source_line ((unsigned int) desc);
34782159047fSniklas #endif
34792159047fSniklas 
34802159047fSniklas       dummy_symr.index = desc;
34812159047fSniklas       if (dummy_symr.index != desc)
34822159047fSniklas 	{
3483c074d1c9Sdrahn 	  as_warn (_("line number (%d) for .stab%c directive cannot fit in index field (20 bits)"),
34842159047fSniklas 		   desc, what);
34852159047fSniklas 	  return;
34862159047fSniklas 	}
34872159047fSniklas 
34882159047fSniklas       name = input_line_pointer;
34892159047fSniklas       name_end = get_symbol_end ();
34902159047fSniklas 
34912159047fSniklas       sym = symbol_find_or_make (name);
34922159047fSniklas       *input_line_pointer = name_end;
34932159047fSniklas 
34942159047fSniklas       value = 0;
3495191aa565Sniklas       addend = 0;
34962159047fSniklas       st = st_Label;
34972159047fSniklas       sc = sc_Text;
34982159047fSniklas       indx = desc;
34992159047fSniklas     }
35002159047fSniklas   else
35012159047fSniklas     {
35022159047fSniklas #ifndef NO_LISTING
35032159047fSniklas       if (listing && (type == N_SO || type == N_SOL))
35042159047fSniklas 	listing_source_file (string);
35052159047fSniklas #endif
35062159047fSniklas 
3507c074d1c9Sdrahn       if (ISDIGIT (*input_line_pointer)
35082159047fSniklas 	  || *input_line_pointer == '-'
35092159047fSniklas 	  || *input_line_pointer == '+')
35102159047fSniklas 	{
35112159047fSniklas 	  st = st_Nil;
35122159047fSniklas 	  sc = sc_Nil;
35132159047fSniklas 	  sym = (symbolS *) NULL;
35142159047fSniklas 	  value = get_absolute_expression ();
3515191aa565Sniklas 	  addend = 0;
35162159047fSniklas 	}
35172159047fSniklas       else if (! is_name_beginner ((unsigned char) *input_line_pointer))
35182159047fSniklas 	{
3519c074d1c9Sdrahn 	  as_warn (_("illegal .stab%c directive, bad character"), what);
35202159047fSniklas 	  return;
35212159047fSniklas 	}
35222159047fSniklas       else
35232159047fSniklas 	{
3524191aa565Sniklas 	  expressionS exp;
35252159047fSniklas 
35262159047fSniklas 	  sc = sc_Nil;
35272159047fSniklas 	  st = st_Nil;
35282159047fSniklas 
3529191aa565Sniklas 	  expression (&exp);
3530191aa565Sniklas 	  if (exp.X_op == O_constant)
35312159047fSniklas 	    {
3532191aa565Sniklas 	      sym = NULL;
3533191aa565Sniklas 	      value = exp.X_add_number;
3534191aa565Sniklas 	      addend = 0;
3535191aa565Sniklas 	    }
3536191aa565Sniklas 	  else if (exp.X_op == O_symbol)
3537191aa565Sniklas 	    {
3538191aa565Sniklas 	      sym = exp.X_add_symbol;
3539191aa565Sniklas 	      value = 0;
3540191aa565Sniklas 	      addend = exp.X_add_number;
3541191aa565Sniklas 	    }
3542191aa565Sniklas 	  else
3543191aa565Sniklas 	    {
3544e93f7393Sniklas 	      sym = make_expr_symbol (&exp);
3545191aa565Sniklas 	      value = 0;
3546191aa565Sniklas 	      addend = 0;
35472159047fSniklas 	    }
35482159047fSniklas 	}
35492159047fSniklas 
35502159047fSniklas       indx = ECOFF_MARK_STAB (type);
35512159047fSniklas     }
35522159047fSniklas 
35532159047fSniklas   /* Don't store the stabs symbol we are creating as the type of the
35542159047fSniklas      ECOFF symbol.  We want to compute the type of the ECOFF symbol
35552159047fSniklas      independently.  */
35562159047fSniklas   if (sym != (symbolS *) NULL)
3557b305b0f1Sespie     hold = symbol_get_obj (sym)->ecoff_symbol;
35582159047fSniklas 
3559191aa565Sniklas   (void) add_ecoff_symbol (string, st, sc, sym, addend, value, indx);
35602159047fSniklas 
35612159047fSniklas   if (sym != (symbolS *) NULL)
3562b305b0f1Sespie     symbol_get_obj (sym)->ecoff_symbol = hold;
35632159047fSniklas 
35642159047fSniklas   /* Restore normal file type.  */
35652159047fSniklas   cur_file_ptr = save_file_ptr;
35662159047fSniklas }
35672159047fSniklas 
35682159047fSniklas /* Frob an ECOFF symbol.  Small common symbols go into a special
35692159047fSniklas    .scommon section rather than bfd_com_section.  */
35702159047fSniklas 
35712159047fSniklas void
ecoff_frob_symbol(symbolS * sym)3572*007c2a45Smiod ecoff_frob_symbol (symbolS *sym)
35732159047fSniklas {
35742159047fSniklas   if (S_IS_COMMON (sym)
35752159047fSniklas       && S_GET_VALUE (sym) > 0
3576c074d1c9Sdrahn       && S_GET_VALUE (sym) <= bfd_get_gp_size (stdoutput))
35772159047fSniklas     {
35782159047fSniklas       static asection scom_section;
35792159047fSniklas       static asymbol scom_symbol;
35802159047fSniklas 
35812159047fSniklas       /* We must construct a fake section similar to bfd_com_section
35822159047fSniklas          but with the name .scommon.  */
35832159047fSniklas       if (scom_section.name == NULL)
35842159047fSniklas 	{
35852159047fSniklas 	  scom_section = bfd_com_section;
35862159047fSniklas 	  scom_section.name = ".scommon";
35872159047fSniklas 	  scom_section.output_section = &scom_section;
35882159047fSniklas 	  scom_section.symbol = &scom_symbol;
35892159047fSniklas 	  scom_section.symbol_ptr_ptr = &scom_section.symbol;
35902159047fSniklas 	  scom_symbol = *bfd_com_section.symbol;
35912159047fSniklas 	  scom_symbol.name = ".scommon";
35922159047fSniklas 	  scom_symbol.section = &scom_section;
35932159047fSniklas 	}
35942159047fSniklas       S_SET_SEGMENT (sym, &scom_section);
35952159047fSniklas     }
35962159047fSniklas 
35972159047fSniklas   /* Double check weak symbols.  */
3598b305b0f1Sespie   if (S_IS_WEAK (sym))
35992159047fSniklas     {
36002159047fSniklas       if (S_IS_COMMON (sym))
3601c074d1c9Sdrahn 	as_bad (_("symbol `%s' can not be both weak and common"),
36022159047fSniklas 		S_GET_NAME (sym));
36032159047fSniklas     }
36042159047fSniklas }
36052159047fSniklas 
36062159047fSniklas /* Add bytes to the symbolic information buffer.  */
36072159047fSniklas 
36082159047fSniklas static char *
ecoff_add_bytes(char ** buf,char ** bufend,char * bufptr,unsigned long need)3609*007c2a45Smiod ecoff_add_bytes (char **buf,
3610*007c2a45Smiod 		 char **bufend,
3611*007c2a45Smiod 		 char *bufptr,
3612*007c2a45Smiod 		 unsigned long need)
36132159047fSniklas {
36142159047fSniklas   unsigned long at;
36152159047fSniklas   unsigned long want;
36162159047fSniklas 
36172159047fSniklas   at = bufptr - *buf;
36182159047fSniklas   need -= *bufend - bufptr;
36192159047fSniklas   if (need < PAGE_SIZE)
36202159047fSniklas     need = PAGE_SIZE;
36212159047fSniklas   want = (*bufend - *buf) + need;
36222159047fSniklas   *buf = xrealloc (*buf, want);
36232159047fSniklas   *bufend = *buf + want;
36242159047fSniklas   return *buf + at;
36252159047fSniklas }
36262159047fSniklas 
36272159047fSniklas /* Adjust the symbolic information buffer to the alignment required
36282159047fSniklas    for the ECOFF target debugging information.  */
36292159047fSniklas 
36302159047fSniklas static unsigned long
ecoff_padding_adjust(const struct ecoff_debug_swap * backend,char ** buf,char ** bufend,unsigned long offset,char ** bufptrptr)3631*007c2a45Smiod ecoff_padding_adjust (const struct ecoff_debug_swap *backend,
3632*007c2a45Smiod 		      char **buf,
3633*007c2a45Smiod 		      char **bufend,
3634*007c2a45Smiod 		      unsigned long offset,
3635*007c2a45Smiod 		      char **bufptrptr)
36362159047fSniklas {
36372159047fSniklas   bfd_size_type align;
36382159047fSniklas 
36392159047fSniklas   align = backend->debug_align;
36402159047fSniklas   if ((offset & (align - 1)) != 0)
36412159047fSniklas     {
36422159047fSniklas       unsigned long add;
36432159047fSniklas 
36442159047fSniklas       add = align - (offset & (align - 1));
3645b55d4692Sfgsch       if ((unsigned long) (*bufend - (*buf + offset)) < add)
36462159047fSniklas 	(void) ecoff_add_bytes (buf, bufend, *buf + offset, add);
36472159047fSniklas       memset (*buf + offset, 0, add);
36482159047fSniklas       offset += add;
36492159047fSniklas       if (bufptrptr != (char **) NULL)
36502159047fSniklas 	*bufptrptr = *buf + offset;
36512159047fSniklas     }
36522159047fSniklas 
36532159047fSniklas   return offset;
36542159047fSniklas }
36552159047fSniklas 
36562159047fSniklas /* Build the line number information.  */
36572159047fSniklas 
36582159047fSniklas static unsigned long
ecoff_build_lineno(const struct ecoff_debug_swap * backend,char ** buf,char ** bufend,unsigned long offset,long * linecntptr)3659*007c2a45Smiod ecoff_build_lineno (const struct ecoff_debug_swap *backend,
3660*007c2a45Smiod 		    char **buf,
3661*007c2a45Smiod 		    char **bufend,
3662*007c2a45Smiod 		    unsigned long offset,
3663*007c2a45Smiod 		    long *linecntptr)
36642159047fSniklas {
36652159047fSniklas   char *bufptr;
36662159047fSniklas   register lineno_list_t *l;
36672159047fSniklas   lineno_list_t *last;
36682159047fSniklas   efdr_t *file;
36692159047fSniklas   proc_t *proc;
36702159047fSniklas   unsigned long c;
36712159047fSniklas   long iline;
36722159047fSniklas   long totcount;
36732159047fSniklas   lineno_list_t first;
3674b305b0f1Sespie   lineno_list_t *local_first_lineno = first_lineno;
36752159047fSniklas 
36762159047fSniklas   if (linecntptr != (long *) NULL)
36772159047fSniklas     *linecntptr = 0;
36782159047fSniklas 
36792159047fSniklas   bufptr = *buf + offset;
36802159047fSniklas 
36812159047fSniklas   file = (efdr_t *) NULL;
36822159047fSniklas   proc = (proc_t *) NULL;
36832159047fSniklas   last = (lineno_list_t *) NULL;
36842159047fSniklas   c = offset;
36852159047fSniklas   iline = 0;
36862159047fSniklas   totcount = 0;
36872159047fSniklas 
36882159047fSniklas   /* For some reason the address of the first procedure is ignored
36892159047fSniklas      when reading line numbers.  This doesn't matter if the address of
36902159047fSniklas      the first procedure is 0, but when gcc is generating MIPS
36912159047fSniklas      embedded PIC code, it will put strings in the .text section
36922159047fSniklas      before the first procedure.  We cope by inserting a dummy line if
36932159047fSniklas      the address of the first procedure is not 0.  Hopefully this
3694b305b0f1Sespie      won't screw things up too badly.
3695b305b0f1Sespie 
3696b305b0f1Sespie      Don't do this for ECOFF assembly source line numbers.  They work
3697b305b0f1Sespie      without this extra attention.  */
3698b305b0f1Sespie   if (debug_type != DEBUG_ECOFF
3699b305b0f1Sespie       && first_proc_ptr != (proc_t *) NULL
3700b305b0f1Sespie       && local_first_lineno != (lineno_list_t *) NULL
37012159047fSniklas       && ((S_GET_VALUE (first_proc_ptr->sym->as_sym)
37022159047fSniklas 	   + bfd_get_section_vma (stdoutput,
37032159047fSniklas 				  S_GET_SEGMENT (first_proc_ptr->sym->as_sym)))
37042159047fSniklas 	  != 0))
37052159047fSniklas     {
3706b305b0f1Sespie       first.file = local_first_lineno->file;
3707b305b0f1Sespie       first.proc = local_first_lineno->proc;
37082159047fSniklas       first.frag = &zero_address_frag;
37092159047fSniklas       first.paddr = 0;
37102159047fSniklas       first.lineno = 0;
37112159047fSniklas 
3712b305b0f1Sespie       first.next = local_first_lineno;
3713b305b0f1Sespie       local_first_lineno = &first;
37142159047fSniklas     }
37152159047fSniklas 
3716b305b0f1Sespie   for (l = local_first_lineno; l != (lineno_list_t *) NULL; l = l->next)
37172159047fSniklas     {
37182159047fSniklas       long count;
37192159047fSniklas       long delta;
37202159047fSniklas 
37212159047fSniklas       /* Get the offset to the memory address of the next line number
37222159047fSniklas          (in words).  Do this first, so that we can skip ahead to the
37232159047fSniklas          next useful line number entry.  */
37242159047fSniklas       if (l->next == (lineno_list_t *) NULL)
37252159047fSniklas 	{
37262159047fSniklas 	  /* We want a count of zero, but it will be decremented
37272159047fSniklas 	     before it is used.  */
37282159047fSniklas 	  count = 1;
37292159047fSniklas 	}
3730191aa565Sniklas       else if (l->next->frag->fr_address + l->next->paddr
3731191aa565Sniklas 	       > l->frag->fr_address + l->paddr)
37322159047fSniklas 	{
37332159047fSniklas 	  count = ((l->next->frag->fr_address + l->next->paddr
37342159047fSniklas 		    - (l->frag->fr_address + l->paddr))
37352159047fSniklas 		   >> 2);
3736191aa565Sniklas 	}
3737191aa565Sniklas       else
37382159047fSniklas 	{
37392159047fSniklas 	  /* Don't change last, so we still get the right delta.  */
37402159047fSniklas 	  continue;
37412159047fSniklas 	}
37422159047fSniklas 
37432159047fSniklas       if (l->file != file || l->proc != proc)
37442159047fSniklas 	{
37452159047fSniklas 	  if (l->proc != proc && proc != (proc_t *) NULL)
37462159047fSniklas 	    proc->pdr.lnHigh = last->lineno;
37472159047fSniklas 	  if (l->file != file && file != (efdr_t *) NULL)
37482159047fSniklas 	    {
37492159047fSniklas 	      file->fdr.cbLine = c - file->fdr.cbLineOffset;
37502159047fSniklas 	      file->fdr.cline = totcount + count;
37512159047fSniklas 	      if (linecntptr != (long *) NULL)
37522159047fSniklas 		*linecntptr += totcount + count;
37532159047fSniklas 	      totcount = 0;
37542159047fSniklas 	    }
37552159047fSniklas 
37562159047fSniklas 	  if (l->file != file)
37572159047fSniklas 	    {
37582159047fSniklas 	      efdr_t *last_file = file;
37592159047fSniklas 
37602159047fSniklas 	      file = l->file;
37612159047fSniklas 	      if (last_file != (efdr_t *) NULL)
37622159047fSniklas 		file->fdr.ilineBase
37632159047fSniklas 		  = last_file->fdr.ilineBase + last_file->fdr.cline;
37642159047fSniklas 	      else
37652159047fSniklas 		file->fdr.ilineBase = 0;
37662159047fSniklas 	      file->fdr.cbLineOffset = c;
37672159047fSniklas 	    }
37682159047fSniklas 	  if (l->proc != proc)
37692159047fSniklas 	    {
37702159047fSniklas 	      proc = l->proc;
37712159047fSniklas 	      if (proc != (proc_t *) NULL)
37722159047fSniklas 		{
37732159047fSniklas 		  proc->pdr.lnLow = l->lineno;
37742159047fSniklas 		  proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset;
37752159047fSniklas 		  proc->pdr.iline = totcount;
37762159047fSniklas 		}
37772159047fSniklas 	    }
37782159047fSniklas 
37792159047fSniklas 	  last = (lineno_list_t *) NULL;
37802159047fSniklas 	}
37812159047fSniklas 
37822159047fSniklas       totcount += count;
37832159047fSniklas 
37842159047fSniklas       /* Get the offset to this line number.  */
37852159047fSniklas       if (last == (lineno_list_t *) NULL)
37862159047fSniklas 	delta = 0;
37872159047fSniklas       else
37882159047fSniklas 	delta = l->lineno - last->lineno;
37892159047fSniklas 
37902159047fSniklas       /* Put in the offset to this line number.  */
37912159047fSniklas       while (delta != 0)
37922159047fSniklas 	{
37932159047fSniklas 	  int setcount;
37942159047fSniklas 
37952159047fSniklas 	  /* 1 is added to each count read.  */
37962159047fSniklas 	  --count;
37972159047fSniklas 	  /* We can only adjust the word count by up to 15 words at a
37982159047fSniklas 	     time.  */
37992159047fSniklas 	  if (count <= 0x0f)
38002159047fSniklas 	    {
38012159047fSniklas 	      setcount = count;
38022159047fSniklas 	      count = 0;
38032159047fSniklas 	    }
38042159047fSniklas 	  else
38052159047fSniklas 	    {
38062159047fSniklas 	      setcount = 0x0f;
38072159047fSniklas 	      count -= 0x0f;
38082159047fSniklas 	    }
38092159047fSniklas 	  if (delta >= -7 && delta <= 7)
38102159047fSniklas 	    {
38112159047fSniklas 	      if (bufptr >= *bufend)
38122159047fSniklas 		bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
38132159047fSniklas 	      *bufptr++ = setcount + (delta << 4);
38142159047fSniklas 	      delta = 0;
38152159047fSniklas 	      ++c;
38162159047fSniklas 	    }
38172159047fSniklas 	  else
38182159047fSniklas 	    {
38192159047fSniklas 	      int set;
38202159047fSniklas 
38212159047fSniklas 	      if (*bufend - bufptr < 3)
38222159047fSniklas 		bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3);
38232159047fSniklas 	      *bufptr++ = setcount + (8 << 4);
38242159047fSniklas 	      if (delta < -0x8000)
38252159047fSniklas 		{
38262159047fSniklas 		  set = -0x8000;
38272159047fSniklas 		  delta += 0x8000;
38282159047fSniklas 		}
38292159047fSniklas 	      else if (delta > 0x7fff)
38302159047fSniklas 		{
38312159047fSniklas 		  set = 0x7fff;
38322159047fSniklas 		  delta -= 0x7fff;
38332159047fSniklas 		}
38342159047fSniklas 	      else
38352159047fSniklas 		{
38362159047fSniklas 		  set = delta;
38372159047fSniklas 		  delta = 0;
38382159047fSniklas 		}
38392159047fSniklas 	      *bufptr++ = set >> 8;
38402159047fSniklas 	      *bufptr++ = set & 0xffff;
38412159047fSniklas 	      c += 3;
38422159047fSniklas 	    }
38432159047fSniklas 	}
38442159047fSniklas 
38452159047fSniklas       /* Finish adjusting the count.  */
38462159047fSniklas       while (count > 0)
38472159047fSniklas 	{
38482159047fSniklas 	  if (bufptr >= *bufend)
38492159047fSniklas 	    bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
38502159047fSniklas 	  /* 1 is added to each count read.  */
38512159047fSniklas 	  --count;
38522159047fSniklas 	  if (count > 0x0f)
38532159047fSniklas 	    {
38542159047fSniklas 	      *bufptr++ = 0x0f;
38552159047fSniklas 	      count -= 0x0f;
38562159047fSniklas 	    }
38572159047fSniklas 	  else
38582159047fSniklas 	    {
38592159047fSniklas 	      *bufptr++ = count;
38602159047fSniklas 	      count = 0;
38612159047fSniklas 	    }
38622159047fSniklas 	  ++c;
38632159047fSniklas 	}
38642159047fSniklas 
38652159047fSniklas       ++iline;
38662159047fSniklas       last = l;
38672159047fSniklas     }
38682159047fSniklas 
38692159047fSniklas   if (proc != (proc_t *) NULL)
38702159047fSniklas     proc->pdr.lnHigh = last->lineno;
38712159047fSniklas   if (file != (efdr_t *) NULL)
38722159047fSniklas     {
38732159047fSniklas       file->fdr.cbLine = c - file->fdr.cbLineOffset;
38742159047fSniklas       file->fdr.cline = totcount;
38752159047fSniklas     }
38762159047fSniklas 
38772159047fSniklas   if (linecntptr != (long *) NULL)
38782159047fSniklas     *linecntptr += totcount;
38792159047fSniklas 
38802159047fSniklas   c = ecoff_padding_adjust (backend, buf, bufend, c, &bufptr);
38812159047fSniklas 
38822159047fSniklas   return c;
38832159047fSniklas }
38842159047fSniklas 
38852159047fSniklas /* Build and swap out the symbols.  */
38862159047fSniklas 
38872159047fSniklas static unsigned long
ecoff_build_symbols(const struct ecoff_debug_swap * backend,char ** buf,char ** bufend,unsigned long offset)3888*007c2a45Smiod ecoff_build_symbols (const struct ecoff_debug_swap *backend,
3889*007c2a45Smiod 		     char **buf,
3890*007c2a45Smiod 		     char **bufend,
3891*007c2a45Smiod 		     unsigned long offset)
38922159047fSniklas {
38932159047fSniklas   const bfd_size_type external_sym_size = backend->external_sym_size;
3894*007c2a45Smiod   void (* const swap_sym_out) (bfd *, const SYMR *, PTR)
38952159047fSniklas     = backend->swap_sym_out;
38962159047fSniklas   char *sym_out;
38972159047fSniklas   long isym;
38982159047fSniklas   vlinks_t *file_link;
38992159047fSniklas 
39002159047fSniklas   sym_out = *buf + offset;
39012159047fSniklas 
39022159047fSniklas   isym = 0;
39032159047fSniklas 
39042159047fSniklas   /* The symbols are stored by file.  */
39052159047fSniklas   for (file_link = file_desc.first;
39062159047fSniklas        file_link != (vlinks_t *) NULL;
39072159047fSniklas        file_link = file_link->next)
39082159047fSniklas     {
39092159047fSniklas       int ifilesym;
39102159047fSniklas       int fil_cnt;
39112159047fSniklas       efdr_t *fil_ptr;
39122159047fSniklas       efdr_t *fil_end;
39132159047fSniklas 
39142159047fSniklas       if (file_link->next == (vlinks_t *) NULL)
39152159047fSniklas 	fil_cnt = file_desc.objects_last_page;
39162159047fSniklas       else
39172159047fSniklas 	fil_cnt = file_desc.objects_per_page;
39182159047fSniklas       fil_ptr = file_link->datum->file;
39192159047fSniklas       fil_end = fil_ptr + fil_cnt;
39202159047fSniklas       for (; fil_ptr < fil_end; fil_ptr++)
39212159047fSniklas 	{
39222159047fSniklas 	  vlinks_t *sym_link;
39232159047fSniklas 
39242159047fSniklas 	  fil_ptr->fdr.isymBase = isym;
39252159047fSniklas 	  ifilesym = isym;
39262159047fSniklas 	  for (sym_link = fil_ptr->symbols.first;
39272159047fSniklas 	       sym_link != (vlinks_t *) NULL;
39282159047fSniklas 	       sym_link = sym_link->next)
39292159047fSniklas 	    {
39302159047fSniklas 	      int sym_cnt;
39312159047fSniklas 	      localsym_t *sym_ptr;
39322159047fSniklas 	      localsym_t *sym_end;
39332159047fSniklas 
39342159047fSniklas 	      if (sym_link->next == (vlinks_t *) NULL)
39352159047fSniklas 		sym_cnt = fil_ptr->symbols.objects_last_page;
39362159047fSniklas 	      else
39372159047fSniklas 		sym_cnt = fil_ptr->symbols.objects_per_page;
39382159047fSniklas 	      sym_ptr = sym_link->datum->sym;
39392159047fSniklas 	      sym_end = sym_ptr + sym_cnt;
39402159047fSniklas 	      for (; sym_ptr < sym_end; sym_ptr++)
39412159047fSniklas 		{
39422159047fSniklas 		  int local;
39432159047fSniklas 		  symbolS *as_sym;
39442159047fSniklas 		  forward_t *f;
39452159047fSniklas 
39462159047fSniklas 		  know (sym_ptr->file_ptr == fil_ptr);
39472159047fSniklas 
39482159047fSniklas 		  /* If there is no associated gas symbol, then this
39492159047fSniklas 		     is a pure debugging symbol.  We have already
39502159047fSniklas 		     added the name (if any) to fil_ptr->strings.
39512159047fSniklas 		     Otherwise we must decide whether this is an
39522159047fSniklas 		     external or a local symbol (actually, it may be
39532159047fSniklas 		     both if the local provides additional debugging
39542159047fSniklas 		     information for the external).  */
39552159047fSniklas 		  local = 1;
39562159047fSniklas 		  as_sym = sym_ptr->as_sym;
39572159047fSniklas 		  if (as_sym != (symbolS *) NULL)
39582159047fSniklas 		    {
39592159047fSniklas 		      symint_t indx;
39602159047fSniklas 
39612159047fSniklas 		      /* The value of a block start symbol is the
39622159047fSniklas 		         offset from the start of the procedure.  For
39632159047fSniklas 		         other symbols we just use the gas value (but
39642159047fSniklas 		         we must offset it by the vma of the section,
39652159047fSniklas 		         just as BFD does, because BFD will not see
39662159047fSniklas 		         this value).  */
39672159047fSniklas 		      if (sym_ptr->ecoff_sym.asym.st == (int) st_Block
39682159047fSniklas 			  && sym_ptr->ecoff_sym.asym.sc == (int) sc_Text)
39692159047fSniklas 			{
39702159047fSniklas 			  symbolS *begin_sym;
39712159047fSniklas 
39722159047fSniklas 			  know (sym_ptr->proc_ptr != (proc_t *) NULL);
39732159047fSniklas 			  begin_sym = sym_ptr->proc_ptr->sym->as_sym;
39742159047fSniklas 			  if (S_GET_SEGMENT (as_sym)
39752159047fSniklas 			      != S_GET_SEGMENT (begin_sym))
3976b305b0f1Sespie 			    as_warn (_(".begin/.bend in different segments"));
39772159047fSniklas 			  sym_ptr->ecoff_sym.asym.value =
39782159047fSniklas 			    S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
39792159047fSniklas 			}
39802159047fSniklas 		      else
39812159047fSniklas 			sym_ptr->ecoff_sym.asym.value =
39822159047fSniklas 			  (S_GET_VALUE (as_sym)
39832159047fSniklas 			   + bfd_get_section_vma (stdoutput,
3984191aa565Sniklas 						  S_GET_SEGMENT (as_sym))
3985191aa565Sniklas 			   + sym_ptr->addend);
39862159047fSniklas 
39872159047fSniklas 		      sym_ptr->ecoff_sym.weakext = S_IS_WEAK (as_sym);
39882159047fSniklas 
39892159047fSniklas 		      /* Set st_Proc to st_StaticProc for local
39902159047fSniklas 			 functions.  */
39912159047fSniklas 		      if (sym_ptr->ecoff_sym.asym.st == st_Proc
39922159047fSniklas 			  && S_IS_DEFINED (as_sym)
39932159047fSniklas 			  && ! S_IS_EXTERNAL (as_sym)
39942159047fSniklas 			  && ! S_IS_WEAK (as_sym))
39952159047fSniklas 			sym_ptr->ecoff_sym.asym.st = st_StaticProc;
39962159047fSniklas 
39972159047fSniklas 		      /* Get the type and storage class based on where
39982159047fSniklas 		         the symbol actually wound up.  Traditionally,
39992159047fSniklas 		         N_LBRAC and N_RBRAC are *not* relocated.  */
40002159047fSniklas 		      indx = sym_ptr->ecoff_sym.asym.index;
40012159047fSniklas 		      if (sym_ptr->ecoff_sym.asym.st == st_Nil
40022159047fSniklas 			  && sym_ptr->ecoff_sym.asym.sc == sc_Nil
40032159047fSniklas 			  && (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
40042159047fSniklas 			      || ((ECOFF_UNMARK_STAB (indx) != N_LBRAC)
40052159047fSniklas 				  && (ECOFF_UNMARK_STAB (indx) != N_RBRAC))))
40062159047fSniklas 			{
40072159047fSniklas 			  segT seg;
40082159047fSniklas 			  const char *segname;
40092159047fSniklas 			  st_t st;
40102159047fSniklas 			  sc_t sc;
40112159047fSniklas 
40122159047fSniklas 			  seg = S_GET_SEGMENT (as_sym);
40132159047fSniklas 			  segname = segment_name (seg);
40142159047fSniklas 
40152159047fSniklas 			  if (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
40162159047fSniklas 			      && (S_IS_EXTERNAL (as_sym)
40172159047fSniklas 				  || S_IS_WEAK (as_sym)
40182159047fSniklas 				  || ! S_IS_DEFINED (as_sym)))
40192159047fSniklas 			    {
4020b305b0f1Sespie 			      if ((symbol_get_bfdsym (as_sym)->flags
4021b305b0f1Sespie 				   & BSF_FUNCTION) != 0)
40222159047fSniklas 				st = st_Proc;
40232159047fSniklas 			      else
40242159047fSniklas 				st = st_Global;
40252159047fSniklas 			    }
40262159047fSniklas 			  else if (seg == text_section)
40272159047fSniklas 			    st = st_Label;
40282159047fSniklas 			  else
40292159047fSniklas 			    st = st_Static;
40302159047fSniklas 
40312159047fSniklas 			  if (! S_IS_DEFINED (as_sym))
40322159047fSniklas 			    {
4033b305b0f1Sespie 			      valueT s;
4034b305b0f1Sespie 
4035b305b0f1Sespie 			      s = symbol_get_obj (as_sym)->ecoff_extern_size;
4036b305b0f1Sespie 			      if (s == 0
4037c074d1c9Sdrahn 				  || s > bfd_get_gp_size (stdoutput))
40382159047fSniklas 				sc = sc_Undefined;
40392159047fSniklas 			      else
40402159047fSniklas 				{
40412159047fSniklas 				  sc = sc_SUndefined;
4042b305b0f1Sespie 				  sym_ptr->ecoff_sym.asym.value = s;
40432159047fSniklas 				}
4044191aa565Sniklas #ifdef S_SET_SIZE
4045b305b0f1Sespie 			      S_SET_SIZE (as_sym, s);
4046191aa565Sniklas #endif
40472159047fSniklas 			    }
40482159047fSniklas 			  else if (S_IS_COMMON (as_sym))
40492159047fSniklas 			    {
40502159047fSniklas 			      if (S_GET_VALUE (as_sym) > 0
40512159047fSniklas 				  && (S_GET_VALUE (as_sym)
4052c074d1c9Sdrahn 				      <= bfd_get_gp_size (stdoutput)))
40532159047fSniklas 				sc = sc_SCommon;
40542159047fSniklas 			      else
40552159047fSniklas 				sc = sc_Common;
40562159047fSniklas 			    }
40572159047fSniklas 			  else if (seg == text_section)
40582159047fSniklas 			    sc = sc_Text;
40592159047fSniklas 			  else if (seg == data_section)
40602159047fSniklas 			    sc = sc_Data;
40612159047fSniklas 			  else if (strcmp (segname, ".rdata") == 0
40622159047fSniklas 				   || strcmp (segname, ".rodata") == 0)
40632159047fSniklas 			    sc = sc_RData;
40642159047fSniklas 			  else if (strcmp (segname, ".sdata") == 0)
40652159047fSniklas 			    sc = sc_SData;
40662159047fSniklas 			  else if (seg == bss_section)
40672159047fSniklas 			    sc = sc_Bss;
40682159047fSniklas 			  else if (strcmp (segname, ".sbss") == 0)
40692159047fSniklas 			    sc = sc_SBss;
40702159047fSniklas 			  else if (seg == &bfd_abs_section)
40712159047fSniklas 			    sc = sc_Abs;
40722159047fSniklas 			  else
40732159047fSniklas 			    {
40742159047fSniklas 			      /* This must be a user named section.
40752159047fSniklas 			         This is not possible in ECOFF, but it
40762159047fSniklas 			         is in ELF.  */
40772159047fSniklas 			      sc = sc_Data;
40782159047fSniklas 			    }
40792159047fSniklas 
40802159047fSniklas 			  sym_ptr->ecoff_sym.asym.st = (int) st;
40812159047fSniklas 			  sym_ptr->ecoff_sym.asym.sc = (int) sc;
40822159047fSniklas 			}
40832159047fSniklas 
40842159047fSniklas 		      /* This is just an external symbol if it is
40852159047fSniklas 		         outside a procedure and it has a type.
40862159047fSniklas 		         FIXME: g++ will generate symbols which have
40872159047fSniklas 		         different names in the debugging information
40882159047fSniklas 		         than the actual symbol.  Should we handle
40892159047fSniklas 		         them here?  */
40902159047fSniklas 		      if ((S_IS_EXTERNAL (as_sym)
40912159047fSniklas 			   || S_IS_WEAK (as_sym)
40922159047fSniklas 			   || ! S_IS_DEFINED (as_sym))
40932159047fSniklas 			  && sym_ptr->proc_ptr == (proc_t *) NULL
40942159047fSniklas 			  && sym_ptr->ecoff_sym.asym.st != (int) st_Nil
40952159047fSniklas 			  && ! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym))
40962159047fSniklas 			local = 0;
40972159047fSniklas 
40986a4c786fSespie 		      /* This is just an external symbol if it is a
40996a4c786fSespie 		         common symbol.  */
41006a4c786fSespie 		      if (S_IS_COMMON (as_sym))
41016a4c786fSespie 			local = 0;
41026a4c786fSespie 
41032159047fSniklas 		      /* If an st_end symbol has an associated gas
41042159047fSniklas 		         symbol, then it is a local label created for
41052159047fSniklas 		         a .bend or .end directive.  Stabs line
41062159047fSniklas 		         numbers will have \001 in the names.  */
41072159047fSniklas 		      if (local
41082159047fSniklas 			  && sym_ptr->ecoff_sym.asym.st != st_End
41092159047fSniklas 			  && strchr (sym_ptr->name, '\001') == 0)
41102159047fSniklas 			sym_ptr->ecoff_sym.asym.iss =
41112159047fSniklas 			  add_string (&fil_ptr->strings,
41122159047fSniklas 				      fil_ptr->str_hash,
41132159047fSniklas 				      sym_ptr->name,
41142159047fSniklas 				      (shash_t **) NULL);
41152159047fSniklas 		    }
41162159047fSniklas 
41172159047fSniklas 		  /* We now know the index of this symbol; fill in
41182159047fSniklas 		     locations that have been waiting for that
41192159047fSniklas 		     information.  */
41202159047fSniklas 		  if (sym_ptr->begin_ptr != (localsym_t *) NULL)
41212159047fSniklas 		    {
41222159047fSniklas 		      localsym_t *begin_ptr;
41232159047fSniklas 		      st_t begin_type;
41242159047fSniklas 
41252159047fSniklas 		      know (local);
41262159047fSniklas 		      begin_ptr = sym_ptr->begin_ptr;
41272159047fSniklas 		      know (begin_ptr->sym_index != -1);
41282159047fSniklas 		      sym_ptr->ecoff_sym.asym.index = begin_ptr->sym_index;
41292159047fSniklas 		      if (sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
41302159047fSniklas 			sym_ptr->ecoff_sym.asym.iss =
41312159047fSniklas 			  begin_ptr->ecoff_sym.asym.iss;
41322159047fSniklas 
41332159047fSniklas 		      begin_type = begin_ptr->ecoff_sym.asym.st;
41342159047fSniklas 		      if (begin_type == st_File
41352159047fSniklas 			  || begin_type == st_Block)
41362159047fSniklas 			{
41372159047fSniklas 			  begin_ptr->ecoff_sym.asym.index =
41382159047fSniklas 			    isym - ifilesym + 1;
41392159047fSniklas 			  (*swap_sym_out) (stdoutput,
41402159047fSniklas 					   &begin_ptr->ecoff_sym.asym,
41412159047fSniklas 					   (*buf
41422159047fSniklas 					    + offset
41432159047fSniklas 					    + (begin_ptr->sym_index
41442159047fSniklas 					       * external_sym_size)));
41452159047fSniklas 			}
41462159047fSniklas 		      else
41472159047fSniklas 			{
41482159047fSniklas 			  know (begin_ptr->index_ptr != (aux_t *) NULL);
41492159047fSniklas 			  begin_ptr->index_ptr->data.isym =
41502159047fSniklas 			    isym - ifilesym + 1;
41512159047fSniklas 			}
41522159047fSniklas 
41532159047fSniklas 		      /* The value of the symbol marking the end of a
41542159047fSniklas 		         procedure is the size of the procedure.  The
41552159047fSniklas 		         value of the symbol marking the end of a
41562159047fSniklas 		         block is the offset from the start of the
41572159047fSniklas 		         procedure to the block.  */
41582159047fSniklas 		      if (begin_type == st_Proc
41592159047fSniklas 			  || begin_type == st_StaticProc)
41602159047fSniklas 			{
41612159047fSniklas 			  know (as_sym != (symbolS *) NULL);
41622159047fSniklas 			  know (begin_ptr->as_sym != (symbolS *) NULL);
41632159047fSniklas 			  if (S_GET_SEGMENT (as_sym)
41642159047fSniklas 			      != S_GET_SEGMENT (begin_ptr->as_sym))
4165b305b0f1Sespie 			    as_warn (_(".begin/.bend in different segments"));
41662159047fSniklas 			  sym_ptr->ecoff_sym.asym.value =
41672159047fSniklas 			    (S_GET_VALUE (as_sym)
41682159047fSniklas 			     - S_GET_VALUE (begin_ptr->as_sym));
41696a4c786fSespie 
41706a4c786fSespie 			  /* If the size is odd, this is probably a
41716a4c786fSespie 			     mips16 function; force it to be even.  */
41726a4c786fSespie 			  if ((sym_ptr->ecoff_sym.asym.value & 1) != 0)
41736a4c786fSespie 			    ++sym_ptr->ecoff_sym.asym.value;
41746a4c786fSespie 
4175191aa565Sniklas #ifdef S_SET_SIZE
4176191aa565Sniklas 			  S_SET_SIZE (begin_ptr->as_sym,
4177191aa565Sniklas 				      sym_ptr->ecoff_sym.asym.value);
4178191aa565Sniklas #endif
41792159047fSniklas 			}
41802159047fSniklas 		      else if (begin_type == st_Block
41812159047fSniklas 			       && sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
41822159047fSniklas 			{
41832159047fSniklas 			  symbolS *begin_sym;
41842159047fSniklas 
41852159047fSniklas 			  know (as_sym != (symbolS *) NULL);
41862159047fSniklas 			  know (sym_ptr->proc_ptr != (proc_t *) NULL);
41872159047fSniklas 			  begin_sym = sym_ptr->proc_ptr->sym->as_sym;
41882159047fSniklas 			  if (S_GET_SEGMENT (as_sym)
41892159047fSniklas 			      != S_GET_SEGMENT (begin_sym))
4190b305b0f1Sespie 			    as_warn (_(".begin/.bend in different segments"));
41912159047fSniklas 			  sym_ptr->ecoff_sym.asym.value =
41922159047fSniklas 			    S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
41932159047fSniklas 			}
41942159047fSniklas 		    }
41952159047fSniklas 
41962159047fSniklas 		  for (f = sym_ptr->forward_ref;
41972159047fSniklas 		       f != (forward_t *) NULL;
41982159047fSniklas 		       f = f->next)
41992159047fSniklas 		    {
42002159047fSniklas 		      know (local);
42012159047fSniklas 		      f->ifd_ptr->data.isym = fil_ptr->file_index;
42022159047fSniklas 		      f->index_ptr->data.rndx.index = isym - ifilesym;
42032159047fSniklas 		    }
42042159047fSniklas 
42052159047fSniklas 		  if (local)
42062159047fSniklas 		    {
4207b55d4692Sfgsch 		      if ((bfd_size_type)(*bufend - sym_out) < external_sym_size)
42082159047fSniklas 			sym_out = ecoff_add_bytes (buf, bufend,
42092159047fSniklas 						   sym_out,
42102159047fSniklas 						   external_sym_size);
42112159047fSniklas 		      (*swap_sym_out) (stdoutput, &sym_ptr->ecoff_sym.asym,
42122159047fSniklas 				       sym_out);
42132159047fSniklas 		      sym_out += external_sym_size;
42142159047fSniklas 
42152159047fSniklas 		      sym_ptr->sym_index = isym;
42162159047fSniklas 
42172159047fSniklas 		      if (sym_ptr->proc_ptr != (proc_t *) NULL
42182159047fSniklas 			  && sym_ptr->proc_ptr->sym == sym_ptr)
42192159047fSniklas 			sym_ptr->proc_ptr->pdr.isym = isym - ifilesym;
42202159047fSniklas 
42212159047fSniklas 		      ++isym;
42222159047fSniklas 		    }
42232159047fSniklas 
42242159047fSniklas 		  /* Record the local symbol index and file number in
42252159047fSniklas 		     case this is an external symbol.  Note that this
42262159047fSniklas 		     destroys the asym.index field.  */
42272159047fSniklas 		  if (as_sym != (symbolS *) NULL
4228b305b0f1Sespie 		      && symbol_get_obj (as_sym)->ecoff_symbol == sym_ptr)
42292159047fSniklas 		    {
42302159047fSniklas 		      if ((sym_ptr->ecoff_sym.asym.st == st_Proc
42312159047fSniklas 			   || sym_ptr->ecoff_sym.asym.st == st_StaticProc)
42322159047fSniklas 			  && local)
42332159047fSniklas 			sym_ptr->ecoff_sym.asym.index = isym - ifilesym - 1;
42342159047fSniklas 		      sym_ptr->ecoff_sym.ifd = fil_ptr->file_index;
4235b305b0f1Sespie 
4236b305b0f1Sespie 		      /* Don't try to merge an FDR which has an
4237b305b0f1Sespie 		         external symbol attached to it.  */
4238b305b0f1Sespie 		      if (S_IS_EXTERNAL (as_sym) || S_IS_WEAK (as_sym))
4239b305b0f1Sespie 			fil_ptr->fdr.fMerge = 0;
42402159047fSniklas 		    }
42412159047fSniklas 		}
42422159047fSniklas 	    }
42432159047fSniklas 	  fil_ptr->fdr.csym = isym - fil_ptr->fdr.isymBase;
42442159047fSniklas 	}
42452159047fSniklas     }
42462159047fSniklas 
42472159047fSniklas   return offset + isym * external_sym_size;
42482159047fSniklas }
42492159047fSniklas 
42502159047fSniklas /* Swap out the procedure information.  */
42512159047fSniklas 
42522159047fSniklas static unsigned long
ecoff_build_procs(const struct ecoff_debug_swap * backend,char ** buf,char ** bufend,unsigned long offset)4253*007c2a45Smiod ecoff_build_procs (const struct ecoff_debug_swap *backend,
4254*007c2a45Smiod 		   char **buf,
4255*007c2a45Smiod 		   char **bufend,
4256*007c2a45Smiod 		   unsigned long offset)
42572159047fSniklas {
42582159047fSniklas   const bfd_size_type external_pdr_size = backend->external_pdr_size;
4259*007c2a45Smiod   void (* const swap_pdr_out) (bfd *, const PDR *, PTR)
42602159047fSniklas     = backend->swap_pdr_out;
42612159047fSniklas   char *pdr_out;
42622159047fSniklas   long iproc;
42632159047fSniklas   vlinks_t *file_link;
42642159047fSniklas 
42652159047fSniklas   pdr_out = *buf + offset;
42662159047fSniklas 
42672159047fSniklas   iproc = 0;
42682159047fSniklas 
42692159047fSniklas   /* The procedures are stored by file.  */
42702159047fSniklas   for (file_link = file_desc.first;
42712159047fSniklas        file_link != (vlinks_t *) NULL;
42722159047fSniklas        file_link = file_link->next)
42732159047fSniklas     {
42742159047fSniklas       int fil_cnt;
42752159047fSniklas       efdr_t *fil_ptr;
42762159047fSniklas       efdr_t *fil_end;
42772159047fSniklas 
42782159047fSniklas       if (file_link->next == (vlinks_t *) NULL)
42792159047fSniklas 	fil_cnt = file_desc.objects_last_page;
42802159047fSniklas       else
42812159047fSniklas 	fil_cnt = file_desc.objects_per_page;
42822159047fSniklas       fil_ptr = file_link->datum->file;
42832159047fSniklas       fil_end = fil_ptr + fil_cnt;
42842159047fSniklas       for (; fil_ptr < fil_end; fil_ptr++)
42852159047fSniklas 	{
42862159047fSniklas 	  vlinks_t *proc_link;
42872159047fSniklas 	  int first;
42882159047fSniklas 
42892159047fSniklas 	  fil_ptr->fdr.ipdFirst = iproc;
42902159047fSniklas 	  first = 1;
42912159047fSniklas 	  for (proc_link = fil_ptr->procs.first;
42922159047fSniklas 	       proc_link != (vlinks_t *) NULL;
42932159047fSniklas 	       proc_link = proc_link->next)
42942159047fSniklas 	    {
42952159047fSniklas 	      int prc_cnt;
42962159047fSniklas 	      proc_t *proc_ptr;
42972159047fSniklas 	      proc_t *proc_end;
42982159047fSniklas 
42992159047fSniklas 	      if (proc_link->next == (vlinks_t *) NULL)
43002159047fSniklas 		prc_cnt = fil_ptr->procs.objects_last_page;
43012159047fSniklas 	      else
43022159047fSniklas 		prc_cnt = fil_ptr->procs.objects_per_page;
43032159047fSniklas 	      proc_ptr = proc_link->datum->proc;
43042159047fSniklas 	      proc_end = proc_ptr + prc_cnt;
43052159047fSniklas 	      for (; proc_ptr < proc_end; proc_ptr++)
43062159047fSniklas 		{
43072159047fSniklas 		  symbolS *adr_sym;
43082159047fSniklas 		  unsigned long adr;
43092159047fSniklas 
43102159047fSniklas 		  adr_sym = proc_ptr->sym->as_sym;
43112159047fSniklas 		  adr = (S_GET_VALUE (adr_sym)
43122159047fSniklas 			 + bfd_get_section_vma (stdoutput,
43132159047fSniklas 						S_GET_SEGMENT (adr_sym)));
43142159047fSniklas 		  if (first)
43152159047fSniklas 		    {
43162159047fSniklas 		      /* This code used to force the adr of the very
43172159047fSniklas 		         first fdr to be 0.  However, the native tools
43182159047fSniklas 		         don't do that, and I can't remember why it
43192159047fSniklas 		         used to work that way, so I took it out.  */
43202159047fSniklas 		      fil_ptr->fdr.adr = adr;
43212159047fSniklas 		      first = 0;
43222159047fSniklas 		    }
43232159047fSniklas 		  proc_ptr->pdr.adr = adr - fil_ptr->fdr.adr;
4324b55d4692Sfgsch 		  if ((bfd_size_type)(*bufend - pdr_out) < external_pdr_size)
43252159047fSniklas 		    pdr_out = ecoff_add_bytes (buf, bufend,
43262159047fSniklas 					       pdr_out,
43272159047fSniklas 					       external_pdr_size);
43282159047fSniklas 		  (*swap_pdr_out) (stdoutput, &proc_ptr->pdr, pdr_out);
43292159047fSniklas 		  pdr_out += external_pdr_size;
43302159047fSniklas 		  ++iproc;
43312159047fSniklas 		}
43322159047fSniklas 	    }
43332159047fSniklas 	  fil_ptr->fdr.cpd = iproc - fil_ptr->fdr.ipdFirst;
43342159047fSniklas 	}
43352159047fSniklas     }
43362159047fSniklas 
43372159047fSniklas   return offset + iproc * external_pdr_size;
43382159047fSniklas }
43392159047fSniklas 
43402159047fSniklas /* Swap out the aux information.  */
43412159047fSniklas 
43422159047fSniklas static unsigned long
ecoff_build_aux(const struct ecoff_debug_swap * backend,char ** buf,char ** bufend,unsigned long offset)4343*007c2a45Smiod ecoff_build_aux (const struct ecoff_debug_swap *backend,
4344*007c2a45Smiod 		 char **buf,
4345*007c2a45Smiod 		 char **bufend,
4346*007c2a45Smiod 		 unsigned long offset)
43472159047fSniklas {
43482159047fSniklas   int bigendian;
43492159047fSniklas   union aux_ext *aux_out;
43502159047fSniklas   long iaux;
43512159047fSniklas   vlinks_t *file_link;
43522159047fSniklas 
4353191aa565Sniklas   bigendian = bfd_big_endian (stdoutput);
43542159047fSniklas 
43552159047fSniklas   aux_out = (union aux_ext *) (*buf + offset);
43562159047fSniklas 
43572159047fSniklas   iaux = 0;
43582159047fSniklas 
43592159047fSniklas   /* The aux entries are stored by file.  */
43602159047fSniklas   for (file_link = file_desc.first;
43612159047fSniklas        file_link != (vlinks_t *) NULL;
43622159047fSniklas        file_link = file_link->next)
43632159047fSniklas     {
43642159047fSniklas       int fil_cnt;
43652159047fSniklas       efdr_t *fil_ptr;
43662159047fSniklas       efdr_t *fil_end;
43672159047fSniklas 
43682159047fSniklas       if (file_link->next == (vlinks_t *) NULL)
43692159047fSniklas 	fil_cnt = file_desc.objects_last_page;
43702159047fSniklas       else
43712159047fSniklas 	fil_cnt = file_desc.objects_per_page;
43722159047fSniklas       fil_ptr = file_link->datum->file;
43732159047fSniklas       fil_end = fil_ptr + fil_cnt;
43742159047fSniklas       for (; fil_ptr < fil_end; fil_ptr++)
43752159047fSniklas 	{
43762159047fSniklas 	  vlinks_t *aux_link;
43772159047fSniklas 
43782159047fSniklas 	  fil_ptr->fdr.fBigendian = bigendian;
43792159047fSniklas 	  fil_ptr->fdr.iauxBase = iaux;
43802159047fSniklas 	  for (aux_link = fil_ptr->aux_syms.first;
43812159047fSniklas 	       aux_link != (vlinks_t *) NULL;
43822159047fSniklas 	       aux_link = aux_link->next)
43832159047fSniklas 	    {
43842159047fSniklas 	      int aux_cnt;
43852159047fSniklas 	      aux_t *aux_ptr;
43862159047fSniklas 	      aux_t *aux_end;
43872159047fSniklas 
43882159047fSniklas 	      if (aux_link->next == (vlinks_t *) NULL)
43892159047fSniklas 		aux_cnt = fil_ptr->aux_syms.objects_last_page;
43902159047fSniklas 	      else
43912159047fSniklas 		aux_cnt = fil_ptr->aux_syms.objects_per_page;
43922159047fSniklas 	      aux_ptr = aux_link->datum->aux;
43932159047fSniklas 	      aux_end = aux_ptr + aux_cnt;
43942159047fSniklas 	      for (; aux_ptr < aux_end; aux_ptr++)
43952159047fSniklas 		{
4396b55d4692Sfgsch 		  if ((unsigned long) (*bufend - (char *) aux_out)
4397b55d4692Sfgsch 		      < sizeof (union aux_ext))
43982159047fSniklas 		    aux_out = ((union aux_ext *)
43992159047fSniklas 			       ecoff_add_bytes (buf, bufend,
44002159047fSniklas 						(char *) aux_out,
44012159047fSniklas 						sizeof (union aux_ext)));
44022159047fSniklas 		  switch (aux_ptr->type)
44032159047fSniklas 		    {
44042159047fSniklas 		    case aux_tir:
44052159047fSniklas 		      (*backend->swap_tir_out) (bigendian,
44062159047fSniklas 						&aux_ptr->data.ti,
44072159047fSniklas 						&aux_out->a_ti);
44082159047fSniklas 		      break;
44092159047fSniklas 		    case aux_rndx:
44102159047fSniklas 		      (*backend->swap_rndx_out) (bigendian,
44112159047fSniklas 						 &aux_ptr->data.rndx,
44122159047fSniklas 						 &aux_out->a_rndx);
44132159047fSniklas 		      break;
44142159047fSniklas 		    case aux_dnLow:
44152159047fSniklas 		      AUX_PUT_DNLOW (bigendian, aux_ptr->data.dnLow,
44162159047fSniklas 				     aux_out);
44172159047fSniklas 		      break;
44182159047fSniklas 		    case aux_dnHigh:
44192159047fSniklas 		      AUX_PUT_DNHIGH (bigendian, aux_ptr->data.dnHigh,
44202159047fSniklas 				      aux_out);
44212159047fSniklas 		      break;
44222159047fSniklas 		    case aux_isym:
44232159047fSniklas 		      AUX_PUT_ISYM (bigendian, aux_ptr->data.isym,
44242159047fSniklas 				    aux_out);
44252159047fSniklas 		      break;
44262159047fSniklas 		    case aux_iss:
44272159047fSniklas 		      AUX_PUT_ISS (bigendian, aux_ptr->data.iss,
44282159047fSniklas 				   aux_out);
44292159047fSniklas 		      break;
44302159047fSniklas 		    case aux_width:
44312159047fSniklas 		      AUX_PUT_WIDTH (bigendian, aux_ptr->data.width,
44322159047fSniklas 				     aux_out);
44332159047fSniklas 		      break;
44342159047fSniklas 		    case aux_count:
44352159047fSniklas 		      AUX_PUT_COUNT (bigendian, aux_ptr->data.count,
44362159047fSniklas 				     aux_out);
44372159047fSniklas 		      break;
44382159047fSniklas 		    }
44392159047fSniklas 
44402159047fSniklas 		  ++aux_out;
44412159047fSniklas 		  ++iaux;
44422159047fSniklas 		}
44432159047fSniklas 	    }
44442159047fSniklas 	  fil_ptr->fdr.caux = iaux - fil_ptr->fdr.iauxBase;
44452159047fSniklas 	}
44462159047fSniklas     }
44472159047fSniklas 
44482159047fSniklas   return ecoff_padding_adjust (backend, buf, bufend,
44492159047fSniklas 			       offset + iaux * sizeof (union aux_ext),
44502159047fSniklas 			       (char **) NULL);
44512159047fSniklas }
44522159047fSniklas 
44532159047fSniklas /* Copy out the strings from a varray_t.  This returns the number of
44542159047fSniklas    bytes copied, rather than the new offset.  */
44552159047fSniklas 
44562159047fSniklas static unsigned long
ecoff_build_strings(char ** buf,char ** bufend,unsigned long offset,varray_t * vp)4457*007c2a45Smiod ecoff_build_strings (char **buf,
4458*007c2a45Smiod 		     char **bufend,
4459*007c2a45Smiod 		     unsigned long offset,
4460*007c2a45Smiod 		     varray_t *vp)
44612159047fSniklas {
44622159047fSniklas   unsigned long istr;
44632159047fSniklas   char *str_out;
44642159047fSniklas   vlinks_t *str_link;
44652159047fSniklas 
44662159047fSniklas   str_out = *buf + offset;
44672159047fSniklas 
44682159047fSniklas   istr = 0;
44692159047fSniklas 
44702159047fSniklas   for (str_link = vp->first;
44712159047fSniklas        str_link != (vlinks_t *) NULL;
44722159047fSniklas        str_link = str_link->next)
44732159047fSniklas     {
44742159047fSniklas       unsigned long str_cnt;
44752159047fSniklas 
44762159047fSniklas       if (str_link->next == (vlinks_t *) NULL)
44772159047fSniklas 	str_cnt = vp->objects_last_page;
44782159047fSniklas       else
44792159047fSniklas 	str_cnt = vp->objects_per_page;
44802159047fSniklas 
4481b55d4692Sfgsch       if ((unsigned long)(*bufend - str_out) < str_cnt)
44822159047fSniklas 	str_out = ecoff_add_bytes (buf, bufend, str_out, str_cnt);
44832159047fSniklas 
44842159047fSniklas       memcpy (str_out, str_link->datum->byte, str_cnt);
44852159047fSniklas       str_out += str_cnt;
44862159047fSniklas       istr += str_cnt;
44872159047fSniklas     }
44882159047fSniklas 
44892159047fSniklas   return istr;
44902159047fSniklas }
44912159047fSniklas 
44922159047fSniklas /* Dump out the local strings.  */
44932159047fSniklas 
44942159047fSniklas static unsigned long
ecoff_build_ss(const struct ecoff_debug_swap * backend,char ** buf,char ** bufend,unsigned long offset)4495*007c2a45Smiod ecoff_build_ss (const struct ecoff_debug_swap *backend,
4496*007c2a45Smiod 		char **buf,
4497*007c2a45Smiod 		char **bufend,
4498*007c2a45Smiod 		unsigned long offset)
44992159047fSniklas {
45002159047fSniklas   long iss;
45012159047fSniklas   vlinks_t *file_link;
45022159047fSniklas 
45032159047fSniklas   iss = 0;
45042159047fSniklas 
45052159047fSniklas   for (file_link = file_desc.first;
45062159047fSniklas        file_link != (vlinks_t *) NULL;
45072159047fSniklas        file_link = file_link->next)
45082159047fSniklas     {
45092159047fSniklas       int fil_cnt;
45102159047fSniklas       efdr_t *fil_ptr;
45112159047fSniklas       efdr_t *fil_end;
45122159047fSniklas 
45132159047fSniklas       if (file_link->next == (vlinks_t *) NULL)
45142159047fSniklas 	fil_cnt = file_desc.objects_last_page;
45152159047fSniklas       else
45162159047fSniklas 	fil_cnt = file_desc.objects_per_page;
45172159047fSniklas       fil_ptr = file_link->datum->file;
45182159047fSniklas       fil_end = fil_ptr + fil_cnt;
45192159047fSniklas       for (; fil_ptr < fil_end; fil_ptr++)
45202159047fSniklas 	{
45212159047fSniklas 	  long ss_cnt;
45222159047fSniklas 
45232159047fSniklas 	  fil_ptr->fdr.issBase = iss;
45242159047fSniklas 	  ss_cnt = ecoff_build_strings (buf, bufend, offset + iss,
45252159047fSniklas 					&fil_ptr->strings);
45262159047fSniklas 	  fil_ptr->fdr.cbSs = ss_cnt;
45272159047fSniklas 	  iss += ss_cnt;
45282159047fSniklas 	}
45292159047fSniklas     }
45302159047fSniklas 
45312159047fSniklas   return ecoff_padding_adjust (backend, buf, bufend, offset + iss,
45322159047fSniklas 			       (char **) NULL);
45332159047fSniklas }
45342159047fSniklas 
45352159047fSniklas /* Swap out the file descriptors.  */
45362159047fSniklas 
45372159047fSniklas static unsigned long
ecoff_build_fdr(const struct ecoff_debug_swap * backend,char ** buf,char ** bufend,unsigned long offset)4538*007c2a45Smiod ecoff_build_fdr (const struct ecoff_debug_swap *backend,
4539*007c2a45Smiod 		 char **buf,
4540*007c2a45Smiod 		 char **bufend,
4541*007c2a45Smiod 		 unsigned long offset)
45422159047fSniklas {
45432159047fSniklas   const bfd_size_type external_fdr_size = backend->external_fdr_size;
4544*007c2a45Smiod   void (* const swap_fdr_out) (bfd *, const FDR *, PTR)
45452159047fSniklas     = backend->swap_fdr_out;
45462159047fSniklas   long ifile;
45472159047fSniklas   char *fdr_out;
45482159047fSniklas   vlinks_t *file_link;
45492159047fSniklas 
45502159047fSniklas   ifile = 0;
45512159047fSniklas 
45522159047fSniklas   fdr_out = *buf + offset;
45532159047fSniklas 
45542159047fSniklas   for (file_link = file_desc.first;
45552159047fSniklas        file_link != (vlinks_t *) NULL;
45562159047fSniklas        file_link = file_link->next)
45572159047fSniklas     {
45582159047fSniklas       int fil_cnt;
45592159047fSniklas       efdr_t *fil_ptr;
45602159047fSniklas       efdr_t *fil_end;
45612159047fSniklas 
45622159047fSniklas       if (file_link->next == (vlinks_t *) NULL)
45632159047fSniklas 	fil_cnt = file_desc.objects_last_page;
45642159047fSniklas       else
45652159047fSniklas 	fil_cnt = file_desc.objects_per_page;
45662159047fSniklas       fil_ptr = file_link->datum->file;
45672159047fSniklas       fil_end = fil_ptr + fil_cnt;
45682159047fSniklas       for (; fil_ptr < fil_end; fil_ptr++)
45692159047fSniklas 	{
4570b55d4692Sfgsch 	  if ((bfd_size_type)(*bufend - fdr_out) < external_fdr_size)
45712159047fSniklas 	    fdr_out = ecoff_add_bytes (buf, bufend, fdr_out,
45722159047fSniklas 				       external_fdr_size);
45732159047fSniklas 	  (*swap_fdr_out) (stdoutput, &fil_ptr->fdr, fdr_out);
45742159047fSniklas 	  fdr_out += external_fdr_size;
45752159047fSniklas 	  ++ifile;
45762159047fSniklas 	}
45772159047fSniklas     }
45782159047fSniklas 
45792159047fSniklas   return offset + ifile * external_fdr_size;
45802159047fSniklas }
45812159047fSniklas 
45822159047fSniklas /* Set up the external symbols.  These are supposed to be handled by
45832159047fSniklas    the backend.  This routine just gets the right information and
45842159047fSniklas    calls a backend function to deal with it.  */
45852159047fSniklas 
45862159047fSniklas static void
ecoff_setup_ext(void)4587*007c2a45Smiod ecoff_setup_ext (void)
45882159047fSniklas {
45892159047fSniklas   register symbolS *sym;
45902159047fSniklas 
45912159047fSniklas   for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
45922159047fSniklas     {
4593b305b0f1Sespie       if (symbol_get_obj (sym)->ecoff_symbol == NULL)
45942159047fSniklas 	continue;
45952159047fSniklas 
45962159047fSniklas       /* If this is a local symbol, then force the fields to zero.  */
45972159047fSniklas       if (! S_IS_EXTERNAL (sym)
45982159047fSniklas 	  && ! S_IS_WEAK (sym)
45992159047fSniklas 	  && S_IS_DEFINED (sym))
46002159047fSniklas 	{
4601b305b0f1Sespie 	  struct localsym *lsym;
4602b305b0f1Sespie 
4603b305b0f1Sespie 	  lsym = symbol_get_obj (sym)->ecoff_symbol;
4604b305b0f1Sespie 	  lsym->ecoff_sym.asym.value = 0;
4605b305b0f1Sespie 	  lsym->ecoff_sym.asym.st = (int) st_Nil;
4606b305b0f1Sespie 	  lsym->ecoff_sym.asym.sc = (int) sc_Nil;
4607b305b0f1Sespie 	  lsym->ecoff_sym.asym.index = indexNil;
46082159047fSniklas 	}
46092159047fSniklas 
4610b305b0f1Sespie       obj_ecoff_set_ext (sym, &symbol_get_obj (sym)->ecoff_symbol->ecoff_sym);
46112159047fSniklas     }
46122159047fSniklas }
46132159047fSniklas 
46142159047fSniklas /* Build the ECOFF debugging information.  */
46152159047fSniklas 
46162159047fSniklas unsigned long
ecoff_build_debug(HDRR * hdr,char ** bufp,const struct ecoff_debug_swap * backend)4617*007c2a45Smiod ecoff_build_debug (HDRR *hdr,
4618*007c2a45Smiod 		   char **bufp,
4619*007c2a45Smiod 		   const struct ecoff_debug_swap *backend)
46202159047fSniklas {
46212159047fSniklas   const bfd_size_type external_pdr_size = backend->external_pdr_size;
46222159047fSniklas   tag_t *ptag;
46232159047fSniklas   tag_t *ptag_next;
46242159047fSniklas   efdr_t *fil_ptr;
46252159047fSniklas   int end_warning;
46262159047fSniklas   efdr_t *hold_file_ptr;
46272159047fSniklas   proc_t *hold_proc_ptr;
46282159047fSniklas   symbolS *sym;
46292159047fSniklas   char *buf;
46302159047fSniklas   char *bufend;
46312159047fSniklas   unsigned long offset;
46322159047fSniklas 
46332159047fSniklas   /* Make sure we have a file.  */
46342159047fSniklas   if (first_file == (efdr_t *) NULL)
46352159047fSniklas     add_file ((const char *) NULL, 0, 1);
46362159047fSniklas 
46372159047fSniklas   /* Handle any top level tags.  */
46382159047fSniklas   for (ptag = top_tag_head->first_tag;
46392159047fSniklas        ptag != (tag_t *) NULL;
46402159047fSniklas        ptag = ptag_next)
46412159047fSniklas     {
46422159047fSniklas       if (ptag->forward_ref != (forward_t *) NULL)
46432159047fSniklas 	add_unknown_tag (ptag);
46442159047fSniklas 
46452159047fSniklas       ptag_next = ptag->same_block;
46462159047fSniklas       ptag->hash_ptr->tag_ptr = ptag->same_name;
46472159047fSniklas       free_tag (ptag);
46482159047fSniklas     }
46492159047fSniklas 
46502159047fSniklas   free_thead (top_tag_head);
46512159047fSniklas 
46522159047fSniklas   /* Look through the symbols.  Add debugging information for each
46532159047fSniklas      symbol that has not already received it.  */
46542159047fSniklas   hold_file_ptr = cur_file_ptr;
46552159047fSniklas   hold_proc_ptr = cur_proc_ptr;
46562159047fSniklas   cur_proc_ptr = (proc_t *) NULL;
46572159047fSniklas   for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
46582159047fSniklas     {
4659b305b0f1Sespie       if (symbol_get_obj (sym)->ecoff_symbol != NULL
4660b305b0f1Sespie 	  || symbol_get_obj (sym)->ecoff_file == (efdr_t *) NULL
4661b305b0f1Sespie 	  || (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0)
46622159047fSniklas 	continue;
46632159047fSniklas 
4664b305b0f1Sespie       cur_file_ptr = symbol_get_obj (sym)->ecoff_file;
46652159047fSniklas       add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym,
4666191aa565Sniklas 			(bfd_vma) 0, S_GET_VALUE (sym), indexNil);
46672159047fSniklas     }
46682159047fSniklas   cur_proc_ptr = hold_proc_ptr;
46692159047fSniklas   cur_file_ptr = hold_file_ptr;
46702159047fSniklas 
46712159047fSniklas   /* Output an ending symbol for all the files.  We have to do this
46722159047fSniklas      here for the last file, so we may as well do it for all of the
46732159047fSniklas      files.  */
46742159047fSniklas   end_warning = 0;
46752159047fSniklas   for (fil_ptr = first_file;
46762159047fSniklas        fil_ptr != (efdr_t *) NULL;
46772159047fSniklas        fil_ptr = fil_ptr->next_file)
46782159047fSniklas     {
46792159047fSniklas       cur_file_ptr = fil_ptr;
46802159047fSniklas       while (cur_file_ptr->cur_scope != (scope_t *) NULL
46812159047fSniklas 	     && cur_file_ptr->cur_scope->prev != (scope_t *) NULL)
46822159047fSniklas 	{
46832159047fSniklas 	  cur_file_ptr->cur_scope = cur_file_ptr->cur_scope->prev;
46842159047fSniklas 	  if (! end_warning && ! cur_file_ptr->fake)
46852159047fSniklas 	    {
4686c074d1c9Sdrahn 	      as_warn (_("missing .end or .bend at end of file"));
46872159047fSniklas 	      end_warning = 1;
46882159047fSniklas 	    }
46892159047fSniklas 	}
46902159047fSniklas       if (cur_file_ptr->cur_scope != (scope_t *) NULL)
46912159047fSniklas 	(void) add_ecoff_symbol ((const char *) NULL,
46922159047fSniklas 				 st_End, sc_Text,
46932159047fSniklas 				 (symbolS *) NULL,
4694191aa565Sniklas 				 (bfd_vma) 0,
46952159047fSniklas 				 (symint_t) 0,
46962159047fSniklas 				 (symint_t) 0);
46972159047fSniklas     }
46982159047fSniklas 
46992159047fSniklas   /* Build the symbolic information.  */
47002159047fSniklas   offset = 0;
47012159047fSniklas   buf = xmalloc (PAGE_SIZE);
47022159047fSniklas   bufend = buf + PAGE_SIZE;
47032159047fSniklas 
47042159047fSniklas   /* Build the line number information.  */
47052159047fSniklas   hdr->cbLineOffset = offset;
47062159047fSniklas   offset = ecoff_build_lineno (backend, &buf, &bufend, offset,
47072159047fSniklas 			       &hdr->ilineMax);
47082159047fSniklas   hdr->cbLine = offset - hdr->cbLineOffset;
47092159047fSniklas 
47102159047fSniklas   /* We don't use dense numbers at all.  */
47112159047fSniklas   hdr->idnMax = 0;
47122159047fSniklas   hdr->cbDnOffset = 0;
47132159047fSniklas 
47142159047fSniklas   /* We can't build the PDR table until we have built the symbols,
47152159047fSniklas      because a PDR contains a symbol index.  However, we set aside
47162159047fSniklas      space at this point.  */
47172159047fSniklas   hdr->ipdMax = proc_cnt;
47182159047fSniklas   hdr->cbPdOffset = offset;
4719b55d4692Sfgsch   if ((bfd_size_type)(bufend - (buf + offset)) < proc_cnt * external_pdr_size)
47202159047fSniklas     (void) ecoff_add_bytes (&buf, &bufend, buf + offset,
47212159047fSniklas 			    proc_cnt * external_pdr_size);
47222159047fSniklas   offset += proc_cnt * external_pdr_size;
47232159047fSniklas 
47242159047fSniklas   /* Build the local symbols.  */
47252159047fSniklas   hdr->cbSymOffset = offset;
47262159047fSniklas   offset = ecoff_build_symbols (backend, &buf, &bufend, offset);
47272159047fSniklas   hdr->isymMax = (offset - hdr->cbSymOffset) / backend->external_sym_size;
47282159047fSniklas 
47292159047fSniklas   /* Building the symbols initializes the symbol index in the PDR's.
47302159047fSniklas      Now we can swap out the PDR's.  */
47312159047fSniklas   (void) ecoff_build_procs (backend, &buf, &bufend, hdr->cbPdOffset);
47322159047fSniklas 
47332159047fSniklas   /* We don't use optimization symbols.  */
47342159047fSniklas   hdr->ioptMax = 0;
47352159047fSniklas   hdr->cbOptOffset = 0;
47362159047fSniklas 
47372159047fSniklas   /* Swap out the auxiliary type information.  */
47382159047fSniklas   hdr->cbAuxOffset = offset;
47392159047fSniklas   offset = ecoff_build_aux (backend, &buf, &bufend, offset);
47402159047fSniklas   hdr->iauxMax = (offset - hdr->cbAuxOffset) / sizeof (union aux_ext);
47412159047fSniklas 
47422159047fSniklas   /* Copy out the local strings.  */
47432159047fSniklas   hdr->cbSsOffset = offset;
47442159047fSniklas   offset = ecoff_build_ss (backend, &buf, &bufend, offset);
47452159047fSniklas   hdr->issMax = offset - hdr->cbSsOffset;
47462159047fSniklas 
47472159047fSniklas   /* We don't use relative file descriptors.  */
47482159047fSniklas   hdr->crfd = 0;
47492159047fSniklas   hdr->cbRfdOffset = 0;
47502159047fSniklas 
47512159047fSniklas   /* Swap out the file descriptors.  */
47522159047fSniklas   hdr->cbFdOffset = offset;
47532159047fSniklas   offset = ecoff_build_fdr (backend, &buf, &bufend, offset);
47542159047fSniklas   hdr->ifdMax = (offset - hdr->cbFdOffset) / backend->external_fdr_size;
47552159047fSniklas 
47562159047fSniklas   /* Set up the external symbols, which are handled by the BFD back
47572159047fSniklas      end.  */
47582159047fSniklas   hdr->issExtMax = 0;
47592159047fSniklas   hdr->cbSsExtOffset = 0;
47602159047fSniklas   hdr->iextMax = 0;
47612159047fSniklas   hdr->cbExtOffset = 0;
47622159047fSniklas   ecoff_setup_ext ();
47632159047fSniklas 
47642159047fSniklas   know ((offset & (backend->debug_align - 1)) == 0);
47652159047fSniklas 
47662159047fSniklas   /* FIXME: This value should be determined from the .verstamp directive,
47672159047fSniklas      with reasonable defaults in config files.  */
47682159047fSniklas #ifdef TC_ALPHA
47692159047fSniklas   hdr->vstamp = 0x030b;
47702159047fSniklas #else
47712159047fSniklas   hdr->vstamp = 0x020b;
47722159047fSniklas #endif
47732159047fSniklas 
47742159047fSniklas   *bufp = buf;
47752159047fSniklas   return offset;
47762159047fSniklas }
47772159047fSniklas 
47782159047fSniklas /* Allocate a cluster of pages.  */
47792159047fSniklas 
47802159047fSniklas #ifndef MALLOC_CHECK
47812159047fSniklas 
4782b305b0f1Sespie static page_type *
allocate_cluster(unsigned long npages)4783*007c2a45Smiod allocate_cluster (unsigned long npages)
47842159047fSniklas {
4785b305b0f1Sespie   register page_type *value = (page_type *) xmalloc (npages * PAGE_USIZE);
47862159047fSniklas 
47872159047fSniklas #ifdef ECOFF_DEBUG
47882159047fSniklas   if (debug > 3)
47892159047fSniklas     fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
47902159047fSniklas #endif
47912159047fSniklas 
47922159047fSniklas   memset (value, 0, npages * PAGE_USIZE);
47932159047fSniklas 
47942159047fSniklas   return value;
47952159047fSniklas }
47962159047fSniklas 
4797b305b0f1Sespie static page_type *cluster_ptr = NULL;
47982159047fSniklas static unsigned long pages_left = 0;
47992159047fSniklas 
48002159047fSniklas #endif /* MALLOC_CHECK */
48012159047fSniklas 
48022159047fSniklas /* Allocate one page (which is initialized to 0).  */
48032159047fSniklas 
4804b305b0f1Sespie static page_type *
allocate_page(void)4805*007c2a45Smiod allocate_page (void)
48062159047fSniklas {
48072159047fSniklas #ifndef MALLOC_CHECK
48082159047fSniklas 
48092159047fSniklas   if (pages_left == 0)
48102159047fSniklas     {
48112159047fSniklas       pages_left = MAX_CLUSTER_PAGES;
48122159047fSniklas       cluster_ptr = allocate_cluster (pages_left);
48132159047fSniklas     }
48142159047fSniklas 
48152159047fSniklas   pages_left--;
48162159047fSniklas   return cluster_ptr++;
48172159047fSniklas 
48182159047fSniklas #else /* MALLOC_CHECK */
48192159047fSniklas 
4820b305b0f1Sespie   page_type *ptr;
48212159047fSniklas 
48222159047fSniklas   ptr = xmalloc (PAGE_USIZE);
48232159047fSniklas   memset (ptr, 0, PAGE_USIZE);
48242159047fSniklas   return ptr;
48252159047fSniklas 
48262159047fSniklas #endif /* MALLOC_CHECK */
48272159047fSniklas }
48282159047fSniklas 
48292159047fSniklas /* Allocate scoping information.  */
48302159047fSniklas 
48312159047fSniklas static scope_t *
allocate_scope(void)4832*007c2a45Smiod allocate_scope (void)
48332159047fSniklas {
48342159047fSniklas   register scope_t *ptr;
48352159047fSniklas   static scope_t initial_scope;
48362159047fSniklas 
48372159047fSniklas #ifndef MALLOC_CHECK
48382159047fSniklas 
48392159047fSniklas   ptr = alloc_counts[(int) alloc_type_scope].free_list.f_scope;
48402159047fSniklas   if (ptr != (scope_t *) NULL)
48412159047fSniklas     alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr->free;
48422159047fSniklas   else
48432159047fSniklas     {
48442159047fSniklas       register int unallocated	= alloc_counts[(int) alloc_type_scope].unallocated;
4845b305b0f1Sespie       register page_type *cur_page	= alloc_counts[(int) alloc_type_scope].cur_page;
48462159047fSniklas 
48472159047fSniklas       if (unallocated == 0)
48482159047fSniklas 	{
48492159047fSniklas 	  unallocated = PAGE_SIZE / sizeof (scope_t);
48502159047fSniklas 	  alloc_counts[(int) alloc_type_scope].cur_page = cur_page = allocate_page ();
48512159047fSniklas 	  alloc_counts[(int) alloc_type_scope].total_pages++;
48522159047fSniklas 	}
48532159047fSniklas 
48542159047fSniklas       ptr = &cur_page->scope[--unallocated];
48552159047fSniklas       alloc_counts[(int) alloc_type_scope].unallocated = unallocated;
48562159047fSniklas     }
48572159047fSniklas 
48582159047fSniklas #else
48592159047fSniklas 
48602159047fSniklas   ptr = (scope_t *) xmalloc (sizeof (scope_t));
48612159047fSniklas 
48622159047fSniklas #endif
48632159047fSniklas 
48642159047fSniklas   alloc_counts[(int) alloc_type_scope].total_alloc++;
48652159047fSniklas   *ptr = initial_scope;
48662159047fSniklas   return ptr;
48672159047fSniklas }
48682159047fSniklas 
48692159047fSniklas /* Free scoping information.  */
48702159047fSniklas 
48712159047fSniklas static void
free_scope(scope_t * ptr)4872*007c2a45Smiod free_scope (scope_t *ptr)
48732159047fSniklas {
48742159047fSniklas   alloc_counts[(int) alloc_type_scope].total_free++;
48752159047fSniklas 
48762159047fSniklas #ifndef MALLOC_CHECK
48772159047fSniklas   ptr->free = alloc_counts[(int) alloc_type_scope].free_list.f_scope;
48782159047fSniklas   alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr;
48792159047fSniklas #else
48802159047fSniklas   free ((PTR) ptr);
48812159047fSniklas #endif
48822159047fSniklas }
48832159047fSniklas 
48842159047fSniklas /* Allocate links for pages in a virtual array.  */
48852159047fSniklas 
48862159047fSniklas static vlinks_t *
allocate_vlinks(void)4887*007c2a45Smiod allocate_vlinks (void)
48882159047fSniklas {
48892159047fSniklas   register vlinks_t *ptr;
48902159047fSniklas   static vlinks_t initial_vlinks;
48912159047fSniklas 
48922159047fSniklas #ifndef MALLOC_CHECK
48932159047fSniklas 
48942159047fSniklas   register int unallocated = alloc_counts[(int) alloc_type_vlinks].unallocated;
4895b305b0f1Sespie   register page_type *cur_page = alloc_counts[(int) alloc_type_vlinks].cur_page;
48962159047fSniklas 
48972159047fSniklas   if (unallocated == 0)
48982159047fSniklas     {
48992159047fSniklas       unallocated = PAGE_SIZE / sizeof (vlinks_t);
49002159047fSniklas       alloc_counts[(int) alloc_type_vlinks].cur_page = cur_page = allocate_page ();
49012159047fSniklas       alloc_counts[(int) alloc_type_vlinks].total_pages++;
49022159047fSniklas     }
49032159047fSniklas 
49042159047fSniklas   ptr = &cur_page->vlinks[--unallocated];
49052159047fSniklas   alloc_counts[(int) alloc_type_vlinks].unallocated = unallocated;
49062159047fSniklas 
49072159047fSniklas #else
49082159047fSniklas 
49092159047fSniklas   ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t));
49102159047fSniklas 
49112159047fSniklas #endif
49122159047fSniklas 
49132159047fSniklas   alloc_counts[(int) alloc_type_vlinks].total_alloc++;
49142159047fSniklas   *ptr = initial_vlinks;
49152159047fSniklas   return ptr;
49162159047fSniklas }
49172159047fSniklas 
49182159047fSniklas /* Allocate string hash buckets.  */
49192159047fSniklas 
49202159047fSniklas static shash_t *
allocate_shash(void)4921*007c2a45Smiod allocate_shash (void)
49222159047fSniklas {
49232159047fSniklas   register shash_t *ptr;
49242159047fSniklas   static shash_t initial_shash;
49252159047fSniklas 
49262159047fSniklas #ifndef MALLOC_CHECK
49272159047fSniklas 
49282159047fSniklas   register int unallocated = alloc_counts[(int) alloc_type_shash].unallocated;
4929b305b0f1Sespie   register page_type *cur_page = alloc_counts[(int) alloc_type_shash].cur_page;
49302159047fSniklas 
49312159047fSniklas   if (unallocated == 0)
49322159047fSniklas     {
49332159047fSniklas       unallocated = PAGE_SIZE / sizeof (shash_t);
49342159047fSniklas       alloc_counts[(int) alloc_type_shash].cur_page = cur_page = allocate_page ();
49352159047fSniklas       alloc_counts[(int) alloc_type_shash].total_pages++;
49362159047fSniklas     }
49372159047fSniklas 
49382159047fSniklas   ptr = &cur_page->shash[--unallocated];
49392159047fSniklas   alloc_counts[(int) alloc_type_shash].unallocated = unallocated;
49402159047fSniklas 
49412159047fSniklas #else
49422159047fSniklas 
49432159047fSniklas   ptr = (shash_t *) xmalloc (sizeof (shash_t));
49442159047fSniklas 
49452159047fSniklas #endif
49462159047fSniklas 
49472159047fSniklas   alloc_counts[(int) alloc_type_shash].total_alloc++;
49482159047fSniklas   *ptr = initial_shash;
49492159047fSniklas   return ptr;
49502159047fSniklas }
49512159047fSniklas 
49522159047fSniklas /* Allocate type hash buckets.  */
49532159047fSniklas 
49542159047fSniklas static thash_t *
allocate_thash(void)4955*007c2a45Smiod allocate_thash (void)
49562159047fSniklas {
49572159047fSniklas   register thash_t *ptr;
49582159047fSniklas   static thash_t initial_thash;
49592159047fSniklas 
49602159047fSniklas #ifndef MALLOC_CHECK
49612159047fSniklas 
49622159047fSniklas   register int unallocated = alloc_counts[(int) alloc_type_thash].unallocated;
4963b305b0f1Sespie   register page_type *cur_page = alloc_counts[(int) alloc_type_thash].cur_page;
49642159047fSniklas 
49652159047fSniklas   if (unallocated == 0)
49662159047fSniklas     {
49672159047fSniklas       unallocated = PAGE_SIZE / sizeof (thash_t);
49682159047fSniklas       alloc_counts[(int) alloc_type_thash].cur_page = cur_page = allocate_page ();
49692159047fSniklas       alloc_counts[(int) alloc_type_thash].total_pages++;
49702159047fSniklas     }
49712159047fSniklas 
49722159047fSniklas   ptr = &cur_page->thash[--unallocated];
49732159047fSniklas   alloc_counts[(int) alloc_type_thash].unallocated = unallocated;
49742159047fSniklas 
49752159047fSniklas #else
49762159047fSniklas 
49772159047fSniklas   ptr = (thash_t *) xmalloc (sizeof (thash_t));
49782159047fSniklas 
49792159047fSniklas #endif
49802159047fSniklas 
49812159047fSniklas   alloc_counts[(int) alloc_type_thash].total_alloc++;
49822159047fSniklas   *ptr = initial_thash;
49832159047fSniklas   return ptr;
49842159047fSniklas }
49852159047fSniklas 
49862159047fSniklas /* Allocate structure, union, or enum tag information.  */
49872159047fSniklas 
49882159047fSniklas static tag_t *
allocate_tag(void)4989*007c2a45Smiod allocate_tag (void)
49902159047fSniklas {
49912159047fSniklas   register tag_t *ptr;
49922159047fSniklas   static tag_t initial_tag;
49932159047fSniklas 
49942159047fSniklas #ifndef MALLOC_CHECK
49952159047fSniklas 
49962159047fSniklas   ptr = alloc_counts[(int) alloc_type_tag].free_list.f_tag;
49972159047fSniklas   if (ptr != (tag_t *) NULL)
49982159047fSniklas     alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr->free;
49992159047fSniklas   else
50002159047fSniklas     {
50012159047fSniklas       register int unallocated = alloc_counts[(int) alloc_type_tag].unallocated;
5002b305b0f1Sespie       register page_type *cur_page = alloc_counts[(int) alloc_type_tag].cur_page;
50032159047fSniklas 
50042159047fSniklas       if (unallocated == 0)
50052159047fSniklas 	{
50062159047fSniklas 	  unallocated = PAGE_SIZE / sizeof (tag_t);
50072159047fSniklas 	  alloc_counts[(int) alloc_type_tag].cur_page = cur_page = allocate_page ();
50082159047fSniklas 	  alloc_counts[(int) alloc_type_tag].total_pages++;
50092159047fSniklas 	}
50102159047fSniklas 
50112159047fSniklas       ptr = &cur_page->tag[--unallocated];
50122159047fSniklas       alloc_counts[(int) alloc_type_tag].unallocated = unallocated;
50132159047fSniklas     }
50142159047fSniklas 
50152159047fSniklas #else
50162159047fSniklas 
50172159047fSniklas   ptr = (tag_t *) xmalloc (sizeof (tag_t));
50182159047fSniklas 
50192159047fSniklas #endif
50202159047fSniklas 
50212159047fSniklas   alloc_counts[(int) alloc_type_tag].total_alloc++;
50222159047fSniklas   *ptr = initial_tag;
50232159047fSniklas   return ptr;
50242159047fSniklas }
50252159047fSniklas 
50262159047fSniklas /* Free scoping information.  */
50272159047fSniklas 
50282159047fSniklas static void
free_tag(tag_t * ptr)5029*007c2a45Smiod free_tag (tag_t *ptr)
50302159047fSniklas {
50312159047fSniklas   alloc_counts[(int) alloc_type_tag].total_free++;
50322159047fSniklas 
50332159047fSniklas #ifndef MALLOC_CHECK
50342159047fSniklas   ptr->free = alloc_counts[(int) alloc_type_tag].free_list.f_tag;
50352159047fSniklas   alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr;
50362159047fSniklas #else
50372159047fSniklas   free ((PTR_T) ptr);
50382159047fSniklas #endif
50392159047fSniklas }
50402159047fSniklas 
50412159047fSniklas /* Allocate forward reference to a yet unknown tag.  */
50422159047fSniklas 
50432159047fSniklas static forward_t *
allocate_forward(void)5044*007c2a45Smiod allocate_forward (void)
50452159047fSniklas {
50462159047fSniklas   register forward_t *ptr;
50472159047fSniklas   static forward_t initial_forward;
50482159047fSniklas 
50492159047fSniklas #ifndef MALLOC_CHECK
50502159047fSniklas 
50512159047fSniklas   register int unallocated = alloc_counts[(int) alloc_type_forward].unallocated;
5052b305b0f1Sespie   register page_type *cur_page = alloc_counts[(int) alloc_type_forward].cur_page;
50532159047fSniklas 
50542159047fSniklas   if (unallocated == 0)
50552159047fSniklas     {
50562159047fSniklas       unallocated = PAGE_SIZE / sizeof (forward_t);
50572159047fSniklas       alloc_counts[(int) alloc_type_forward].cur_page = cur_page = allocate_page ();
50582159047fSniklas       alloc_counts[(int) alloc_type_forward].total_pages++;
50592159047fSniklas     }
50602159047fSniklas 
50612159047fSniklas   ptr = &cur_page->forward[--unallocated];
50622159047fSniklas   alloc_counts[(int) alloc_type_forward].unallocated = unallocated;
50632159047fSniklas 
50642159047fSniklas #else
50652159047fSniklas 
50662159047fSniklas   ptr = (forward_t *) xmalloc (sizeof (forward_t));
50672159047fSniklas 
50682159047fSniklas #endif
50692159047fSniklas 
50702159047fSniklas   alloc_counts[(int) alloc_type_forward].total_alloc++;
50712159047fSniklas   *ptr = initial_forward;
50722159047fSniklas   return ptr;
50732159047fSniklas }
50742159047fSniklas 
50752159047fSniklas /* Allocate head of type hash list.  */
50762159047fSniklas 
50772159047fSniklas static thead_t *
allocate_thead(void)5078*007c2a45Smiod allocate_thead (void)
50792159047fSniklas {
50802159047fSniklas   register thead_t *ptr;
50812159047fSniklas   static thead_t initial_thead;
50822159047fSniklas 
50832159047fSniklas #ifndef MALLOC_CHECK
50842159047fSniklas 
50852159047fSniklas   ptr = alloc_counts[(int) alloc_type_thead].free_list.f_thead;
50862159047fSniklas   if (ptr != (thead_t *) NULL)
50872159047fSniklas     alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr->free;
50882159047fSniklas   else
50892159047fSniklas     {
50902159047fSniklas       register int unallocated = alloc_counts[(int) alloc_type_thead].unallocated;
5091b305b0f1Sespie       register page_type *cur_page = alloc_counts[(int) alloc_type_thead].cur_page;
50922159047fSniklas 
50932159047fSniklas       if (unallocated == 0)
50942159047fSniklas 	{
50952159047fSniklas 	  unallocated = PAGE_SIZE / sizeof (thead_t);
50962159047fSniklas 	  alloc_counts[(int) alloc_type_thead].cur_page = cur_page = allocate_page ();
50972159047fSniklas 	  alloc_counts[(int) alloc_type_thead].total_pages++;
50982159047fSniklas 	}
50992159047fSniklas 
51002159047fSniklas       ptr = &cur_page->thead[--unallocated];
51012159047fSniklas       alloc_counts[(int) alloc_type_thead].unallocated = unallocated;
51022159047fSniklas     }
51032159047fSniklas 
51042159047fSniklas #else
51052159047fSniklas 
51062159047fSniklas   ptr = (thead_t *) xmalloc (sizeof (thead_t));
51072159047fSniklas 
51082159047fSniklas #endif
51092159047fSniklas 
51102159047fSniklas   alloc_counts[(int) alloc_type_thead].total_alloc++;
51112159047fSniklas   *ptr = initial_thead;
51122159047fSniklas   return ptr;
51132159047fSniklas }
51142159047fSniklas 
51152159047fSniklas /* Free scoping information.  */
51162159047fSniklas 
51172159047fSniklas static void
free_thead(thead_t * ptr)5118*007c2a45Smiod free_thead (thead_t *ptr)
51192159047fSniklas {
51202159047fSniklas   alloc_counts[(int) alloc_type_thead].total_free++;
51212159047fSniklas 
51222159047fSniklas #ifndef MALLOC_CHECK
51232159047fSniklas   ptr->free = (thead_t *) alloc_counts[(int) alloc_type_thead].free_list.f_thead;
51242159047fSniklas   alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr;
51252159047fSniklas #else
51262159047fSniklas   free ((PTR_T) ptr);
51272159047fSniklas #endif
51282159047fSniklas }
51292159047fSniklas 
51302159047fSniklas static lineno_list_t *
allocate_lineno_list(void)5131*007c2a45Smiod allocate_lineno_list (void)
51322159047fSniklas {
51332159047fSniklas   register lineno_list_t *ptr;
51342159047fSniklas   static lineno_list_t initial_lineno_list;
51352159047fSniklas 
51362159047fSniklas #ifndef MALLOC_CHECK
51372159047fSniklas 
51382159047fSniklas   register int unallocated = alloc_counts[(int) alloc_type_lineno].unallocated;
5139b305b0f1Sespie   register page_type *cur_page = alloc_counts[(int) alloc_type_lineno].cur_page;
51402159047fSniklas 
51412159047fSniklas   if (unallocated == 0)
51422159047fSniklas     {
51432159047fSniklas       unallocated = PAGE_SIZE / sizeof (lineno_list_t);
51442159047fSniklas       alloc_counts[(int) alloc_type_lineno].cur_page = cur_page = allocate_page ();
51452159047fSniklas       alloc_counts[(int) alloc_type_lineno].total_pages++;
51462159047fSniklas     }
51472159047fSniklas 
51482159047fSniklas   ptr = &cur_page->lineno[--unallocated];
51492159047fSniklas   alloc_counts[(int) alloc_type_lineno].unallocated = unallocated;
51502159047fSniklas 
51512159047fSniklas #else
51522159047fSniklas 
51532159047fSniklas   ptr = (lineno_list_t *) xmalloc (sizeof (lineno_list_t));
51542159047fSniklas 
51552159047fSniklas #endif
51562159047fSniklas 
51572159047fSniklas   alloc_counts[(int) alloc_type_lineno].total_alloc++;
51582159047fSniklas   *ptr = initial_lineno_list;
51592159047fSniklas   return ptr;
51602159047fSniklas }
51612159047fSniklas 
51622159047fSniklas void
ecoff_set_gp_prolog_size(int sz)5163*007c2a45Smiod ecoff_set_gp_prolog_size (int sz)
51642159047fSniklas {
51652159047fSniklas   if (cur_proc_ptr == 0)
51662159047fSniklas     return;
51672159047fSniklas 
51682159047fSniklas   cur_proc_ptr->pdr.gp_prologue = sz;
51692159047fSniklas   if (cur_proc_ptr->pdr.gp_prologue != sz)
51702159047fSniklas     {
5171b305b0f1Sespie       as_warn (_("GP prologue size exceeds field size, using 0 instead"));
51722159047fSniklas       cur_proc_ptr->pdr.gp_prologue = 0;
51732159047fSniklas     }
51742159047fSniklas 
51752159047fSniklas   cur_proc_ptr->pdr.gp_used = 1;
51762159047fSniklas }
51772159047fSniklas 
51782159047fSniklas int
ecoff_no_current_file(void)5179*007c2a45Smiod ecoff_no_current_file (void)
51802159047fSniklas {
51812159047fSniklas   return cur_file_ptr == (efdr_t *) NULL;
51822159047fSniklas }
51832159047fSniklas 
51842159047fSniklas void
ecoff_generate_asm_lineno(void)5185*007c2a45Smiod ecoff_generate_asm_lineno (void)
51862159047fSniklas {
5187b305b0f1Sespie   unsigned int lineno;
5188b305b0f1Sespie   char *filename;
51892159047fSniklas   lineno_list_t *list;
51902159047fSniklas 
5191b305b0f1Sespie   as_where (&filename, &lineno);
51922159047fSniklas 
5193b305b0f1Sespie   if (current_stabs_filename == (char *) NULL
5194b305b0f1Sespie       || strcmp (current_stabs_filename, filename))
51952159047fSniklas     add_file (filename, 0, 1);
51962159047fSniklas 
51972159047fSniklas   list = allocate_lineno_list ();
51982159047fSniklas 
51992159047fSniklas   list->next = (lineno_list_t *) NULL;
52002159047fSniklas   list->file = cur_file_ptr;
52012159047fSniklas   list->proc = cur_proc_ptr;
52022159047fSniklas   list->frag = frag_now;
52032159047fSniklas   list->paddr = frag_now_fix ();
52042159047fSniklas   list->lineno = lineno;
52052159047fSniklas 
52060c6d0228Sniklas   /* We don't want to merge files which have line numbers.  */
52070c6d0228Sniklas   cur_file_ptr->fdr.fMerge = 0;
52080c6d0228Sniklas 
52092159047fSniklas   /* A .loc directive will sometimes appear before a .ent directive,
52102159047fSniklas      which means that cur_proc_ptr will be NULL here.  Arrange to
52112159047fSniklas      patch this up.  */
52122159047fSniklas   if (cur_proc_ptr == (proc_t *) NULL)
52132159047fSniklas     {
52142159047fSniklas       lineno_list_t **pl;
52152159047fSniklas 
52162159047fSniklas       pl = &noproc_lineno;
52172159047fSniklas       while (*pl != (lineno_list_t *) NULL)
52182159047fSniklas 	pl = &(*pl)->next;
52192159047fSniklas       *pl = list;
52202159047fSniklas     }
52212159047fSniklas   else
52222159047fSniklas     {
52230c6d0228Sniklas       last_lineno = list;
52242159047fSniklas       *last_lineno_ptr = list;
52252159047fSniklas       last_lineno_ptr = &list->next;
52262159047fSniklas     }
52272159047fSniklas }
52282159047fSniklas 
5229b305b0f1Sespie #else
5230b305b0f1Sespie 
52312159047fSniklas void
ecoff_generate_asm_lineno(void)5232*007c2a45Smiod ecoff_generate_asm_lineno (void)
52332159047fSniklas {
52342159047fSniklas }
52352159047fSniklas 
52362159047fSniklas #endif /* ECOFF_DEBUGGING */
5237