Rev 5222 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5222 | serge | 1 | /* ECOFF debugging support. |
6324 | serge | 2 | Copyright (C) 1993-2015 Free Software Foundation, Inc. |
5222 | serge | 3 | Contributed by Cygnus Support. |
4 | This file was put together by Ian Lance Taylor |
||
5 | good deal of it comes directly from mips-tfile.c, by Michael |
||
6 | Meissner |
||
7 | |||
8 | This file is part of GAS. |
||
9 | |||
10 | GAS is free software; you can redistribute it and/or modify |
||
11 | it under the terms of the GNU General Public License as published by |
||
12 | the Free Software Foundation; either version 3, or (at your option) |
||
13 | any later version. |
||
14 | |||
15 | GAS is distributed in the hope that it will be useful, |
||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 | GNU General Public License for more details. |
||
19 | |||
20 | You should have received a copy of the GNU General Public License |
||
21 | along with GAS; see the file COPYING. If not, write to the Free |
||
22 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
||
23 | 02110-1301, USA. */ |
||
24 | |||
25 | #include "as.h" |
||
26 | |||
27 | /* This file is compiled conditionally for those targets which use |
||
28 | ECOFF debugging information (e.g., MIPS ELF, Alpha ECOFF). */ |
||
29 | |||
30 | #include "ecoff.h" |
||
31 | |||
32 | #ifdef ECOFF_DEBUGGING |
||
33 | |||
34 | #include "coff/internal.h" |
||
35 | #include "coff/symconst.h" |
||
36 | #include "aout/stab_gnu.h" |
||
37 | #include "filenames.h" |
||
38 | #include "safe-ctype.h" |
||
39 | |||
40 | /* Why isn't this in coff/sym.h? */ |
||
41 | #define ST_RFDESCAPE 0xfff |
||
42 | |||
43 | /* This file constructs the information used by the ECOFF debugging |
||
44 | format. It just builds a large block of data. |
||
45 | |||
46 | We support both ECOFF style debugging and stabs debugging (the |
||
47 | stabs symbols are encapsulated in ECOFF symbols). This should let |
||
48 | us handle anything the compiler might throw at us. */ |
||
49 | |||
50 | /* Here is a brief description of the MIPS ECOFF symbol table, by |
||
51 | Michael Meissner. The MIPS symbol table has the following pieces: |
||
52 | |||
53 | Symbolic Header |
||
54 | | |
||
55 | +-- Auxiliary Symbols |
||
56 | | |
||
57 | +-- Dense number table |
||
58 | | |
||
59 | +-- Optimizer Symbols |
||
60 | | |
||
61 | +-- External Strings |
||
62 | | |
||
63 | +-- External Symbols |
||
64 | | |
||
65 | +-- Relative file descriptors |
||
66 | | |
||
67 | +-- File table |
||
68 | | |
||
69 | +-- Procedure table |
||
70 | | |
||
71 | +-- Line number table |
||
72 | | |
||
73 | +-- Local Strings |
||
74 | | |
||
75 | +-- Local Symbols |
||
76 | |||
77 | The symbolic header points to each of the other tables, and also |
||
78 | contains the number of entries. It also contains a magic number |
||
79 | and MIPS compiler version number, such as 2.0. |
||
80 | |||
81 | The auxiliary table is a series of 32 bit integers, that are |
||
82 | referenced as needed from the local symbol table. Unlike standard |
||
83 | COFF, the aux. information does not follow the symbol that uses |
||
84 | it, but rather is a separate table. In theory, this would allow |
||
85 | the MIPS compilers to collapse duplicate aux. entries, but I've not |
||
86 | noticed this happening with the 1.31 compiler suite. The different |
||
87 | types of aux. entries are: |
||
88 | |||
89 | 1) dnLow: Low bound on array dimension. |
||
90 | |||
91 | 2) dnHigh: High bound on array dimension. |
||
92 | |||
93 | 3) isym: Index to the local symbol which is the start of the |
||
94 | function for the end of function first aux. entry. |
||
95 | |||
96 | 4) width: Width of structures and bitfields. |
||
97 | |||
98 | 5) count: Count of ranges for variant part. |
||
99 | |||
100 | 6) rndx: A relative index into the symbol table. The relative |
||
101 | index field has two parts: rfd which is a pointer into the |
||
102 | relative file index table or ST_RFDESCAPE which says the next |
||
103 | aux. entry is the file number, and index: which is the pointer |
||
104 | into the local symbol within a given file table. This is for |
||
105 | things like references to types defined in another file. |
||
106 | |||
107 | 7) Type information: This is like the COFF type bits, except it |
||
108 | is 32 bits instead of 16; they still have room to add new |
||
109 | basic types; and they can handle more than 6 levels of array, |
||
110 | pointer, function, etc. Each type information field contains |
||
111 | the following structure members: |
||
112 | |||
113 | a) fBitfield: a bit that says this is a bitfield, and the |
||
114 | size in bits follows as the next aux. entry. |
||
115 | |||
116 | b) continued: a bit that says the next aux. entry is a |
||
117 | continuation of the current type information (in case |
||
118 | there are more than 6 levels of array/ptr/function). |
||
119 | |||
120 | c) bt: an integer containing the base type before adding |
||
121 | array, pointer, function, etc. qualifiers. The |
||
122 | current base types that I have documentation for are: |
||
123 | |||
124 | btNil -- undefined |
||
125 | btAdr -- address - integer same size as ptr |
||
126 | btChar -- character |
||
127 | btUChar -- unsigned character |
||
128 | btShort -- short |
||
129 | btUShort -- unsigned short |
||
130 | btInt -- int |
||
131 | btUInt -- unsigned int |
||
132 | btLong -- long |
||
133 | btULong -- unsigned long |
||
134 | btFloat -- float (real) |
||
135 | btDouble -- Double (real) |
||
136 | btStruct -- Structure (Record) |
||
137 | btUnion -- Union (variant) |
||
138 | btEnum -- Enumerated |
||
139 | btTypedef -- defined via a typedef isymRef |
||
140 | btRange -- subrange of int |
||
141 | btSet -- pascal sets |
||
142 | btComplex -- fortran complex |
||
143 | btDComplex -- fortran double complex |
||
144 | btIndirect -- forward or unnamed typedef |
||
145 | btFixedDec -- Fixed Decimal |
||
146 | btFloatDec -- Float Decimal |
||
147 | btString -- Varying Length Character String |
||
148 | btBit -- Aligned Bit String |
||
149 | btPicture -- Picture |
||
150 | btVoid -- Void (MIPS cc revision >= 2.00) |
||
151 | |||
152 | d) tq0 - tq5: type qualifier fields as needed. The |
||
153 | current type qualifier fields I have documentation for |
||
154 | are: |
||
155 | |||
156 | tqNil -- no more qualifiers |
||
157 | tqPtr -- pointer |
||
158 | tqProc -- procedure |
||
159 | tqArray -- array |
||
160 | tqFar -- 8086 far pointers |
||
161 | tqVol -- volatile |
||
162 | |||
163 | The dense number table is used in the front ends, and disappears by |
||
164 | the time the .o is created. |
||
165 | |||
166 | With the 1.31 compiler suite, the optimization symbols don't seem |
||
167 | to be used as far as I can tell. |
||
168 | |||
169 | The linker is the first entity that creates the relative file |
||
170 | descriptor table, and I believe it is used so that the individual |
||
171 | file table pointers don't have to be rewritten when the objects are |
||
172 | merged together into the program file. |
||
173 | |||
174 | Unlike COFF, the basic symbol & string tables are split into |
||
175 | external and local symbols/strings. The relocation information |
||
176 | only goes off of the external symbol table, and the debug |
||
177 | information only goes off of the internal symbol table. The |
||
178 | external symbols can have links to an appropriate file index and |
||
179 | symbol within the file to give it the appropriate type information. |
||
180 | Because of this, the external symbols are actually larger than the |
||
181 | internal symbols (to contain the link information), and contain the |
||
182 | local symbol structure as a member, though this member is not the |
||
183 | first member of the external symbol structure (!). I suspect this |
||
184 | split is to make strip easier to deal with. |
||
185 | |||
186 | Each file table has offsets for where the line numbers, local |
||
187 | strings, local symbols, and procedure table starts from within the |
||
188 | global tables, and the indexs are reset to 0 for each of those |
||
189 | tables for the file. |
||
190 | |||
191 | The procedure table contains the binary equivalents of the .ent |
||
192 | (start of the function address), .frame (what register is the |
||
193 | virtual frame pointer, constant offset from the register to obtain |
||
194 | the VFP, and what register holds the return address), .mask/.fmask |
||
195 | (bitmask of saved registers, and where the first register is stored |
||
196 | relative to the VFP) assembler directives. It also contains the |
||
197 | low and high bounds of the line numbers if debugging is turned on. |
||
198 | |||
199 | The line number table is a compressed form of the normal COFF line |
||
200 | table. Each line number entry is either 1 or 3 bytes long, and |
||
201 | contains a signed delta from the previous line, and an unsigned |
||
202 | count of the number of instructions this statement takes. |
||
203 | |||
204 | The local symbol table contains the following fields: |
||
205 | |||
206 | 1) iss: index to the local string table giving the name of the |
||
207 | symbol. |
||
208 | |||
209 | 2) value: value of the symbol (address, register number, etc.). |
||
210 | |||
211 | 3) st: symbol type. The current symbol types are: |
||
212 | |||
213 | stNil -- Nuthin' special |
||
214 | stGlobal -- external symbol |
||
215 | stStatic -- static |
||
216 | stParam -- procedure argument |
||
217 | stLocal -- local variable |
||
218 | stLabel -- label |
||
219 | stProc -- External Procedure |
||
220 | stBlock -- beginning of block |
||
221 | stEnd -- end (of anything) |
||
222 | stMember -- member (of anything) |
||
223 | stTypedef -- type definition |
||
224 | stFile -- file name |
||
225 | stRegReloc -- register relocation |
||
226 | stForward -- forwarding address |
||
227 | stStaticProc -- Static procedure |
||
228 | stConstant -- const |
||
229 | |||
230 | 4) sc: storage class. The current storage classes are: |
||
231 | |||
232 | scText -- text symbol |
||
233 | scData -- initialized data symbol |
||
234 | scBss -- un-initialized data symbol |
||
235 | scRegister -- value of symbol is register number |
||
236 | scAbs -- value of symbol is absolute |
||
237 | scUndefined -- who knows? |
||
238 | scCdbLocal -- variable's value is IN se->va.?? |
||
239 | scBits -- this is a bit field |
||
240 | scCdbSystem -- value is IN debugger's address space |
||
241 | scRegImage -- register value saved on stack |
||
242 | scInfo -- symbol contains debugger information |
||
243 | scUserStruct -- addr in struct user for current process |
||
244 | scSData -- load time only small data |
||
245 | scSBss -- load time only small common |
||
246 | scRData -- load time only read only data |
||
247 | scVar -- Var parameter (fortranpascal) |
||
248 | scCommon -- common variable |
||
249 | scSCommon -- small common |
||
250 | scVarRegister -- Var parameter in a register |
||
251 | scVariant -- Variant record |
||
252 | scSUndefined -- small undefined(external) data |
||
253 | scInit -- .init section symbol |
||
254 | |||
255 | 5) index: pointer to a local symbol or aux. entry. |
||
256 | |||
257 | For the following program: |
||
258 | |||
259 | #include |
||
260 | |||
261 | main(){ |
||
262 | printf("Hello World!\n"); |
||
263 | return 0; |
||
264 | } |
||
265 | |||
266 | Mips-tdump produces the following information: |
||
267 | |||
268 | Global file header: |
||
269 | magic number 0x162 |
||
270 | # sections 2 |
||
271 | timestamp 645311799, Wed Jun 13 17:16:39 1990 |
||
272 | symbolic header offset 284 |
||
273 | symbolic header size 96 |
||
274 | optional header 56 |
||
275 | flags 0x0 |
||
276 | |||
277 | Symbolic header, magic number = 0x7009, vstamp = 1.31: |
||
278 | |||
279 | Info Offset Number Bytes |
||
280 | ==== ====== ====== ===== |
||
281 | |||
282 | Line numbers 380 4 4 [13] |
||
283 | Dense numbers 0 0 0 |
||
284 | Procedures Tables 384 1 52 |
||
285 | Local Symbols 436 16 192 |
||
286 | Optimization Symbols 0 0 0 |
||
287 | Auxiliary Symbols 628 39 156 |
||
288 | Local Strings 784 80 80 |
||
289 | External Strings 864 144 144 |
||
290 | File Tables 1008 2 144 |
||
291 | Relative Files 0 0 0 |
||
292 | External Symbols 1152 20 320 |
||
293 | |||
294 | File #0, "hello2.c" |
||
295 | |||
296 | Name index = 1 Readin = No |
||
297 | Merge = No Endian = LITTLE |
||
298 | Debug level = G2 Language = C |
||
299 | Adr = 0x00000000 |
||
300 | |||
301 | Info Start Number Size Offset |
||
302 | ==== ===== ====== ==== ====== |
||
303 | Local strings 0 15 15 784 |
||
304 | Local symbols 0 6 72 436 |
||
305 | Line numbers 0 13 13 380 |
||
306 | Optimization symbols 0 0 0 0 |
||
307 | Procedures 0 1 52 384 |
||
308 | Auxiliary symbols 0 14 56 628 |
||
309 | Relative Files 0 0 0 0 |
||
310 | |||
311 | There are 6 local symbols, starting at 436 |
||
312 | |||
313 | Symbol# 0: "hello2.c" |
||
314 | End+1 symbol = 6 |
||
315 | String index = 1 |
||
316 | Storage class = Text Index = 6 |
||
317 | Symbol type = File Value = 0 |
||
318 | |||
319 | Symbol# 1: "main" |
||
320 | End+1 symbol = 5 |
||
321 | Type = int |
||
322 | String index = 10 |
||
323 | Storage class = Text Index = 12 |
||
324 | Symbol type = Proc Value = 0 |
||
325 | |||
326 | Symbol# 2: "" |
||
327 | End+1 symbol = 4 |
||
328 | String index = 0 |
||
329 | Storage class = Text Index = 4 |
||
330 | Symbol type = Block Value = 8 |
||
331 | |||
332 | Symbol# 3: "" |
||
333 | First symbol = 2 |
||
334 | String index = 0 |
||
335 | Storage class = Text Index = 2 |
||
336 | Symbol type = End Value = 28 |
||
337 | |||
338 | Symbol# 4: "main" |
||
339 | First symbol = 1 |
||
340 | String index = 10 |
||
341 | Storage class = Text Index = 1 |
||
342 | Symbol type = End Value = 52 |
||
343 | |||
344 | Symbol# 5: "hello2.c" |
||
345 | First symbol = 0 |
||
346 | String index = 1 |
||
347 | Storage class = Text Index = 0 |
||
348 | Symbol type = End Value = 0 |
||
349 | |||
350 | There are 14 auxiliary table entries, starting at 628. |
||
351 | |||
352 | * #0 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
353 | * #1 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0] |
||
354 | * #2 8, [ 8/ 0], [ 2 0:0 0:0:0:0:0:0] |
||
355 | * #3 16, [ 16/ 0], [ 4 0:0 0:0:0:0:0:0] |
||
356 | * #4 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0] |
||
357 | * #5 32, [ 32/ 0], [ 8 0:0 0:0:0:0:0:0] |
||
358 | * #6 40, [ 40/ 0], [10 0:0 0:0:0:0:0:0] |
||
359 | * #7 44, [ 44/ 0], [11 0:0 0:0:0:0:0:0] |
||
360 | * #8 12, [ 12/ 0], [ 3 0:0 0:0:0:0:0:0] |
||
361 | * #9 20, [ 20/ 0], [ 5 0:0 0:0:0:0:0:0] |
||
362 | * #10 28, [ 28/ 0], [ 7 0:0 0:0:0:0:0:0] |
||
363 | * #11 36, [ 36/ 0], [ 9 0:0 0:0:0:0:0:0] |
||
364 | #12 5, [ 5/ 0], [ 1 1:0 0:0:0:0:0:0] |
||
365 | #13 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0] |
||
366 | |||
367 | There are 1 procedure descriptor entries, starting at 0. |
||
368 | |||
369 | Procedure descriptor 0: |
||
370 | Name index = 10 Name = "main" |
||
371 | .mask 0x80000000,-4 .fmask 0x00000000,0 |
||
372 | .frame $29,24,$31 |
||
373 | Opt. start = -1 Symbols start = 1 |
||
374 | First line # = 3 Last line # = 6 |
||
375 | Line Offset = 0 Address = 0x00000000 |
||
376 | |||
377 | There are 4 bytes holding line numbers, starting at 380. |
||
378 | Line 3, delta 0, count 2 |
||
379 | Line 4, delta 1, count 3 |
||
380 | Line 5, delta 1, count 2 |
||
381 | Line 6, delta 1, count 6 |
||
382 | |||
383 | File #1, "/usr/include/stdio.h" |
||
384 | |||
385 | Name index = 1 Readin = No |
||
386 | Merge = Yes Endian = LITTLE |
||
387 | Debug level = G2 Language = C |
||
388 | Adr = 0x00000000 |
||
389 | |||
390 | Info Start Number Size Offset |
||
391 | ==== ===== ====== ==== ====== |
||
392 | Local strings 15 65 65 799 |
||
393 | Local symbols 6 10 120 508 |
||
394 | Line numbers 0 0 0 380 |
||
395 | Optimization symbols 0 0 0 0 |
||
396 | Procedures 1 0 0 436 |
||
397 | Auxiliary symbols 14 25 100 684 |
||
398 | Relative Files 0 0 0 0 |
||
399 | |||
400 | There are 10 local symbols, starting at 442 |
||
401 | |||
402 | Symbol# 0: "/usr/include/stdio.h" |
||
403 | End+1 symbol = 10 |
||
404 | String index = 1 |
||
405 | Storage class = Text Index = 10 |
||
406 | Symbol type = File Value = 0 |
||
407 | |||
408 | Symbol# 1: "_iobuf" |
||
409 | End+1 symbol = 9 |
||
410 | String index = 22 |
||
411 | Storage class = Info Index = 9 |
||
412 | Symbol type = Block Value = 20 |
||
413 | |||
414 | Symbol# 2: "_cnt" |
||
415 | Type = int |
||
416 | String index = 29 |
||
417 | Storage class = Info Index = 4 |
||
418 | Symbol type = Member Value = 0 |
||
419 | |||
420 | Symbol# 3: "_ptr" |
||
421 | Type = ptr to char |
||
422 | String index = 34 |
||
423 | Storage class = Info Index = 15 |
||
424 | Symbol type = Member Value = 32 |
||
425 | |||
426 | Symbol# 4: "_base" |
||
427 | Type = ptr to char |
||
428 | String index = 39 |
||
429 | Storage class = Info Index = 16 |
||
430 | Symbol type = Member Value = 64 |
||
431 | |||
432 | Symbol# 5: "_bufsiz" |
||
433 | Type = int |
||
434 | String index = 45 |
||
435 | Storage class = Info Index = 4 |
||
436 | Symbol type = Member Value = 96 |
||
437 | |||
438 | Symbol# 6: "_flag" |
||
439 | Type = short |
||
440 | String index = 53 |
||
441 | Storage class = Info Index = 3 |
||
442 | Symbol type = Member Value = 128 |
||
443 | |||
444 | Symbol# 7: "_file" |
||
445 | Type = char |
||
446 | String index = 59 |
||
447 | Storage class = Info Index = 2 |
||
448 | Symbol type = Member Value = 144 |
||
449 | |||
450 | Symbol# 8: "" |
||
451 | First symbol = 1 |
||
452 | String index = 0 |
||
453 | Storage class = Info Index = 1 |
||
454 | Symbol type = End Value = 0 |
||
455 | |||
456 | Symbol# 9: "/usr/include/stdio.h" |
||
457 | First symbol = 0 |
||
458 | String index = 1 |
||
459 | Storage class = Text Index = 0 |
||
460 | Symbol type = End Value = 0 |
||
461 | |||
462 | There are 25 auxiliary table entries, starting at 642. |
||
463 | |||
464 | * #14 -1, [4095/1048575], [63 1:1 f:f:f:f:f:f] |
||
465 | #15 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0] |
||
466 | #16 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0] |
||
467 | * #17 196656, [ 48/ 48], [12 0:0 3:0:0:0:0:0] |
||
468 | * #18 8191, [4095/ 1], [63 1:1 0:0:0:0:f:1] |
||
469 | * #19 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0] |
||
470 | * #20 20479, [4095/ 4], [63 1:1 0:0:0:0:f:4] |
||
471 | * #21 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0] |
||
472 | * #22 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
473 | * #23 2, [ 2/ 0], [ 0 0:1 0:0:0:0:0:0] |
||
474 | * #24 160, [ 160/ 0], [40 0:0 0:0:0:0:0:0] |
||
475 | * #25 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
476 | * #26 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
477 | * #27 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
478 | * #28 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
479 | * #29 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
480 | * #30 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
481 | * #31 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
482 | * #32 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
483 | * #33 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
484 | * #34 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
485 | * #35 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
486 | * #36 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
487 | * #37 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
488 | * #38 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0] |
||
489 | |||
490 | There are 0 procedure descriptor entries, starting at 1. |
||
491 | |||
492 | There are 20 external symbols, starting at 1152 |
||
493 | |||
494 | Symbol# 0: "_iob" |
||
495 | Type = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 } |
||
496 | String index = 0 Ifd = 1 |
||
497 | Storage class = Nil Index = 17 |
||
498 | Symbol type = Global Value = 60 |
||
499 | |||
500 | Symbol# 1: "fopen" |
||
501 | String index = 5 Ifd = 1 |
||
502 | Storage class = Nil Index = 1048575 |
||
503 | Symbol type = Proc Value = 0 |
||
504 | |||
505 | Symbol# 2: "fdopen" |
||
506 | String index = 11 Ifd = 1 |
||
507 | Storage class = Nil Index = 1048575 |
||
508 | Symbol type = Proc Value = 0 |
||
509 | |||
510 | Symbol# 3: "freopen" |
||
511 | String index = 18 Ifd = 1 |
||
512 | Storage class = Nil Index = 1048575 |
||
513 | Symbol type = Proc Value = 0 |
||
514 | |||
515 | Symbol# 4: "popen" |
||
516 | String index = 26 Ifd = 1 |
||
517 | Storage class = Nil Index = 1048575 |
||
518 | Symbol type = Proc Value = 0 |
||
519 | |||
520 | Symbol# 5: "tmpfile" |
||
521 | String index = 32 Ifd = 1 |
||
522 | Storage class = Nil Index = 1048575 |
||
523 | Symbol type = Proc Value = 0 |
||
524 | |||
525 | Symbol# 6: "ftell" |
||
526 | String index = 40 Ifd = 1 |
||
527 | Storage class = Nil Index = 1048575 |
||
528 | Symbol type = Proc Value = 0 |
||
529 | |||
530 | Symbol# 7: "rewind" |
||
531 | String index = 46 Ifd = 1 |
||
532 | Storage class = Nil Index = 1048575 |
||
533 | Symbol type = Proc Value = 0 |
||
534 | |||
535 | Symbol# 8: "setbuf" |
||
536 | String index = 53 Ifd = 1 |
||
537 | Storage class = Nil Index = 1048575 |
||
538 | Symbol type = Proc Value = 0 |
||
539 | |||
540 | Symbol# 9: "setbuffer" |
||
541 | String index = 60 Ifd = 1 |
||
542 | Storage class = Nil Index = 1048575 |
||
543 | Symbol type = Proc Value = 0 |
||
544 | |||
545 | Symbol# 10: "setlinebuf" |
||
546 | String index = 70 Ifd = 1 |
||
547 | Storage class = Nil Index = 1048575 |
||
548 | Symbol type = Proc Value = 0 |
||
549 | |||
550 | Symbol# 11: "fgets" |
||
551 | String index = 81 Ifd = 1 |
||
552 | Storage class = Nil Index = 1048575 |
||
553 | Symbol type = Proc Value = 0 |
||
554 | |||
555 | Symbol# 12: "gets" |
||
556 | String index = 87 Ifd = 1 |
||
557 | Storage class = Nil Index = 1048575 |
||
558 | Symbol type = Proc Value = 0 |
||
559 | |||
560 | Symbol# 13: "ctermid" |
||
561 | String index = 92 Ifd = 1 |
||
562 | Storage class = Nil Index = 1048575 |
||
563 | Symbol type = Proc Value = 0 |
||
564 | |||
565 | Symbol# 14: "cuserid" |
||
566 | String index = 100 Ifd = 1 |
||
567 | Storage class = Nil Index = 1048575 |
||
568 | Symbol type = Proc Value = 0 |
||
569 | |||
570 | Symbol# 15: "tempnam" |
||
571 | String index = 108 Ifd = 1 |
||
572 | Storage class = Nil Index = 1048575 |
||
573 | Symbol type = Proc Value = 0 |
||
574 | |||
575 | Symbol# 16: "tmpnam" |
||
576 | String index = 116 Ifd = 1 |
||
577 | Storage class = Nil Index = 1048575 |
||
578 | Symbol type = Proc Value = 0 |
||
579 | |||
580 | Symbol# 17: "sprintf" |
||
581 | String index = 123 Ifd = 1 |
||
582 | Storage class = Nil Index = 1048575 |
||
583 | Symbol type = Proc Value = 0 |
||
584 | |||
585 | Symbol# 18: "main" |
||
586 | Type = int |
||
587 | String index = 131 Ifd = 0 |
||
588 | Storage class = Text Index = 1 |
||
589 | Symbol type = Proc Value = 0 |
||
590 | |||
591 | Symbol# 19: "printf" |
||
592 | String index = 136 Ifd = 0 |
||
593 | Storage class = Undefined Index = 1048575 |
||
594 | Symbol type = Proc Value = 0 |
||
595 | |||
596 | The following auxiliary table entries were unused: |
||
597 | |||
598 | #0 0 0x00000000 void |
||
599 | #2 8 0x00000008 char |
||
600 | #3 16 0x00000010 short |
||
601 | #4 24 0x00000018 int |
||
602 | #5 32 0x00000020 long |
||
603 | #6 40 0x00000028 float |
||
604 | #7 44 0x0000002c double |
||
605 | #8 12 0x0000000c unsigned char |
||
606 | #9 20 0x00000014 unsigned short |
||
607 | #10 28 0x0000001c unsigned int |
||
608 | #11 36 0x00000024 unsigned long |
||
609 | #14 0 0x00000000 void |
||
610 | #15 24 0x00000018 int |
||
611 | #19 32 0x00000020 long |
||
612 | #20 40 0x00000028 float |
||
613 | #21 44 0x0000002c double |
||
614 | #22 12 0x0000000c unsigned char |
||
615 | #23 20 0x00000014 unsigned short |
||
616 | #24 28 0x0000001c unsigned int |
||
617 | #25 36 0x00000024 unsigned long |
||
618 | #26 48 0x00000030 struct no name { ifd = -1, index = 1048575 } |
||
619 | */ |
||
620 | |||
621 | /* Redefinition of of storage classes as an enumeration for better |
||
622 | debugging. */ |
||
623 | |||
624 | typedef enum sc { |
||
625 | sc_Nil = scNil, /* no storage class */ |
||
626 | sc_Text = scText, /* text symbol */ |
||
627 | sc_Data = scData, /* initialized data symbol */ |
||
628 | sc_Bss = scBss, /* un-initialized data symbol */ |
||
629 | sc_Register = scRegister, /* value of symbol is register number */ |
||
630 | sc_Abs = scAbs, /* value of symbol is absolute */ |
||
631 | sc_Undefined = scUndefined, /* who knows? */ |
||
632 | sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */ |
||
633 | sc_Bits = scBits, /* this is a bit field */ |
||
634 | sc_CdbSystem = scCdbSystem, /* value is IN CDB's address space */ |
||
635 | sc_RegImage = scRegImage, /* register value saved on stack */ |
||
636 | sc_Info = scInfo, /* symbol contains debugger information */ |
||
637 | sc_UserStruct = scUserStruct, /* addr in struct user for current process */ |
||
638 | sc_SData = scSData, /* load time only small data */ |
||
639 | sc_SBss = scSBss, /* load time only small common */ |
||
640 | sc_RData = scRData, /* load time only read only data */ |
||
641 | sc_Var = scVar, /* Var parameter (fortran,pascal) */ |
||
642 | sc_Common = scCommon, /* common variable */ |
||
643 | sc_SCommon = scSCommon, /* small common */ |
||
644 | sc_VarRegister = scVarRegister, /* Var parameter in a register */ |
||
645 | sc_Variant = scVariant, /* Variant record */ |
||
646 | sc_SUndefined = scSUndefined, /* small undefined(external) data */ |
||
647 | sc_Init = scInit, /* .init section symbol */ |
||
648 | sc_Max = scMax /* Max storage class+1 */ |
||
649 | } sc_t; |
||
650 | |||
651 | /* Redefinition of symbol type. */ |
||
652 | |||
653 | typedef enum st { |
||
654 | st_Nil = stNil, /* Nuthin' special */ |
||
655 | st_Global = stGlobal, /* external symbol */ |
||
656 | st_Static = stStatic, /* static */ |
||
657 | st_Param = stParam, /* procedure argument */ |
||
658 | st_Local = stLocal, /* local variable */ |
||
659 | st_Label = stLabel, /* label */ |
||
660 | st_Proc = stProc, /* " " Procedure */ |
||
661 | st_Block = stBlock, /* beginning of block */ |
||
662 | st_End = stEnd, /* end (of anything) */ |
||
663 | st_Member = stMember, /* member (of anything - struct/union/enum */ |
||
664 | st_Typedef = stTypedef, /* type definition */ |
||
665 | st_File = stFile, /* file name */ |
||
666 | st_RegReloc = stRegReloc, /* register relocation */ |
||
667 | st_Forward = stForward, /* forwarding address */ |
||
668 | st_StaticProc = stStaticProc, /* load time only static procs */ |
||
669 | st_Constant = stConstant, /* const */ |
||
670 | st_Str = stStr, /* string */ |
||
671 | st_Number = stNumber, /* pure number (ie. 4 NOR 2+2) */ |
||
672 | st_Expr = stExpr, /* 2+2 vs. 4 */ |
||
673 | st_Type = stType, /* post-coercion SER */ |
||
674 | st_Max = stMax /* max type+1 */ |
||
675 | } st_t; |
||
676 | |||
677 | /* Redefinition of type qualifiers. */ |
||
678 | |||
679 | typedef enum tq { |
||
680 | tq_Nil = tqNil, /* bt is what you see */ |
||
681 | tq_Ptr = tqPtr, /* pointer */ |
||
682 | tq_Proc = tqProc, /* procedure */ |
||
683 | tq_Array = tqArray, /* duh */ |
||
684 | tq_Far = tqFar, /* longer addressing - 8086/8 land */ |
||
685 | tq_Vol = tqVol, /* volatile */ |
||
686 | tq_Max = tqMax /* Max type qualifier+1 */ |
||
687 | } tq_t; |
||
688 | |||
689 | /* Redefinition of basic types. */ |
||
690 | |||
691 | typedef enum bt { |
||
692 | bt_Nil = btNil, /* undefined */ |
||
693 | bt_Adr = btAdr, /* address - integer same size as pointer */ |
||
694 | bt_Char = btChar, /* character */ |
||
695 | bt_UChar = btUChar, /* unsigned character */ |
||
696 | bt_Short = btShort, /* short */ |
||
697 | bt_UShort = btUShort, /* unsigned short */ |
||
698 | bt_Int = btInt, /* int */ |
||
699 | bt_UInt = btUInt, /* unsigned int */ |
||
700 | bt_Long = btLong, /* long */ |
||
701 | bt_ULong = btULong, /* unsigned long */ |
||
702 | bt_Float = btFloat, /* float (real) */ |
||
703 | bt_Double = btDouble, /* Double (real) */ |
||
704 | bt_Struct = btStruct, /* Structure (Record) */ |
||
705 | bt_Union = btUnion, /* Union (variant) */ |
||
706 | bt_Enum = btEnum, /* Enumerated */ |
||
707 | bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */ |
||
708 | bt_Range = btRange, /* subrange of int */ |
||
709 | bt_Set = btSet, /* pascal sets */ |
||
710 | bt_Complex = btComplex, /* fortran complex */ |
||
711 | bt_DComplex = btDComplex, /* fortran double complex */ |
||
712 | bt_Indirect = btIndirect, /* forward or unnamed typedef */ |
||
713 | bt_FixedDec = btFixedDec, /* Fixed Decimal */ |
||
714 | bt_FloatDec = btFloatDec, /* Float Decimal */ |
||
715 | bt_String = btString, /* Varying Length Character String */ |
||
716 | bt_Bit = btBit, /* Aligned Bit String */ |
||
717 | bt_Picture = btPicture, /* Picture */ |
||
718 | bt_Void = btVoid, /* Void */ |
||
719 | bt_Max = btMax /* Max basic type+1 */ |
||
720 | } bt_t; |
||
721 | |||
722 | #define N_TQ itqMax |
||
723 | |||
724 | /* States for whether to hash type or not. */ |
||
725 | typedef enum hash_state { |
||
726 | hash_no = 0, /* Don't hash type */ |
||
727 | hash_yes = 1, /* OK to hash type, or use previous hash */ |
||
728 | hash_record = 2 /* OK to record hash, but don't use prev. */ |
||
729 | } hash_state_t; |
||
730 | |||
731 | /* Types of different sized allocation requests. */ |
||
732 | enum alloc_type { |
||
733 | alloc_type_none, /* dummy value */ |
||
734 | alloc_type_scope, /* nested scopes linked list */ |
||
735 | alloc_type_vlinks, /* glue linking pages in varray */ |
||
736 | alloc_type_shash, /* string hash element */ |
||
737 | alloc_type_thash, /* type hash element */ |
||
738 | alloc_type_tag, /* struct/union/tag element */ |
||
739 | alloc_type_forward, /* element to hold unknown tag */ |
||
740 | alloc_type_thead, /* head of type hash list */ |
||
741 | alloc_type_varray, /* general varray allocation */ |
||
742 | alloc_type_lineno, /* line number list */ |
||
743 | alloc_type_last /* last+1 element for array bounds */ |
||
744 | }; |
||
745 | |||
746 | /* Types of auxiliary type information. */ |
||
747 | enum aux_type { |
||
748 | aux_tir, /* TIR type information */ |
||
749 | aux_rndx, /* relative index into symbol table */ |
||
750 | aux_dnLow, /* low dimension */ |
||
751 | aux_dnHigh, /* high dimension */ |
||
752 | aux_isym, /* symbol table index (end of proc) */ |
||
753 | aux_iss, /* index into string space (not used) */ |
||
754 | aux_width, /* width for non-default sized struc fields */ |
||
755 | aux_count /* count of ranges for variant arm */ |
||
756 | }; |
||
757 | |||
758 | /* Structures to provide n-number of virtual arrays, each of which can |
||
759 | grow linearly, and which are written in the object file as |
||
760 | sequential pages. On systems with a BSD malloc, the |
||
761 | MAX_CLUSTER_PAGES should be 1 less than a power of two, since |
||
762 | malloc adds it's overhead, and rounds up to the next power of 2. |
||
763 | Pages are linked together via a linked list. |
||
764 | |||
765 | If PAGE_SIZE is > 4096, the string length in the shash_t structure |
||
766 | can't be represented (assuming there are strings > 4096 bytes). */ |
||
767 | |||
768 | /* FIXME: Yes, there can be such strings while emitting C++ class debug |
||
769 | info. Templates are the offender here, the test case in question |
||
770 | having a mangled class name of |
||
771 | |||
772 | t7rb_tree4Z4xkeyZt4pair2ZC4xkeyZt7xsocket1Z4UserZt9select1st2Zt4pair\ |
||
773 | 2ZC4xkeyZt7xsocket1Z4UserZ4xkeyZt4less1Z4xkey |
||
774 | |||
775 | Repeat that a couple dozen times while listing the class members and |
||
776 | you've got strings over 4k. Hack around this for now by increasing |
||
777 | the page size. A proper solution would abandon this structure scheme |
||
778 | certainly for very large strings, and possibly entirely. */ |
||
779 | |||
780 | #ifndef PAGE_SIZE |
||
781 | #define PAGE_SIZE (8*1024) /* size of varray pages */ |
||
782 | #endif |
||
783 | |||
784 | #define PAGE_USIZE ((unsigned long) PAGE_SIZE) |
||
785 | |||
786 | #ifndef MAX_CLUSTER_PAGES /* # pages to get from system */ |
||
787 | #define MAX_CLUSTER_PAGES 63 |
||
788 | #endif |
||
789 | |||
790 | /* Linked list connecting separate page allocations. */ |
||
791 | typedef struct vlinks { |
||
792 | struct vlinks *prev; /* previous set of pages */ |
||
793 | struct vlinks *next; /* next set of pages */ |
||
794 | union page *datum; /* start of page */ |
||
795 | unsigned long start_index; /* starting index # of page */ |
||
796 | } vlinks_t; |
||
797 | |||
798 | /* Virtual array header. */ |
||
799 | typedef struct varray { |
||
800 | vlinks_t *first; /* first page link */ |
||
801 | vlinks_t *last; /* last page link */ |
||
802 | unsigned long num_allocated; /* # objects allocated */ |
||
803 | unsigned short object_size; /* size in bytes of each object */ |
||
804 | unsigned short objects_per_page; /* # objects that can fit on a page */ |
||
805 | unsigned short objects_last_page; /* # objects allocated on last page */ |
||
806 | } varray_t; |
||
807 | |||
808 | #ifndef MALLOC_CHECK |
||
809 | #define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type)) |
||
810 | #else |
||
811 | #define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE) |
||
812 | #endif |
||
813 | |||
814 | #define INIT_VARRAY(type) { /* macro to initialize a varray */ \ |
||
815 | (vlinks_t *)0, /* first */ \ |
||
816 | (vlinks_t *)0, /* last */ \ |
||
817 | 0, /* num_allocated */ \ |
||
818 | sizeof (type), /* object_size */ \ |
||
819 | OBJECTS_PER_PAGE (type), /* objects_per_page */ \ |
||
820 | OBJECTS_PER_PAGE (type), /* objects_last_page */ \ |
||
821 | } |
||
822 | |||
823 | /* Master type for indexes within the symbol table. */ |
||
824 | typedef unsigned long symint_t; |
||
825 | |||
826 | /* Linked list support for nested scopes (file, block, structure, etc.). */ |
||
827 | typedef struct scope { |
||
828 | struct scope *prev; /* previous scope level */ |
||
829 | struct scope *free; /* free list pointer */ |
||
830 | struct localsym *lsym; /* pointer to local symbol node */ |
||
831 | st_t type; /* type of the node */ |
||
832 | } scope_t; |
||
833 | |||
834 | /* For a local symbol we store a gas symbol as well as the debugging |
||
835 | information we generate. The gas symbol will be NULL if this is |
||
836 | only a debugging symbol. */ |
||
837 | typedef struct localsym { |
||
838 | const char *name; /* symbol name */ |
||
839 | symbolS *as_sym; /* symbol as seen by gas */ |
||
840 | bfd_vma addend; /* addend to as_sym value */ |
||
841 | struct efdr *file_ptr; /* file pointer */ |
||
842 | struct ecoff_proc *proc_ptr; /* proc pointer */ |
||
843 | struct localsym *begin_ptr; /* symbol at start of block */ |
||
844 | struct ecoff_aux *index_ptr; /* index value to be filled in */ |
||
845 | struct forward *forward_ref; /* forward references to this symbol */ |
||
846 | long sym_index; /* final symbol index */ |
||
847 | EXTR ecoff_sym; /* ECOFF debugging symbol */ |
||
848 | } localsym_t; |
||
849 | |||
850 | /* For aux information we keep the type and the data. */ |
||
851 | typedef struct ecoff_aux { |
||
852 | enum aux_type type; /* aux type */ |
||
853 | AUXU data; /* aux data */ |
||
854 | } aux_t; |
||
855 | |||
856 | /* For a procedure we store the gas symbol as well as the PDR |
||
857 | debugging information. */ |
||
858 | typedef struct ecoff_proc { |
||
859 | localsym_t *sym; /* associated symbol */ |
||
860 | PDR pdr; /* ECOFF debugging info */ |
||
861 | } proc_t; |
||
862 | |||
863 | /* Number of proc_t structures allocated. */ |
||
864 | static unsigned long proc_cnt; |
||
865 | |||
866 | /* Forward reference list for tags referenced, but not yet defined. */ |
||
867 | typedef struct forward { |
||
868 | struct forward *next; /* next forward reference */ |
||
869 | struct forward *free; /* free list pointer */ |
||
870 | aux_t *ifd_ptr; /* pointer to store file index */ |
||
871 | aux_t *index_ptr; /* pointer to store symbol index */ |
||
872 | } forward_t; |
||
873 | |||
874 | /* Linked list support for tags. The first tag in the list is always |
||
875 | the current tag for that block. */ |
||
876 | typedef struct tag { |
||
877 | struct tag *free; /* free list pointer */ |
||
878 | struct shash *hash_ptr; /* pointer to the hash table head */ |
||
879 | struct tag *same_name; /* tag with same name in outer scope */ |
||
880 | struct tag *same_block; /* next tag defined in the same block. */ |
||
881 | struct forward *forward_ref; /* list of forward references */ |
||
882 | bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */ |
||
883 | symint_t ifd; /* file # tag defined in */ |
||
884 | localsym_t *sym; /* file's local symbols */ |
||
885 | } tag_t; |
||
886 | |||
887 | /* Head of a block's linked list of tags. */ |
||
888 | typedef struct thead { |
||
889 | struct thead *prev; /* previous block */ |
||
890 | struct thead *free; /* free list pointer */ |
||
891 | struct tag *first_tag; /* first tag in block defined */ |
||
892 | } thead_t; |
||
893 | |||
894 | /* Union containing pointers to each the small structures which are freed up. */ |
||
895 | typedef union small_free { |
||
896 | scope_t *f_scope; /* scope structure */ |
||
897 | thead_t *f_thead; /* tag head structure */ |
||
898 | tag_t *f_tag; /* tag element structure */ |
||
899 | forward_t *f_forward; /* forward tag reference */ |
||
900 | } small_free_t; |
||
901 | |||
902 | /* String hash table entry. */ |
||
903 | |||
904 | typedef struct shash { |
||
905 | char *string; /* string we are hashing */ |
||
906 | symint_t indx; /* index within string table */ |
||
907 | EXTR *esym_ptr; /* global symbol pointer */ |
||
908 | localsym_t *sym_ptr; /* local symbol pointer */ |
||
909 | localsym_t *end_ptr; /* symbol pointer to end block */ |
||
910 | tag_t *tag_ptr; /* tag pointer */ |
||
911 | proc_t *proc_ptr; /* procedure descriptor pointer */ |
||
912 | } shash_t; |
||
913 | |||
914 | /* Type hash table support. The size of the hash table must fit |
||
915 | within a page with the other extended file descriptor information. |
||
916 | Because unique types which are hashed are fewer in number than |
||
917 | strings, we use a smaller hash value. */ |
||
918 | |||
919 | #define HASHBITS 30 |
||
920 | |||
921 | #ifndef THASH_SIZE |
||
922 | #define THASH_SIZE 113 |
||
923 | #endif |
||
924 | |||
925 | typedef struct thash { |
||
926 | struct thash *next; /* next hash value */ |
||
927 | AUXU type; /* type we are hashing */ |
||
928 | symint_t indx; /* index within string table */ |
||
929 | } thash_t; |
||
930 | |||
931 | /* Extended file descriptor that contains all of the support necessary |
||
932 | to add things to each file separately. */ |
||
933 | typedef struct efdr { |
||
934 | FDR fdr; /* File header to be written out */ |
||
935 | FDR *orig_fdr; /* original file header */ |
||
936 | char *name; /* filename */ |
||
937 | int fake; /* whether this is faked .file */ |
||
938 | symint_t void_type; /* aux. pointer to 'void' type */ |
||
939 | symint_t int_type; /* aux. pointer to 'int' type */ |
||
940 | scope_t *cur_scope; /* current nested scopes */ |
||
941 | symint_t file_index; /* current file number */ |
||
942 | int nested_scopes; /* # nested scopes */ |
||
943 | varray_t strings; /* local strings */ |
||
944 | varray_t symbols; /* local symbols */ |
||
945 | varray_t procs; /* procedures */ |
||
946 | varray_t aux_syms; /* auxiliary symbols */ |
||
947 | struct efdr *next_file; /* next file descriptor */ |
||
948 | /* string/type hash tables */ |
||
949 | struct hash_control *str_hash; /* string hash table */ |
||
950 | thash_t *thash_head[THASH_SIZE]; |
||
951 | } efdr_t; |
||
952 | |||
953 | /* Pre-initialized extended file structure. */ |
||
954 | static const efdr_t init_file = { |
||
955 | { /* FDR structure */ |
||
956 | 0, /* adr: memory address of beginning of file */ |
||
957 | 0, /* rss: file name (of source, if known) */ |
||
958 | 0, /* issBase: file's string space */ |
||
959 | 0, /* cbSs: number of bytes in the ss */ |
||
960 | 0, /* isymBase: beginning of symbols */ |
||
961 | 0, /* csym: count file's of symbols */ |
||
962 | 0, /* ilineBase: file's line symbols */ |
||
963 | 0, /* cline: count of file's line symbols */ |
||
964 | 0, /* ioptBase: file's optimization entries */ |
||
965 | 0, /* copt: count of file's optimization entries */ |
||
966 | 0, /* ipdFirst: start of procedures for this file */ |
||
967 | 0, /* cpd: count of procedures for this file */ |
||
968 | 0, /* iauxBase: file's auxiliary entries */ |
||
969 | 0, /* caux: count of file's auxiliary entries */ |
||
970 | 0, /* rfdBase: index into the file indirect table */ |
||
971 | 0, /* crfd: count file indirect entries */ |
||
972 | langC, /* lang: language for this file */ |
||
973 | 1, /* fMerge: whether this file can be merged */ |
||
974 | 0, /* fReadin: true if read in (not just created) */ |
||
975 | TARGET_BYTES_BIG_ENDIAN, /* fBigendian: if 1, compiled on big endian machine */ |
||
976 | GLEVEL_2, /* glevel: level this file was compiled with */ |
||
977 | 0, /* reserved: reserved for future use */ |
||
978 | 0, /* cbLineOffset: byte offset from header for this file ln's */ |
||
979 | 0, /* cbLine: size of lines for this file */ |
||
980 | }, |
||
981 | |||
982 | (FDR *)0, /* orig_fdr: original file header pointer */ |
||
983 | (char *)0, /* name: pointer to filename */ |
||
984 | 0, /* fake: whether this is a faked .file */ |
||
985 | 0, /* void_type: ptr to aux node for void type */ |
||
986 | 0, /* int_type: ptr to aux node for int type */ |
||
987 | (scope_t *)0, /* cur_scope: current scope being processed */ |
||
988 | 0, /* file_index: current file # */ |
||
989 | 0, /* nested_scopes: # nested scopes */ |
||
990 | INIT_VARRAY (char), /* strings: local string varray */ |
||
991 | INIT_VARRAY (localsym_t), /* symbols: local symbols varray */ |
||
992 | INIT_VARRAY (proc_t), /* procs: procedure varray */ |
||
993 | INIT_VARRAY (aux_t), /* aux_syms: auxiliary symbols varray */ |
||
994 | |||
995 | (struct efdr *)0, /* next_file: next file structure */ |
||
996 | |||
997 | (struct hash_control *)0, /* str_hash: string hash table */ |
||
998 | { 0 }, /* thash_head: type hash table */ |
||
999 | }; |
||
1000 | |||
1001 | static efdr_t *first_file; /* first file descriptor */ |
||
1002 | static efdr_t **last_file_ptr = &first_file; /* file descriptor tail */ |
||
1003 | |||
1004 | /* Line number information is kept in a list until the assembly is |
||
1005 | finished. */ |
||
1006 | typedef struct lineno_list { |
||
1007 | struct lineno_list *next; /* next element in list */ |
||
1008 | efdr_t *file; /* file this line is in */ |
||
1009 | proc_t *proc; /* procedure this line is in */ |
||
1010 | fragS *frag; /* fragment this line number is in */ |
||
1011 | unsigned long paddr; /* offset within fragment */ |
||
1012 | long lineno; /* actual line number */ |
||
1013 | } lineno_list_t; |
||
1014 | |||
1015 | static lineno_list_t *first_lineno; |
||
1016 | static lineno_list_t *last_lineno; |
||
1017 | static lineno_list_t **last_lineno_ptr = &first_lineno; |
||
1018 | |||
1019 | /* Sometimes there will be some .loc statements before a .ent. We |
||
1020 | keep them in this list so that we can fill in the procedure pointer |
||
1021 | after we see the .ent. */ |
||
1022 | static lineno_list_t *noproc_lineno; |
||
1023 | |||
1024 | /* Union of various things that are held in pages. */ |
||
1025 | typedef union page { |
||
1026 | char byte [ PAGE_SIZE ]; |
||
1027 | unsigned char ubyte [ PAGE_SIZE ]; |
||
1028 | efdr_t file [ PAGE_SIZE / sizeof (efdr_t) ]; |
||
1029 | FDR ofile [ PAGE_SIZE / sizeof (FDR) ]; |
||
1030 | proc_t proc [ PAGE_SIZE / sizeof (proc_t) ]; |
||
1031 | localsym_t sym [ PAGE_SIZE / sizeof (localsym_t) ]; |
||
1032 | aux_t aux [ PAGE_SIZE / sizeof (aux_t) ]; |
||
1033 | DNR dense [ PAGE_SIZE / sizeof (DNR) ]; |
||
1034 | scope_t scope [ PAGE_SIZE / sizeof (scope_t) ]; |
||
1035 | vlinks_t vlinks [ PAGE_SIZE / sizeof (vlinks_t) ]; |
||
1036 | shash_t shash [ PAGE_SIZE / sizeof (shash_t) ]; |
||
1037 | thash_t thash [ PAGE_SIZE / sizeof (thash_t) ]; |
||
1038 | tag_t tag [ PAGE_SIZE / sizeof (tag_t) ]; |
||
1039 | forward_t forward [ PAGE_SIZE / sizeof (forward_t) ]; |
||
1040 | thead_t thead [ PAGE_SIZE / sizeof (thead_t) ]; |
||
1041 | lineno_list_t lineno [ PAGE_SIZE / sizeof (lineno_list_t) ]; |
||
1042 | } page_type; |
||
1043 | |||
1044 | /* Structure holding allocation information for small sized structures. */ |
||
1045 | typedef struct alloc_info { |
||
1046 | char *alloc_name; /* name of this allocation type (must be first) */ |
||
1047 | page_type *cur_page; /* current page being allocated from */ |
||
1048 | small_free_t free_list; /* current free list if any */ |
||
1049 | int unallocated; /* number of elements unallocated on page */ |
||
1050 | int total_alloc; /* total number of allocations */ |
||
1051 | int total_free; /* total number of frees */ |
||
1052 | int total_pages; /* total number of pages allocated */ |
||
1053 | } alloc_info_t; |
||
1054 | |||
1055 | /* Type information collected together. */ |
||
1056 | typedef struct type_info { |
||
1057 | bt_t basic_type; /* basic type */ |
||
1058 | int orig_type; /* original COFF-based type */ |
||
1059 | int num_tq; /* # type qualifiers */ |
||
1060 | int num_dims; /* # dimensions */ |
||
1061 | int num_sizes; /* # sizes */ |
||
1062 | int extra_sizes; /* # extra sizes not tied with dims */ |
||
1063 | tag_t * tag_ptr; /* tag pointer */ |
||
1064 | int bitfield; /* symbol is a bitfield */ |
||
1065 | tq_t type_qualifiers[N_TQ]; /* type qualifiers (ptr, func, array)*/ |
||
1066 | symint_t dimensions [N_TQ]; /* dimensions for each array */ |
||
1067 | symint_t sizes [N_TQ+2]; /* sizes of each array slice + size of |
||
1068 | struct/union/enum + bitfield size */ |
||
1069 | } type_info_t; |
||
1070 | |||
1071 | /* Pre-initialized type_info struct. */ |
||
1072 | static const type_info_t type_info_init = { |
||
1073 | bt_Nil, /* basic type */ |
||
1074 | T_NULL, /* original COFF-based type */ |
||
1075 | 0, /* # type qualifiers */ |
||
1076 | 0, /* # dimensions */ |
||
1077 | 0, /* # sizes */ |
||
1078 | 0, /* sizes not tied with dims */ |
||
1079 | NULL, /* ptr to tag */ |
||
1080 | 0, /* bitfield */ |
||
1081 | { /* type qualifiers */ |
||
1082 | tq_Nil, |
||
1083 | tq_Nil, |
||
1084 | tq_Nil, |
||
1085 | tq_Nil, |
||
1086 | tq_Nil, |
||
1087 | tq_Nil, |
||
1088 | }, |
||
1089 | { /* dimensions */ |
||
1090 | 0, |
||
1091 | 0, |
||
1092 | 0, |
||
1093 | 0, |
||
1094 | 0, |
||
1095 | |||
1096 | }, |
||
1097 | { /* sizes */ |
||
1098 | 0, |
||
1099 | 0, |
||
1100 | 0, |
||
1101 | 0, |
||
1102 | 0, |
||
1103 | 0, |
||
1104 | 0, |
||
1105 | 0, |
||
1106 | }, |
||
1107 | }; |
||
1108 | |||
1109 | /* Global hash table for the tags table and global table for file |
||
1110 | descriptors. */ |
||
1111 | |||
1112 | static varray_t file_desc = INIT_VARRAY (efdr_t); |
||
1113 | |||
1114 | static struct hash_control *tag_hash; |
||
1115 | |||
1116 | /* Static types for int and void. Also, remember the last function's |
||
1117 | type (which is set up when we encounter the declaration for the |
||
1118 | function, and used when the end block for the function is emitted. */ |
||
1119 | |||
1120 | static type_info_t int_type_info; |
||
1121 | static type_info_t void_type_info; |
||
1122 | static type_info_t last_func_type_info; |
||
1123 | static symbolS *last_func_sym_value; |
||
1124 | |||
1125 | /* Convert COFF basic type to ECOFF basic type. The T_NULL type |
||
1126 | really should use bt_Void, but this causes the current ecoff GDB to |
||
1127 | issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS |
||
1128 | 2.0) doesn't understand it, even though the compiler generates it. |
||
1129 | Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler |
||
1130 | suite, but for now go with what works. |
||
1131 | |||
1132 | It would make sense for the .type and .scl directives to use the |
||
1133 | ECOFF numbers directly, rather than using the COFF numbers and |
||
1134 | mapping them. Unfortunately, this is historically what mips-tfile |
||
1135 | expects, and changing gcc now would be a considerable pain (the |
||
1136 | native compiler generates debugging information internally, rather |
||
1137 | than via the assembler, so it will never use .type or .scl). */ |
||
1138 | |||
1139 | static const bt_t map_coff_types[] = { |
||
1140 | bt_Nil, /* T_NULL */ |
||
1141 | bt_Nil, /* T_ARG */ |
||
1142 | bt_Char, /* T_CHAR */ |
||
1143 | bt_Short, /* T_SHORT */ |
||
1144 | bt_Int, /* T_INT */ |
||
1145 | bt_Long, /* T_LONG */ |
||
1146 | bt_Float, /* T_FLOAT */ |
||
1147 | bt_Double, /* T_DOUBLE */ |
||
1148 | bt_Struct, /* T_STRUCT */ |
||
1149 | bt_Union, /* T_UNION */ |
||
1150 | bt_Enum, /* T_ENUM */ |
||
1151 | bt_Enum, /* T_MOE */ |
||
1152 | bt_UChar, /* T_UCHAR */ |
||
1153 | bt_UShort, /* T_USHORT */ |
||
1154 | bt_UInt, /* T_UINT */ |
||
1155 | bt_ULong /* T_ULONG */ |
||
1156 | }; |
||
1157 | |||
1158 | /* Convert COFF storage class to ECOFF storage class. */ |
||
1159 | static const sc_t map_coff_storage[] = { |
||
1160 | sc_Nil, /* 0: C_NULL */ |
||
1161 | sc_Abs, /* 1: C_AUTO auto var */ |
||
1162 | sc_Undefined, /* 2: C_EXT external */ |
||
1163 | sc_Data, /* 3: C_STAT static */ |
||
1164 | sc_Register, /* 4: C_REG register */ |
||
1165 | sc_Undefined, /* 5: C_EXTDEF ??? */ |
||
1166 | sc_Text, /* 6: C_LABEL label */ |
||
1167 | sc_Text, /* 7: C_ULABEL user label */ |
||
1168 | sc_Info, /* 8: C_MOS member of struct */ |
||
1169 | sc_Abs, /* 9: C_ARG argument */ |
||
1170 | sc_Info, /* 10: C_STRTAG struct tag */ |
||
1171 | sc_Info, /* 11: C_MOU member of union */ |
||
1172 | sc_Info, /* 12: C_UNTAG union tag */ |
||
1173 | sc_Info, /* 13: C_TPDEF typedef */ |
||
1174 | sc_Data, /* 14: C_USTATIC ??? */ |
||
1175 | sc_Info, /* 15: C_ENTAG enum tag */ |
||
1176 | sc_Info, /* 16: C_MOE member of enum */ |
||
1177 | sc_Register, /* 17: C_REGPARM register parameter */ |
||
1178 | sc_Bits, /* 18; C_FIELD bitfield */ |
||
1179 | sc_Nil, /* 19 */ |
||
1180 | sc_Nil, /* 20 */ |
||
1181 | sc_Nil, /* 21 */ |
||
1182 | sc_Nil, /* 22 */ |
||
1183 | sc_Nil, /* 23 */ |
||
1184 | sc_Nil, /* 24 */ |
||
1185 | sc_Nil, /* 25 */ |
||
1186 | sc_Nil, /* 26 */ |
||
1187 | sc_Nil, /* 27 */ |
||
1188 | sc_Nil, /* 28 */ |
||
1189 | sc_Nil, /* 29 */ |
||
1190 | sc_Nil, /* 30 */ |
||
1191 | sc_Nil, /* 31 */ |
||
1192 | sc_Nil, /* 32 */ |
||
1193 | sc_Nil, /* 33 */ |
||
1194 | sc_Nil, /* 34 */ |
||
1195 | sc_Nil, /* 35 */ |
||
1196 | sc_Nil, /* 36 */ |
||
1197 | sc_Nil, /* 37 */ |
||
1198 | sc_Nil, /* 38 */ |
||
1199 | sc_Nil, /* 39 */ |
||
1200 | sc_Nil, /* 40 */ |
||
1201 | sc_Nil, /* 41 */ |
||
1202 | sc_Nil, /* 42 */ |
||
1203 | sc_Nil, /* 43 */ |
||
1204 | sc_Nil, /* 44 */ |
||
1205 | sc_Nil, /* 45 */ |
||
1206 | sc_Nil, /* 46 */ |
||
1207 | sc_Nil, /* 47 */ |
||
1208 | sc_Nil, /* 48 */ |
||
1209 | sc_Nil, /* 49 */ |
||
1210 | sc_Nil, /* 50 */ |
||
1211 | sc_Nil, /* 51 */ |
||
1212 | sc_Nil, /* 52 */ |
||
1213 | sc_Nil, /* 53 */ |
||
1214 | sc_Nil, /* 54 */ |
||
1215 | sc_Nil, /* 55 */ |
||
1216 | sc_Nil, /* 56 */ |
||
1217 | sc_Nil, /* 57 */ |
||
1218 | sc_Nil, /* 58 */ |
||
1219 | sc_Nil, /* 59 */ |
||
1220 | sc_Nil, /* 60 */ |
||
1221 | sc_Nil, /* 61 */ |
||
1222 | sc_Nil, /* 62 */ |
||
1223 | sc_Nil, /* 63 */ |
||
1224 | sc_Nil, /* 64 */ |
||
1225 | sc_Nil, /* 65 */ |
||
1226 | sc_Nil, /* 66 */ |
||
1227 | sc_Nil, /* 67 */ |
||
1228 | sc_Nil, /* 68 */ |
||
1229 | sc_Nil, /* 69 */ |
||
1230 | sc_Nil, /* 70 */ |
||
1231 | sc_Nil, /* 71 */ |
||
1232 | sc_Nil, /* 72 */ |
||
1233 | sc_Nil, /* 73 */ |
||
1234 | sc_Nil, /* 74 */ |
||
1235 | sc_Nil, /* 75 */ |
||
1236 | sc_Nil, /* 76 */ |
||
1237 | sc_Nil, /* 77 */ |
||
1238 | sc_Nil, /* 78 */ |
||
1239 | sc_Nil, /* 79 */ |
||
1240 | sc_Nil, /* 80 */ |
||
1241 | sc_Nil, /* 81 */ |
||
1242 | sc_Nil, /* 82 */ |
||
1243 | sc_Nil, /* 83 */ |
||
1244 | sc_Nil, /* 84 */ |
||
1245 | sc_Nil, /* 85 */ |
||
1246 | sc_Nil, /* 86 */ |
||
1247 | sc_Nil, /* 87 */ |
||
1248 | sc_Nil, /* 88 */ |
||
1249 | sc_Nil, /* 89 */ |
||
1250 | sc_Nil, /* 90 */ |
||
1251 | sc_Nil, /* 91 */ |
||
1252 | sc_Nil, /* 92 */ |
||
1253 | sc_Nil, /* 93 */ |
||
1254 | sc_Nil, /* 94 */ |
||
1255 | sc_Nil, /* 95 */ |
||
1256 | sc_Nil, /* 96 */ |
||
1257 | sc_Nil, /* 97 */ |
||
1258 | sc_Nil, /* 98 */ |
||
1259 | sc_Nil, /* 99 */ |
||
1260 | sc_Text, /* 100: C_BLOCK block start/end */ |
||
1261 | sc_Text, /* 101: C_FCN function start/end */ |
||
1262 | sc_Info, /* 102: C_EOS end of struct/union/enum */ |
||
1263 | sc_Nil, /* 103: C_FILE file start */ |
||
1264 | sc_Nil, /* 104: C_LINE line number */ |
||
1265 | sc_Nil, /* 105: C_ALIAS combined type info */ |
||
1266 | sc_Nil, /* 106: C_HIDDEN ??? */ |
||
1267 | }; |
||
1268 | |||
1269 | /* Convert COFF storage class to ECOFF symbol type. */ |
||
1270 | static const st_t map_coff_sym_type[] = { |
||
1271 | st_Nil, /* 0: C_NULL */ |
||
1272 | st_Local, /* 1: C_AUTO auto var */ |
||
1273 | st_Global, /* 2: C_EXT external */ |
||
1274 | st_Static, /* 3: C_STAT static */ |
||
1275 | st_Local, /* 4: C_REG register */ |
||
1276 | st_Global, /* 5: C_EXTDEF ??? */ |
||
1277 | st_Label, /* 6: C_LABEL label */ |
||
1278 | st_Label, /* 7: C_ULABEL user label */ |
||
1279 | st_Member, /* 8: C_MOS member of struct */ |
||
1280 | st_Param, /* 9: C_ARG argument */ |
||
1281 | st_Block, /* 10: C_STRTAG struct tag */ |
||
1282 | st_Member, /* 11: C_MOU member of union */ |
||
1283 | st_Block, /* 12: C_UNTAG union tag */ |
||
1284 | st_Typedef, /* 13: C_TPDEF typedef */ |
||
1285 | st_Static, /* 14: C_USTATIC ??? */ |
||
1286 | st_Block, /* 15: C_ENTAG enum tag */ |
||
1287 | st_Member, /* 16: C_MOE member of enum */ |
||
1288 | st_Param, /* 17: C_REGPARM register parameter */ |
||
1289 | st_Member, /* 18; C_FIELD bitfield */ |
||
1290 | st_Nil, /* 19 */ |
||
1291 | st_Nil, /* 20 */ |
||
1292 | st_Nil, /* 21 */ |
||
1293 | st_Nil, /* 22 */ |
||
1294 | st_Nil, /* 23 */ |
||
1295 | st_Nil, /* 24 */ |
||
1296 | st_Nil, /* 25 */ |
||
1297 | st_Nil, /* 26 */ |
||
1298 | st_Nil, /* 27 */ |
||
1299 | st_Nil, /* 28 */ |
||
1300 | st_Nil, /* 29 */ |
||
1301 | st_Nil, /* 30 */ |
||
1302 | st_Nil, /* 31 */ |
||
1303 | st_Nil, /* 32 */ |
||
1304 | st_Nil, /* 33 */ |
||
1305 | st_Nil, /* 34 */ |
||
1306 | st_Nil, /* 35 */ |
||
1307 | st_Nil, /* 36 */ |
||
1308 | st_Nil, /* 37 */ |
||
1309 | st_Nil, /* 38 */ |
||
1310 | st_Nil, /* 39 */ |
||
1311 | st_Nil, /* 40 */ |
||
1312 | st_Nil, /* 41 */ |
||
1313 | st_Nil, /* 42 */ |
||
1314 | st_Nil, /* 43 */ |
||
1315 | st_Nil, /* 44 */ |
||
1316 | st_Nil, /* 45 */ |
||
1317 | st_Nil, /* 46 */ |
||
1318 | st_Nil, /* 47 */ |
||
1319 | st_Nil, /* 48 */ |
||
1320 | st_Nil, /* 49 */ |
||
1321 | st_Nil, /* 50 */ |
||
1322 | st_Nil, /* 51 */ |
||
1323 | st_Nil, /* 52 */ |
||
1324 | st_Nil, /* 53 */ |
||
1325 | st_Nil, /* 54 */ |
||
1326 | st_Nil, /* 55 */ |
||
1327 | st_Nil, /* 56 */ |
||
1328 | st_Nil, /* 57 */ |
||
1329 | st_Nil, /* 58 */ |
||
1330 | st_Nil, /* 59 */ |
||
1331 | st_Nil, /* 60 */ |
||
1332 | st_Nil, /* 61 */ |
||
1333 | st_Nil, /* 62 */ |
||
1334 | st_Nil, /* 63 */ |
||
1335 | st_Nil, /* 64 */ |
||
1336 | st_Nil, /* 65 */ |
||
1337 | st_Nil, /* 66 */ |
||
1338 | st_Nil, /* 67 */ |
||
1339 | st_Nil, /* 68 */ |
||
1340 | st_Nil, /* 69 */ |
||
1341 | st_Nil, /* 70 */ |
||
1342 | st_Nil, /* 71 */ |
||
1343 | st_Nil, /* 72 */ |
||
1344 | st_Nil, /* 73 */ |
||
1345 | st_Nil, /* 74 */ |
||
1346 | st_Nil, /* 75 */ |
||
1347 | st_Nil, /* 76 */ |
||
1348 | st_Nil, /* 77 */ |
||
1349 | st_Nil, /* 78 */ |
||
1350 | st_Nil, /* 79 */ |
||
1351 | st_Nil, /* 80 */ |
||
1352 | st_Nil, /* 81 */ |
||
1353 | st_Nil, /* 82 */ |
||
1354 | st_Nil, /* 83 */ |
||
1355 | st_Nil, /* 84 */ |
||
1356 | st_Nil, /* 85 */ |
||
1357 | st_Nil, /* 86 */ |
||
1358 | st_Nil, /* 87 */ |
||
1359 | st_Nil, /* 88 */ |
||
1360 | st_Nil, /* 89 */ |
||
1361 | st_Nil, /* 90 */ |
||
1362 | st_Nil, /* 91 */ |
||
1363 | st_Nil, /* 92 */ |
||
1364 | st_Nil, /* 93 */ |
||
1365 | st_Nil, /* 94 */ |
||
1366 | st_Nil, /* 95 */ |
||
1367 | st_Nil, /* 96 */ |
||
1368 | st_Nil, /* 97 */ |
||
1369 | st_Nil, /* 98 */ |
||
1370 | st_Nil, /* 99 */ |
||
1371 | st_Block, /* 100: C_BLOCK block start/end */ |
||
1372 | st_Proc, /* 101: C_FCN function start/end */ |
||
1373 | st_End, /* 102: C_EOS end of struct/union/enum */ |
||
1374 | st_File, /* 103: C_FILE file start */ |
||
1375 | st_Nil, /* 104: C_LINE line number */ |
||
1376 | st_Nil, /* 105: C_ALIAS combined type info */ |
||
1377 | st_Nil, /* 106: C_HIDDEN ??? */ |
||
1378 | }; |
||
1379 | |||
1380 | /* Keep track of different sized allocation requests. */ |
||
1381 | static alloc_info_t alloc_counts[(int) alloc_type_last]; |
||
1382 | |||
1383 | /* Record whether we have seen any debugging information. */ |
||
1384 | int ecoff_debugging_seen = 0; |
||
1385 | |||
1386 | /* Various statics. */ |
||
1387 | static efdr_t *cur_file_ptr = (efdr_t *) 0; /* current file desc. header */ |
||
1388 | static proc_t *cur_proc_ptr = (proc_t *) 0; /* current procedure header */ |
||
1389 | static proc_t *first_proc_ptr = (proc_t *) 0; /* first procedure header */ |
||
1390 | static thead_t *top_tag_head = (thead_t *) 0; /* top level tag head */ |
||
1391 | static thead_t *cur_tag_head = (thead_t *) 0; /* current tag head */ |
||
1392 | #ifdef ECOFF_DEBUG |
||
1393 | static int debug = 0; /* trace functions */ |
||
1394 | #endif |
||
1395 | static int stabs_seen = 0; /* != 0 if stabs have been seen */ |
||
1396 | |||
1397 | static int current_file_idx; |
||
1398 | static const char *current_stabs_filename; |
||
1399 | |||
1400 | /* Pseudo symbol to use when putting stabs into the symbol table. */ |
||
1401 | #ifndef STABS_SYMBOL |
||
1402 | #define STABS_SYMBOL "@stabs" |
||
1403 | #endif |
||
1404 | |||
1405 | static char stabs_symbol[] = STABS_SYMBOL; |
||
1406 | |||
1407 | /* Prototypes for functions defined in this file. */ |
||
1408 | |||
1409 | static void add_varray_page (varray_t *vp); |
||
1410 | static symint_t add_string (varray_t *vp, |
||
1411 | struct hash_control *hash_tbl, |
||
1412 | const char *str, |
||
1413 | shash_t **ret_hash); |
||
1414 | static localsym_t *add_ecoff_symbol (const char *str, st_t type, |
||
1415 | sc_t storage, symbolS *sym, |
||
1416 | bfd_vma addend, symint_t value, |
||
1417 | symint_t indx); |
||
1418 | static symint_t add_aux_sym_symint (symint_t aux_word); |
||
1419 | static symint_t add_aux_sym_rndx (int file_index, symint_t sym_index); |
||
1420 | static symint_t add_aux_sym_tir (type_info_t *t, |
||
1421 | hash_state_t state, |
||
1422 | thash_t **hash_tbl); |
||
1423 | static tag_t *get_tag (const char *tag, localsym_t *sym, bt_t basic_type); |
||
1424 | static void add_unknown_tag (tag_t *ptag); |
||
1425 | static void add_procedure (char *func); |
||
1426 | static void add_file (const char *file_name, int indx, int fake); |
||
1427 | #ifdef ECOFF_DEBUG |
||
1428 | static char *sc_to_string (sc_t storage_class); |
||
1429 | static char *st_to_string (st_t symbol_type); |
||
1430 | #endif |
||
1431 | static void mark_stabs (int); |
||
1432 | static char *ecoff_add_bytes (char **buf, char **bufend, |
||
1433 | char *bufptr, unsigned long need); |
||
1434 | static unsigned long ecoff_padding_adjust |
||
1435 | (const struct ecoff_debug_swap *backend, char **buf, char **bufend, |
||
1436 | unsigned long offset, char **bufptrptr); |
||
1437 | static unsigned long ecoff_build_lineno |
||
1438 | (const struct ecoff_debug_swap *backend, char **buf, char **bufend, |
||
1439 | unsigned long offset, long *linecntptr); |
||
1440 | static unsigned long ecoff_build_symbols |
||
1441 | (const struct ecoff_debug_swap *backend, char **buf, char **bufend, |
||
1442 | unsigned long offset); |
||
1443 | static unsigned long ecoff_build_procs |
||
1444 | (const struct ecoff_debug_swap *backend, char **buf, char **bufend, |
||
1445 | unsigned long offset); |
||
1446 | static unsigned long ecoff_build_aux |
||
1447 | (const struct ecoff_debug_swap *backend, char **buf, char **bufend, |
||
1448 | unsigned long offset); |
||
1449 | static unsigned long ecoff_build_strings (char **buf, char **bufend, |
||
1450 | unsigned long offset, |
||
1451 | varray_t *vp); |
||
1452 | static unsigned long ecoff_build_ss |
||
1453 | (const struct ecoff_debug_swap *backend, char **buf, char **bufend, |
||
1454 | unsigned long offset); |
||
1455 | static unsigned long ecoff_build_fdr |
||
1456 | (const struct ecoff_debug_swap *backend, char **buf, char **bufend, |
||
1457 | unsigned long offset); |
||
1458 | static void ecoff_setup_ext (void); |
||
1459 | static page_type *allocate_cluster (unsigned long npages); |
||
1460 | static page_type *allocate_page (void); |
||
1461 | static scope_t *allocate_scope (void); |
||
1462 | static void free_scope (scope_t *ptr); |
||
1463 | static vlinks_t *allocate_vlinks (void); |
||
1464 | static shash_t *allocate_shash (void); |
||
1465 | static thash_t *allocate_thash (void); |
||
1466 | static tag_t *allocate_tag (void); |
||
1467 | static void free_tag (tag_t *ptr); |
||
1468 | static forward_t *allocate_forward (void); |
||
1469 | static thead_t *allocate_thead (void); |
||
1470 | static void free_thead (thead_t *ptr); |
||
1471 | static lineno_list_t *allocate_lineno_list (void); |
||
1472 | |||
1473 | /* This function should be called when the assembler starts up. */ |
||
1474 | |||
1475 | void |
||
1476 | ecoff_read_begin_hook (void) |
||
1477 | { |
||
1478 | tag_hash = hash_new (); |
||
1479 | top_tag_head = allocate_thead (); |
||
1480 | top_tag_head->first_tag = (tag_t *) NULL; |
||
1481 | top_tag_head->free = (thead_t *) NULL; |
||
1482 | top_tag_head->prev = cur_tag_head; |
||
1483 | cur_tag_head = top_tag_head; |
||
1484 | } |
||
1485 | |||
1486 | /* This function should be called when a symbol is created. */ |
||
1487 | |||
1488 | void |
||
1489 | ecoff_symbol_new_hook (symbolS *symbolP) |
||
1490 | { |
||
1491 | OBJ_SYMFIELD_TYPE *obj; |
||
1492 | |||
1493 | /* Make sure that we have a file pointer, but only if we have seen a |
||
1494 | file. If we haven't seen a file, then this is a probably special |
||
1495 | symbol created by md_begin which may required special handling at |
||
1496 | some point. Creating a dummy file with a dummy name is certainly |
||
1497 | wrong. */ |
||
1498 | if (cur_file_ptr == (efdr_t *) NULL |
||
1499 | && seen_at_least_1_file ()) |
||
1500 | add_file ((const char *) NULL, 0, 1); |
||
1501 | obj = symbol_get_obj (symbolP); |
||
1502 | obj->ecoff_file = cur_file_ptr; |
||
1503 | obj->ecoff_symbol = NULL; |
||
1504 | obj->ecoff_extern_size = 0; |
||
1505 | } |
||
1506 | |||
1507 | void |
||
1508 | ecoff_symbol_clone_hook (symbolS *newsymP, symbolS *orgsymP) |
||
1509 | { |
||
1510 | OBJ_SYMFIELD_TYPE *n, *o; |
||
1511 | |||
1512 | n = symbol_get_obj (newsymP); |
||
1513 | o = symbol_get_obj (orgsymP); |
||
1514 | memcpy (n, o, sizeof *n); |
||
1515 | } |
||
1516 | |||
1517 | /* Add a page to a varray object. */ |
||
1518 | |||
1519 | static void |
||
1520 | add_varray_page (varray_t *vp /* varray to add page to */) |
||
1521 | { |
||
1522 | vlinks_t *new_links = allocate_vlinks (); |
||
1523 | |||
1524 | #ifdef MALLOC_CHECK |
||
1525 | if (vp->object_size > 1) |
||
1526 | new_links->datum = (page_type *) xcalloc (1, vp->object_size); |
||
1527 | else |
||
1528 | #endif |
||
1529 | new_links->datum = allocate_page (); |
||
1530 | |||
1531 | alloc_counts[(int) alloc_type_varray].total_alloc++; |
||
1532 | alloc_counts[(int) alloc_type_varray].total_pages++; |
||
1533 | |||
1534 | new_links->start_index = vp->num_allocated; |
||
1535 | vp->objects_last_page = 0; |
||
1536 | |||
1537 | if (vp->first == (vlinks_t *) NULL) /* first allocation? */ |
||
1538 | vp->first = vp->last = new_links; |
||
1539 | else |
||
1540 | { /* 2nd or greater allocation */ |
||
1541 | new_links->prev = vp->last; |
||
1542 | vp->last->next = new_links; |
||
1543 | vp->last = new_links; |
||
1544 | } |
||
1545 | } |
||
1546 | |||
1547 | /* Add a string (and null pad) to one of the string tables. */ |
||
1548 | |||
1549 | static symint_t |
||
1550 | add_string (varray_t *vp, /* string obstack */ |
||
1551 | struct hash_control *hash_tbl, /* ptr to hash table */ |
||
1552 | const char *str, /* string */ |
||
1553 | shash_t **ret_hash /* return hash pointer */) |
||
1554 | { |
||
6324 | serge | 1555 | unsigned long len = strlen (str); |
1556 | shash_t *hash_ptr; |
||
5222 | serge | 1557 | |
1558 | if (len >= PAGE_USIZE) |
||
1559 | as_fatal (_("string too big (%lu bytes)"), len); |
||
1560 | |||
1561 | hash_ptr = (shash_t *) hash_find (hash_tbl, str); |
||
1562 | if (hash_ptr == (shash_t *) NULL) |
||
1563 | { |
||
6324 | serge | 1564 | const char *err; |
5222 | serge | 1565 | |
1566 | if (vp->objects_last_page + len >= PAGE_USIZE) |
||
1567 | { |
||
1568 | vp->num_allocated = |
||
1569 | ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE; |
||
1570 | add_varray_page (vp); |
||
1571 | } |
||
1572 | |||
1573 | hash_ptr = allocate_shash (); |
||
1574 | hash_ptr->indx = vp->num_allocated; |
||
1575 | |||
1576 | hash_ptr->string = &vp->last->datum->byte[vp->objects_last_page]; |
||
1577 | |||
1578 | vp->objects_last_page += len + 1; |
||
1579 | vp->num_allocated += len + 1; |
||
1580 | |||
1581 | strcpy (hash_ptr->string, str); |
||
1582 | |||
1583 | err = hash_insert (hash_tbl, str, (char *) hash_ptr); |
||
1584 | if (err) |
||
1585 | as_fatal (_("inserting \"%s\" into string hash table: %s"), |
||
1586 | str, err); |
||
1587 | } |
||
1588 | |||
1589 | if (ret_hash != (shash_t **) NULL) |
||
1590 | *ret_hash = hash_ptr; |
||
1591 | |||
1592 | return hash_ptr->indx; |
||
1593 | } |
||
1594 | |||
1595 | /* Add debugging information for a symbol. */ |
||
1596 | |||
1597 | static localsym_t * |
||
1598 | add_ecoff_symbol (const char *str, /* symbol name */ |
||
1599 | st_t type, /* symbol type */ |
||
1600 | sc_t storage, /* storage class */ |
||
1601 | symbolS *sym_value, /* associated symbol. */ |
||
1602 | bfd_vma addend, /* addend to sym_value. */ |
||
1603 | symint_t value, /* value of symbol */ |
||
1604 | symint_t indx /* index to local/aux. syms */) |
||
1605 | { |
||
1606 | localsym_t *psym; |
||
6324 | serge | 1607 | scope_t *pscope; |
1608 | thead_t *ptag_head; |
||
1609 | tag_t *ptag; |
||
1610 | tag_t *ptag_next; |
||
1611 | varray_t *vp; |
||
1612 | int scope_delta = 0; |
||
5222 | serge | 1613 | shash_t *hash_ptr = (shash_t *) NULL; |
1614 | |||
1615 | if (cur_file_ptr == (efdr_t *) NULL) |
||
1616 | as_fatal (_("no current file pointer")); |
||
1617 | |||
1618 | vp = &cur_file_ptr->symbols; |
||
1619 | |||
1620 | if (vp->objects_last_page == vp->objects_per_page) |
||
1621 | add_varray_page (vp); |
||
1622 | |||
1623 | psym = &vp->last->datum->sym[vp->objects_last_page++]; |
||
1624 | |||
1625 | if (str == (const char *) NULL && sym_value != (symbolS *) NULL) |
||
1626 | psym->name = S_GET_NAME (sym_value); |
||
1627 | else |
||
1628 | psym->name = str; |
||
1629 | psym->as_sym = sym_value; |
||
1630 | if (sym_value != (symbolS *) NULL) |
||
1631 | symbol_get_obj (sym_value)->ecoff_symbol = psym; |
||
1632 | psym->addend = addend; |
||
1633 | psym->file_ptr = cur_file_ptr; |
||
1634 | psym->proc_ptr = cur_proc_ptr; |
||
1635 | psym->begin_ptr = (localsym_t *) NULL; |
||
1636 | psym->index_ptr = (aux_t *) NULL; |
||
1637 | psym->forward_ref = (forward_t *) NULL; |
||
1638 | psym->sym_index = -1; |
||
1639 | memset (&psym->ecoff_sym, 0, sizeof (EXTR)); |
||
1640 | psym->ecoff_sym.asym.value = value; |
||
1641 | psym->ecoff_sym.asym.st = (unsigned) type; |
||
1642 | psym->ecoff_sym.asym.sc = (unsigned) storage; |
||
1643 | psym->ecoff_sym.asym.index = indx; |
||
1644 | |||
1645 | /* If there is an associated symbol, we wait until the end of the |
||
1646 | assembly before deciding where to put the name (it may be just an |
||
1647 | external symbol). Otherwise, this is just a debugging symbol and |
||
1648 | the name should go with the current file. */ |
||
1649 | if (sym_value == (symbolS *) NULL) |
||
1650 | psym->ecoff_sym.asym.iss = ((str == (const char *) NULL) |
||
1651 | ? 0 |
||
1652 | : add_string (&cur_file_ptr->strings, |
||
1653 | cur_file_ptr->str_hash, |
||
1654 | str, |
||
1655 | &hash_ptr)); |
||
1656 | |||
1657 | ++vp->num_allocated; |
||
1658 | |||
1659 | if (ECOFF_IS_STAB (&psym->ecoff_sym.asym)) |
||
1660 | return psym; |
||
1661 | |||
1662 | /* Save the symbol within the hash table if this is a static |
||
1663 | item, and it has a name. */ |
||
1664 | if (hash_ptr != (shash_t *) NULL |
||
1665 | && (type == st_Global || type == st_Static || type == st_Label |
||
1666 | || type == st_Proc || type == st_StaticProc)) |
||
1667 | hash_ptr->sym_ptr = psym; |
||
1668 | |||
1669 | /* push or pop a scope if appropriate. */ |
||
1670 | switch (type) |
||
1671 | { |
||
1672 | default: |
||
1673 | break; |
||
1674 | |||
1675 | case st_File: /* beginning of file */ |
||
1676 | case st_Proc: /* procedure */ |
||
1677 | case st_StaticProc: /* static procedure */ |
||
1678 | case st_Block: /* begin scope */ |
||
1679 | pscope = allocate_scope (); |
||
1680 | pscope->prev = cur_file_ptr->cur_scope; |
||
1681 | pscope->lsym = psym; |
||
1682 | pscope->type = type; |
||
1683 | cur_file_ptr->cur_scope = pscope; |
||
1684 | |||
1685 | if (type != st_File) |
||
1686 | scope_delta = 1; |
||
1687 | |||
1688 | /* For every block type except file, struct, union, or |
||
1689 | enumeration blocks, push a level on the tag stack. We omit |
||
1690 | file types, so that tags can span file boundaries. */ |
||
1691 | if (type != st_File && storage != sc_Info) |
||
1692 | { |
||
1693 | ptag_head = allocate_thead (); |
||
1694 | ptag_head->first_tag = 0; |
||
1695 | ptag_head->prev = cur_tag_head; |
||
1696 | cur_tag_head = ptag_head; |
||
1697 | } |
||
1698 | break; |
||
1699 | |||
1700 | case st_End: |
||
1701 | pscope = cur_file_ptr->cur_scope; |
||
1702 | if (pscope == (scope_t *) NULL) |
||
1703 | as_fatal (_("too many st_End's")); |
||
1704 | else |
||
1705 | { |
||
1706 | st_t begin_type = (st_t) pscope->lsym->ecoff_sym.asym.st; |
||
1707 | |||
1708 | psym->begin_ptr = pscope->lsym; |
||
1709 | |||
1710 | if (begin_type != st_File) |
||
1711 | scope_delta = -1; |
||
1712 | |||
1713 | /* Except for file, structure, union, or enumeration end |
||
1714 | blocks remove all tags created within this scope. */ |
||
1715 | if (begin_type != st_File && storage != sc_Info) |
||
1716 | { |
||
1717 | ptag_head = cur_tag_head; |
||
1718 | cur_tag_head = ptag_head->prev; |
||
1719 | |||
1720 | for (ptag = ptag_head->first_tag; |
||
1721 | ptag != (tag_t *) NULL; |
||
1722 | ptag = ptag_next) |
||
1723 | { |
||
1724 | if (ptag->forward_ref != (forward_t *) NULL) |
||
1725 | add_unknown_tag (ptag); |
||
1726 | |||
1727 | ptag_next = ptag->same_block; |
||
1728 | ptag->hash_ptr->tag_ptr = ptag->same_name; |
||
1729 | free_tag (ptag); |
||
1730 | } |
||
1731 | |||
1732 | free_thead (ptag_head); |
||
1733 | } |
||
1734 | |||
1735 | cur_file_ptr->cur_scope = pscope->prev; |
||
1736 | |||
1737 | /* block begin gets next sym #. This is set when we know |
||
1738 | the symbol index value. */ |
||
1739 | |||
1740 | /* Functions push two or more aux words as follows: |
||
1741 | 1st word: index+1 of the end symbol (filled in later). |
||
1742 | 2nd word: type of the function (plus any aux words needed). |
||
1743 | Also, tie the external pointer back to the function begin symbol. */ |
||
1744 | if (begin_type != st_File && begin_type != st_Block) |
||
1745 | { |
||
1746 | symint_t ty; |
||
1747 | varray_t *svp = &cur_file_ptr->aux_syms; |
||
1748 | |||
1749 | pscope->lsym->ecoff_sym.asym.index = add_aux_sym_symint (0); |
||
1750 | pscope->lsym->index_ptr = |
||
1751 | &svp->last->datum->aux[svp->objects_last_page - 1]; |
||
1752 | ty = add_aux_sym_tir (&last_func_type_info, |
||
1753 | hash_no, |
||
1754 | &cur_file_ptr->thash_head[0]); |
||
1755 | (void) ty; |
||
1756 | /* This seems to be unnecessary. I'm not even sure what it is |
||
1757 | * intended to do. It's from mips-tfile. |
||
1758 | * if (last_func_sym_value != (symbolS *) NULL) |
||
1759 | * { |
||
1760 | * last_func_sym_value->ifd = cur_file_ptr->file_index; |
||
1761 | * last_func_sym_value->index = ty; |
||
1762 | * } |
||
1763 | */ |
||
1764 | } |
||
1765 | |||
1766 | free_scope (pscope); |
||
1767 | } |
||
1768 | } |
||
1769 | |||
1770 | cur_file_ptr->nested_scopes += scope_delta; |
||
1771 | |||
1772 | #ifdef ECOFF_DEBUG |
||
1773 | if (debug && type != st_File |
||
1774 | && (debug > 2 || type == st_Block || type == st_End |
||
1775 | || type == st_Proc || type == st_StaticProc)) |
||
1776 | { |
||
1777 | char *sc_str = sc_to_string (storage); |
||
1778 | char *st_str = st_to_string (type); |
||
1779 | int depth = cur_file_ptr->nested_scopes + (scope_delta < 0); |
||
1780 | |||
1781 | fprintf (stderr, |
||
1782 | "\tlsym\tv= %10ld, depth= %2d, sc= %-12s", |
||
1783 | value, depth, sc_str); |
||
1784 | |||
1785 | if (str_start && str_end_p1 - str_start > 0) |
||
1786 | fprintf (stderr, " st= %-11s name= %.*s\n", |
||
1787 | st_str, str_end_p1 - str_start, str_start); |
||
1788 | else |
||
1789 | { |
||
1790 | unsigned long len = strlen (st_str); |
||
1791 | fprintf (stderr, " st= %.*s\n", len - 1, st_str); |
||
1792 | } |
||
1793 | } |
||
1794 | #endif |
||
1795 | |||
1796 | return psym; |
||
1797 | } |
||
1798 | |||
1799 | /* Add an auxiliary symbol (passing a symint). This is actually used |
||
1800 | for integral aux types, not just symints. */ |
||
1801 | |||
1802 | static symint_t |
||
1803 | add_aux_sym_symint (symint_t aux_word /* auxiliary information word */) |
||
1804 | { |
||
6324 | serge | 1805 | varray_t *vp; |
1806 | aux_t *aux_ptr; |
||
5222 | serge | 1807 | |
1808 | if (cur_file_ptr == (efdr_t *) NULL) |
||
1809 | as_fatal (_("no current file pointer")); |
||
1810 | |||
1811 | vp = &cur_file_ptr->aux_syms; |
||
1812 | |||
1813 | if (vp->objects_last_page == vp->objects_per_page) |
||
1814 | add_varray_page (vp); |
||
1815 | |||
1816 | aux_ptr = &vp->last->datum->aux[vp->objects_last_page++]; |
||
1817 | aux_ptr->type = aux_isym; |
||
1818 | aux_ptr->data.isym = aux_word; |
||
1819 | |||
1820 | return vp->num_allocated++; |
||
1821 | } |
||
1822 | |||
1823 | /* Add an auxiliary symbol (passing a file/symbol index combo). */ |
||
1824 | |||
1825 | static symint_t |
||
1826 | add_aux_sym_rndx (int file_index, symint_t sym_index) |
||
1827 | { |
||
6324 | serge | 1828 | varray_t *vp; |
1829 | aux_t *aux_ptr; |
||
5222 | serge | 1830 | |
1831 | if (cur_file_ptr == (efdr_t *) NULL) |
||
1832 | as_fatal (_("no current file pointer")); |
||
1833 | |||
1834 | vp = &cur_file_ptr->aux_syms; |
||
1835 | |||
1836 | if (vp->objects_last_page == vp->objects_per_page) |
||
1837 | add_varray_page (vp); |
||
1838 | |||
1839 | aux_ptr = &vp->last->datum->aux[vp->objects_last_page++]; |
||
1840 | aux_ptr->type = aux_rndx; |
||
1841 | aux_ptr->data.rndx.rfd = file_index; |
||
1842 | aux_ptr->data.rndx.index = sym_index; |
||
1843 | |||
1844 | return vp->num_allocated++; |
||
1845 | } |
||
1846 | |||
1847 | /* Add an auxiliary symbol (passing the basic type and possibly |
||
1848 | type qualifiers). */ |
||
1849 | |||
1850 | static symint_t |
||
1851 | add_aux_sym_tir (type_info_t *t, /* current type information */ |
||
1852 | hash_state_t state, /* whether to hash type or not */ |
||
1853 | thash_t **hash_tbl /* pointer to hash table to use */) |
||
1854 | { |
||
6324 | serge | 1855 | varray_t *vp; |
1856 | aux_t *aux_ptr; |
||
5222 | serge | 1857 | static AUXU init_aux; |
1858 | symint_t ret; |
||
1859 | int i; |
||
1860 | AUXU aux; |
||
1861 | |||
1862 | if (cur_file_ptr == (efdr_t *) NULL) |
||
1863 | as_fatal (_("no current file pointer")); |
||
1864 | |||
1865 | vp = &cur_file_ptr->aux_syms; |
||
1866 | |||
1867 | aux = init_aux; |
||
1868 | aux.ti.bt = (int) t->basic_type; |
||
1869 | aux.ti.continued = 0; |
||
1870 | aux.ti.fBitfield = t->bitfield; |
||
1871 | |||
1872 | aux.ti.tq0 = (int) t->type_qualifiers[0]; |
||
1873 | aux.ti.tq1 = (int) t->type_qualifiers[1]; |
||
1874 | aux.ti.tq2 = (int) t->type_qualifiers[2]; |
||
1875 | aux.ti.tq3 = (int) t->type_qualifiers[3]; |
||
1876 | aux.ti.tq4 = (int) t->type_qualifiers[4]; |
||
1877 | aux.ti.tq5 = (int) t->type_qualifiers[5]; |
||
1878 | |||
1879 | /* For anything that adds additional information, we must not hash, |
||
1880 | so check here, and reset our state. */ |
||
1881 | |||
1882 | if (state != hash_no |
||
1883 | && (t->type_qualifiers[0] == tq_Array |
||
1884 | || t->type_qualifiers[1] == tq_Array |
||
1885 | || t->type_qualifiers[2] == tq_Array |
||
1886 | || t->type_qualifiers[3] == tq_Array |
||
1887 | || t->type_qualifiers[4] == tq_Array |
||
1888 | || t->type_qualifiers[5] == tq_Array |
||
1889 | || t->basic_type == bt_Struct |
||
1890 | || t->basic_type == bt_Union |
||
1891 | || t->basic_type == bt_Enum |
||
1892 | || t->bitfield |
||
1893 | || t->num_dims > 0)) |
||
1894 | state = hash_no; |
||
1895 | |||
1896 | /* See if we can hash this type, and save some space, but some types |
||
1897 | can't be hashed (because they contain arrays or continuations), |
||
1898 | and others can be put into the hash list, but cannot use existing |
||
1899 | types because other aux entries precede this one. */ |
||
1900 | |||
1901 | if (state != hash_no) |
||
1902 | { |
||
6324 | serge | 1903 | thash_t *hash_ptr; |
1904 | symint_t hi; |
||
5222 | serge | 1905 | |
1906 | hi = aux.isym & ((1 << HASHBITS) - 1); |
||
1907 | hi %= THASH_SIZE; |
||
1908 | |||
1909 | for (hash_ptr = hash_tbl[hi]; |
||
1910 | hash_ptr != (thash_t *)0; |
||
1911 | hash_ptr = hash_ptr->next) |
||
1912 | { |
||
1913 | if (aux.isym == hash_ptr->type.isym) |
||
1914 | break; |
||
1915 | } |
||
1916 | |||
1917 | if (hash_ptr != (thash_t *) NULL && state == hash_yes) |
||
1918 | return hash_ptr->indx; |
||
1919 | |||
1920 | if (hash_ptr == (thash_t *) NULL) |
||
1921 | { |
||
1922 | hash_ptr = allocate_thash (); |
||
1923 | hash_ptr->next = hash_tbl[hi]; |
||
1924 | hash_ptr->type = aux; |
||
1925 | hash_ptr->indx = vp->num_allocated; |
||
1926 | hash_tbl[hi] = hash_ptr; |
||
1927 | } |
||
1928 | } |
||
1929 | |||
1930 | /* Everything is set up, add the aux symbol. */ |
||
1931 | if (vp->objects_last_page == vp->objects_per_page) |
||
1932 | add_varray_page (vp); |
||
1933 | |||
1934 | aux_ptr = &vp->last->datum->aux[vp->objects_last_page++]; |
||
1935 | aux_ptr->type = aux_tir; |
||
1936 | aux_ptr->data = aux; |
||
1937 | |||
1938 | ret = vp->num_allocated++; |
||
1939 | |||
1940 | /* Add bitfield length if it exists. |
||
1941 | |||
1942 | NOTE: Mips documentation claims bitfield goes at the end of the |
||
1943 | AUX record, but the DECstation compiler emits it here. |
||
1944 | (This would only make a difference for enum bitfields.) |
||
1945 | |||
1946 | Also note: We use the last size given since gcc may emit 2 |
||
1947 | for an enum bitfield. */ |
||
1948 | |||
1949 | if (t->bitfield) |
||
1950 | (void) add_aux_sym_symint ((symint_t) t->sizes[t->num_sizes - 1]); |
||
1951 | |||
1952 | /* Add tag information if needed. Structure, union, and enum |
||
1953 | references add 2 aux symbols: a [file index, symbol index] |
||
1954 | pointer to the structure type, and the current file index. */ |
||
1955 | |||
1956 | if (t->basic_type == bt_Struct |
||
1957 | || t->basic_type == bt_Union |
||
1958 | || t->basic_type == bt_Enum) |
||
1959 | { |
||
6324 | serge | 1960 | symint_t file_index = t->tag_ptr->ifd; |
1961 | localsym_t *sym = t->tag_ptr->sym; |
||
1962 | forward_t *forward_ref = allocate_forward (); |
||
5222 | serge | 1963 | |
1964 | if (sym != (localsym_t *) NULL) |
||
1965 | { |
||
1966 | forward_ref->next = sym->forward_ref; |
||
1967 | sym->forward_ref = forward_ref; |
||
1968 | } |
||
1969 | else |
||
1970 | { |
||
1971 | forward_ref->next = t->tag_ptr->forward_ref; |
||
1972 | t->tag_ptr->forward_ref = forward_ref; |
||
1973 | } |
||
1974 | |||
1975 | (void) add_aux_sym_rndx (ST_RFDESCAPE, indexNil); |
||
1976 | forward_ref->index_ptr |
||
1977 | = &vp->last->datum->aux[vp->objects_last_page - 1]; |
||
1978 | |||
1979 | (void) add_aux_sym_symint (file_index); |
||
1980 | forward_ref->ifd_ptr |
||
1981 | = &vp->last->datum->aux[vp->objects_last_page - 1]; |
||
1982 | } |
||
1983 | |||
1984 | /* Add information about array bounds if they exist. */ |
||
1985 | for (i = 0; i < t->num_dims; i++) |
||
1986 | { |
||
1987 | (void) add_aux_sym_rndx (ST_RFDESCAPE, |
||
1988 | cur_file_ptr->int_type); |
||
1989 | |||
1990 | (void) add_aux_sym_symint (cur_file_ptr->file_index); /* file index*/ |
||
1991 | (void) add_aux_sym_symint ((symint_t) 0); /* low bound */ |
||
1992 | (void) add_aux_sym_symint (t->dimensions[i] - 1); /* high bound*/ |
||
1993 | (void) add_aux_sym_symint ((t->dimensions[i] == 0) /* stride */ |
||
1994 | ? 0 |
||
1995 | : (t->sizes[i] * 8) / t->dimensions[i]); |
||
1996 | }; |
||
1997 | |||
1998 | /* NOTE: Mips documentation claims that the bitfield width goes here. |
||
1999 | But it needs to be emitted earlier. */ |
||
2000 | |||
2001 | return ret; |
||
2002 | } |
||
2003 | |||
2004 | /* Add a tag to the tag table (unless it already exists). */ |
||
2005 | |||
2006 | static tag_t * |
||
2007 | get_tag (const char *tag, /* tag name */ |
||
2008 | localsym_t *sym, /* tag start block */ |
||
2009 | bt_t basic_type /* bt_Struct, bt_Union, or bt_Enum */) |
||
2010 | { |
||
2011 | shash_t *hash_ptr; |
||
2012 | const char *err; |
||
2013 | tag_t *tag_ptr; |
||
2014 | |||
2015 | if (cur_file_ptr == (efdr_t *) NULL) |
||
2016 | as_fatal (_("no current file pointer")); |
||
2017 | |||
2018 | hash_ptr = (shash_t *) hash_find (tag_hash, tag); |
||
2019 | |||
2020 | if (hash_ptr != (shash_t *) NULL |
||
2021 | && hash_ptr->tag_ptr != (tag_t *) NULL) |
||
2022 | { |
||
2023 | tag_ptr = hash_ptr->tag_ptr; |
||
2024 | if (sym != (localsym_t *) NULL) |
||
2025 | { |
||
2026 | tag_ptr->basic_type = basic_type; |
||
2027 | tag_ptr->ifd = cur_file_ptr->file_index; |
||
2028 | tag_ptr->sym = sym; |
||
2029 | } |
||
2030 | return tag_ptr; |
||
2031 | } |
||
2032 | |||
2033 | if (hash_ptr == (shash_t *) NULL) |
||
2034 | { |
||
2035 | char *perm; |
||
2036 | |||
2037 | perm = xstrdup (tag); |
||
2038 | hash_ptr = allocate_shash (); |
||
2039 | err = hash_insert (tag_hash, perm, (char *) hash_ptr); |
||
2040 | if (err) |
||
2041 | as_fatal (_("inserting \"%s\" into tag hash table: %s"), |
||
2042 | tag, err); |
||
2043 | hash_ptr->string = perm; |
||
2044 | } |
||
2045 | |||
2046 | tag_ptr = allocate_tag (); |
||
2047 | tag_ptr->forward_ref = (forward_t *) NULL; |
||
2048 | tag_ptr->hash_ptr = hash_ptr; |
||
2049 | tag_ptr->same_name = hash_ptr->tag_ptr; |
||
2050 | tag_ptr->basic_type = basic_type; |
||
2051 | tag_ptr->sym = sym; |
||
2052 | tag_ptr->ifd = ((sym == (localsym_t *) NULL) |
||
2053 | ? (symint_t) -1 |
||
2054 | : cur_file_ptr->file_index); |
||
2055 | tag_ptr->same_block = cur_tag_head->first_tag; |
||
2056 | |||
2057 | cur_tag_head->first_tag = tag_ptr; |
||
2058 | hash_ptr->tag_ptr = tag_ptr; |
||
2059 | |||
2060 | return tag_ptr; |
||
2061 | } |
||
2062 | |||
2063 | /* Add an unknown {struct, union, enum} tag. */ |
||
2064 | |||
2065 | static void |
||
2066 | add_unknown_tag (tag_t *ptag /* pointer to tag information */) |
||
2067 | { |
||
2068 | shash_t *hash_ptr = ptag->hash_ptr; |
||
2069 | char *name = hash_ptr->string; |
||
2070 | localsym_t *sym; |
||
2071 | forward_t **pf; |
||
2072 | |||
2073 | #ifdef ECOFF_DEBUG |
||
2074 | if (debug > 1) |
||
2075 | { |
||
2076 | char *agg_type = "{unknown aggregate type}"; |
||
2077 | switch (ptag->basic_type) |
||
2078 | { |
||
2079 | case bt_Struct: agg_type = "struct"; break; |
||
2080 | case bt_Union: agg_type = "union"; break; |
||
2081 | case bt_Enum: agg_type = "enum"; break; |
||
2082 | default: break; |
||
2083 | } |
||
2084 | |||
2085 | fprintf (stderr, "unknown %s %.*s found\n", agg_type, |
||
2086 | hash_ptr->len, name_start); |
||
2087 | } |
||
2088 | #endif |
||
2089 | |||
2090 | sym = add_ecoff_symbol (name, |
||
2091 | st_Block, |
||
2092 | sc_Info, |
||
2093 | (symbolS *) NULL, |
||
2094 | (bfd_vma) 0, |
||
2095 | (symint_t) 0, |
||
2096 | (symint_t) 0); |
||
2097 | |||
2098 | (void) add_ecoff_symbol (name, |
||
2099 | st_End, |
||
2100 | sc_Info, |
||
2101 | (symbolS *) NULL, |
||
2102 | (bfd_vma) 0, |
||
2103 | (symint_t) 0, |
||
2104 | (symint_t) 0); |
||
2105 | |||
2106 | for (pf = &sym->forward_ref; *pf != (forward_t *) NULL; pf = &(*pf)->next) |
||
2107 | ; |
||
2108 | *pf = ptag->forward_ref; |
||
2109 | } |
||
2110 | |||
2111 | /* Add a procedure to the current file's list of procedures, and record |
||
2112 | this is the current procedure. */ |
||
2113 | |||
2114 | static void |
||
2115 | add_procedure (char *func /* func name */) |
||
2116 | { |
||
6324 | serge | 2117 | varray_t *vp; |
2118 | proc_t *new_proc_ptr; |
||
5222 | serge | 2119 | symbolS *sym; |
2120 | |||
2121 | #ifdef ECOFF_DEBUG |
||
2122 | if (debug) |
||
2123 | fputc ('\n', stderr); |
||
2124 | #endif |
||
2125 | |||
2126 | if (cur_file_ptr == (efdr_t *) NULL) |
||
2127 | as_fatal (_("no current file pointer")); |
||
2128 | |||
2129 | vp = &cur_file_ptr->procs; |
||
2130 | |||
2131 | if (vp->objects_last_page == vp->objects_per_page) |
||
2132 | add_varray_page (vp); |
||
2133 | |||
2134 | cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[vp->objects_last_page++]; |
||
2135 | |||
2136 | if (first_proc_ptr == (proc_t *) NULL) |
||
2137 | first_proc_ptr = new_proc_ptr; |
||
2138 | |||
2139 | vp->num_allocated++; |
||
2140 | |||
2141 | new_proc_ptr->pdr.isym = -1; |
||
2142 | new_proc_ptr->pdr.iline = -1; |
||
2143 | new_proc_ptr->pdr.lnLow = -1; |
||
2144 | new_proc_ptr->pdr.lnHigh = -1; |
||
2145 | |||
2146 | /* Set the BSF_FUNCTION flag for the symbol. */ |
||
2147 | sym = symbol_find_or_make (func); |
||
2148 | symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; |
||
2149 | |||
2150 | /* Push the start of the function. */ |
||
2151 | new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text, |
||
2152 | sym, (bfd_vma) 0, (symint_t) 0, |
||
2153 | (symint_t) 0); |
||
2154 | |||
2155 | ++proc_cnt; |
||
2156 | |||
2157 | /* Fill in the linenos preceding the .ent, if any. */ |
||
2158 | if (noproc_lineno != (lineno_list_t *) NULL) |
||
2159 | { |
||
2160 | lineno_list_t *l; |
||
2161 | |||
2162 | for (l = noproc_lineno; l != (lineno_list_t *) NULL; l = l->next) |
||
2163 | l->proc = new_proc_ptr; |
||
2164 | *last_lineno_ptr = noproc_lineno; |
||
2165 | while (*last_lineno_ptr != NULL) |
||
2166 | { |
||
2167 | last_lineno = *last_lineno_ptr; |
||
2168 | last_lineno_ptr = &last_lineno->next; |
||
2169 | } |
||
2170 | noproc_lineno = (lineno_list_t *) NULL; |
||
2171 | } |
||
2172 | } |
||
2173 | |||
2174 | symbolS * |
||
2175 | ecoff_get_cur_proc_sym (void) |
||
2176 | { |
||
2177 | return (cur_proc_ptr ? cur_proc_ptr->sym->as_sym : NULL); |
||
2178 | } |
||
2179 | |||
2180 | /* Add a new filename, and set up all of the file relative |
||
2181 | virtual arrays (strings, symbols, aux syms, etc.). Record |
||
2182 | where the current file structure lives. */ |
||
2183 | |||
2184 | static void |
||
2185 | add_file (const char *file_name, int indx ATTRIBUTE_UNUSED, int fake) |
||
2186 | { |
||
6324 | serge | 2187 | int first_ch; |
2188 | efdr_t *fil_ptr; |
||
5222 | serge | 2189 | |
2190 | #ifdef ECOFF_DEBUG |
||
2191 | if (debug) |
||
2192 | fprintf (stderr, "\tfile\t%.*s\n", len, file_start); |
||
2193 | #endif |
||
2194 | |||
2195 | /* If the file name is NULL, then no .file symbol appeared, and we |
||
2196 | want to use the actual file name. */ |
||
2197 | if (file_name == (const char *) NULL) |
||
2198 | { |
||
2199 | char *file; |
||
2200 | |||
2201 | if (first_file != (efdr_t *) NULL) |
||
2202 | as_fatal (_("fake .file after real one")); |
||
2203 | as_where (&file, (unsigned int *) NULL); |
||
2204 | file_name = (const char *) file; |
||
2205 | |||
2206 | /* Automatically generate ECOFF debugging information, since I |
||
2207 | think that's what other ECOFF assemblers do. We don't do |
||
2208 | this if we see a .file directive with a string, since that |
||
2209 | implies that some sort of debugging information is being |
||
2210 | provided. */ |
||
2211 | if (! symbol_table_frozen && debug_type == DEBUG_UNSPECIFIED) |
||
2212 | debug_type = DEBUG_ECOFF; |
||
2213 | } |
||
2214 | else if (debug_type == DEBUG_UNSPECIFIED) |
||
2215 | debug_type = DEBUG_NONE; |
||
2216 | |||
2217 | #ifndef NO_LISTING |
||
2218 | if (listing) |
||
2219 | listing_source_file (file_name); |
||
2220 | #endif |
||
2221 | |||
2222 | current_stabs_filename = file_name; |
||
2223 | |||
2224 | /* If we're creating stabs, then we don't actually make a new FDR. |
||
2225 | Instead, we just create a stabs symbol. */ |
||
2226 | if (stabs_seen) |
||
2227 | { |
||
2228 | (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil, |
||
2229 | symbol_new ("L0\001", now_seg, |
||
2230 | (valueT) frag_now_fix (), |
||
2231 | frag_now), |
||
2232 | (bfd_vma) 0, 0, ECOFF_MARK_STAB (N_SOL)); |
||
2233 | return; |
||
2234 | } |
||
2235 | |||
2236 | first_ch = *file_name; |
||
2237 | |||
2238 | /* FIXME: We can't safely merge files which have line number |
||
2239 | information (fMerge will be zero in this case). Otherwise, we |
||
2240 | get incorrect line number debugging info. See for instance |
||
2241 | ecoff_build_lineno, which will end up setting all file->fdr.* |
||
2242 | fields multiple times, resulting in incorrect debug info. In |
||
2243 | order to make this work right, all line number and symbol info |
||
2244 | for the same source file has to be adjacent in the object file, |
||
2245 | so that a single file descriptor can be used to point to them. |
||
2246 | This would require maintaining file specific lists of line |
||
2247 | numbers and symbols for each file, so that they can be merged |
||
2248 | together (or output together) when two .file pseudo-ops are |
||
2249 | merged into one file descriptor. */ |
||
2250 | |||
2251 | /* See if the file has already been created. */ |
||
2252 | for (fil_ptr = first_file; |
||
2253 | fil_ptr != (efdr_t *) NULL; |
||
2254 | fil_ptr = fil_ptr->next_file) |
||
2255 | { |
||
2256 | if (first_ch == fil_ptr->name[0] |
||
2257 | && filename_cmp (file_name, fil_ptr->name) == 0 |
||
2258 | && fil_ptr->fdr.fMerge) |
||
2259 | { |
||
2260 | cur_file_ptr = fil_ptr; |
||
2261 | if (! fake) |
||
2262 | cur_file_ptr->fake = 0; |
||
2263 | break; |
||
2264 | } |
||
2265 | } |
||
2266 | |||
2267 | /* If this is a new file, create it. */ |
||
2268 | if (fil_ptr == (efdr_t *) NULL) |
||
2269 | { |
||
2270 | if (file_desc.objects_last_page == file_desc.objects_per_page) |
||
2271 | add_varray_page (&file_desc); |
||
2272 | |||
2273 | fil_ptr = cur_file_ptr = |
||
2274 | &file_desc.last->datum->file[file_desc.objects_last_page++]; |
||
2275 | *fil_ptr = init_file; |
||
2276 | |||
2277 | fil_ptr->file_index = current_file_idx++; |
||
2278 | ++file_desc.num_allocated; |
||
2279 | |||
2280 | fil_ptr->fake = fake; |
||
2281 | |||
2282 | /* Allocate the string hash table. */ |
||
2283 | fil_ptr->str_hash = hash_new (); |
||
2284 | |||
2285 | /* Make sure 0 byte in string table is null */ |
||
2286 | add_string (&fil_ptr->strings, |
||
2287 | fil_ptr->str_hash, |
||
2288 | "", |
||
2289 | (shash_t **)0); |
||
2290 | |||
2291 | if (strlen (file_name) > PAGE_USIZE - 2) |
||
2292 | as_fatal (_("filename goes over one page boundary")); |
||
2293 | |||
2294 | /* Push the start of the filename. We assume that the filename |
||
2295 | will be stored at string offset 1. */ |
||
2296 | (void) add_ecoff_symbol (file_name, st_File, sc_Text, |
||
2297 | (symbolS *) NULL, (bfd_vma) 0, |
||
2298 | (symint_t) 0, (symint_t) 0); |
||
2299 | fil_ptr->fdr.rss = 1; |
||
2300 | fil_ptr->name = &fil_ptr->strings.last->datum->byte[1]; |
||
2301 | |||
2302 | /* Update the linked list of file descriptors. */ |
||
2303 | *last_file_ptr = fil_ptr; |
||
2304 | last_file_ptr = &fil_ptr->next_file; |
||
2305 | |||
2306 | /* Add void & int types to the file (void should be first to catch |
||
2307 | errant 0's within the index fields). */ |
||
2308 | fil_ptr->void_type = add_aux_sym_tir (&void_type_info, |
||
2309 | hash_yes, |
||
2310 | &cur_file_ptr->thash_head[0]); |
||
2311 | |||
2312 | fil_ptr->int_type = add_aux_sym_tir (&int_type_info, |
||
2313 | hash_yes, |
||
2314 | &cur_file_ptr->thash_head[0]); |
||
2315 | } |
||
2316 | } |
||
2317 | |||
2318 | /* This function is called when the assembler notices a preprocessor |
||
2319 | directive switching to a new file. This will not happen in |
||
2320 | compiler output, only in hand coded assembler. */ |
||
2321 | |||
2322 | void |
||
2323 | ecoff_new_file (const char *name, int appfile ATTRIBUTE_UNUSED) |
||
2324 | { |
||
2325 | if (cur_file_ptr != NULL && filename_cmp (cur_file_ptr->name, name) == 0) |
||
2326 | return; |
||
2327 | add_file (name, 0, 0); |
||
2328 | |||
2329 | /* This is a hand coded assembler file, so automatically turn on |
||
2330 | debugging information. */ |
||
2331 | if (debug_type == DEBUG_UNSPECIFIED) |
||
2332 | debug_type = DEBUG_ECOFF; |
||
2333 | } |
||
2334 | |||
2335 | #ifdef ECOFF_DEBUG |
||
2336 | |||
2337 | /* Convert storage class to string. */ |
||
2338 | |||
2339 | static char * |
||
2340 | sc_to_string (storage_class) |
||
2341 | sc_t storage_class; |
||
2342 | { |
||
2343 | switch (storage_class) |
||
2344 | { |
||
2345 | case sc_Nil: return "Nil,"; |
||
2346 | case sc_Text: return "Text,"; |
||
2347 | case sc_Data: return "Data,"; |
||
2348 | case sc_Bss: return "Bss,"; |
||
2349 | case sc_Register: return "Register,"; |
||
2350 | case sc_Abs: return "Abs,"; |
||
2351 | case sc_Undefined: return "Undefined,"; |
||
2352 | case sc_CdbLocal: return "CdbLocal,"; |
||
2353 | case sc_Bits: return "Bits,"; |
||
2354 | case sc_CdbSystem: return "CdbSystem,"; |
||
2355 | case sc_RegImage: return "RegImage,"; |
||
2356 | case sc_Info: return "Info,"; |
||
2357 | case sc_UserStruct: return "UserStruct,"; |
||
2358 | case sc_SData: return "SData,"; |
||
2359 | case sc_SBss: return "SBss,"; |
||
2360 | case sc_RData: return "RData,"; |
||
2361 | case sc_Var: return "Var,"; |
||
2362 | case sc_Common: return "Common,"; |
||
2363 | case sc_SCommon: return "SCommon,"; |
||
2364 | case sc_VarRegister: return "VarRegister,"; |
||
2365 | case sc_Variant: return "Variant,"; |
||
2366 | case sc_SUndefined: return "SUndefined,"; |
||
2367 | case sc_Init: return "Init,"; |
||
2368 | case sc_Max: return "Max,"; |
||
2369 | } |
||
2370 | |||
2371 | return "???,"; |
||
2372 | } |
||
2373 | |||
2374 | #endif /* DEBUG */ |
||
2375 | |||
2376 | #ifdef ECOFF_DEBUG |
||
2377 | |||
2378 | /* Convert symbol type to string. */ |
||
2379 | |||
2380 | static char * |
||
2381 | st_to_string (symbol_type) |
||
2382 | st_t symbol_type; |
||
2383 | { |
||
2384 | switch (symbol_type) |
||
2385 | { |
||
2386 | case st_Nil: return "Nil,"; |
||
2387 | case st_Global: return "Global,"; |
||
2388 | case st_Static: return "Static,"; |
||
2389 | case st_Param: return "Param,"; |
||
2390 | case st_Local: return "Local,"; |
||
2391 | case st_Label: return "Label,"; |
||
2392 | case st_Proc: return "Proc,"; |
||
2393 | case st_Block: return "Block,"; |
||
2394 | case st_End: return "End,"; |
||
2395 | case st_Member: return "Member,"; |
||
2396 | case st_Typedef: return "Typedef,"; |
||
2397 | case st_File: return "File,"; |
||
2398 | case st_RegReloc: return "RegReloc,"; |
||
2399 | case st_Forward: return "Forward,"; |
||
2400 | case st_StaticProc: return "StaticProc,"; |
||
2401 | case st_Constant: return "Constant,"; |
||
2402 | case st_Str: return "String,"; |
||
2403 | case st_Number: return "Number,"; |
||
2404 | case st_Expr: return "Expr,"; |
||
2405 | case st_Type: return "Type,"; |
||
2406 | case st_Max: return "Max,"; |
||
2407 | } |
||
2408 | |||
2409 | return "???,"; |
||
2410 | } |
||
2411 | |||
2412 | #endif /* DEBUG */ |
||
2413 | |||
2414 | /* Parse .begin directives which have a label as the first argument |
||
2415 | which gives the location of the start of the block. */ |
||
2416 | |||
2417 | void |
||
2418 | ecoff_directive_begin (int ignore ATTRIBUTE_UNUSED) |
||
2419 | { |
||
2420 | char *name; |
||
2421 | char name_end; |
||
2422 | |||
2423 | if (cur_file_ptr == (efdr_t *) NULL) |
||
2424 | { |
||
2425 | as_warn (_(".begin directive without a preceding .file directive")); |
||
2426 | demand_empty_rest_of_line (); |
||
2427 | return; |
||
2428 | } |
||
2429 | |||
2430 | if (cur_proc_ptr == (proc_t *) NULL) |
||
2431 | { |
||
2432 | as_warn (_(".begin directive without a preceding .ent directive")); |
||
2433 | demand_empty_rest_of_line (); |
||
2434 | return; |
||
2435 | } |
||
2436 | |||
6324 | serge | 2437 | name_end = get_symbol_name (&name); |
5222 | serge | 2438 | |
2439 | (void) add_ecoff_symbol ((const char *) NULL, st_Block, sc_Text, |
||
2440 | symbol_find_or_make (name), |
||
2441 | (bfd_vma) 0, (symint_t) 0, (symint_t) 0); |
||
2442 | |||
6324 | serge | 2443 | (void) restore_line_pointer (name_end); |
5222 | serge | 2444 | |
2445 | /* The line number follows, but we don't use it. */ |
||
2446 | (void) get_absolute_expression (); |
||
2447 | demand_empty_rest_of_line (); |
||
2448 | } |
||
2449 | |||
2450 | /* Parse .bend directives which have a label as the first argument |
||
2451 | which gives the location of the end of the block. */ |
||
2452 | |||
2453 | void |
||
2454 | ecoff_directive_bend (int ignore ATTRIBUTE_UNUSED) |
||
2455 | { |
||
2456 | char *name; |
||
2457 | char name_end; |
||
2458 | symbolS *endsym; |
||
2459 | |||
2460 | if (cur_file_ptr == (efdr_t *) NULL) |
||
2461 | { |
||
2462 | as_warn (_(".bend directive without a preceding .file directive")); |
||
2463 | demand_empty_rest_of_line (); |
||
2464 | return; |
||
2465 | } |
||
2466 | |||
2467 | if (cur_proc_ptr == (proc_t *) NULL) |
||
2468 | { |
||
2469 | as_warn (_(".bend directive without a preceding .ent directive")); |
||
2470 | demand_empty_rest_of_line (); |
||
2471 | return; |
||
2472 | } |
||
2473 | |||
6324 | serge | 2474 | name_end = get_symbol_name (&name); |
5222 | serge | 2475 | |
2476 | /* The value is the distance between the .bend directive and the |
||
2477 | corresponding symbol. We fill in the offset when we write out |
||
2478 | the symbol. */ |
||
2479 | endsym = symbol_find (name); |
||
2480 | if (endsym == (symbolS *) NULL) |
||
2481 | as_warn (_(".bend directive names unknown symbol")); |
||
2482 | else |
||
2483 | (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym, |
||
2484 | (bfd_vma) 0, (symint_t) 0, (symint_t) 0); |
||
2485 | |||
6324 | serge | 2486 | restore_line_pointer (name_end); |
5222 | serge | 2487 | |
2488 | /* The line number follows, but we don't use it. */ |
||
2489 | (void) get_absolute_expression (); |
||
2490 | demand_empty_rest_of_line (); |
||
2491 | } |
||
2492 | |||
2493 | /* COFF debugging information is provided as a series of directives |
||
2494 | (.def, .scl, etc.). We build up information as we read the |
||
2495 | directives in the following static variables, and file it away when |
||
2496 | we reach the .endef directive. */ |
||
2497 | static char *coff_sym_name; |
||
2498 | static type_info_t coff_type; |
||
2499 | static sc_t coff_storage_class; |
||
2500 | static st_t coff_symbol_typ; |
||
2501 | static int coff_is_function; |
||
2502 | static char *coff_tag; |
||
2503 | static valueT coff_value; |
||
2504 | static symbolS *coff_sym_value; |
||
2505 | static bfd_vma coff_sym_addend; |
||
2506 | static int coff_inside_enumeration; |
||
2507 | |||
2508 | /* Handle a .def directive: start defining a symbol. */ |
||
2509 | |||
2510 | void |
||
2511 | ecoff_directive_def (int ignore ATTRIBUTE_UNUSED) |
||
2512 | { |
||
2513 | char *name; |
||
2514 | char name_end; |
||
2515 | |||
2516 | ecoff_debugging_seen = 1; |
||
2517 | |||
2518 | SKIP_WHITESPACE (); |
||
2519 | |||
6324 | serge | 2520 | name_end = get_symbol_name (&name); |
5222 | serge | 2521 | |
2522 | if (coff_sym_name != (char *) NULL) |
||
2523 | as_warn (_(".def pseudo-op used inside of .def/.endef; ignored")); |
||
2524 | else if (*name == '\0') |
||
2525 | as_warn (_("empty symbol name in .def; ignored")); |
||
2526 | else |
||
2527 | { |
||
2528 | if (coff_sym_name != (char *) NULL) |
||
2529 | free (coff_sym_name); |
||
2530 | if (coff_tag != (char *) NULL) |
||
2531 | free (coff_tag); |
||
2532 | |||
2533 | coff_sym_name = xstrdup (name); |
||
2534 | coff_type = type_info_init; |
||
2535 | coff_storage_class = sc_Nil; |
||
2536 | coff_symbol_typ = st_Nil; |
||
2537 | coff_is_function = 0; |
||
2538 | coff_tag = (char *) NULL; |
||
2539 | coff_value = 0; |
||
2540 | coff_sym_value = (symbolS *) NULL; |
||
2541 | coff_sym_addend = 0; |
||
2542 | } |
||
2543 | |||
6324 | serge | 2544 | restore_line_pointer (name_end); |
5222 | serge | 2545 | |
2546 | demand_empty_rest_of_line (); |
||
2547 | } |
||
2548 | |||
2549 | /* Handle a .dim directive, used to give dimensions for an array. The |
||
2550 | arguments are comma separated numbers. mips-tfile assumes that |
||
2551 | there will not be more than 6 dimensions, and gdb won't read any |
||
2552 | more than that anyhow, so I will also make that assumption. */ |
||
2553 | |||
2554 | void |
||
2555 | ecoff_directive_dim (int ignore ATTRIBUTE_UNUSED) |
||
2556 | { |
||
2557 | int dimens[N_TQ]; |
||
2558 | int i; |
||
2559 | |||
2560 | if (coff_sym_name == (char *) NULL) |
||
2561 | { |
||
2562 | as_warn (_(".dim pseudo-op used outside of .def/.endef; ignored")); |
||
2563 | demand_empty_rest_of_line (); |
||
2564 | return; |
||
2565 | } |
||
2566 | |||
2567 | for (i = 0; i < N_TQ; i++) |
||
2568 | { |
||
2569 | SKIP_WHITESPACE (); |
||
2570 | dimens[i] = get_absolute_expression (); |
||
2571 | if (*input_line_pointer == ',') |
||
2572 | ++input_line_pointer; |
||
2573 | else |
||
2574 | { |
||
2575 | if (*input_line_pointer != '\n' |
||
2576 | && *input_line_pointer != ';') |
||
2577 | as_warn (_("badly formed .dim directive")); |
||
2578 | break; |
||
2579 | } |
||
2580 | } |
||
2581 | |||
2582 | if (i == N_TQ) |
||
2583 | --i; |
||
2584 | |||
2585 | /* The dimensions are stored away in reverse order. */ |
||
2586 | for (; i >= 0; i--) |
||
2587 | { |
||
2588 | if (coff_type.num_dims >= N_TQ) |
||
2589 | { |
||
2590 | as_warn (_("too many .dim entries")); |
||
2591 | break; |
||
2592 | } |
||
2593 | coff_type.dimensions[coff_type.num_dims] = dimens[i]; |
||
2594 | ++coff_type.num_dims; |
||
2595 | } |
||
2596 | |||
2597 | demand_empty_rest_of_line (); |
||
2598 | } |
||
2599 | |||
2600 | /* Handle a .scl directive, which sets the COFF storage class of the |
||
2601 | symbol. */ |
||
2602 | |||
2603 | void |
||
2604 | ecoff_directive_scl (int ignore ATTRIBUTE_UNUSED) |
||
2605 | { |
||
2606 | long val; |
||
2607 | |||
2608 | if (coff_sym_name == (char *) NULL) |
||
2609 | { |
||
2610 | as_warn (_(".scl pseudo-op used outside of .def/.endef; ignored")); |
||
2611 | demand_empty_rest_of_line (); |
||
2612 | return; |
||
2613 | } |
||
2614 | |||
2615 | val = get_absolute_expression (); |
||
2616 | |||
2617 | coff_symbol_typ = map_coff_sym_type[val]; |
||
2618 | coff_storage_class = map_coff_storage[val]; |
||
2619 | |||
2620 | demand_empty_rest_of_line (); |
||
2621 | } |
||
2622 | |||
2623 | /* Handle a .size directive. For some reason mips-tfile.c thinks that |
||
2624 | .size can have multiple arguments. We humor it, although gcc will |
||
2625 | never generate more than one argument. */ |
||
2626 | |||
2627 | void |
||
2628 | ecoff_directive_size (int ignore ATTRIBUTE_UNUSED) |
||
2629 | { |
||
2630 | int sizes[N_TQ]; |
||
2631 | int i; |
||
2632 | |||
2633 | if (coff_sym_name == (char *) NULL) |
||
2634 | { |
||
2635 | as_warn (_(".size pseudo-op used outside of .def/.endef; ignored")); |
||
2636 | demand_empty_rest_of_line (); |
||
2637 | return; |
||
2638 | } |
||
2639 | |||
2640 | for (i = 0; i < N_TQ; i++) |
||
2641 | { |
||
2642 | SKIP_WHITESPACE (); |
||
2643 | sizes[i] = get_absolute_expression (); |
||
2644 | if (*input_line_pointer == ',') |
||
2645 | ++input_line_pointer; |
||
2646 | else |
||
2647 | { |
||
2648 | if (*input_line_pointer != '\n' |
||
2649 | && *input_line_pointer != ';') |
||
2650 | as_warn (_("badly formed .size directive")); |
||
2651 | break; |
||
2652 | } |
||
2653 | } |
||
2654 | |||
2655 | if (i == N_TQ) |
||
2656 | --i; |
||
2657 | |||
2658 | /* The sizes are stored away in reverse order. */ |
||
2659 | for (; i >= 0; i--) |
||
2660 | { |
||
2661 | if (coff_type.num_sizes >= N_TQ) |
||
2662 | { |
||
2663 | as_warn (_("too many .size entries")); |
||
2664 | break; |
||
2665 | } |
||
2666 | coff_type.sizes[coff_type.num_sizes] = sizes[i]; |
||
2667 | ++coff_type.num_sizes; |
||
2668 | } |
||
2669 | |||
2670 | demand_empty_rest_of_line (); |
||
2671 | } |
||
2672 | |||
2673 | /* Handle the .type directive, which gives the COFF type of the |
||
2674 | symbol. */ |
||
2675 | |||
2676 | void |
||
2677 | ecoff_directive_type (int ignore ATTRIBUTE_UNUSED) |
||
2678 | { |
||
2679 | long val; |
||
2680 | tq_t *tq_ptr; |
||
2681 | tq_t *tq_shft; |
||
2682 | |||
2683 | if (coff_sym_name == (char *) NULL) |
||
2684 | { |
||
2685 | as_warn (_(".type pseudo-op used outside of .def/.endef; ignored")); |
||
2686 | demand_empty_rest_of_line (); |
||
2687 | return; |
||
2688 | } |
||
2689 | |||
2690 | val = get_absolute_expression (); |
||
2691 | |||
2692 | coff_type.orig_type = BTYPE (val); |
||
2693 | coff_type.basic_type = map_coff_types[coff_type.orig_type]; |
||
2694 | |||
2695 | tq_ptr = &coff_type.type_qualifiers[N_TQ]; |
||
2696 | while (val & ~N_BTMASK) |
||
2697 | { |
||
2698 | if (tq_ptr == &coff_type.type_qualifiers[0]) |
||
2699 | { |
||
2700 | /* FIXME: We could handle this by setting the continued bit. |
||
2701 | There would still be a limit: the .type argument can not |
||
2702 | be infinite. */ |
||
2703 | as_warn (_("the type of %s is too complex; it will be simplified"), |
||
2704 | coff_sym_name); |
||
2705 | break; |
||
2706 | } |
||
2707 | if (ISPTR (val)) |
||
2708 | *--tq_ptr = tq_Ptr; |
||
2709 | else if (ISFCN (val)) |
||
2710 | *--tq_ptr = tq_Proc; |
||
2711 | else if (ISARY (val)) |
||
2712 | *--tq_ptr = tq_Array; |
||
2713 | else |
||
2714 | as_fatal (_("Unrecognized .type argument")); |
||
2715 | |||
2716 | val = DECREF (val); |
||
2717 | } |
||
2718 | |||
2719 | tq_shft = &coff_type.type_qualifiers[0]; |
||
2720 | while (tq_ptr != &coff_type.type_qualifiers[N_TQ]) |
||
2721 | *tq_shft++ = *tq_ptr++; |
||
2722 | |||
2723 | if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc) |
||
2724 | { |
||
2725 | /* If this is a function, ignore it, so that we don't get two |
||
2726 | entries (one from the .ent, and one for the .def that |
||
2727 | precedes it). Save the type information so that the end |
||
2728 | block can properly add it after the begin block index. For |
||
2729 | MIPS knows what reason, we must strip off the function type |
||
2730 | at this point. */ |
||
2731 | coff_is_function = 1; |
||
2732 | tq_shft[-1] = tq_Nil; |
||
2733 | } |
||
2734 | |||
2735 | while (tq_shft != &coff_type.type_qualifiers[N_TQ]) |
||
2736 | *tq_shft++ = tq_Nil; |
||
2737 | |||
2738 | demand_empty_rest_of_line (); |
||
2739 | } |
||
2740 | |||
2741 | /* Handle the .tag directive, which gives the name of a structure, |
||
2742 | union or enum. */ |
||
2743 | |||
2744 | void |
||
2745 | ecoff_directive_tag (int ignore ATTRIBUTE_UNUSED) |
||
2746 | { |
||
2747 | char *name; |
||
2748 | char name_end; |
||
2749 | |||
2750 | if (coff_sym_name == (char *) NULL) |
||
2751 | { |
||
2752 | as_warn (_(".tag pseudo-op used outside of .def/.endef; ignored")); |
||
2753 | demand_empty_rest_of_line (); |
||
2754 | return; |
||
2755 | } |
||
2756 | |||
6324 | serge | 2757 | name_end = get_symbol_name (&name); |
5222 | serge | 2758 | |
2759 | coff_tag = xstrdup (name); |
||
2760 | |||
6324 | serge | 2761 | (void) restore_line_pointer (name_end); |
5222 | serge | 2762 | |
2763 | demand_empty_rest_of_line (); |
||
2764 | } |
||
2765 | |||
2766 | /* Handle the .val directive, which gives the value of the symbol. It |
||
2767 | may be the name of a static or global symbol. */ |
||
2768 | |||
2769 | void |
||
2770 | ecoff_directive_val (int ignore ATTRIBUTE_UNUSED) |
||
2771 | { |
||
2772 | expressionS exp; |
||
2773 | |||
2774 | if (coff_sym_name == (char *) NULL) |
||
2775 | { |
||
2776 | as_warn (_(".val pseudo-op used outside of .def/.endef; ignored")); |
||
2777 | demand_empty_rest_of_line (); |
||
2778 | return; |
||
2779 | } |
||
2780 | |||
2781 | expression (&exp); |
||
2782 | if (exp.X_op != O_constant && exp.X_op != O_symbol) |
||
2783 | { |
||
2784 | as_bad (_(".val expression is too complex")); |
||
2785 | demand_empty_rest_of_line (); |
||
2786 | return; |
||
2787 | } |
||
2788 | |||
2789 | if (exp.X_op == O_constant) |
||
2790 | coff_value = exp.X_add_number; |
||
2791 | else |
||
2792 | { |
||
2793 | coff_sym_value = exp.X_add_symbol; |
||
2794 | coff_sym_addend = exp.X_add_number; |
||
2795 | } |
||
2796 | |||
2797 | demand_empty_rest_of_line (); |
||
2798 | } |
||
2799 | |||
2800 | /* Handle the .endef directive, which terminates processing of COFF |
||
2801 | debugging information for a symbol. */ |
||
2802 | |||
2803 | void |
||
2804 | ecoff_directive_endef (int ignore ATTRIBUTE_UNUSED) |
||
2805 | { |
||
2806 | char *name; |
||
2807 | symint_t indx; |
||
2808 | localsym_t *sym; |
||
2809 | |||
2810 | demand_empty_rest_of_line (); |
||
2811 | |||
2812 | if (coff_sym_name == (char *) NULL) |
||
2813 | { |
||
2814 | as_warn (_(".endef pseudo-op used before .def; ignored")); |
||
2815 | return; |
||
2816 | } |
||
2817 | |||
2818 | name = coff_sym_name; |
||
2819 | coff_sym_name = (char *) NULL; |
||
2820 | |||
2821 | /* If the symbol is a static or external, we have already gotten the |
||
2822 | appropriate type and class, so make sure we don't override those |
||
2823 | values. This is needed because there are some type and classes |
||
2824 | that are not in COFF, such as short data, etc. */ |
||
2825 | if (coff_sym_value != (symbolS *) NULL) |
||
2826 | { |
||
2827 | coff_symbol_typ = st_Nil; |
||
2828 | coff_storage_class = sc_Nil; |
||
2829 | } |
||
2830 | |||
2831 | coff_type.extra_sizes = coff_tag != (char *) NULL; |
||
2832 | if (coff_type.num_dims > 0) |
||
2833 | { |
||
2834 | int diff = coff_type.num_dims - coff_type.num_sizes; |
||
2835 | int i = coff_type.num_dims - 1; |
||
2836 | int j; |
||
2837 | |||
2838 | if (coff_type.num_sizes != 1 || diff < 0) |
||
2839 | { |
||
2840 | as_warn (_("bad COFF debugging information")); |
||
2841 | return; |
||
2842 | } |
||
2843 | |||
2844 | /* If this is an array, make sure the same number of dimensions |
||
2845 | and sizes were passed, creating extra sizes for multiply |
||
2846 | dimensioned arrays if not passed. */ |
||
2847 | coff_type.extra_sizes = 0; |
||
2848 | if (diff) |
||
2849 | { |
||
2850 | j = (sizeof (coff_type.sizes) / sizeof (coff_type.sizes[0])) - 1; |
||
2851 | while (j >= 0) |
||
2852 | { |
||
2853 | coff_type.sizes[j] = (((j - diff) >= 0) |
||
2854 | ? coff_type.sizes[j - diff] |
||
2855 | : 0); |
||
2856 | j--; |
||
2857 | } |
||
2858 | |||
2859 | coff_type.num_sizes = i + 1; |
||
2860 | for (i--; i >= 0; i--) |
||
2861 | coff_type.sizes[i] = (coff_type.dimensions[i + 1] == 0 |
||
2862 | ? 0 |
||
2863 | : (coff_type.sizes[i + 1] |
||
2864 | / coff_type.dimensions[i + 1])); |
||
2865 | } |
||
2866 | } |
||
2867 | else if (coff_symbol_typ == st_Member |
||
2868 | && coff_type.num_sizes - coff_type.extra_sizes == 1) |
||
2869 | { |
||
2870 | /* Is this a bitfield? This is indicated by a structure member |
||
2871 | having a size field that isn't an array. */ |
||
2872 | coff_type.bitfield = 1; |
||
2873 | } |
||
2874 | |||
2875 | /* Except for enumeration members & begin/ending of scopes, put the |
||
2876 | type word in the aux. symbol table. */ |
||
2877 | if (coff_symbol_typ == st_Block || coff_symbol_typ == st_End) |
||
2878 | indx = 0; |
||
2879 | else if (coff_inside_enumeration) |
||
2880 | indx = cur_file_ptr->void_type; |
||
2881 | else |
||
2882 | { |
||
2883 | if (coff_type.basic_type == bt_Struct |
||
2884 | || coff_type.basic_type == bt_Union |
||
2885 | || coff_type.basic_type == bt_Enum) |
||
2886 | { |
||
2887 | if (coff_tag == (char *) NULL) |
||
2888 | { |
||
2889 | as_warn (_("no tag specified for %s"), name); |
||
2890 | return; |
||
2891 | } |
||
2892 | |||
2893 | coff_type.tag_ptr = get_tag (coff_tag, (localsym_t *) NULL, |
||
2894 | coff_type.basic_type); |
||
2895 | } |
||
2896 | |||
2897 | if (coff_is_function) |
||
2898 | { |
||
2899 | last_func_type_info = coff_type; |
||
2900 | last_func_sym_value = coff_sym_value; |
||
2901 | return; |
||
2902 | } |
||
2903 | |||
2904 | indx = add_aux_sym_tir (&coff_type, |
||
2905 | hash_yes, |
||
2906 | &cur_file_ptr->thash_head[0]); |
||
2907 | } |
||
2908 | |||
2909 | /* Do any last minute adjustments that are necessary. */ |
||
2910 | switch (coff_symbol_typ) |
||
2911 | { |
||
2912 | default: |
||
2913 | break; |
||
2914 | |||
2915 | /* For the beginning of structs, unions, and enumerations, the |
||
2916 | size info needs to be passed in the value field. */ |
||
2917 | case st_Block: |
||
2918 | if (coff_type.num_sizes - coff_type.num_dims - coff_type.extra_sizes |
||
2919 | != 1) |
||
2920 | { |
||
2921 | as_warn (_("bad COFF debugging information")); |
||
2922 | return; |
||
2923 | } |
||
2924 | else |
||
2925 | coff_value = coff_type.sizes[0]; |
||
2926 | |||
2927 | coff_inside_enumeration = (coff_type.orig_type == T_ENUM); |
||
2928 | break; |
||
2929 | |||
2930 | /* For the end of structs, unions, and enumerations, omit the |
||
2931 | name which is always ".eos". This needs to be done last, so |
||
2932 | that any error reporting above gives the correct name. */ |
||
2933 | case st_End: |
||
2934 | free (name); |
||
2935 | name = (char *) NULL; |
||
2936 | coff_value = 0; |
||
2937 | coff_inside_enumeration = 0; |
||
2938 | break; |
||
2939 | |||
2940 | /* Members of structures and unions that aren't bitfields, need |
||
2941 | to adjust the value from a byte offset to a bit offset. |
||
2942 | Members of enumerations do not have the value adjusted, and |
||
2943 | can be distinguished by indx == indexNil. For enumerations, |
||
2944 | update the maximum enumeration value. */ |
||
2945 | case st_Member: |
||
2946 | if (! coff_type.bitfield && ! coff_inside_enumeration) |
||
2947 | coff_value *= 8; |
||
2948 | |||
2949 | break; |
||
2950 | } |
||
2951 | |||
2952 | /* Add the symbol. */ |
||
2953 | sym = add_ecoff_symbol (name, |
||
2954 | coff_symbol_typ, |
||
2955 | coff_storage_class, |
||
2956 | coff_sym_value, |
||
2957 | coff_sym_addend, |
||
2958 | (symint_t) coff_value, |
||
2959 | indx); |
||
2960 | |||
2961 | /* deal with struct, union, and enum tags. */ |
||
2962 | if (coff_symbol_typ == st_Block) |
||
2963 | { |
||
2964 | /* Create or update the tag information. */ |
||
2965 | tag_t *tag_ptr = get_tag (name, |
||
2966 | sym, |
||
2967 | coff_type.basic_type); |
||
2968 | forward_t **pf; |
||
2969 | |||
2970 | /* Remember any forward references. */ |
||
2971 | for (pf = &sym->forward_ref; |
||
2972 | *pf != (forward_t *) NULL; |
||
2973 | pf = &(*pf)->next) |
||
2974 | ; |
||
2975 | *pf = tag_ptr->forward_ref; |
||
2976 | tag_ptr->forward_ref = (forward_t *) NULL; |
||
2977 | } |
||
2978 | } |
||
2979 | |||
2980 | /* Parse .end directives. */ |
||
2981 | |||
2982 | void |
||
2983 | ecoff_directive_end (int ignore ATTRIBUTE_UNUSED) |
||
2984 | { |
||
2985 | char *name; |
||
2986 | char name_end; |
||
2987 | symbolS *ent; |
||
2988 | |||
2989 | if (cur_file_ptr == (efdr_t *) NULL) |
||
2990 | { |
||
2991 | as_warn (_(".end directive without a preceding .file directive")); |
||
2992 | demand_empty_rest_of_line (); |
||
2993 | return; |
||
2994 | } |
||
2995 | |||
2996 | if (cur_proc_ptr == (proc_t *) NULL) |
||
2997 | { |
||
2998 | as_warn (_(".end directive without a preceding .ent directive")); |
||
2999 | demand_empty_rest_of_line (); |
||
3000 | return; |
||
3001 | } |
||
3002 | |||
6324 | serge | 3003 | name_end = get_symbol_name (&name); |
5222 | serge | 3004 | |
3005 | if (name == input_line_pointer) |
||
3006 | { |
||
3007 | as_warn (_(".end directive has no name")); |
||
6324 | serge | 3008 | (void) restore_line_pointer (name_end); |
5222 | serge | 3009 | demand_empty_rest_of_line (); |
3010 | return; |
||
3011 | } |
||
3012 | |||
3013 | /* The value is the distance between the .end directive and the |
||
3014 | corresponding symbol. We create a fake symbol to hold the |
||
3015 | current location, and put in the offset when we write out the |
||
3016 | symbol. */ |
||
3017 | ent = symbol_find (name); |
||
3018 | if (ent == (symbolS *) NULL) |
||
3019 | as_warn (_(".end directive names unknown symbol")); |
||
3020 | else |
||
3021 | (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, |
||
3022 | symbol_new ("L0\001", now_seg, |
||
3023 | (valueT) frag_now_fix (), |
||
3024 | frag_now), |
||
3025 | (bfd_vma) 0, (symint_t) 0, (symint_t) 0); |
||
3026 | |||
3027 | cur_proc_ptr = (proc_t *) NULL; |
||
3028 | |||
6324 | serge | 3029 | (void) restore_line_pointer (name_end); |
5222 | serge | 3030 | demand_empty_rest_of_line (); |
3031 | } |
||
3032 | |||
3033 | /* Parse .ent directives. */ |
||
3034 | |||
3035 | void |
||
3036 | ecoff_directive_ent (int ignore ATTRIBUTE_UNUSED) |
||
3037 | { |
||
3038 | char *name; |
||
3039 | char name_end; |
||
3040 | |||
3041 | if (cur_file_ptr == (efdr_t *) NULL) |
||
3042 | add_file ((const char *) NULL, 0, 1); |
||
3043 | |||
3044 | if (cur_proc_ptr != (proc_t *) NULL) |
||
3045 | { |
||
3046 | as_warn (_("second .ent directive found before .end directive")); |
||
3047 | demand_empty_rest_of_line (); |
||
3048 | return; |
||
3049 | } |
||
3050 | |||
6324 | serge | 3051 | name_end = get_symbol_name (&name); |
5222 | serge | 3052 | |
3053 | if (name == input_line_pointer) |
||
3054 | { |
||
3055 | as_warn (_(".ent directive has no name")); |
||
6324 | serge | 3056 | (void) restore_line_pointer (name_end); |
5222 | serge | 3057 | demand_empty_rest_of_line (); |
3058 | return; |
||
3059 | } |
||
3060 | |||
3061 | add_procedure (name); |
||
3062 | |||
6324 | serge | 3063 | (void) restore_line_pointer (name_end); |
5222 | serge | 3064 | |
3065 | /* The .ent directive is sometimes followed by a number. I'm not |
||
3066 | really sure what the number means. I don't see any way to store |
||
3067 | the information in the PDR. The Irix 4 assembler seems to ignore |
||
3068 | the information. */ |
||
3069 | SKIP_WHITESPACE (); |
||
3070 | if (*input_line_pointer == ',') |
||
3071 | { |
||
3072 | ++input_line_pointer; |
||
3073 | SKIP_WHITESPACE (); |
||
3074 | } |
||
3075 | if (ISDIGIT (*input_line_pointer) |
||
3076 | || *input_line_pointer == '-') |
||
3077 | (void) get_absolute_expression (); |
||
3078 | |||
3079 | demand_empty_rest_of_line (); |
||
3080 | } |
||
3081 | |||
3082 | /* Parse .extern directives. */ |
||
3083 | |||
3084 | void |
||
3085 | ecoff_directive_extern (int ignore ATTRIBUTE_UNUSED) |
||
3086 | { |
||
3087 | char *name; |
||
3088 | int c; |
||
3089 | symbolS *symbolp; |
||
3090 | valueT size; |
||
3091 | |||
6324 | serge | 3092 | c = get_symbol_name (&name); |
5222 | serge | 3093 | symbolp = symbol_find_or_make (name); |
6324 | serge | 3094 | (void) restore_line_pointer (c); |
5222 | serge | 3095 | |
3096 | S_SET_EXTERNAL (symbolp); |
||
3097 | |||
3098 | if (*input_line_pointer == ',') |
||
3099 | ++input_line_pointer; |
||
3100 | size = get_absolute_expression (); |
||
3101 | |||
3102 | symbol_get_obj (symbolp)->ecoff_extern_size = size; |
||
3103 | } |
||
3104 | |||
3105 | /* Parse .file directives. */ |
||
3106 | |||
3107 | void |
||
3108 | ecoff_directive_file (int ignore ATTRIBUTE_UNUSED) |
||
3109 | { |
||
3110 | int indx; |
||
3111 | char *name; |
||
3112 | int len; |
||
3113 | |||
3114 | if (cur_proc_ptr != (proc_t *) NULL) |
||
3115 | { |
||
3116 | as_warn (_("no way to handle .file within .ent/.end section")); |
||
3117 | demand_empty_rest_of_line (); |
||
3118 | return; |
||
3119 | } |
||
3120 | |||
3121 | indx = (int) get_absolute_expression (); |
||
3122 | |||
3123 | /* FIXME: we don't have to save the name here. */ |
||
3124 | name = demand_copy_C_string (&len); |
||
3125 | |||
3126 | add_file (name, indx - 1, 0); |
||
3127 | |||
3128 | demand_empty_rest_of_line (); |
||
3129 | } |
||
3130 | |||
3131 | /* Parse .fmask directives. */ |
||
3132 | |||
3133 | void |
||
3134 | ecoff_directive_fmask (int ignore ATTRIBUTE_UNUSED) |
||
3135 | { |
||
3136 | long val; |
||
3137 | |||
3138 | if (cur_proc_ptr == (proc_t *) NULL) |
||
3139 | { |
||
3140 | as_warn (_(".fmask outside of .ent")); |
||
3141 | demand_empty_rest_of_line (); |
||
3142 | return; |
||
3143 | } |
||
3144 | |||
3145 | if (get_absolute_expression_and_terminator (&val) != ',') |
||
3146 | { |
||
3147 | as_warn (_("bad .fmask directive")); |
||
3148 | --input_line_pointer; |
||
3149 | demand_empty_rest_of_line (); |
||
3150 | return; |
||
3151 | } |
||
3152 | |||
3153 | cur_proc_ptr->pdr.fregmask = val; |
||
3154 | cur_proc_ptr->pdr.fregoffset = get_absolute_expression (); |
||
3155 | |||
3156 | demand_empty_rest_of_line (); |
||
3157 | } |
||
3158 | |||
3159 | /* Parse .frame directives. */ |
||
3160 | |||
3161 | void |
||
3162 | ecoff_directive_frame (int ignore ATTRIBUTE_UNUSED) |
||
3163 | { |
||
3164 | long val; |
||
3165 | |||
3166 | if (cur_proc_ptr == (proc_t *) NULL) |
||
3167 | { |
||
3168 | as_warn (_(".frame outside of .ent")); |
||
3169 | demand_empty_rest_of_line (); |
||
3170 | return; |
||
3171 | } |
||
3172 | |||
3173 | cur_proc_ptr->pdr.framereg = tc_get_register (1); |
||
3174 | |||
3175 | SKIP_WHITESPACE (); |
||
3176 | if (*input_line_pointer++ != ',' |
||
3177 | || get_absolute_expression_and_terminator (&val) != ',') |
||
3178 | { |
||
3179 | as_warn (_("bad .frame directive")); |
||
3180 | --input_line_pointer; |
||
3181 | demand_empty_rest_of_line (); |
||
3182 | return; |
||
3183 | } |
||
3184 | |||
3185 | cur_proc_ptr->pdr.frameoffset = val; |
||
3186 | |||
3187 | cur_proc_ptr->pdr.pcreg = tc_get_register (0); |
||
3188 | |||
3189 | /* Alpha-OSF1 adds "the offset of saved $a0 from $sp", according to |
||
3190 | Sandro. I don't yet know where this value should be stored, if |
||
3191 | anywhere. Don't call demand_empty_rest_of_line (). */ |
||
3192 | s_ignore (42); |
||
3193 | } |
||
3194 | |||
3195 | /* Parse .mask directives. */ |
||
3196 | |||
3197 | void |
||
3198 | ecoff_directive_mask (int ignore ATTRIBUTE_UNUSED) |
||
3199 | { |
||
3200 | long val; |
||
3201 | |||
3202 | if (cur_proc_ptr == (proc_t *) NULL) |
||
3203 | { |
||
3204 | as_warn (_(".mask outside of .ent")); |
||
3205 | demand_empty_rest_of_line (); |
||
3206 | return; |
||
3207 | } |
||
3208 | |||
3209 | if (get_absolute_expression_and_terminator (&val) != ',') |
||
3210 | { |
||
3211 | as_warn (_("bad .mask directive")); |
||
3212 | --input_line_pointer; |
||
3213 | demand_empty_rest_of_line (); |
||
3214 | return; |
||
3215 | } |
||
3216 | |||
3217 | cur_proc_ptr->pdr.regmask = val; |
||
3218 | cur_proc_ptr->pdr.regoffset = get_absolute_expression (); |
||
3219 | |||
3220 | demand_empty_rest_of_line (); |
||
3221 | } |
||
3222 | |||
3223 | /* Parse .loc directives. */ |
||
3224 | |||
3225 | void |
||
3226 | ecoff_directive_loc (int ignore ATTRIBUTE_UNUSED) |
||
3227 | { |
||
3228 | lineno_list_t *list; |
||
3229 | symint_t lineno; |
||
3230 | |||
3231 | if (cur_file_ptr == (efdr_t *) NULL) |
||
3232 | { |
||
3233 | as_warn (_(".loc before .file")); |
||
3234 | demand_empty_rest_of_line (); |
||
3235 | return; |
||
3236 | } |
||
3237 | |||
3238 | if (now_seg != text_section) |
||
3239 | { |
||
3240 | as_warn (_(".loc outside of .text")); |
||
3241 | demand_empty_rest_of_line (); |
||
3242 | return; |
||
3243 | } |
||
3244 | |||
3245 | /* Skip the file number. */ |
||
3246 | SKIP_WHITESPACE (); |
||
3247 | get_absolute_expression (); |
||
3248 | SKIP_WHITESPACE (); |
||
3249 | |||
3250 | lineno = get_absolute_expression (); |
||
3251 | |||
3252 | #ifndef NO_LISTING |
||
3253 | if (listing) |
||
3254 | listing_source_line (lineno); |
||
3255 | #endif |
||
3256 | |||
3257 | /* If we're building stabs, then output a special label rather than |
||
3258 | ECOFF line number info. */ |
||
3259 | if (stabs_seen) |
||
3260 | { |
||
3261 | (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text, |
||
3262 | symbol_new ("L0\001", now_seg, |
||
3263 | (valueT) frag_now_fix (), |
||
3264 | frag_now), |
||
3265 | (bfd_vma) 0, 0, lineno); |
||
3266 | return; |
||
3267 | } |
||
3268 | |||
3269 | list = allocate_lineno_list (); |
||
3270 | |||
3271 | list->next = (lineno_list_t *) NULL; |
||
3272 | list->file = cur_file_ptr; |
||
3273 | list->proc = cur_proc_ptr; |
||
3274 | list->frag = frag_now; |
||
3275 | list->paddr = frag_now_fix (); |
||
3276 | list->lineno = lineno; |
||
3277 | |||
3278 | /* We don't want to merge files which have line numbers. */ |
||
3279 | cur_file_ptr->fdr.fMerge = 0; |
||
3280 | |||
3281 | /* A .loc directive will sometimes appear before a .ent directive, |
||
3282 | which means that cur_proc_ptr will be NULL here. Arrange to |
||
3283 | patch this up. */ |
||
3284 | if (cur_proc_ptr == (proc_t *) NULL) |
||
3285 | { |
||
3286 | lineno_list_t **pl; |
||
3287 | |||
3288 | pl = &noproc_lineno; |
||
3289 | while (*pl != (lineno_list_t *) NULL) |
||
3290 | pl = &(*pl)->next; |
||
3291 | *pl = list; |
||
3292 | } |
||
3293 | else |
||
3294 | { |
||
3295 | last_lineno = list; |
||
3296 | *last_lineno_ptr = list; |
||
3297 | last_lineno_ptr = &list->next; |
||
3298 | } |
||
3299 | } |
||
3300 | |||
3301 | /* The MIPS assembler sometimes inserts nop instructions in the |
||
3302 | instruction stream. When this happens, we must patch up the .loc |
||
3303 | information so that it points to the instruction after the nop. */ |
||
3304 | |||
3305 | void |
||
3306 | ecoff_fix_loc (fragS *old_frag, unsigned long old_frag_offset) |
||
3307 | { |
||
3308 | if (last_lineno != NULL |
||
3309 | && last_lineno->frag == old_frag |
||
3310 | && last_lineno->paddr == old_frag_offset) |
||
3311 | { |
||
3312 | last_lineno->frag = frag_now; |
||
3313 | last_lineno->paddr = frag_now_fix (); |
||
3314 | } |
||
3315 | } |
||
3316 | |||
3317 | /* Make sure the @stabs symbol is emitted. */ |
||
3318 | |||
3319 | static void |
||
3320 | mark_stabs (int ignore ATTRIBUTE_UNUSED) |
||
3321 | { |
||
3322 | if (! stabs_seen) |
||
3323 | { |
||
3324 | /* Add a dummy @stabs dymbol. */ |
||
3325 | stabs_seen = 1; |
||
3326 | (void) add_ecoff_symbol (stabs_symbol, st_Nil, sc_Info, |
||
3327 | (symbolS *) NULL, |
||
3328 | (bfd_vma) 0, (symint_t) -1, |
||
3329 | ECOFF_MARK_STAB (0)); |
||
3330 | } |
||
3331 | } |
||
3332 | |||
3333 | /* Parse .weakext directives. */ |
||
3334 | #ifndef TC_MIPS |
||
3335 | /* For TC_MIPS use the version in tc-mips.c. */ |
||
3336 | void |
||
3337 | ecoff_directive_weakext (int ignore ATTRIBUTE_UNUSED) |
||
3338 | { |
||
3339 | char *name; |
||
3340 | int c; |
||
3341 | symbolS *symbolP; |
||
3342 | expressionS exp; |
||
3343 | |||
6324 | serge | 3344 | c = get_symbol_name (&name); |
5222 | serge | 3345 | symbolP = symbol_find_or_make (name); |
6324 | serge | 3346 | (void) restore_line_pointer (c); |
5222 | serge | 3347 | |
3348 | SKIP_WHITESPACE (); |
||
3349 | |||
3350 | if (*input_line_pointer == ',') |
||
3351 | { |
||
3352 | if (S_IS_DEFINED (symbolP)) |
||
3353 | { |
||
3354 | as_bad (_("symbol `%s' is already defined"), |
||
3355 | S_GET_NAME (symbolP)); |
||
3356 | ignore_rest_of_line (); |
||
3357 | return; |
||
3358 | } |
||
3359 | |||
3360 | ++input_line_pointer; |
||
3361 | SKIP_WHITESPACE (); |
||
3362 | if (! is_end_of_line[(unsigned char) *input_line_pointer]) |
||
3363 | { |
||
3364 | expression (&exp); |
||
3365 | if (exp.X_op != O_symbol) |
||
3366 | { |
||
3367 | as_bad (_("bad .weakext directive")); |
||
3368 | ignore_rest_of_line (); |
||
3369 | return; |
||
3370 | } |
||
3371 | symbol_set_value_expression (symbolP, &exp); |
||
3372 | } |
||
3373 | } |
||
3374 | |||
3375 | S_SET_WEAK (symbolP); |
||
3376 | |||
3377 | demand_empty_rest_of_line (); |
||
3378 | } |
||
3379 | #endif /* not TC_MIPS */ |
||
3380 | |||
3381 | /* Handle .stabs directives. The actual parsing routine is done by a |
||
3382 | generic routine. This routine is called via OBJ_PROCESS_STAB. |
||
3383 | When this is called, input_line_pointer will be pointing at the |
||
3384 | value field of the stab. |
||
3385 | |||
3386 | .stabs directives have five fields: |
||
3387 | "string" a string, encoding the type information. |
||
3388 | code a numeric code, defined in |
||
3389 | |||
3390 | desc a zero or line number |
||
3391 | value a numeric value or an address. |
||
3392 | |||
3393 | If the value is relocatable, we transform this into: |
||
3394 | iss points as an index into string space |
||
3395 | value value from lookup of the name |
||
3396 | st st from lookup of the name |
||
3397 | sc sc from lookup of the name |
||
3398 | index code|CODE_MASK |
||
3399 | |||
3400 | If the value is not relocatable, we transform this into: |
||
3401 | iss points as an index into string space |
||
3402 | value value |
||
3403 | st st_Nil |
||
3404 | sc sc_Nil |
||
3405 | index code|CODE_MASK |
||
3406 | |||
3407 | .stabn directives have four fields (string is null): |
||
3408 | code a numeric code, defined in |
||
3409 | |||
3410 | desc a zero or a line number |
||
3411 | value a numeric value or an address. */ |
||
3412 | |||
3413 | void |
||
3414 | ecoff_stab (segT sec ATTRIBUTE_UNUSED, |
||
3415 | int what, |
||
3416 | const char *string, |
||
3417 | int type, |
||
3418 | int other, |
||
3419 | int desc) |
||
3420 | { |
||
3421 | efdr_t *save_file_ptr = cur_file_ptr; |
||
3422 | symbolS *sym; |
||
3423 | symint_t value; |
||
3424 | bfd_vma addend; |
||
3425 | st_t st; |
||
3426 | sc_t sc; |
||
3427 | symint_t indx; |
||
3428 | localsym_t *hold = NULL; |
||
3429 | |||
3430 | ecoff_debugging_seen = 1; |
||
3431 | |||
3432 | /* We don't handle .stabd. */ |
||
3433 | if (what != 's' && what != 'n') |
||
3434 | { |
||
3435 | as_bad (_(".stab%c is not supported"), what); |
||
3436 | return; |
||
3437 | } |
||
3438 | |||
3439 | /* A .stabn uses a null name, not an empty string. */ |
||
3440 | if (what == 'n') |
||
3441 | string = NULL; |
||
3442 | |||
3443 | /* We ignore the other field. */ |
||
3444 | if (other != 0) |
||
3445 | as_warn (_(".stab%c: ignoring non-zero other field"), what); |
||
3446 | |||
3447 | /* Make sure we have a current file. */ |
||
3448 | if (cur_file_ptr == (efdr_t *) NULL) |
||
3449 | { |
||
3450 | add_file ((const char *) NULL, 0, 1); |
||
3451 | save_file_ptr = cur_file_ptr; |
||
3452 | } |
||
3453 | |||
3454 | /* For stabs in ECOFF, the first symbol must be @stabs. This is a |
||
3455 | signal to gdb. */ |
||
3456 | if (stabs_seen == 0) |
||
3457 | mark_stabs (0); |
||
3458 | |||
3459 | /* Line number stabs are handled differently, since they have two |
||
3460 | values, the line number and the address of the label. We use the |
||
3461 | index field (aka desc) to hold the line number, and the value |
||
3462 | field to hold the address. The symbol type is st_Label, which |
||
3463 | should be different from the other stabs, so that gdb can |
||
3464 | recognize it. */ |
||
3465 | if (type == N_SLINE) |
||
3466 | { |
||
3467 | SYMR dummy_symr; |
||
3468 | char *name; |
||
3469 | char name_end; |
||
3470 | |||
3471 | #ifndef NO_LISTING |
||
3472 | if (listing) |
||
3473 | listing_source_line ((unsigned int) desc); |
||
3474 | #endif |
||
3475 | |||
3476 | dummy_symr.index = desc; |
||
3477 | if (dummy_symr.index != desc) |
||
3478 | { |
||
3479 | as_warn (_("line number (%d) for .stab%c directive cannot fit in index field (20 bits)"), |
||
3480 | desc, what); |
||
3481 | return; |
||
3482 | } |
||
3483 | |||
6324 | serge | 3484 | name_end = get_symbol_name (&name); |
5222 | serge | 3485 | sym = symbol_find_or_make (name); |
6324 | serge | 3486 | (void) restore_line_pointer (name_end); |
5222 | serge | 3487 | |
3488 | value = 0; |
||
3489 | addend = 0; |
||
3490 | st = st_Label; |
||
3491 | sc = sc_Text; |
||
3492 | indx = desc; |
||
3493 | } |
||
3494 | else |
||
3495 | { |
||
3496 | #ifndef NO_LISTING |
||
3497 | if (listing && (type == N_SO || type == N_SOL)) |
||
3498 | listing_source_file (string); |
||
3499 | #endif |
||
3500 | |||
3501 | if (ISDIGIT (*input_line_pointer) |
||
3502 | || *input_line_pointer == '-' |
||
3503 | || *input_line_pointer == '+') |
||
3504 | { |
||
3505 | st = st_Nil; |
||
3506 | sc = sc_Nil; |
||
3507 | sym = (symbolS *) NULL; |
||
3508 | value = get_absolute_expression (); |
||
3509 | addend = 0; |
||
3510 | } |
||
3511 | else if (! is_name_beginner ((unsigned char) *input_line_pointer)) |
||
3512 | { |
||
3513 | as_warn (_("illegal .stab%c directive, bad character"), what); |
||
3514 | return; |
||
3515 | } |
||
3516 | else |
||
3517 | { |
||
3518 | expressionS exp; |
||
3519 | |||
3520 | sc = sc_Nil; |
||
3521 | st = st_Nil; |
||
3522 | |||
3523 | expression (&exp); |
||
3524 | if (exp.X_op == O_constant) |
||
3525 | { |
||
3526 | sym = NULL; |
||
3527 | value = exp.X_add_number; |
||
3528 | addend = 0; |
||
3529 | } |
||
3530 | else if (exp.X_op == O_symbol) |
||
3531 | { |
||
3532 | sym = exp.X_add_symbol; |
||
3533 | value = 0; |
||
3534 | addend = exp.X_add_number; |
||
3535 | } |
||
3536 | else |
||
3537 | { |
||
3538 | sym = make_expr_symbol (&exp); |
||
3539 | value = 0; |
||
3540 | addend = 0; |
||
3541 | } |
||
3542 | } |
||
3543 | |||
3544 | indx = ECOFF_MARK_STAB (type); |
||
3545 | } |
||
3546 | |||
3547 | /* Don't store the stabs symbol we are creating as the type of the |
||
3548 | ECOFF symbol. We want to compute the type of the ECOFF symbol |
||
3549 | independently. */ |
||
3550 | if (sym != (symbolS *) NULL) |
||
3551 | hold = symbol_get_obj (sym)->ecoff_symbol; |
||
3552 | |||
3553 | (void) add_ecoff_symbol (string, st, sc, sym, addend, value, indx); |
||
3554 | |||
3555 | if (sym != (symbolS *) NULL) |
||
3556 | symbol_get_obj (sym)->ecoff_symbol = hold; |
||
3557 | |||
3558 | /* Restore normal file type. */ |
||
3559 | cur_file_ptr = save_file_ptr; |
||
3560 | } |
||
3561 | |||
3562 | /* Frob an ECOFF symbol. Small common symbols go into a special |
||
3563 | .scommon section rather than bfd_com_section. */ |
||
3564 | |||
3565 | void |
||
3566 | ecoff_frob_symbol (symbolS *sym) |
||
3567 | { |
||
3568 | if (S_IS_COMMON (sym) |
||
3569 | && S_GET_VALUE (sym) > 0 |
||
3570 | && S_GET_VALUE (sym) <= bfd_get_gp_size (stdoutput)) |
||
3571 | { |
||
3572 | static asection scom_section; |
||
3573 | static asymbol scom_symbol; |
||
3574 | |||
3575 | /* We must construct a fake section similar to bfd_com_section |
||
3576 | but with the name .scommon. */ |
||
3577 | if (scom_section.name == NULL) |
||
3578 | { |
||
3579 | scom_section = *bfd_com_section_ptr; |
||
3580 | scom_section.name = ".scommon"; |
||
3581 | scom_section.output_section = &scom_section; |
||
3582 | scom_section.symbol = &scom_symbol; |
||
3583 | scom_section.symbol_ptr_ptr = &scom_section.symbol; |
||
3584 | scom_symbol = *bfd_com_section_ptr->symbol; |
||
3585 | scom_symbol.name = ".scommon"; |
||
3586 | scom_symbol.section = &scom_section; |
||
3587 | } |
||
3588 | S_SET_SEGMENT (sym, &scom_section); |
||
3589 | } |
||
3590 | |||
3591 | /* Double check weak symbols. */ |
||
3592 | if (S_IS_WEAK (sym)) |
||
3593 | { |
||
3594 | if (S_IS_COMMON (sym)) |
||
3595 | as_bad (_("symbol `%s' can not be both weak and common"), |
||
3596 | S_GET_NAME (sym)); |
||
3597 | } |
||
3598 | } |
||
3599 | |||
3600 | /* Add bytes to the symbolic information buffer. */ |
||
3601 | |||
3602 | static char * |
||
3603 | ecoff_add_bytes (char **buf, |
||
3604 | char **bufend, |
||
3605 | char *bufptr, |
||
3606 | unsigned long need) |
||
3607 | { |
||
3608 | unsigned long at; |
||
3609 | unsigned long want; |
||
3610 | |||
3611 | at = bufptr - *buf; |
||
3612 | need -= *bufend - bufptr; |
||
3613 | if (need < PAGE_SIZE) |
||
3614 | need = PAGE_SIZE; |
||
3615 | want = (*bufend - *buf) + need; |
||
3616 | *buf = (char *) xrealloc (*buf, want); |
||
3617 | *bufend = *buf + want; |
||
3618 | return *buf + at; |
||
3619 | } |
||
3620 | |||
3621 | /* Adjust the symbolic information buffer to the alignment required |
||
3622 | for the ECOFF target debugging information. */ |
||
3623 | |||
3624 | static unsigned long |
||
3625 | ecoff_padding_adjust (const struct ecoff_debug_swap *backend, |
||
3626 | char **buf, |
||
3627 | char **bufend, |
||
3628 | unsigned long offset, |
||
3629 | char **bufptrptr) |
||
3630 | { |
||
3631 | bfd_size_type align; |
||
3632 | |||
3633 | align = backend->debug_align; |
||
3634 | if ((offset & (align - 1)) != 0) |
||
3635 | { |
||
3636 | unsigned long add; |
||
3637 | |||
3638 | add = align - (offset & (align - 1)); |
||
3639 | if ((unsigned long) (*bufend - (*buf + offset)) < add) |
||
3640 | (void) ecoff_add_bytes (buf, bufend, *buf + offset, add); |
||
3641 | memset (*buf + offset, 0, add); |
||
3642 | offset += add; |
||
3643 | if (bufptrptr != (char **) NULL) |
||
3644 | *bufptrptr = *buf + offset; |
||
3645 | } |
||
3646 | |||
3647 | return offset; |
||
3648 | } |
||
3649 | |||
3650 | /* Build the line number information. */ |
||
3651 | |||
3652 | static unsigned long |
||
3653 | ecoff_build_lineno (const struct ecoff_debug_swap *backend, |
||
3654 | char **buf, |
||
3655 | char **bufend, |
||
3656 | unsigned long offset, |
||
3657 | long *linecntptr) |
||
3658 | { |
||
3659 | char *bufptr; |
||
6324 | serge | 3660 | lineno_list_t *l; |
5222 | serge | 3661 | lineno_list_t *last; |
3662 | efdr_t *file; |
||
3663 | proc_t *proc; |
||
3664 | unsigned long c; |
||
3665 | long iline; |
||
3666 | long totcount; |
||
3667 | lineno_list_t first; |
||
3668 | lineno_list_t *local_first_lineno = first_lineno; |
||
3669 | |||
3670 | if (linecntptr != (long *) NULL) |
||
3671 | *linecntptr = 0; |
||
3672 | |||
3673 | bufptr = *buf + offset; |
||
3674 | |||
3675 | file = (efdr_t *) NULL; |
||
3676 | proc = (proc_t *) NULL; |
||
3677 | last = (lineno_list_t *) NULL; |
||
3678 | c = offset; |
||
3679 | iline = 0; |
||
3680 | totcount = 0; |
||
3681 | |||
3682 | /* FIXME? Now that MIPS embedded-PIC is gone, it may be safe to |
||
3683 | remove this code. */ |
||
3684 | /* For some reason the address of the first procedure is ignored |
||
3685 | when reading line numbers. This doesn't matter if the address of |
||
3686 | the first procedure is 0, but when gcc is generating MIPS |
||
3687 | embedded PIC code, it will put strings in the .text section |
||
3688 | before the first procedure. We cope by inserting a dummy line if |
||
3689 | the address of the first procedure is not 0. Hopefully this |
||
3690 | won't screw things up too badly. |
||
3691 | |||
3692 | Don't do this for ECOFF assembly source line numbers. They work |
||
3693 | without this extra attention. */ |
||
3694 | if (debug_type != DEBUG_ECOFF |
||
3695 | && first_proc_ptr != (proc_t *) NULL |
||
3696 | && local_first_lineno != (lineno_list_t *) NULL |
||
3697 | && ((S_GET_VALUE (first_proc_ptr->sym->as_sym) |
||
3698 | + bfd_get_section_vma (stdoutput, |
||
3699 | S_GET_SEGMENT (first_proc_ptr->sym->as_sym))) |
||
3700 | != 0)) |
||
3701 | { |
||
3702 | first.file = local_first_lineno->file; |
||
3703 | first.proc = local_first_lineno->proc; |
||
3704 | first.frag = &zero_address_frag; |
||
3705 | first.paddr = 0; |
||
3706 | first.lineno = 0; |
||
3707 | |||
3708 | first.next = local_first_lineno; |
||
3709 | local_first_lineno = &first; |
||
3710 | } |
||
3711 | |||
3712 | for (l = local_first_lineno; l != (lineno_list_t *) NULL; l = l->next) |
||
3713 | { |
||
3714 | long count; |
||
3715 | long delta; |
||
3716 | |||
3717 | /* Get the offset to the memory address of the next line number |
||
3718 | (in words). Do this first, so that we can skip ahead to the |
||
3719 | next useful line number entry. */ |
||
3720 | if (l->next == (lineno_list_t *) NULL) |
||
3721 | { |
||
3722 | /* We want a count of zero, but it will be decremented |
||
3723 | before it is used. */ |
||
3724 | count = 1; |
||
3725 | } |
||
3726 | else if (l->next->frag->fr_address + l->next->paddr |
||
3727 | > l->frag->fr_address + l->paddr) |
||
3728 | { |
||
3729 | count = ((l->next->frag->fr_address + l->next->paddr |
||
3730 | - (l->frag->fr_address + l->paddr)) |
||
3731 | >> 2); |
||
3732 | } |
||
3733 | else |
||
3734 | { |
||
3735 | /* Don't change last, so we still get the right delta. */ |
||
3736 | continue; |
||
3737 | } |
||
3738 | |||
3739 | if (l->file != file || l->proc != proc) |
||
3740 | { |
||
3741 | if (l->proc != proc && proc != (proc_t *) NULL) |
||
3742 | proc->pdr.lnHigh = last->lineno; |
||
3743 | if (l->file != file && file != (efdr_t *) NULL) |
||
3744 | { |
||
3745 | file->fdr.cbLine = c - file->fdr.cbLineOffset; |
||
3746 | file->fdr.cline = totcount + count; |
||
3747 | if (linecntptr != (long *) NULL) |
||
3748 | *linecntptr += totcount + count; |
||
3749 | totcount = 0; |
||
3750 | } |
||
3751 | |||
3752 | if (l->file != file) |
||
3753 | { |
||
3754 | efdr_t *last_file = file; |
||
3755 | |||
3756 | file = l->file; |
||
3757 | if (last_file != (efdr_t *) NULL) |
||
3758 | file->fdr.ilineBase |
||
3759 | = last_file->fdr.ilineBase + last_file->fdr.cline; |
||
3760 | else |
||
3761 | file->fdr.ilineBase = 0; |
||
3762 | file->fdr.cbLineOffset = c; |
||
3763 | } |
||
3764 | if (l->proc != proc) |
||
3765 | { |
||
3766 | proc = l->proc; |
||
3767 | if (proc != (proc_t *) NULL) |
||
3768 | { |
||
3769 | proc->pdr.lnLow = l->lineno; |
||
3770 | proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset; |
||
3771 | proc->pdr.iline = totcount; |
||
3772 | } |
||
3773 | } |
||
3774 | |||
3775 | last = (lineno_list_t *) NULL; |
||
3776 | } |
||
3777 | |||
3778 | totcount += count; |
||
3779 | |||
3780 | /* Get the offset to this line number. */ |
||
3781 | if (last == (lineno_list_t *) NULL) |
||
3782 | delta = 0; |
||
3783 | else |
||
3784 | delta = l->lineno - last->lineno; |
||
3785 | |||
3786 | /* Put in the offset to this line number. */ |
||
3787 | while (delta != 0) |
||
3788 | { |
||
3789 | int setcount; |
||
3790 | |||
3791 | /* 1 is added to each count read. */ |
||
3792 | --count; |
||
3793 | /* We can only adjust the word count by up to 15 words at a |
||
3794 | time. */ |
||
3795 | if (count <= 0x0f) |
||
3796 | { |
||
3797 | setcount = count; |
||
3798 | count = 0; |
||
3799 | } |
||
3800 | else |
||
3801 | { |
||
3802 | setcount = 0x0f; |
||
3803 | count -= 0x0f; |
||
3804 | } |
||
3805 | if (delta >= -7 && delta <= 7) |
||
3806 | { |
||
3807 | if (bufptr >= *bufend) |
||
3808 | bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1); |
||
3809 | *bufptr++ = setcount + (delta << 4); |
||
3810 | delta = 0; |
||
3811 | ++c; |
||
3812 | } |
||
3813 | else |
||
3814 | { |
||
3815 | int set; |
||
3816 | |||
3817 | if (*bufend - bufptr < 3) |
||
3818 | bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3); |
||
3819 | *bufptr++ = setcount + (8 << 4); |
||
3820 | if (delta < -0x8000) |
||
3821 | { |
||
3822 | set = -0x8000; |
||
3823 | delta += 0x8000; |
||
3824 | } |
||
3825 | else if (delta > 0x7fff) |
||
3826 | { |
||
3827 | set = 0x7fff; |
||
3828 | delta -= 0x7fff; |
||
3829 | } |
||
3830 | else |
||
3831 | { |
||
3832 | set = delta; |
||
3833 | delta = 0; |
||
3834 | } |
||
3835 | *bufptr++ = set >> 8; |
||
3836 | *bufptr++ = set & 0xffff; |
||
3837 | c += 3; |
||
3838 | } |
||
3839 | } |
||
3840 | |||
3841 | /* Finish adjusting the count. */ |
||
3842 | while (count > 0) |
||
3843 | { |
||
3844 | if (bufptr >= *bufend) |
||
3845 | bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1); |
||
3846 | /* 1 is added to each count read. */ |
||
3847 | --count; |
||
3848 | if (count > 0x0f) |
||
3849 | { |
||
3850 | *bufptr++ = 0x0f; |
||
3851 | count -= 0x0f; |
||
3852 | } |
||
3853 | else |
||
3854 | { |
||
3855 | *bufptr++ = count; |
||
3856 | count = 0; |
||
3857 | } |
||
3858 | ++c; |
||
3859 | } |
||
3860 | |||
3861 | ++iline; |
||
3862 | last = l; |
||
3863 | } |
||
3864 | |||
3865 | if (proc != (proc_t *) NULL) |
||
3866 | proc->pdr.lnHigh = last->lineno; |
||
3867 | if (file != (efdr_t *) NULL) |
||
3868 | { |
||
3869 | file->fdr.cbLine = c - file->fdr.cbLineOffset; |
||
3870 | file->fdr.cline = totcount; |
||
3871 | } |
||
3872 | |||
3873 | if (linecntptr != (long *) NULL) |
||
3874 | *linecntptr += totcount; |
||
3875 | |||
3876 | c = ecoff_padding_adjust (backend, buf, bufend, c, &bufptr); |
||
3877 | |||
3878 | return c; |
||
3879 | } |
||
3880 | |||
3881 | /* Build and swap out the symbols. */ |
||
3882 | |||
3883 | static unsigned long |
||
3884 | ecoff_build_symbols (const struct ecoff_debug_swap *backend, |
||
3885 | char **buf, |
||
3886 | char **bufend, |
||
3887 | unsigned long offset) |
||
3888 | { |
||
3889 | const bfd_size_type external_sym_size = backend->external_sym_size; |
||
3890 | void (* const swap_sym_out) (bfd *, const SYMR *, void *) |
||
3891 | = backend->swap_sym_out; |
||
3892 | char *sym_out; |
||
3893 | long isym; |
||
3894 | vlinks_t *file_link; |
||
3895 | |||
3896 | sym_out = *buf + offset; |
||
3897 | |||
3898 | isym = 0; |
||
3899 | |||
3900 | /* The symbols are stored by file. */ |
||
3901 | for (file_link = file_desc.first; |
||
3902 | file_link != (vlinks_t *) NULL; |
||
3903 | file_link = file_link->next) |
||
3904 | { |
||
3905 | int ifilesym; |
||
3906 | int fil_cnt; |
||
3907 | efdr_t *fil_ptr; |
||
3908 | efdr_t *fil_end; |
||
3909 | |||
3910 | if (file_link->next == (vlinks_t *) NULL) |
||
3911 | fil_cnt = file_desc.objects_last_page; |
||
3912 | else |
||
3913 | fil_cnt = file_desc.objects_per_page; |
||
3914 | fil_ptr = file_link->datum->file; |
||
3915 | fil_end = fil_ptr + fil_cnt; |
||
3916 | for (; fil_ptr < fil_end; fil_ptr++) |
||
3917 | { |
||
3918 | vlinks_t *sym_link; |
||
3919 | |||
3920 | fil_ptr->fdr.isymBase = isym; |
||
3921 | ifilesym = isym; |
||
3922 | for (sym_link = fil_ptr->symbols.first; |
||
3923 | sym_link != (vlinks_t *) NULL; |
||
3924 | sym_link = sym_link->next) |
||
3925 | { |
||
3926 | int sym_cnt; |
||
3927 | localsym_t *sym_ptr; |
||
3928 | localsym_t *sym_end; |
||
3929 | |||
3930 | if (sym_link->next == (vlinks_t *) NULL) |
||
3931 | sym_cnt = fil_ptr->symbols.objects_last_page; |
||
3932 | else |
||
3933 | sym_cnt = fil_ptr->symbols.objects_per_page; |
||
3934 | sym_ptr = sym_link->datum->sym; |
||
3935 | sym_end = sym_ptr + sym_cnt; |
||
3936 | for (; sym_ptr < sym_end; sym_ptr++) |
||
3937 | { |
||
3938 | int local; |
||
3939 | symbolS *as_sym; |
||
3940 | forward_t *f; |
||
3941 | |||
3942 | know (sym_ptr->file_ptr == fil_ptr); |
||
3943 | |||
3944 | /* If there is no associated gas symbol, then this |
||
3945 | is a pure debugging symbol. We have already |
||
3946 | added the name (if any) to fil_ptr->strings. |
||
3947 | Otherwise we must decide whether this is an |
||
3948 | external or a local symbol (actually, it may be |
||
3949 | both if the local provides additional debugging |
||
3950 | information for the external). */ |
||
3951 | local = 1; |
||
3952 | as_sym = sym_ptr->as_sym; |
||
3953 | if (as_sym != (symbolS *) NULL) |
||
3954 | { |
||
3955 | symint_t indx; |
||
3956 | |||
3957 | /* The value of a block start symbol is the |
||
3958 | offset from the start of the procedure. For |
||
3959 | other symbols we just use the gas value (but |
||
3960 | we must offset it by the vma of the section, |
||
3961 | just as BFD does, because BFD will not see |
||
3962 | this value). */ |
||
3963 | if (sym_ptr->ecoff_sym.asym.st == (int) st_Block |
||
3964 | && sym_ptr->ecoff_sym.asym.sc == (int) sc_Text) |
||
3965 | { |
||
3966 | symbolS *begin_sym; |
||
3967 | |||
3968 | know (sym_ptr->proc_ptr != (proc_t *) NULL); |
||
3969 | begin_sym = sym_ptr->proc_ptr->sym->as_sym; |
||
3970 | if (S_GET_SEGMENT (as_sym) |
||
3971 | != S_GET_SEGMENT (begin_sym)) |
||
3972 | as_warn (_(".begin/.bend in different segments")); |
||
3973 | sym_ptr->ecoff_sym.asym.value = |
||
3974 | S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym); |
||
3975 | } |
||
3976 | else |
||
3977 | sym_ptr->ecoff_sym.asym.value = |
||
3978 | (S_GET_VALUE (as_sym) |
||
3979 | + bfd_get_section_vma (stdoutput, |
||
3980 | S_GET_SEGMENT (as_sym)) |
||
3981 | + sym_ptr->addend); |
||
3982 | |||
3983 | sym_ptr->ecoff_sym.weakext = S_IS_WEAK (as_sym); |
||
3984 | |||
3985 | /* Set st_Proc to st_StaticProc for local |
||
3986 | functions. */ |
||
3987 | if (sym_ptr->ecoff_sym.asym.st == st_Proc |
||
3988 | && S_IS_DEFINED (as_sym) |
||
3989 | && ! S_IS_EXTERNAL (as_sym) |
||
3990 | && ! S_IS_WEAK (as_sym)) |
||
3991 | sym_ptr->ecoff_sym.asym.st = st_StaticProc; |
||
3992 | |||
3993 | /* Get the type and storage class based on where |
||
3994 | the symbol actually wound up. Traditionally, |
||
3995 | N_LBRAC and N_RBRAC are *not* relocated. */ |
||
3996 | indx = sym_ptr->ecoff_sym.asym.index; |
||
3997 | if (sym_ptr->ecoff_sym.asym.st == st_Nil |
||
3998 | && sym_ptr->ecoff_sym.asym.sc == sc_Nil |
||
3999 | && (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym) |
||
4000 | || ((ECOFF_UNMARK_STAB (indx) != N_LBRAC) |
||
4001 | && (ECOFF_UNMARK_STAB (indx) != N_RBRAC)))) |
||
4002 | { |
||
4003 | segT seg; |
||
4004 | const char *segname; |
||
4005 | st_t st; |
||
4006 | sc_t sc; |
||
4007 | |||
4008 | seg = S_GET_SEGMENT (as_sym); |
||
4009 | segname = segment_name (seg); |
||
4010 | |||
4011 | if (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym) |
||
4012 | && (S_IS_EXTERNAL (as_sym) |
||
4013 | || S_IS_WEAK (as_sym) |
||
4014 | || ! S_IS_DEFINED (as_sym))) |
||
4015 | { |
||
4016 | if ((symbol_get_bfdsym (as_sym)->flags |
||
4017 | & BSF_FUNCTION) != 0) |
||
4018 | st = st_Proc; |
||
4019 | else |
||
4020 | st = st_Global; |
||
4021 | } |
||
4022 | else if (seg == text_section) |
||
4023 | st = st_Label; |
||
4024 | else |
||
4025 | st = st_Static; |
||
4026 | |||
4027 | if (! S_IS_DEFINED (as_sym)) |
||
4028 | { |
||
4029 | valueT s; |
||
4030 | |||
4031 | s = symbol_get_obj (as_sym)->ecoff_extern_size; |
||
4032 | if (s == 0 |
||
4033 | || s > bfd_get_gp_size (stdoutput)) |
||
4034 | sc = sc_Undefined; |
||
4035 | else |
||
4036 | { |
||
4037 | sc = sc_SUndefined; |
||
4038 | sym_ptr->ecoff_sym.asym.value = s; |
||
4039 | } |
||
4040 | #ifdef S_SET_SIZE |
||
4041 | S_SET_SIZE (as_sym, s); |
||
4042 | #endif |
||
4043 | } |
||
4044 | else if (S_IS_COMMON (as_sym)) |
||
4045 | { |
||
4046 | if (S_GET_VALUE (as_sym) > 0 |
||
4047 | && (S_GET_VALUE (as_sym) |
||
4048 | <= bfd_get_gp_size (stdoutput))) |
||
4049 | sc = sc_SCommon; |
||
4050 | else |
||
4051 | sc = sc_Common; |
||
4052 | } |
||
4053 | else if (seg == text_section) |
||
4054 | sc = sc_Text; |
||
4055 | else if (seg == data_section) |
||
4056 | sc = sc_Data; |
||
4057 | else if (strcmp (segname, ".rdata") == 0 |
||
4058 | || strcmp (segname, ".rodata") == 0) |
||
4059 | sc = sc_RData; |
||
4060 | else if (strcmp (segname, ".sdata") == 0) |
||
4061 | sc = sc_SData; |
||
4062 | else if (seg == bss_section) |
||
4063 | sc = sc_Bss; |
||
4064 | else if (strcmp (segname, ".sbss") == 0) |
||
4065 | sc = sc_SBss; |
||
4066 | else if (seg == bfd_abs_section_ptr) |
||
4067 | sc = sc_Abs; |
||
4068 | else |
||
4069 | { |
||
4070 | /* This must be a user named section. |
||
4071 | This is not possible in ECOFF, but it |
||
4072 | is in ELF. */ |
||
4073 | sc = sc_Data; |
||
4074 | } |
||
4075 | |||
4076 | sym_ptr->ecoff_sym.asym.st = (int) st; |
||
4077 | sym_ptr->ecoff_sym.asym.sc = (int) sc; |
||
4078 | } |
||
4079 | |||
4080 | /* This is just an external symbol if it is |
||
4081 | outside a procedure and it has a type. |
||
4082 | FIXME: g++ will generate symbols which have |
||
4083 | different names in the debugging information |
||
4084 | than the actual symbol. Should we handle |
||
4085 | them here? */ |
||
4086 | if ((S_IS_EXTERNAL (as_sym) |
||
4087 | || S_IS_WEAK (as_sym) |
||
4088 | || ! S_IS_DEFINED (as_sym)) |
||
4089 | && sym_ptr->proc_ptr == (proc_t *) NULL |
||
4090 | && sym_ptr->ecoff_sym.asym.st != (int) st_Nil |
||
4091 | && ! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)) |
||
4092 | local = 0; |
||
4093 | |||
4094 | /* This is just an external symbol if it is a |
||
4095 | common symbol. */ |
||
4096 | if (S_IS_COMMON (as_sym)) |
||
4097 | local = 0; |
||
4098 | |||
4099 | /* If an st_end symbol has an associated gas |
||
4100 | symbol, then it is a local label created for |
||
4101 | a .bend or .end directive. Stabs line |
||
4102 | numbers will have \001 in the names. */ |
||
4103 | if (local |
||
4104 | && sym_ptr->ecoff_sym.asym.st != st_End |
||
4105 | && strchr (sym_ptr->name, '\001') == 0) |
||
4106 | sym_ptr->ecoff_sym.asym.iss = |
||
4107 | add_string (&fil_ptr->strings, |
||
4108 | fil_ptr->str_hash, |
||
4109 | sym_ptr->name, |
||
4110 | (shash_t **) NULL); |
||
4111 | } |
||
4112 | |||
4113 | /* We now know the index of this symbol; fill in |
||
4114 | locations that have been waiting for that |
||
4115 | information. */ |
||
4116 | if (sym_ptr->begin_ptr != (localsym_t *) NULL) |
||
4117 | { |
||
4118 | localsym_t *begin_ptr; |
||
4119 | st_t begin_type; |
||
4120 | |||
4121 | know (local); |
||
4122 | begin_ptr = sym_ptr->begin_ptr; |
||
4123 | know (begin_ptr->sym_index != -1); |
||
4124 | sym_ptr->ecoff_sym.asym.index = begin_ptr->sym_index; |
||
4125 | if (sym_ptr->ecoff_sym.asym.sc != (int) sc_Info) |
||
4126 | sym_ptr->ecoff_sym.asym.iss = |
||
4127 | begin_ptr->ecoff_sym.asym.iss; |
||
4128 | |||
4129 | begin_type = (st_t) begin_ptr->ecoff_sym.asym.st; |
||
4130 | if (begin_type == st_File |
||
4131 | || begin_type == st_Block) |
||
4132 | { |
||
4133 | begin_ptr->ecoff_sym.asym.index = |
||
4134 | isym - ifilesym + 1; |
||
4135 | (*swap_sym_out) (stdoutput, |
||
4136 | &begin_ptr->ecoff_sym.asym, |
||
4137 | (*buf |
||
4138 | + offset |
||
4139 | + (begin_ptr->sym_index |
||
4140 | * external_sym_size))); |
||
4141 | } |
||
4142 | else |
||
4143 | { |
||
4144 | know (begin_ptr->index_ptr != (aux_t *) NULL); |
||
4145 | begin_ptr->index_ptr->data.isym = |
||
4146 | isym - ifilesym + 1; |
||
4147 | } |
||
4148 | |||
4149 | /* The value of the symbol marking the end of a |
||
4150 | procedure is the size of the procedure. The |
||
4151 | value of the symbol marking the end of a |
||
4152 | block is the offset from the start of the |
||
4153 | procedure to the block. */ |
||
4154 | if (begin_type == st_Proc |
||
4155 | || begin_type == st_StaticProc) |
||
4156 | { |
||
4157 | know (as_sym != (symbolS *) NULL); |
||
4158 | know (begin_ptr->as_sym != (symbolS *) NULL); |
||
4159 | if (S_GET_SEGMENT (as_sym) |
||
4160 | != S_GET_SEGMENT (begin_ptr->as_sym)) |
||
4161 | as_warn (_(".begin/.bend in different segments")); |
||
4162 | sym_ptr->ecoff_sym.asym.value = |
||
4163 | (S_GET_VALUE (as_sym) |
||
4164 | - S_GET_VALUE (begin_ptr->as_sym)); |
||
4165 | |||
4166 | /* If the size is odd, this is probably a |
||
4167 | mips16 function; force it to be even. */ |
||
4168 | if ((sym_ptr->ecoff_sym.asym.value & 1) != 0) |
||
4169 | ++sym_ptr->ecoff_sym.asym.value; |
||
4170 | |||
4171 | #ifdef S_SET_SIZE |
||
4172 | S_SET_SIZE (begin_ptr->as_sym, |
||
4173 | sym_ptr->ecoff_sym.asym.value); |
||
4174 | #endif |
||
4175 | } |
||
4176 | else if (begin_type == st_Block |
||
4177 | && sym_ptr->ecoff_sym.asym.sc != (int) sc_Info) |
||
4178 | { |
||
4179 | symbolS *begin_sym; |
||
4180 | |||
4181 | know (as_sym != (symbolS *) NULL); |
||
4182 | know (sym_ptr->proc_ptr != (proc_t *) NULL); |
||
4183 | begin_sym = sym_ptr->proc_ptr->sym->as_sym; |
||
4184 | if (S_GET_SEGMENT (as_sym) |
||
4185 | != S_GET_SEGMENT (begin_sym)) |
||
4186 | as_warn (_(".begin/.bend in different segments")); |
||
4187 | sym_ptr->ecoff_sym.asym.value = |
||
4188 | S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym); |
||
4189 | } |
||
4190 | } |
||
4191 | |||
4192 | for (f = sym_ptr->forward_ref; |
||
4193 | f != (forward_t *) NULL; |
||
4194 | f = f->next) |
||
4195 | { |
||
4196 | know (local); |
||
4197 | f->ifd_ptr->data.isym = fil_ptr->file_index; |
||
4198 | f->index_ptr->data.rndx.index = isym - ifilesym; |
||
4199 | } |
||
4200 | |||
4201 | if (local) |
||
4202 | { |
||
4203 | if ((bfd_size_type)(*bufend - sym_out) < external_sym_size) |
||
4204 | sym_out = ecoff_add_bytes (buf, bufend, |
||
4205 | sym_out, |
||
4206 | external_sym_size); |
||
4207 | (*swap_sym_out) (stdoutput, &sym_ptr->ecoff_sym.asym, |
||
4208 | sym_out); |
||
4209 | sym_out += external_sym_size; |
||
4210 | |||
4211 | sym_ptr->sym_index = isym; |
||
4212 | |||
4213 | if (sym_ptr->proc_ptr != (proc_t *) NULL |
||
4214 | && sym_ptr->proc_ptr->sym == sym_ptr) |
||
4215 | sym_ptr->proc_ptr->pdr.isym = isym - ifilesym; |
||
4216 | |||
4217 | ++isym; |
||
4218 | } |
||
4219 | |||
4220 | /* Record the local symbol index and file number in |
||
4221 | case this is an external symbol. Note that this |
||
4222 | destroys the asym.index field. */ |
||
4223 | if (as_sym != (symbolS *) NULL |
||
4224 | && symbol_get_obj (as_sym)->ecoff_symbol == sym_ptr) |
||
4225 | { |
||
4226 | if ((sym_ptr->ecoff_sym.asym.st == st_Proc |
||
4227 | || sym_ptr->ecoff_sym.asym.st == st_StaticProc) |
||
4228 | && local) |
||
4229 | sym_ptr->ecoff_sym.asym.index = isym - ifilesym - 1; |
||
4230 | sym_ptr->ecoff_sym.ifd = fil_ptr->file_index; |
||
4231 | |||
4232 | /* Don't try to merge an FDR which has an |
||
4233 | external symbol attached to it. */ |
||
4234 | if (S_IS_EXTERNAL (as_sym) || S_IS_WEAK (as_sym)) |
||
4235 | fil_ptr->fdr.fMerge = 0; |
||
4236 | } |
||
4237 | } |
||
4238 | } |
||
4239 | fil_ptr->fdr.csym = isym - fil_ptr->fdr.isymBase; |
||
4240 | } |
||
4241 | } |
||
4242 | |||
4243 | return offset + isym * external_sym_size; |
||
4244 | } |
||
4245 | |||
4246 | /* Swap out the procedure information. */ |
||
4247 | |||
4248 | static unsigned long |
||
4249 | ecoff_build_procs (const struct ecoff_debug_swap *backend, |
||
4250 | char **buf, |
||
4251 | char **bufend, |
||
4252 | unsigned long offset) |
||
4253 | { |
||
4254 | const bfd_size_type external_pdr_size = backend->external_pdr_size; |
||
4255 | void (* const swap_pdr_out) (bfd *, const PDR *, void *) |
||
4256 | = backend->swap_pdr_out; |
||
4257 | char *pdr_out; |
||
4258 | long iproc; |
||
4259 | vlinks_t *file_link; |
||
4260 | |||
4261 | pdr_out = *buf + offset; |
||
4262 | |||
4263 | iproc = 0; |
||
4264 | |||
4265 | /* The procedures are stored by file. */ |
||
4266 | for (file_link = file_desc.first; |
||
4267 | file_link != (vlinks_t *) NULL; |
||
4268 | file_link = file_link->next) |
||
4269 | { |
||
4270 | int fil_cnt; |
||
4271 | efdr_t *fil_ptr; |
||
4272 | efdr_t *fil_end; |
||
4273 | |||
4274 | if (file_link->next == (vlinks_t *) NULL) |
||
4275 | fil_cnt = file_desc.objects_last_page; |
||
4276 | else |
||
4277 | fil_cnt = file_desc.objects_per_page; |
||
4278 | fil_ptr = file_link->datum->file; |
||
4279 | fil_end = fil_ptr + fil_cnt; |
||
4280 | for (; fil_ptr < fil_end; fil_ptr++) |
||
4281 | { |
||
4282 | vlinks_t *proc_link; |
||
4283 | int first; |
||
4284 | |||
4285 | fil_ptr->fdr.ipdFirst = iproc; |
||
4286 | first = 1; |
||
4287 | for (proc_link = fil_ptr->procs.first; |
||
4288 | proc_link != (vlinks_t *) NULL; |
||
4289 | proc_link = proc_link->next) |
||
4290 | { |
||
4291 | int prc_cnt; |
||
4292 | proc_t *proc_ptr; |
||
4293 | proc_t *proc_end; |
||
4294 | |||
4295 | if (proc_link->next == (vlinks_t *) NULL) |
||
4296 | prc_cnt = fil_ptr->procs.objects_last_page; |
||
4297 | else |
||
4298 | prc_cnt = fil_ptr->procs.objects_per_page; |
||
4299 | proc_ptr = proc_link->datum->proc; |
||
4300 | proc_end = proc_ptr + prc_cnt; |
||
4301 | for (; proc_ptr < proc_end; proc_ptr++) |
||
4302 | { |
||
4303 | symbolS *adr_sym; |
||
4304 | unsigned long adr; |
||
4305 | |||
4306 | adr_sym = proc_ptr->sym->as_sym; |
||
4307 | adr = (S_GET_VALUE (adr_sym) |
||
4308 | + bfd_get_section_vma (stdoutput, |
||
4309 | S_GET_SEGMENT (adr_sym))); |
||
4310 | if (first) |
||
4311 | { |
||
4312 | /* This code used to force the adr of the very |
||
4313 | first fdr to be 0. However, the native tools |
||
4314 | don't do that, and I can't remember why it |
||
4315 | used to work that way, so I took it out. */ |
||
4316 | fil_ptr->fdr.adr = adr; |
||
4317 | first = 0; |
||
4318 | } |
||
4319 | proc_ptr->pdr.adr = adr - fil_ptr->fdr.adr; |
||
4320 | if ((bfd_size_type)(*bufend - pdr_out) < external_pdr_size) |
||
4321 | pdr_out = ecoff_add_bytes (buf, bufend, |
||
4322 | pdr_out, |
||
4323 | external_pdr_size); |
||
4324 | (*swap_pdr_out) (stdoutput, &proc_ptr->pdr, pdr_out); |
||
4325 | pdr_out += external_pdr_size; |
||
4326 | ++iproc; |
||
4327 | } |
||
4328 | } |
||
4329 | fil_ptr->fdr.cpd = iproc - fil_ptr->fdr.ipdFirst; |
||
4330 | } |
||
4331 | } |
||
4332 | |||
4333 | return offset + iproc * external_pdr_size; |
||
4334 | } |
||
4335 | |||
4336 | /* Swap out the aux information. */ |
||
4337 | |||
4338 | static unsigned long |
||
4339 | ecoff_build_aux (const struct ecoff_debug_swap *backend, |
||
4340 | char **buf, |
||
4341 | char **bufend, |
||
4342 | unsigned long offset) |
||
4343 | { |
||
4344 | int bigendian; |
||
4345 | union aux_ext *aux_out; |
||
4346 | long iaux; |
||
4347 | vlinks_t *file_link; |
||
4348 | |||
4349 | bigendian = bfd_big_endian (stdoutput); |
||
4350 | |||
4351 | aux_out = (union aux_ext *) (*buf + offset); |
||
4352 | |||
4353 | iaux = 0; |
||
4354 | |||
4355 | /* The aux entries are stored by file. */ |
||
4356 | for (file_link = file_desc.first; |
||
4357 | file_link != (vlinks_t *) NULL; |
||
4358 | file_link = file_link->next) |
||
4359 | { |
||
4360 | int fil_cnt; |
||
4361 | efdr_t *fil_ptr; |
||
4362 | efdr_t *fil_end; |
||
4363 | |||
4364 | if (file_link->next == (vlinks_t *) NULL) |
||
4365 | fil_cnt = file_desc.objects_last_page; |
||
4366 | else |
||
4367 | fil_cnt = file_desc.objects_per_page; |
||
4368 | fil_ptr = file_link->datum->file; |
||
4369 | fil_end = fil_ptr + fil_cnt; |
||
4370 | for (; fil_ptr < fil_end; fil_ptr++) |
||
4371 | { |
||
4372 | vlinks_t *aux_link; |
||
4373 | |||
4374 | fil_ptr->fdr.fBigendian = bigendian; |
||
4375 | fil_ptr->fdr.iauxBase = iaux; |
||
4376 | for (aux_link = fil_ptr->aux_syms.first; |
||
4377 | aux_link != (vlinks_t *) NULL; |
||
4378 | aux_link = aux_link->next) |
||
4379 | { |
||
4380 | int aux_cnt; |
||
4381 | aux_t *aux_ptr; |
||
4382 | aux_t *aux_end; |
||
4383 | |||
4384 | if (aux_link->next == (vlinks_t *) NULL) |
||
4385 | aux_cnt = fil_ptr->aux_syms.objects_last_page; |
||
4386 | else |
||
4387 | aux_cnt = fil_ptr->aux_syms.objects_per_page; |
||
4388 | aux_ptr = aux_link->datum->aux; |
||
4389 | aux_end = aux_ptr + aux_cnt; |
||
4390 | for (; aux_ptr < aux_end; aux_ptr++) |
||
4391 | { |
||
4392 | if ((unsigned long) (*bufend - (char *) aux_out) |
||
4393 | < sizeof (union aux_ext)) |
||
4394 | aux_out = ((union aux_ext *) |
||
4395 | ecoff_add_bytes (buf, bufend, |
||
4396 | (char *) aux_out, |
||
4397 | sizeof (union aux_ext))); |
||
4398 | switch (aux_ptr->type) |
||
4399 | { |
||
4400 | case aux_tir: |
||
4401 | (*backend->swap_tir_out) (bigendian, |
||
4402 | &aux_ptr->data.ti, |
||
4403 | &aux_out->a_ti); |
||
4404 | break; |
||
4405 | case aux_rndx: |
||
4406 | (*backend->swap_rndx_out) (bigendian, |
||
4407 | &aux_ptr->data.rndx, |
||
4408 | &aux_out->a_rndx); |
||
4409 | break; |
||
4410 | case aux_dnLow: |
||
4411 | AUX_PUT_DNLOW (bigendian, aux_ptr->data.dnLow, |
||
4412 | aux_out); |
||
4413 | break; |
||
4414 | case aux_dnHigh: |
||
4415 | AUX_PUT_DNHIGH (bigendian, aux_ptr->data.dnHigh, |
||
4416 | aux_out); |
||
4417 | break; |
||
4418 | case aux_isym: |
||
4419 | AUX_PUT_ISYM (bigendian, aux_ptr->data.isym, |
||
4420 | aux_out); |
||
4421 | break; |
||
4422 | case aux_iss: |
||
4423 | AUX_PUT_ISS (bigendian, aux_ptr->data.iss, |
||
4424 | aux_out); |
||
4425 | break; |
||
4426 | case aux_width: |
||
4427 | AUX_PUT_WIDTH (bigendian, aux_ptr->data.width, |
||
4428 | aux_out); |
||
4429 | break; |
||
4430 | case aux_count: |
||
4431 | AUX_PUT_COUNT (bigendian, aux_ptr->data.count, |
||
4432 | aux_out); |
||
4433 | break; |
||
4434 | } |
||
4435 | |||
4436 | ++aux_out; |
||
4437 | ++iaux; |
||
4438 | } |
||
4439 | } |
||
4440 | fil_ptr->fdr.caux = iaux - fil_ptr->fdr.iauxBase; |
||
4441 | } |
||
4442 | } |
||
4443 | |||
4444 | return ecoff_padding_adjust (backend, buf, bufend, |
||
4445 | offset + iaux * sizeof (union aux_ext), |
||
4446 | (char **) NULL); |
||
4447 | } |
||
4448 | |||
4449 | /* Copy out the strings from a varray_t. This returns the number of |
||
4450 | bytes copied, rather than the new offset. */ |
||
4451 | |||
4452 | static unsigned long |
||
4453 | ecoff_build_strings (char **buf, |
||
4454 | char **bufend, |
||
4455 | unsigned long offset, |
||
4456 | varray_t *vp) |
||
4457 | { |
||
4458 | unsigned long istr; |
||
4459 | char *str_out; |
||
4460 | vlinks_t *str_link; |
||
4461 | |||
4462 | str_out = *buf + offset; |
||
4463 | |||
4464 | istr = 0; |
||
4465 | |||
4466 | for (str_link = vp->first; |
||
4467 | str_link != (vlinks_t *) NULL; |
||
4468 | str_link = str_link->next) |
||
4469 | { |
||
4470 | unsigned long str_cnt; |
||
4471 | |||
4472 | if (str_link->next == (vlinks_t *) NULL) |
||
4473 | str_cnt = vp->objects_last_page; |
||
4474 | else |
||
4475 | str_cnt = vp->objects_per_page; |
||
4476 | |||
4477 | if ((unsigned long)(*bufend - str_out) < str_cnt) |
||
4478 | str_out = ecoff_add_bytes (buf, bufend, str_out, str_cnt); |
||
4479 | |||
4480 | memcpy (str_out, str_link->datum->byte, str_cnt); |
||
4481 | str_out += str_cnt; |
||
4482 | istr += str_cnt; |
||
4483 | } |
||
4484 | |||
4485 | return istr; |
||
4486 | } |
||
4487 | |||
4488 | /* Dump out the local strings. */ |
||
4489 | |||
4490 | static unsigned long |
||
4491 | ecoff_build_ss (const struct ecoff_debug_swap *backend, |
||
4492 | char **buf, |
||
4493 | char **bufend, |
||
4494 | unsigned long offset) |
||
4495 | { |
||
4496 | long iss; |
||
4497 | vlinks_t *file_link; |
||
4498 | |||
4499 | iss = 0; |
||
4500 | |||
4501 | for (file_link = file_desc.first; |
||
4502 | file_link != (vlinks_t *) NULL; |
||
4503 | file_link = file_link->next) |
||
4504 | { |
||
4505 | int fil_cnt; |
||
4506 | efdr_t *fil_ptr; |
||
4507 | efdr_t *fil_end; |
||
4508 | |||
4509 | if (file_link->next == (vlinks_t *) NULL) |
||
4510 | fil_cnt = file_desc.objects_last_page; |
||
4511 | else |
||
4512 | fil_cnt = file_desc.objects_per_page; |
||
4513 | fil_ptr = file_link->datum->file; |
||
4514 | fil_end = fil_ptr + fil_cnt; |
||
4515 | for (; fil_ptr < fil_end; fil_ptr++) |
||
4516 | { |
||
4517 | long ss_cnt; |
||
4518 | |||
4519 | fil_ptr->fdr.issBase = iss; |
||
4520 | ss_cnt = ecoff_build_strings (buf, bufend, offset + iss, |
||
4521 | &fil_ptr->strings); |
||
4522 | fil_ptr->fdr.cbSs = ss_cnt; |
||
4523 | iss += ss_cnt; |
||
4524 | } |
||
4525 | } |
||
4526 | |||
4527 | return ecoff_padding_adjust (backend, buf, bufend, offset + iss, |
||
4528 | (char **) NULL); |
||
4529 | } |
||
4530 | |||
4531 | /* Swap out the file descriptors. */ |
||
4532 | |||
4533 | static unsigned long |
||
4534 | ecoff_build_fdr (const struct ecoff_debug_swap *backend, |
||
4535 | char **buf, |
||
4536 | char **bufend, |
||
4537 | unsigned long offset) |
||
4538 | { |
||
4539 | const bfd_size_type external_fdr_size = backend->external_fdr_size; |
||
4540 | void (* const swap_fdr_out) (bfd *, const FDR *, void *) |
||
4541 | = backend->swap_fdr_out; |
||
4542 | long ifile; |
||
4543 | char *fdr_out; |
||
4544 | vlinks_t *file_link; |
||
4545 | |||
4546 | ifile = 0; |
||
4547 | |||
4548 | fdr_out = *buf + offset; |
||
4549 | |||
4550 | for (file_link = file_desc.first; |
||
4551 | file_link != (vlinks_t *) NULL; |
||
4552 | file_link = file_link->next) |
||
4553 | { |
||
4554 | int fil_cnt; |
||
4555 | efdr_t *fil_ptr; |
||
4556 | efdr_t *fil_end; |
||
4557 | |||
4558 | if (file_link->next == (vlinks_t *) NULL) |
||
4559 | fil_cnt = file_desc.objects_last_page; |
||
4560 | else |
||
4561 | fil_cnt = file_desc.objects_per_page; |
||
4562 | fil_ptr = file_link->datum->file; |
||
4563 | fil_end = fil_ptr + fil_cnt; |
||
4564 | for (; fil_ptr < fil_end; fil_ptr++) |
||
4565 | { |
||
4566 | if ((bfd_size_type)(*bufend - fdr_out) < external_fdr_size) |
||
4567 | fdr_out = ecoff_add_bytes (buf, bufend, fdr_out, |
||
4568 | external_fdr_size); |
||
4569 | (*swap_fdr_out) (stdoutput, &fil_ptr->fdr, fdr_out); |
||
4570 | fdr_out += external_fdr_size; |
||
4571 | ++ifile; |
||
4572 | } |
||
4573 | } |
||
4574 | |||
4575 | return offset + ifile * external_fdr_size; |
||
4576 | } |
||
4577 | |||
4578 | /* Set up the external symbols. These are supposed to be handled by |
||
4579 | the backend. This routine just gets the right information and |
||
4580 | calls a backend function to deal with it. */ |
||
4581 | |||
4582 | static void |
||
4583 | ecoff_setup_ext (void) |
||
4584 | { |
||
6324 | serge | 4585 | symbolS *sym; |
5222 | serge | 4586 | |
4587 | for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym)) |
||
4588 | { |
||
4589 | if (symbol_get_obj (sym)->ecoff_symbol == NULL) |
||
4590 | continue; |
||
4591 | |||
4592 | /* If this is a local symbol, then force the fields to zero. */ |
||
4593 | if (! S_IS_EXTERNAL (sym) |
||
4594 | && ! S_IS_WEAK (sym) |
||
4595 | && S_IS_DEFINED (sym)) |
||
4596 | { |
||
4597 | struct localsym *lsym; |
||
4598 | |||
4599 | lsym = symbol_get_obj (sym)->ecoff_symbol; |
||
4600 | lsym->ecoff_sym.asym.value = 0; |
||
4601 | lsym->ecoff_sym.asym.st = (int) st_Nil; |
||
4602 | lsym->ecoff_sym.asym.sc = (int) sc_Nil; |
||
4603 | lsym->ecoff_sym.asym.index = indexNil; |
||
4604 | } |
||
4605 | |||
4606 | obj_ecoff_set_ext (sym, &symbol_get_obj (sym)->ecoff_symbol->ecoff_sym); |
||
4607 | } |
||
4608 | } |
||
4609 | |||
4610 | /* Build the ECOFF debugging information. */ |
||
4611 | |||
4612 | unsigned long |
||
4613 | ecoff_build_debug (HDRR *hdr, |
||
4614 | char **bufp, |
||
4615 | const struct ecoff_debug_swap *backend) |
||
4616 | { |
||
4617 | const bfd_size_type external_pdr_size = backend->external_pdr_size; |
||
4618 | tag_t *ptag; |
||
4619 | tag_t *ptag_next; |
||
4620 | efdr_t *fil_ptr; |
||
4621 | int end_warning; |
||
4622 | efdr_t *hold_file_ptr; |
||
4623 | proc_t *hold_proc_ptr; |
||
4624 | symbolS *sym; |
||
4625 | char *buf; |
||
4626 | char *bufend; |
||
4627 | unsigned long offset; |
||
4628 | |||
4629 | /* Make sure we have a file. */ |
||
4630 | if (first_file == (efdr_t *) NULL) |
||
4631 | add_file ((const char *) NULL, 0, 1); |
||
4632 | |||
4633 | /* Handle any top level tags. */ |
||
4634 | for (ptag = top_tag_head->first_tag; |
||
4635 | ptag != (tag_t *) NULL; |
||
4636 | ptag = ptag_next) |
||
4637 | { |
||
4638 | if (ptag->forward_ref != (forward_t *) NULL) |
||
4639 | add_unknown_tag (ptag); |
||
4640 | |||
4641 | ptag_next = ptag->same_block; |
||
4642 | ptag->hash_ptr->tag_ptr = ptag->same_name; |
||
4643 | free_tag (ptag); |
||
4644 | } |
||
4645 | |||
4646 | free_thead (top_tag_head); |
||
4647 | |||
4648 | /* Look through the symbols. Add debugging information for each |
||
4649 | symbol that has not already received it. */ |
||
4650 | hold_file_ptr = cur_file_ptr; |
||
4651 | hold_proc_ptr = cur_proc_ptr; |
||
4652 | cur_proc_ptr = (proc_t *) NULL; |
||
4653 | for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym)) |
||
4654 | { |
||
4655 | if (symbol_get_obj (sym)->ecoff_symbol != NULL |
||
4656 | || symbol_get_obj (sym)->ecoff_file == (efdr_t *) NULL |
||
4657 | || (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0) |
||
4658 | continue; |
||
4659 | |||
4660 | cur_file_ptr = symbol_get_obj (sym)->ecoff_file; |
||
4661 | add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym, |
||
4662 | (bfd_vma) 0, S_GET_VALUE (sym), indexNil); |
||
4663 | } |
||
4664 | cur_proc_ptr = hold_proc_ptr; |
||
4665 | cur_file_ptr = hold_file_ptr; |
||
4666 | |||
4667 | /* Output an ending symbol for all the files. We have to do this |
||
4668 | here for the last file, so we may as well do it for all of the |
||
4669 | files. */ |
||
4670 | end_warning = 0; |
||
4671 | for (fil_ptr = first_file; |
||
4672 | fil_ptr != (efdr_t *) NULL; |
||
4673 | fil_ptr = fil_ptr->next_file) |
||
4674 | { |
||
4675 | cur_file_ptr = fil_ptr; |
||
4676 | while (cur_file_ptr->cur_scope != (scope_t *) NULL |
||
4677 | && cur_file_ptr->cur_scope->prev != (scope_t *) NULL) |
||
4678 | { |
||
4679 | cur_file_ptr->cur_scope = cur_file_ptr->cur_scope->prev; |
||
4680 | if (! end_warning && ! cur_file_ptr->fake) |
||
4681 | { |
||
4682 | as_warn (_("missing .end or .bend at end of file")); |
||
4683 | end_warning = 1; |
||
4684 | } |
||
4685 | } |
||
4686 | if (cur_file_ptr->cur_scope != (scope_t *) NULL) |
||
4687 | (void) add_ecoff_symbol ((const char *) NULL, |
||
4688 | st_End, sc_Text, |
||
4689 | (symbolS *) NULL, |
||
4690 | (bfd_vma) 0, |
||
4691 | (symint_t) 0, |
||
4692 | (symint_t) 0); |
||
4693 | } |
||
4694 | |||
4695 | /* Build the symbolic information. */ |
||
4696 | offset = 0; |
||
4697 | buf = (char *) xmalloc (PAGE_SIZE); |
||
4698 | bufend = buf + PAGE_SIZE; |
||
4699 | |||
4700 | /* Build the line number information. */ |
||
4701 | hdr->cbLineOffset = offset; |
||
4702 | offset = ecoff_build_lineno (backend, &buf, &bufend, offset, |
||
4703 | &hdr->ilineMax); |
||
4704 | hdr->cbLine = offset - hdr->cbLineOffset; |
||
4705 | |||
4706 | /* We don't use dense numbers at all. */ |
||
4707 | hdr->idnMax = 0; |
||
4708 | hdr->cbDnOffset = 0; |
||
4709 | |||
4710 | /* We can't build the PDR table until we have built the symbols, |
||
4711 | because a PDR contains a symbol index. However, we set aside |
||
4712 | space at this point. */ |
||
4713 | hdr->ipdMax = proc_cnt; |
||
4714 | hdr->cbPdOffset = offset; |
||
4715 | if ((bfd_size_type)(bufend - (buf + offset)) < proc_cnt * external_pdr_size) |
||
4716 | (void) ecoff_add_bytes (&buf, &bufend, buf + offset, |
||
4717 | proc_cnt * external_pdr_size); |
||
4718 | offset += proc_cnt * external_pdr_size; |
||
4719 | |||
4720 | /* Build the local symbols. */ |
||
4721 | hdr->cbSymOffset = offset; |
||
4722 | offset = ecoff_build_symbols (backend, &buf, &bufend, offset); |
||
4723 | hdr->isymMax = (offset - hdr->cbSymOffset) / backend->external_sym_size; |
||
4724 | |||
4725 | /* Building the symbols initializes the symbol index in the PDR's. |
||
4726 | Now we can swap out the PDR's. */ |
||
4727 | (void) ecoff_build_procs (backend, &buf, &bufend, hdr->cbPdOffset); |
||
4728 | |||
4729 | /* We don't use optimization symbols. */ |
||
4730 | hdr->ioptMax = 0; |
||
4731 | hdr->cbOptOffset = 0; |
||
4732 | |||
4733 | /* Swap out the auxiliary type information. */ |
||
4734 | hdr->cbAuxOffset = offset; |
||
4735 | offset = ecoff_build_aux (backend, &buf, &bufend, offset); |
||
4736 | hdr->iauxMax = (offset - hdr->cbAuxOffset) / sizeof (union aux_ext); |
||
4737 | |||
4738 | /* Copy out the local strings. */ |
||
4739 | hdr->cbSsOffset = offset; |
||
4740 | offset = ecoff_build_ss (backend, &buf, &bufend, offset); |
||
4741 | hdr->issMax = offset - hdr->cbSsOffset; |
||
4742 | |||
4743 | /* We don't use relative file descriptors. */ |
||
4744 | hdr->crfd = 0; |
||
4745 | hdr->cbRfdOffset = 0; |
||
4746 | |||
4747 | /* Swap out the file descriptors. */ |
||
4748 | hdr->cbFdOffset = offset; |
||
4749 | offset = ecoff_build_fdr (backend, &buf, &bufend, offset); |
||
4750 | hdr->ifdMax = (offset - hdr->cbFdOffset) / backend->external_fdr_size; |
||
4751 | |||
4752 | /* Set up the external symbols, which are handled by the BFD back |
||
4753 | end. */ |
||
4754 | hdr->issExtMax = 0; |
||
4755 | hdr->cbSsExtOffset = 0; |
||
4756 | hdr->iextMax = 0; |
||
4757 | hdr->cbExtOffset = 0; |
||
4758 | ecoff_setup_ext (); |
||
4759 | |||
4760 | know ((offset & (backend->debug_align - 1)) == 0); |
||
4761 | |||
4762 | /* FIXME: This value should be determined from the .verstamp directive, |
||
4763 | with reasonable defaults in config files. */ |
||
4764 | #ifdef TC_ALPHA |
||
4765 | hdr->vstamp = 0x030b; |
||
4766 | #else |
||
4767 | hdr->vstamp = 0x020b; |
||
4768 | #endif |
||
4769 | |||
4770 | *bufp = buf; |
||
4771 | return offset; |
||
4772 | } |
||
4773 | |||
4774 | /* Allocate a cluster of pages. */ |
||
4775 | |||
4776 | #ifndef MALLOC_CHECK |
||
4777 | |||
4778 | static page_type * |
||
4779 | allocate_cluster (unsigned long npages) |
||
4780 | { |
||
6324 | serge | 4781 | page_type *value = (page_type *) xmalloc (npages * PAGE_USIZE); |
5222 | serge | 4782 | |
4783 | #ifdef ECOFF_DEBUG |
||
4784 | if (debug > 3) |
||
4785 | fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value); |
||
4786 | #endif |
||
4787 | |||
4788 | memset (value, 0, npages * PAGE_USIZE); |
||
4789 | |||
4790 | return value; |
||
4791 | } |
||
4792 | |||
4793 | static page_type *cluster_ptr = NULL; |
||
4794 | static unsigned long pages_left = 0; |
||
4795 | |||
4796 | #endif /* MALLOC_CHECK */ |
||
4797 | |||
4798 | /* Allocate one page (which is initialized to 0). */ |
||
4799 | |||
4800 | static page_type * |
||
4801 | allocate_page (void) |
||
4802 | { |
||
4803 | #ifndef MALLOC_CHECK |
||
4804 | |||
4805 | if (pages_left == 0) |
||
4806 | { |
||
4807 | pages_left = MAX_CLUSTER_PAGES; |
||
4808 | cluster_ptr = allocate_cluster (pages_left); |
||
4809 | } |
||
4810 | |||
4811 | pages_left--; |
||
4812 | return cluster_ptr++; |
||
4813 | |||
4814 | #else /* MALLOC_CHECK */ |
||
4815 | |||
4816 | page_type *ptr; |
||
4817 | |||
4818 | ptr = xmalloc (PAGE_USIZE); |
||
4819 | memset (ptr, 0, PAGE_USIZE); |
||
4820 | return ptr; |
||
4821 | |||
4822 | #endif /* MALLOC_CHECK */ |
||
4823 | } |
||
4824 | |||
4825 | /* Allocate scoping information. */ |
||
4826 | |||
4827 | static scope_t * |
||
4828 | allocate_scope (void) |
||
4829 | { |
||
6324 | serge | 4830 | scope_t *ptr; |
5222 | serge | 4831 | static scope_t initial_scope; |
4832 | |||
4833 | #ifndef MALLOC_CHECK |
||
4834 | |||
4835 | ptr = alloc_counts[(int) alloc_type_scope].free_list.f_scope; |
||
4836 | if (ptr != (scope_t *) NULL) |
||
4837 | alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr->free; |
||
4838 | else |
||
4839 | { |
||
6324 | serge | 4840 | int unallocated = alloc_counts[(int) alloc_type_scope].unallocated; |
4841 | page_type *cur_page = alloc_counts[(int) alloc_type_scope].cur_page; |
||
5222 | serge | 4842 | |
4843 | if (unallocated == 0) |
||
4844 | { |
||
4845 | unallocated = PAGE_SIZE / sizeof (scope_t); |
||
4846 | alloc_counts[(int) alloc_type_scope].cur_page = cur_page = allocate_page (); |
||
4847 | alloc_counts[(int) alloc_type_scope].total_pages++; |
||
4848 | } |
||
4849 | |||
4850 | ptr = &cur_page->scope[--unallocated]; |
||
4851 | alloc_counts[(int) alloc_type_scope].unallocated = unallocated; |
||
4852 | } |
||
4853 | |||
4854 | #else |
||
4855 | |||
4856 | ptr = (scope_t *) xmalloc (sizeof (scope_t)); |
||
4857 | |||
4858 | #endif |
||
4859 | |||
4860 | alloc_counts[(int) alloc_type_scope].total_alloc++; |
||
4861 | *ptr = initial_scope; |
||
4862 | return ptr; |
||
4863 | } |
||
4864 | |||
4865 | /* Free scoping information. */ |
||
4866 | |||
4867 | static void |
||
4868 | free_scope (scope_t *ptr) |
||
4869 | { |
||
4870 | alloc_counts[(int) alloc_type_scope].total_free++; |
||
4871 | |||
4872 | #ifndef MALLOC_CHECK |
||
4873 | ptr->free = alloc_counts[(int) alloc_type_scope].free_list.f_scope; |
||
4874 | alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr; |
||
4875 | #else |
||
4876 | free ((void *) ptr); |
||
4877 | #endif |
||
4878 | } |
||
4879 | |||
4880 | /* Allocate links for pages in a virtual array. */ |
||
4881 | |||
4882 | static vlinks_t * |
||
4883 | allocate_vlinks (void) |
||
4884 | { |
||
6324 | serge | 4885 | vlinks_t *ptr; |
5222 | serge | 4886 | static vlinks_t initial_vlinks; |
4887 | |||
4888 | #ifndef MALLOC_CHECK |
||
4889 | |||
6324 | serge | 4890 | int unallocated = alloc_counts[(int) alloc_type_vlinks].unallocated; |
4891 | page_type *cur_page = alloc_counts[(int) alloc_type_vlinks].cur_page; |
||
5222 | serge | 4892 | |
4893 | if (unallocated == 0) |
||
4894 | { |
||
4895 | unallocated = PAGE_SIZE / sizeof (vlinks_t); |
||
4896 | alloc_counts[(int) alloc_type_vlinks].cur_page = cur_page = allocate_page (); |
||
4897 | alloc_counts[(int) alloc_type_vlinks].total_pages++; |
||
4898 | } |
||
4899 | |||
4900 | ptr = &cur_page->vlinks[--unallocated]; |
||
4901 | alloc_counts[(int) alloc_type_vlinks].unallocated = unallocated; |
||
4902 | |||
4903 | #else |
||
4904 | |||
4905 | ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t)); |
||
4906 | |||
4907 | #endif |
||
4908 | |||
4909 | alloc_counts[(int) alloc_type_vlinks].total_alloc++; |
||
4910 | *ptr = initial_vlinks; |
||
4911 | return ptr; |
||
4912 | } |
||
4913 | |||
4914 | /* Allocate string hash buckets. */ |
||
4915 | |||
4916 | static shash_t * |
||
4917 | allocate_shash (void) |
||
4918 | { |
||
6324 | serge | 4919 | shash_t *ptr; |
5222 | serge | 4920 | static shash_t initial_shash; |
4921 | |||
4922 | #ifndef MALLOC_CHECK |
||
4923 | |||
6324 | serge | 4924 | int unallocated = alloc_counts[(int) alloc_type_shash].unallocated; |
4925 | page_type *cur_page = alloc_counts[(int) alloc_type_shash].cur_page; |
||
5222 | serge | 4926 | |
4927 | if (unallocated == 0) |
||
4928 | { |
||
4929 | unallocated = PAGE_SIZE / sizeof (shash_t); |
||
4930 | alloc_counts[(int) alloc_type_shash].cur_page = cur_page = allocate_page (); |
||
4931 | alloc_counts[(int) alloc_type_shash].total_pages++; |
||
4932 | } |
||
4933 | |||
4934 | ptr = &cur_page->shash[--unallocated]; |
||
4935 | alloc_counts[(int) alloc_type_shash].unallocated = unallocated; |
||
4936 | |||
4937 | #else |
||
4938 | |||
4939 | ptr = (shash_t *) xmalloc (sizeof (shash_t)); |
||
4940 | |||
4941 | #endif |
||
4942 | |||
4943 | alloc_counts[(int) alloc_type_shash].total_alloc++; |
||
4944 | *ptr = initial_shash; |
||
4945 | return ptr; |
||
4946 | } |
||
4947 | |||
4948 | /* Allocate type hash buckets. */ |
||
4949 | |||
4950 | static thash_t * |
||
4951 | allocate_thash (void) |
||
4952 | { |
||
6324 | serge | 4953 | thash_t *ptr; |
5222 | serge | 4954 | static thash_t initial_thash; |
4955 | |||
4956 | #ifndef MALLOC_CHECK |
||
4957 | |||
6324 | serge | 4958 | int unallocated = alloc_counts[(int) alloc_type_thash].unallocated; |
4959 | page_type *cur_page = alloc_counts[(int) alloc_type_thash].cur_page; |
||
5222 | serge | 4960 | |
4961 | if (unallocated == 0) |
||
4962 | { |
||
4963 | unallocated = PAGE_SIZE / sizeof (thash_t); |
||
4964 | alloc_counts[(int) alloc_type_thash].cur_page = cur_page = allocate_page (); |
||
4965 | alloc_counts[(int) alloc_type_thash].total_pages++; |
||
4966 | } |
||
4967 | |||
4968 | ptr = &cur_page->thash[--unallocated]; |
||
4969 | alloc_counts[(int) alloc_type_thash].unallocated = unallocated; |
||
4970 | |||
4971 | #else |
||
4972 | |||
4973 | ptr = (thash_t *) xmalloc (sizeof (thash_t)); |
||
4974 | |||
4975 | #endif |
||
4976 | |||
4977 | alloc_counts[(int) alloc_type_thash].total_alloc++; |
||
4978 | *ptr = initial_thash; |
||
4979 | return ptr; |
||
4980 | } |
||
4981 | |||
4982 | /* Allocate structure, union, or enum tag information. */ |
||
4983 | |||
4984 | static tag_t * |
||
4985 | allocate_tag (void) |
||
4986 | { |
||
6324 | serge | 4987 | tag_t *ptr; |
5222 | serge | 4988 | static tag_t initial_tag; |
4989 | |||
4990 | #ifndef MALLOC_CHECK |
||
4991 | |||
4992 | ptr = alloc_counts[(int) alloc_type_tag].free_list.f_tag; |
||
4993 | if (ptr != (tag_t *) NULL) |
||
4994 | alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr->free; |
||
4995 | else |
||
4996 | { |
||
6324 | serge | 4997 | int unallocated = alloc_counts[(int) alloc_type_tag].unallocated; |
4998 | page_type *cur_page = alloc_counts[(int) alloc_type_tag].cur_page; |
||
5222 | serge | 4999 | |
5000 | if (unallocated == 0) |
||
5001 | { |
||
5002 | unallocated = PAGE_SIZE / sizeof (tag_t); |
||
5003 | alloc_counts[(int) alloc_type_tag].cur_page = cur_page = allocate_page (); |
||
5004 | alloc_counts[(int) alloc_type_tag].total_pages++; |
||
5005 | } |
||
5006 | |||
5007 | ptr = &cur_page->tag[--unallocated]; |
||
5008 | alloc_counts[(int) alloc_type_tag].unallocated = unallocated; |
||
5009 | } |
||
5010 | |||
5011 | #else |
||
5012 | |||
5013 | ptr = (tag_t *) xmalloc (sizeof (tag_t)); |
||
5014 | |||
5015 | #endif |
||
5016 | |||
5017 | alloc_counts[(int) alloc_type_tag].total_alloc++; |
||
5018 | *ptr = initial_tag; |
||
5019 | return ptr; |
||
5020 | } |
||
5021 | |||
5022 | /* Free scoping information. */ |
||
5023 | |||
5024 | static void |
||
5025 | free_tag (tag_t *ptr) |
||
5026 | { |
||
5027 | alloc_counts[(int) alloc_type_tag].total_free++; |
||
5028 | |||
5029 | #ifndef MALLOC_CHECK |
||
5030 | ptr->free = alloc_counts[(int) alloc_type_tag].free_list.f_tag; |
||
5031 | alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr; |
||
5032 | #else |
||
5033 | free ((PTR_T) ptr); |
||
5034 | #endif |
||
5035 | } |
||
5036 | |||
5037 | /* Allocate forward reference to a yet unknown tag. */ |
||
5038 | |||
5039 | static forward_t * |
||
5040 | allocate_forward (void) |
||
5041 | { |
||
6324 | serge | 5042 | forward_t *ptr; |
5222 | serge | 5043 | static forward_t initial_forward; |
5044 | |||
5045 | #ifndef MALLOC_CHECK |
||
5046 | |||
6324 | serge | 5047 | int unallocated = alloc_counts[(int) alloc_type_forward].unallocated; |
5048 | page_type *cur_page = alloc_counts[(int) alloc_type_forward].cur_page; |
||
5222 | serge | 5049 | |
5050 | if (unallocated == 0) |
||
5051 | { |
||
5052 | unallocated = PAGE_SIZE / sizeof (forward_t); |
||
5053 | alloc_counts[(int) alloc_type_forward].cur_page = cur_page = allocate_page (); |
||
5054 | alloc_counts[(int) alloc_type_forward].total_pages++; |
||
5055 | } |
||
5056 | |||
5057 | ptr = &cur_page->forward[--unallocated]; |
||
5058 | alloc_counts[(int) alloc_type_forward].unallocated = unallocated; |
||
5059 | |||
5060 | #else |
||
5061 | |||
5062 | ptr = (forward_t *) xmalloc (sizeof (forward_t)); |
||
5063 | |||
5064 | #endif |
||
5065 | |||
5066 | alloc_counts[(int) alloc_type_forward].total_alloc++; |
||
5067 | *ptr = initial_forward; |
||
5068 | return ptr; |
||
5069 | } |
||
5070 | |||
5071 | /* Allocate head of type hash list. */ |
||
5072 | |||
5073 | static thead_t * |
||
5074 | allocate_thead (void) |
||
5075 | { |
||
6324 | serge | 5076 | thead_t *ptr; |
5222 | serge | 5077 | static thead_t initial_thead; |
5078 | |||
5079 | #ifndef MALLOC_CHECK |
||
5080 | |||
5081 | ptr = alloc_counts[(int) alloc_type_thead].free_list.f_thead; |
||
5082 | if (ptr != (thead_t *) NULL) |
||
5083 | alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr->free; |
||
5084 | else |
||
5085 | { |
||
6324 | serge | 5086 | int unallocated = alloc_counts[(int) alloc_type_thead].unallocated; |
5087 | page_type *cur_page = alloc_counts[(int) alloc_type_thead].cur_page; |
||
5222 | serge | 5088 | |
5089 | if (unallocated == 0) |
||
5090 | { |
||
5091 | unallocated = PAGE_SIZE / sizeof (thead_t); |
||
5092 | alloc_counts[(int) alloc_type_thead].cur_page = cur_page = allocate_page (); |
||
5093 | alloc_counts[(int) alloc_type_thead].total_pages++; |
||
5094 | } |
||
5095 | |||
5096 | ptr = &cur_page->thead[--unallocated]; |
||
5097 | alloc_counts[(int) alloc_type_thead].unallocated = unallocated; |
||
5098 | } |
||
5099 | |||
5100 | #else |
||
5101 | |||
5102 | ptr = (thead_t *) xmalloc (sizeof (thead_t)); |
||
5103 | |||
5104 | #endif |
||
5105 | |||
5106 | alloc_counts[(int) alloc_type_thead].total_alloc++; |
||
5107 | *ptr = initial_thead; |
||
5108 | return ptr; |
||
5109 | } |
||
5110 | |||
5111 | /* Free scoping information. */ |
||
5112 | |||
5113 | static void |
||
5114 | free_thead (thead_t *ptr) |
||
5115 | { |
||
5116 | alloc_counts[(int) alloc_type_thead].total_free++; |
||
5117 | |||
5118 | #ifndef MALLOC_CHECK |
||
5119 | ptr->free = (thead_t *) alloc_counts[(int) alloc_type_thead].free_list.f_thead; |
||
5120 | alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr; |
||
5121 | #else |
||
5122 | free ((PTR_T) ptr); |
||
5123 | #endif |
||
5124 | } |
||
5125 | |||
5126 | static lineno_list_t * |
||
5127 | allocate_lineno_list (void) |
||
5128 | { |
||
6324 | serge | 5129 | lineno_list_t *ptr; |
5222 | serge | 5130 | static lineno_list_t initial_lineno_list; |
5131 | |||
5132 | #ifndef MALLOC_CHECK |
||
5133 | |||
6324 | serge | 5134 | int unallocated = alloc_counts[(int) alloc_type_lineno].unallocated; |
5135 | page_type *cur_page = alloc_counts[(int) alloc_type_lineno].cur_page; |
||
5222 | serge | 5136 | |
5137 | if (unallocated == 0) |
||
5138 | { |
||
5139 | unallocated = PAGE_SIZE / sizeof (lineno_list_t); |
||
5140 | alloc_counts[(int) alloc_type_lineno].cur_page = cur_page = allocate_page (); |
||
5141 | alloc_counts[(int) alloc_type_lineno].total_pages++; |
||
5142 | } |
||
5143 | |||
5144 | ptr = &cur_page->lineno[--unallocated]; |
||
5145 | alloc_counts[(int) alloc_type_lineno].unallocated = unallocated; |
||
5146 | |||
5147 | #else |
||
5148 | |||
5149 | ptr = (lineno_list_t *) xmalloc (sizeof (lineno_list_t)); |
||
5150 | |||
5151 | #endif |
||
5152 | |||
5153 | alloc_counts[(int) alloc_type_lineno].total_alloc++; |
||
5154 | *ptr = initial_lineno_list; |
||
5155 | return ptr; |
||
5156 | } |
||
5157 | |||
5158 | void |
||
5159 | ecoff_set_gp_prolog_size (int sz) |
||
5160 | { |
||
5161 | if (cur_proc_ptr == 0) |
||
5162 | return; |
||
5163 | |||
5164 | cur_proc_ptr->pdr.gp_prologue = sz; |
||
5165 | if (cur_proc_ptr->pdr.gp_prologue != sz) |
||
5166 | { |
||
5167 | as_warn (_("GP prologue size exceeds field size, using 0 instead")); |
||
5168 | cur_proc_ptr->pdr.gp_prologue = 0; |
||
5169 | } |
||
5170 | |||
5171 | cur_proc_ptr->pdr.gp_used = 1; |
||
5172 | } |
||
5173 | |||
5174 | int |
||
5175 | ecoff_no_current_file (void) |
||
5176 | { |
||
5177 | return cur_file_ptr == (efdr_t *) NULL; |
||
5178 | } |
||
5179 | |||
5180 | void |
||
5181 | ecoff_generate_asm_lineno (void) |
||
5182 | { |
||
5183 | unsigned int lineno; |
||
5184 | char *filename; |
||
5185 | lineno_list_t *list; |
||
5186 | |||
5187 | as_where (&filename, &lineno); |
||
5188 | |||
5189 | if (current_stabs_filename == (char *) NULL |
||
5190 | || filename_cmp (current_stabs_filename, filename)) |
||
5191 | add_file (filename, 0, 1); |
||
5192 | |||
5193 | list = allocate_lineno_list (); |
||
5194 | |||
5195 | list->next = (lineno_list_t *) NULL; |
||
5196 | list->file = cur_file_ptr; |
||
5197 | list->proc = cur_proc_ptr; |
||
5198 | list->frag = frag_now; |
||
5199 | list->paddr = frag_now_fix (); |
||
5200 | list->lineno = lineno; |
||
5201 | |||
5202 | /* We don't want to merge files which have line numbers. */ |
||
5203 | cur_file_ptr->fdr.fMerge = 0; |
||
5204 | |||
5205 | /* A .loc directive will sometimes appear before a .ent directive, |
||
5206 | which means that cur_proc_ptr will be NULL here. Arrange to |
||
5207 | patch this up. */ |
||
5208 | if (cur_proc_ptr == (proc_t *) NULL) |
||
5209 | { |
||
5210 | lineno_list_t **pl; |
||
5211 | |||
5212 | pl = &noproc_lineno; |
||
5213 | while (*pl != (lineno_list_t *) NULL) |
||
5214 | pl = &(*pl)->next; |
||
5215 | *pl = list; |
||
5216 | } |
||
5217 | else |
||
5218 | { |
||
5219 | last_lineno = list; |
||
5220 | *last_lineno_ptr = list; |
||
5221 | last_lineno_ptr = &list->next; |
||
5222 | } |
||
5223 | } |
||
5224 | |||
5225 | #else |
||
5226 | |||
5227 | void |
||
5228 | ecoff_generate_asm_lineno (void) |
||
5229 | { |
||
5230 | } |
||
5231 | |||
5232 | #endif /* ECOFF_DEBUGGING */>>>>>>>>>>>>=>>>>><>>><>=>=>>>=>>>>>><>> |