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