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