14dcc127f6d6aaf2a973c230b74f9f5a41dcea95
[binutils-gdb.git] / gas / config / vms / vms.c
1 /* vms.c -- Write out a VAX/VMS object file
2
3 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /* Written by David L. Kashtan */
22 #include <ctype.h>
23 #include <stdio.h>
24
25 #include "as.h"
26 #include "subsegs.h"
27 #include "obstack.h"
28 #include "struc-symbol.h"
29 #include "write.h"
30 #include "symbols.h"
31
32 #ifdef VMS /* THIS MODULE IS FOR VMS ONLY */
33
34 #include <stab.h>
35 #include "objrecdef.h" /* Define VMS Object record lang. */
36 #include <vms/fabdef.h> /* Define File Access Block */
37 #include <vms/namdef.h> /* Define NAM Block */
38 #include <vms/xabdef.h> /* Define XAB */
39 #include <vms/xabdatdef.h> /* Define Date XAB */
40 #include <vms/xabfhcdef.h> /* Define File Header XAB */
41
42 const pseudo_typeS obj_pseudo_table[] = {
43 { "const", s_const, 0 },
44
45 }; /* obj_pseudo_table */
46
47 /*
48 * Version string of the compiler that produced the code we are
49 * assembling. (And this assembler, if we do not have compiler info.)
50 */
51 extern char version_string[];
52 char *compiler_version_string;
53
54 extern char *myname;
55 static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
56
57 /*
58 * We augment the "gas" symbol structure with this
59 */
60 struct VMS_Symbol {
61 struct VMS_Symbol *Next;
62 struct symbol *Symbol;
63 int Size;
64 int Psect_Index;
65 int Psect_Offset;
66 };
67 struct VMS_Symbol *VMS_Symbols = 0;
68
69 /* we need this to keep track of the various input files, so that we can
70 * give the debugger the correct source line
71 */
72
73 struct input_file{
74 struct input_file* next;
75 struct input_file* same_file_fpnt;
76 int file_number;
77 int max_line;
78 int min_line;
79 int offset;
80 char flag;
81 char * name;
82 symbolS * spnt;
83 };
84
85 static struct input_file * file_root = (struct input_file*)NULL;
86
87 struct input_file * find_file(symbolS *);
88
89 \f
90 /*
91 * If the procedure "main()" exists we have to add the instruction
92 * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
93 */
94 VMS_Check_For_Main()
95 {
96 register symbolS *symbolP;
97 #ifdef HACK_DEC_C_STARTUP /* JF */
98 register struct frchain *frchainP;
99 register fragS *fragP;
100 register fragS **prev_fragPP;
101 register struct fix *fixP;
102 register fragS *New_Frag;
103 int i;
104 #endif HACK_DEC_C_STARTUP
105
106 symbolP = (struct symbol *)symbol_find("_main");
107 if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {
108 #ifdef HACK_DEC_C_STARTUP
109 if( !flagseen['+']) {
110 #endif
111 /*
112 * Remember the entry point symbol
113 */
114 Entry_Point_Symbol = symbolP;
115 #ifdef HACK_DEC_C_STARTUP
116 } else {
117 /*
118 * Scan all the fragment chains for the one with "_main"
119 * (Actually we know the fragment from the symbol, but we need
120 * the previous fragment so we can change its pointer)
121 */
122 frchainP = frchain_root;
123 while(frchainP) {
124 /*
125 * Scan all the fragments in this chain, remembering
126 * the "previous fragment"
127 */
128 prev_fragPP = &frchainP->frch_root;
129 fragP = frchainP->frch_root;
130 while(fragP && (fragP != frchainP->frch_last)) {
131 /*
132 * Is this the fragment?
133 */
134 if (fragP == symbolP->sy_frag) {
135 /*
136 * Yes: Modify the fragment by replacing
137 * it with a new fragment.
138 */
139 New_Frag = (fragS *)
140 xmalloc(sizeof(*New_Frag) +
141 fragP->fr_fix +
142 fragP->fr_var +
143 5);
144 /*
145 * The fragments are the same except
146 * that the "fixed" area is larger
147 */
148 *New_Frag = *fragP;
149 New_Frag->fr_fix += 6;
150 /*
151 * Copy the literal data opening a hole
152 * 2 bytes after "_main" (i.e. just after
153 * the entry mask). Into which we place
154 * the JSB instruction.
155 */
156 New_Frag->fr_literal[0] = fragP->fr_literal[0];
157 New_Frag->fr_literal[1] = fragP->fr_literal[1];
158 New_Frag->fr_literal[2] = 0x16; /* Jsb */
159 New_Frag->fr_literal[3] = 0xef;
160 New_Frag->fr_literal[4] = 0;
161 New_Frag->fr_literal[5] = 0;
162 New_Frag->fr_literal[6] = 0;
163 New_Frag->fr_literal[7] = 0;
164 for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
165 New_Frag->fr_literal[i+6] =
166 fragP->fr_literal[i];
167 /*
168 * Now replace the old fragment with the
169 * newly generated one.
170 */
171 *prev_fragPP = New_Frag;
172 /*
173 * Remember the entry point symbol
174 */
175 Entry_Point_Symbol = symbolP;
176 /*
177 * Scan the text area fixup structures
178 * as offsets in the fragment may have
179 * changed
180 */
181 for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
182 /*
183 * Look for references to this
184 * fragment.
185 */
186 if (fixP->fx_frag == fragP) {
187 /*
188 * Change the fragment
189 * pointer
190 */
191 fixP->fx_frag = New_Frag;
192 /*
193 * If the offset is after
194 * the entry mask we need
195 * to account for the JSB
196 * instruction we just
197 * inserted.
198 */
199 if (fixP->fx_where >= 2)
200 fixP->fx_where += 6;
201 }
202 }
203 /*
204 * Scan the symbols as offsets in the
205 * fragment may have changed
206 */
207 for(symbolP = symbol_rootP;
208 symbolP;
209 symbolP = symbol_next(symbolP)) {
210 /*
211 * Look for references to this
212 * fragment.
213 */
214 if (symbolP->sy_frag == fragP) {
215 /*
216 * Change the fragment
217 * pointer
218 */
219 symbolP->sy_frag = New_Frag;
220 /*
221 * If the offset is after
222 * the entry mask we need
223 * to account for the JSB
224 * instruction we just
225 * inserted.
226 */
227 if (symbolP->sy_nlist.n_value >= 2)
228 symbolP->sy_nlist.n_value += 6;
229 }
230 }
231 /*
232 * Make a symbol reference to
233 * "_c$main_args" so we can get
234 * its address inserted into the
235 * JSB instruction.
236 */
237 symbolP = (symbolS *)xmalloc(sizeof(*symbolP));
238 symbolP->sy_nlist.n_un.n_name = "_c$main_args";
239 symbolP->sy_nlist.n_type = N_UNDF;
240 symbolP->sy_nlist.n_other = 0;
241 symbolP->sy_nlist.n_desc = 0;
242 symbolP->sy_nlist.n_value = 0;
243 symbolP->sy_name_offset = 0;
244 symbolP->sy_number = 0;
245 symbolP->sy_frag = New_Frag;
246 symbolP->sy_forward = 0;
247 /* this actually inserts at the beginning of the list */
248 symbol_append(symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP);
249
250 symbol_rootP = symbolP;
251 /*
252 * Generate a text fixup structure
253 * to get "_c$main_args" stored into the
254 * JSB instruction.
255 */
256 fixP = (struct fix *)xmalloc(sizeof(*fixP));
257 fixP->fx_frag = New_Frag;
258 fixP->fx_where = 4;
259 fixP->fx_addsy = symbolP;
260 fixP->fx_subsy = 0;
261 fixP->fx_offset = 0;
262 fixP->fx_size = sizeof(long);
263 fixP->fx_pcrel = 1;
264 fixP->fx_next = text_fix_root;
265 text_fix_root = fixP;
266 /*
267 * Now make sure we exit from the loop
268 */
269 frchainP = 0;
270 break;
271 }
272 /*
273 * Try the next fragment
274 */
275 prev_fragPP = &fragP->fr_next;
276 fragP = fragP->fr_next;
277 }
278 /*
279 * Try the next fragment chain
280 */
281 if (frchainP) frchainP=frchainP->frch_next;
282 }
283 }
284 #endif /* HACK_DEC_C_STARTUP */
285 }
286 }
287 \f
288 /*
289 * Write a VAX/VMS object file (everything else has been done!)
290 */
291 VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)
292 unsigned text_siz;
293 unsigned data_siz;
294 struct frag *text_frag_root;
295 struct frag *data_frag_root;
296 {
297 register fragS * fragP;
298 register symbolS * symbolP;
299 register symbolS * sp;
300 register struct fix * fixP;
301 register struct VMS_Symbol * vsp;
302 int Local_Initialized_Data_Size = 0;
303 int Psect_Number = 0; /* Psect Index Number */
304 int Text_Psect = -1; /* Text Psect Index */
305 int Data_Psect = -2; /* Data Psect Index JF: Was -1 */
306 int Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */
307
308 /*
309 * Create the VMS object file
310 */
311 Create_VMS_Object_File();
312 /*
313 * Write the module header records
314 */
315 Write_VMS_MHD_Records();
316 \f
317 /*
318 * Generate the VMS object file records
319 * 1st GSD then TIR records
320 */
321
322 /******* Global Symbol Dictionary *******/
323 /*
324 * Define the Text Psect
325 */
326 if (text_siz > 0) {
327 Text_Psect = Psect_Number++;
328 VMS_Psect_Spec("$code",text_siz,"TEXT");
329 }
330 /*
331 * Define the BSS Psect
332 */
333 if (local_bss_counter > 0) {
334 Bss_Psect = Psect_Number++;
335 VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA");
336 }
337 /*
338 * Now scan the symbols and emit the appropriate GSD records
339 */
340 for (sp = symbol_rootP; sp; sp = symbol_next(sp)) {
341 /*
342 * Dispatch on symbol type
343 */
344 switch(sp->sy_type) {
345 /*
346 * Global uninitialized data
347 */
348 case N_UNDF | N_EXT:
349 /*
350 * Make a VMS data symbol entry
351 */
352 vsp = (struct VMS_Symbol *)
353 xmalloc(sizeof(*vsp));
354 vsp->Symbol = sp;
355 vsp->Size = sp->sy_nlist.n_value;
356 vsp->Psect_Index = Psect_Number++;
357 vsp->Psect_Offset = 0;
358 vsp->Next = VMS_Symbols;
359 VMS_Symbols = vsp;
360 sp->sy_number = (int)vsp;
361 /*
362 * Make the psect for this data
363 */
364 if(sp->sy_nlist.n_other)
365 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
366 vsp->Size,
367 "CONST");
368 else
369 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
370 vsp->Size,
371 "COMMON");
372 #ifdef NOT_VAX_11_C_COMPATIBLE
373 /*
374 * Place a global symbol at the
375 * beginning of the Psect
376 */
377 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
378 vsp->Psect_Index,
379 0,
380 1);
381 #endif NOT_VAX_11_C_COMPATIBLE
382 break;
383 /*
384 * Local uninitialized data
385 */
386 case N_BSS:
387 /*
388 * Make a VMS data symbol entry
389 */
390 vsp = (struct VMS_Symbol *)
391 xmalloc(sizeof(*vsp));
392 vsp->Symbol = sp;
393 vsp->Size = 0;
394 vsp->Psect_Index = Bss_Psect;
395 vsp->Psect_Offset =
396 sp->sy_nlist.n_value -
397 bss_address_frag . fr_address;
398 vsp->Next = VMS_Symbols;
399 VMS_Symbols = vsp;
400 sp->sy_number = (int)vsp;
401 break;
402 /*
403 * Global initialized data
404 */
405 case N_DATA | N_EXT:
406 /*
407 * Make a VMS data symbol entry
408 */
409 vsp = (struct VMS_Symbol *)
410 xmalloc(sizeof(*vsp));
411 vsp->Symbol = sp;
412 vsp->Size = VMS_Initialized_Data_Size(sp,
413 text_siz + data_siz);
414 vsp->Psect_Index = Psect_Number++;
415 vsp->Psect_Offset = 0;
416 vsp->Next = VMS_Symbols;
417 VMS_Symbols = vsp;
418 sp->sy_number = (int)vsp;
419 /*
420 * Make its psect
421 */
422 if(sp->sy_nlist.n_other)
423 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
424 vsp->Size,
425 "CONST");
426 else
427 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
428 vsp->Size,
429 "COMMON");
430 #ifdef NOT_VAX_11_C_COMPATIBLE
431 /*
432 * Place a global symbol at the
433 * beginning of the Psect
434 */
435 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
436 vsp->Psect_Index,
437 0,
438 1);
439 #endif NOT_VAX_11_C_COMPATIBLE
440 break;
441 /*
442 * Local initialized data
443 */
444 case N_DATA:
445 /*
446 * Make a VMS data symbol entry
447 */
448 vsp = (struct VMS_Symbol *)
449 xmalloc(sizeof(*vsp));
450 vsp->Symbol = sp;
451 vsp->Size =
452 VMS_Initialized_Data_Size(sp,
453 text_siz + data_siz);
454 vsp->Psect_Index = Data_Psect;
455 vsp->Psect_Offset =
456 Local_Initialized_Data_Size;
457 Local_Initialized_Data_Size += vsp->Size;
458 vsp->Next = VMS_Symbols;
459 VMS_Symbols = vsp;
460 sp->sy_number = (int)vsp;
461 break;
462 /*
463 * Global Text definition
464 */
465 case N_TEXT | N_EXT: {
466 unsigned short Entry_Mask;
467
468 /*
469 * Get the entry mask
470 */
471 fragP = sp->sy_frag;
472 Entry_Mask = (fragP->fr_literal[0] & 0xff) +
473 ((fragP->fr_literal[1] & 0xff)
474 << 8);
475 /*
476 * Define the Procedure entry pt.
477 */
478 VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,
479 Text_Psect,
480 sp->sy_nlist.n_value,
481 Entry_Mask);
482 break;
483 }
484 /*
485 * Local Text definition
486 */
487 case N_TEXT:
488 /*
489 * Make a VMS data symbol entry
490 */
491 if(Text_Psect != -1) {
492 vsp = (struct VMS_Symbol *)
493 xmalloc(sizeof(*vsp));
494 vsp->Symbol = sp;
495 vsp->Size = 0;
496 vsp->Psect_Index = Text_Psect;
497 vsp->Psect_Offset = sp->sy_nlist.n_value;
498 vsp->Next = VMS_Symbols;
499 VMS_Symbols = vsp;
500 sp->sy_number = (int)vsp;
501 }
502 break;
503 /*
504 * Global Reference
505 */
506 case N_UNDF:
507 /*
508 * Make a GSD global symbol reference
509 * record.
510 */
511 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
512 0,
513 0,
514 0);
515 break;
516 /*
517 * Anything else
518 */
519 default:
520 /*
521 * Ignore STAB symbols
522 * Including .stabs emitted by g++
523 */
524 if ((sp->sy_type & N_STAB) != 0 || sp->sy_nlist.n_type==22)
525 break;
526 /*
527 * Error
528 */
529 if(sp->sy_nlist.n_type !=22)
530 printf(" ERROR, unknown type (%d)\n",
531 sp->sy_nlist.n_type);
532 break;
533 }
534 }
535 /*
536 * Define the Data Psect
537 */
538 if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {
539 /*
540 * Do it
541 */
542 Data_Psect = Psect_Number++;
543 VMS_Psect_Spec("$data",
544 Local_Initialized_Data_Size,
545 "DATA");
546 /*
547 * Scan the VMS symbols and fill in the data psect
548 */
549 for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
550 /*
551 * Only look for undefined psects
552 */
553 if (vsp->Psect_Index < 0) {
554 /*
555 * And only initialized data
556 */
557 if (vsp->Symbol->sy_nlist.n_type == N_DATA)
558 vsp->Psect_Index = Data_Psect;
559 }
560 }
561 }
562 \f
563 /******* Text Information and Relocation Records *******/
564 /*
565 * Write the text segment data
566 */
567 if (text_siz > 0) {
568 /*
569 * Scan the text fragments
570 */
571 for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
572 /*
573 * Stop if we get to the data fragments
574 */
575 if (fragP == data_frag_root) break;
576 /*
577 * Ignore fragments with no data
578 */
579 if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
580 continue;
581 /*
582 * Go the the appropriate offset in the
583 * Text Psect.
584 */
585 VMS_Set_Psect(Text_Psect,fragP->fr_address,OBJ$C_TIR);
586 /*
587 * Store the "fixed" part
588 */
589 if (fragP->fr_fix)
590 VMS_Store_Immediate_Data(fragP->fr_literal,
591 fragP->fr_fix,
592 OBJ$C_TIR);
593 /*
594 * Store the "variable" part
595 */
596 if (fragP->fr_var && fragP->fr_offset)
597 VMS_Store_Repeated_Data(fragP->fr_offset,
598 fragP->fr_literal+
599 fragP->fr_fix,
600 fragP->fr_var,
601 OBJ$C_TIR);
602 }
603 /*
604 * Now we go through the text segment fixups and
605 * generate TIR records to fix up addresses within
606 * the Text Psect
607 */
608 for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
609 /*
610 * We DO handle the case of "Symbol - Symbol" as
611 * long as it is in the same segment.
612 */
613 if (fixP->fx_subsy && fixP->fx_addsy) {
614 int i;
615
616 /*
617 * They need to be in the same segment
618 */
619 if (fixP->fx_subsy->sy_type !=
620 fixP->fx_addsy->sy_type)
621 error("Fixup data addsy and subsy didn't have the same type");
622 /*
623 * And they need to be in one that we
624 * can check the psect on
625 */
626 if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
627 ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
628 error("Fixup data addsy and subsy didn't have an appropriate type");
629 /*
630 * This had better not be PC relative!
631 */
632 if (fixP->fx_pcrel)
633 error("Fixup data was erroneously \"pcrel\"");
634 /*
635 * Subtract their values to get the
636 * difference.
637 */
638 i = fixP->fx_addsy->sy_value -
639 fixP->fx_subsy->sy_value;
640 /*
641 * Now generate the fixup object records
642 * Set the psect and store the data
643 */
644 VMS_Set_Psect(Text_Psect,
645 fixP->fx_where +
646 fixP->fx_frag->fr_address,
647 OBJ$C_TIR);
648 VMS_Store_Immediate_Data(&i,
649 fixP->fx_size,
650 OBJ$C_TIR);
651 /*
652 * Done
653 */
654 continue;
655 }
656 /*
657 * Size will HAVE to be "long"
658 */
659 if (fixP->fx_size != sizeof(long))
660 error("Fixup datum was not a longword");
661 /*
662 * Symbol must be "added" (if it is ever
663 * subtracted we can
664 * fix this assumption)
665 */
666 if (fixP->fx_addsy == 0)
667 error("Fixup datum was not \"fixP->fx_addsy\"");
668 /*
669 * Store the symbol value in a PIC fashion
670 */
671 VMS_Store_PIC_Symbol_Reference(fixP->fx_addsy,
672 fixP->fx_offset,
673 fixP->fx_pcrel,
674 Text_Psect,
675 fixP->fx_where +
676 fixP->fx_frag->fr_address,
677 OBJ$C_TIR);
678 /*
679 * Check for indirect address reference,
680 * which has to be fixed up (as the linker
681 * will screw it up with TIR$C_STO_PICR).
682 */
683 if (fixP->fx_pcrel)
684 VMS_Fix_Indirect_Reference(Text_Psect,
685 fixP->fx_where +
686 fixP->fx_frag->fr_address,
687 fixP->fx_frag,
688 text_frag_root);
689 }
690 }
691 /*
692 * Store the Data segment:
693 *
694 * Since this is REALLY hard to do any other way,
695 * we actually manufacture the data segment and
696 * the store the appropriate values out of it.
697 */
698 if (data_siz > 0) {
699 char *Data_Segment;
700
701 /*
702 * Allocate the data segment
703 */
704 Data_Segment = (char *)xmalloc(data_siz);
705 /*
706 * Run through the data fragments, filling in the segment
707 */
708 for(fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
709 register long int count;
710 register char * fill_literal;
711 register long int fill_size;
712 int i;
713
714 i = fragP->fr_address - text_siz;
715 if (fragP->fr_fix)
716 bcopy(fragP->fr_literal,
717 Data_Segment + i,
718 fragP->fr_fix);
719 i += fragP->fr_fix;
720
721 fill_literal= fragP -> fr_literal + fragP -> fr_fix;
722 fill_size = fragP -> fr_var;
723 for (count = fragP -> fr_offset; count; count --) {
724 if (fill_size)
725 bcopy(fill_literal,
726 Data_Segment + i,
727 fill_size);
728 i += fill_size;
729 }
730 }
731 /*
732 * Now we can run through all the data symbols
733 * and store the data
734 */
735 for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
736 /*
737 * Ignore anything other than data symbols
738 */
739 if ((vsp->Symbol->sy_nlist.n_type & ~N_EXT) != N_DATA)
740 continue;
741 /*
742 * Set the Psect + Offset
743 */
744 VMS_Set_Psect(vsp->Psect_Index,
745 vsp->Psect_Offset,
746 OBJ$C_TIR);
747 /*
748 * Store the data
749 */
750 VMS_Store_Immediate_Data(Data_Segment +
751 vsp->Symbol->sy_nlist.n_value -
752 text_siz,
753 vsp->Size,
754 OBJ$C_TIR);
755 }
756 /*
757 * Now we go through the data segment fixups and
758 * generate TIR records to fix up addresses within
759 * the Data Psects
760 */
761 for(fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
762 /*
763 * Find the symbol for the containing datum
764 */
765 for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
766 /*
767 * Only bother with Data symbols
768 */
769 sp = vsp->Symbol;
770 if ((sp->sy_nlist.n_type & ~N_EXT) != N_DATA)
771 continue;
772 /*
773 * Ignore symbol if After fixup
774 */
775 if (sp->sy_nlist.n_value >
776 (fixP->fx_where +
777 fixP->fx_frag->fr_address))
778 continue;
779 /*
780 * See if the datum is here
781 */
782 if ((sp->sy_nlist.n_value + vsp->Size) <=
783 (fixP->fx_where +
784 fixP->fx_frag->fr_address))
785 continue;
786 /*
787 * We DO handle the case of "Symbol - Symbol" as
788 * long as it is in the same segment.
789 */
790 if (fixP->fx_subsy && fixP->fx_addsy) {
791 int i;
792
793 /*
794 * They need to be in the same segment
795 */
796 if (fixP->fx_subsy->sy_type !=
797 fixP->fx_addsy->sy_type)
798 error("Fixup data addsy and subsy didn't have the same type");
799 /*
800 * And they need to be in one that we
801 * can check the psect on
802 */
803 if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
804 ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
805 error("Fixup data addsy and subsy didn't have an appropriate type");
806 /*
807 * This had better not be PC relative!
808 */
809 if (fixP->fx_pcrel)
810 error("Fixup data was erroneously \"pcrel\"");
811 /*
812 * Subtract their values to get the
813 * difference.
814 */
815 i = fixP->fx_addsy->sy_value -
816 fixP->fx_subsy->sy_value;
817 /*
818 * Now generate the fixup object records
819 * Set the psect and store the data
820 */
821 VMS_Set_Psect(vsp->Psect_Index,
822 fixP->fx_frag->fr_address +
823 fixP->fx_where -
824 vsp->Symbol->sy_value +
825 vsp->Psect_Offset,
826 OBJ$C_TIR);
827 VMS_Store_Immediate_Data(&i,
828 fixP->fx_size,
829 OBJ$C_TIR);
830 /*
831 * Done
832 */
833 break;
834 }
835 /*
836 * Size will HAVE to be "long"
837 */
838 if (fixP->fx_size != sizeof(long))
839 error("Fixup datum was not a longword");
840 /*
841 * Symbol must be "added" (if it is ever
842 * subtracted we can
843 * fix this assumption)
844 */
845 if (fixP->fx_addsy == 0)
846 error("Fixup datum was not \"fixP->fx_addsy\"");
847 /*
848 * Store the symbol value in a PIC fashion
849 */
850 VMS_Store_PIC_Symbol_Reference(
851 fixP->fx_addsy,
852 fixP->fx_offset,
853 fixP->fx_pcrel,
854 vsp->Psect_Index,
855 fixP->fx_frag->fr_address +
856 fixP->fx_where -
857 vsp->Symbol->sy_value +
858 vsp->Psect_Offset,
859 OBJ$C_TIR);
860 /*
861 * Done
862 */
863 break;
864 }
865
866 }
867 }
868 \f
869 /*
870 * Write the Traceback Begin Module record
871 */
872 VMS_TBT_Module_Begin();
873 /*
874 * Scan the symbols and write out the routines
875 * (this makes the assumption that symbols are in
876 * order of ascending text segment offset)
877 */
878 {
879 struct symbol *Current_Routine = 0;
880 int Current_Line_Number = 0;
881 int Current_Offset = -1;
882 struct input_file * Current_File;
883
884 /* Output debugging info for global variables and static variables that are not
885 * specific to one routine. We also need to examine all stabs directives, to
886 * find the definitions to all of the advanced data types, and this is done by
887 * VMS_LSYM_Parse. This needs to be done before any definitions are output to
888 * the object file, since there can be forward references in the stabs
889 * directives. When through with parsing, the text of the stabs directive
890 * is altered, with the definitions removed, so that later passes will see
891 * directives as they would be written if the type were already defined.
892 *
893 * We also look for files and include files, and make a list of them. We
894 * examine the source file numbers to establish the actual lines that code was
895 * generated from, and then generate offsets.
896 */
897 VMS_LSYM_Parse();
898 for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
899 /*
900 * Deal with STAB symbols
901 */
902 if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
903 /*
904 * Dispatch on STAB type
905 */
906 switch((unsigned char)symbolP->sy_nlist.n_type) {
907 case N_SLINE:
908 if(symbolP->sy_nlist.n_desc > Current_File->max_line)
909 Current_File->max_line = symbolP->sy_nlist.n_desc;
910 if(symbolP->sy_nlist.n_desc < Current_File->min_line)
911 Current_File->min_line = symbolP->sy_nlist.n_desc;
912 break;
913 case N_SO:
914 Current_File =find_file(symbolP);
915 Current_File->flag = 1;
916 Current_File->min_line = 1;
917 break;
918 case N_SOL:
919 Current_File = find_file(symbolP);
920 break;
921 case N_GSYM:
922 VMS_GSYM_Parse(symbolP,Text_Psect);
923 break;
924 case N_LCSYM:
925 VMS_LCSYM_Parse(symbolP,Text_Psect);
926 break;
927 case N_FUN: /* For static constant symbols */
928 case N_STSYM:
929 VMS_STSYM_Parse(symbolP,Text_Psect);
930 break;
931 }
932 }
933 }
934
935 /* now we take a quick sweep through the files and assign offsets
936 to each one. This will essentially be the starting line number to the
937 debugger for each file. Output the info for the debugger to specify the
938 files, and then tell it how many lines to use */
939 {
940 int File_Number = 0;
941 int Debugger_Offset = 0;
942 int file_available;
943 Current_File = file_root;
944 for(Current_File = file_root; Current_File; Current_File = Current_File->next){
945 if(Current_File == (struct input_file*) NULL) break;
946 if(Current_File->max_line == 0) continue;
947 if((strncmp(Current_File->name,"GNU_GXX_INCLUDE:",16) == 0) &&
948 !flagseen['D']) continue;
949 if((strncmp(Current_File->name,"GNU_CC_INCLUDE:",15) == 0) &&
950 !flagseen['D']) continue;
951 /* show a few extra lines at the start of the region selected */
952 if(Current_File->min_line > 2) Current_File->min_line -= 2;
953 Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
954 Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
955 if(Current_File->same_file_fpnt != (struct input_file *) NULL)
956 Current_File->file_number =Current_File->same_file_fpnt->file_number;
957 else {
958 Current_File->file_number = ++File_Number;
959 file_available = VMS_TBT_Source_File(Current_File->name,
960 Current_File->file_number);
961 if(!file_available) {Current_File->file_number = 0;
962 File_Number--;
963 continue;};
964 };
965 VMS_TBT_Source_Lines(Current_File->file_number,
966 Current_File->min_line,
967 Current_File->max_line-Current_File->min_line+1);
968 }; /* for */
969 }; /* scope */
970 Current_File = (struct input_file*) NULL;
971
972 for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
973 /*
974 * Deal with text symbols
975 */
976 if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
977 /*
978 * Ignore symbols starting with "L",
979 * as they are local symbols
980 */
981 if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
982 /*
983 * If there is a routine start defined,
984 * terminate it.
985 */
986 if (Current_Routine) {
987 /*
988 * End the routine
989 */
990 VMS_TBT_Routine_End(text_siz,Current_Routine);
991 }
992 /*
993 * Store the routine begin traceback info
994 */
995 if(Text_Psect != -1) {
996 VMS_TBT_Routine_Begin(symbolP,Text_Psect);
997 Current_Routine = symbolP;
998 }
999 /* Output local symbols, i.e. all symbols that are associated with a specific
1000 * routine. We output them now so the debugger recognizes them as local to
1001 * this routine.
1002 */
1003 { symbolS * symbolP1;
1004 char* pnt;
1005 char* pnt1;
1006 for(symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next(symbolP1)) {
1007 if ((symbolP1->sy_nlist.n_type & N_STAB) == 0) continue;
1008 if (symbolP1->sy_nlist.n_type != N_FUN) continue;
1009 pnt=symbolP->sy_nlist.n_un.n_name;
1010 pnt1=symbolP1->sy_nlist.n_un.n_name;
1011 if(*pnt++ != '_') continue;
1012 while(*pnt++ == *pnt1++) {};
1013 if((*(--pnt) == '\0') && (*(--pnt1) == ':')) break;
1014 };
1015 if(symbolP1 != (symbolS *) NULL)
1016 VMS_DBG_Define_Routine(symbolP1,Current_Routine,Text_Psect);
1017 } /* local symbol block */
1018 /*
1019 * Done
1020 */
1021 continue;
1022 }
1023 /*
1024 * Deal with STAB symbols
1025 */
1026 if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
1027 /*
1028 * Dispatch on STAB type
1029 */
1030 switch((unsigned char)symbolP->sy_nlist.n_type) {
1031 /*
1032 * Line number
1033 */
1034 case N_SLINE:
1035 /* Offset the line into the correct portion
1036 * of the file */
1037 if(Current_File->file_number == 0) break;
1038 /* Sometimes the same offset gets several source
1039 * lines assigned to it.
1040 * We should be selective about which lines
1041 * we allow, we should prefer lines that are
1042 * in the main source file when debugging
1043 * inline functions. */
1044 if((Current_File->file_number != 1) &&
1045 symbolP->sy_nlist.n_value ==
1046 Current_Offset) break;
1047 /* calculate actual debugger source line */
1048 symbolP->sy_nlist.n_desc
1049 += Current_File->offset;
1050 /*
1051 * If this is the 1st N_SLINE, setup
1052 * PC/Line correlation. Otherwise
1053 * do the delta PC/Line. If the offset
1054 * for the line number is not +ve we need
1055 * to do another PC/Line correlation
1056 * setup
1057 */
1058 if (Current_Offset == -1) {
1059 VMS_TBT_Line_PC_Correlation(
1060 symbolP->sy_nlist.n_desc,
1061 symbolP->sy_nlist.n_value,
1062 Text_Psect,
1063 0);
1064 } else {
1065 if ((symbolP->sy_nlist.n_desc -
1066 Current_Line_Number) <= 0) {
1067 /*
1068 * Line delta is not +ve, we
1069 * need to close the line and
1070 * start a new PC/Line
1071 * correlation.
1072 */
1073 VMS_TBT_Line_PC_Correlation(0,
1074 symbolP->sy_nlist.n_value -
1075 Current_Offset,
1076 0,
1077 -1);
1078 VMS_TBT_Line_PC_Correlation(
1079 symbolP->sy_nlist.n_desc,
1080 symbolP->sy_nlist.n_value,
1081 Text_Psect,
1082 0);
1083 } else {
1084 /*
1085 * Line delta is +ve, all is well
1086 */
1087 VMS_TBT_Line_PC_Correlation(
1088 symbolP->sy_nlist.n_desc -
1089 Current_Line_Number,
1090 symbolP->sy_nlist.n_value -
1091 Current_Offset,
1092 0,
1093 1);
1094 }
1095 }
1096 /*
1097 * Update the current line/PC
1098 */
1099 Current_Line_Number = symbolP->sy_nlist.n_desc;
1100 Current_Offset = symbolP->sy_nlist.n_value;
1101 /*
1102 * Done
1103 */
1104 break;
1105 /*
1106 * Source file
1107 */
1108 case N_SO:
1109 /*
1110 * Remember that we had a source file
1111 * and emit the source file debugger
1112 * record
1113 */
1114 Current_File =
1115 find_file(symbolP);
1116 break;
1117 /* We need to make sure that we are really in the actual source file when
1118 * we compute the maximum line number. Otherwise the debugger gets really
1119 * confused */
1120 case N_SOL:
1121 Current_File =
1122 find_file(symbolP);
1123 break;
1124 }
1125 }
1126 }
1127 /*
1128 * If there is a routine start defined,
1129 * terminate it (and the line numbers)
1130 */
1131 if (Current_Routine) {
1132 /*
1133 * Terminate the line numbers
1134 */
1135 VMS_TBT_Line_PC_Correlation(0,
1136 text_siz - Current_Routine->sy_nlist.n_value,
1137 0,
1138 -1);
1139 /*
1140 * Terminate the routine
1141 */
1142 VMS_TBT_Routine_End(text_siz,Current_Routine);
1143 }
1144 }
1145 /*
1146 * Write the Traceback End Module TBT record
1147 */
1148 VMS_TBT_Module_End();
1149 \f
1150 /*
1151 * Write the End Of Module record
1152 */
1153 if (Entry_Point_Symbol == 0)
1154 Write_VMS_EOM_Record(-1,0);
1155 else
1156 Write_VMS_EOM_Record(Text_Psect,
1157 Entry_Point_Symbol->sy_nlist.n_value);
1158 \f
1159 /*
1160 * All done, close the object file
1161 */
1162 Close_VMS_Object_File();
1163 }
1164
1165 \f
1166 /****** VMS OBJECT FILE HACKING ROUTINES *******/
1167
1168
1169 /*
1170 * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
1171 */
1172 static int VMS_Object_File_FD; /* File Descriptor for object file */
1173 static char Object_Record_Buffer[512]; /* Buffer for object file records */
1174 static int Object_Record_Offset; /* Offset to end of data */
1175 static int Current_Object_Record_Type; /* Type of record in above */
1176
1177 /*
1178 * Macros for placing data into the object record buffer
1179 */
1180 #define PUT_LONG(val) *((long *)(Object_Record_Buffer + \
1181 Object_Record_Offset)) = val; \
1182 Object_Record_Offset += sizeof(long)
1183
1184 #define PUT_SHORT(val) *((short *)(Object_Record_Buffer + \
1185 Object_Record_Offset)) = val; \
1186 Object_Record_Offset += sizeof(short)
1187
1188 #define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val
1189
1190 #define PUT_COUNTED_STRING(cp) {\
1191 register char *p = cp; \
1192 PUT_CHAR(strlen(p)); \
1193 while(*p) PUT_CHAR(*p++);}
1194
1195 /*
1196 * Macro for determining if a Name has psect attributes attached
1197 * to it.
1198 */
1199 #define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
1200 #define PSECT_ATTRIBUTES_STRING_LENGTH 18
1201
1202 #define HAS_PSECT_ATTRIBUTES(Name) \
1203 (strncmp((Name[0] == '_' ? Name + 1 : Name), \
1204 PSECT_ATTRIBUTES_STRING, \
1205 PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
1206
1207 \f
1208 /*
1209 * Create the VMS object file
1210 */
1211 Create_VMS_Object_File()
1212 {
1213 #ifdef eunice
1214 VMS_Object_File_FD = creat(out_file_name, 0777, "var");
1215 #else eunice
1216 VMS_Object_File_FD = creat(out_file_name, 0, "rfm=var");
1217 #endif eunice
1218 /*
1219 * Deal with errors
1220 */
1221 if (VMS_Object_File_FD < 0) {
1222 char Error_Line[256];
1223
1224 sprintf(Error_Line,"Couldn't create VMS object file \"%s\"",
1225 out_file_name);
1226 error(Error_Line);
1227 }
1228 /*
1229 * Initialize object file hacking variables
1230 */
1231 Object_Record_Offset = 0;
1232 Current_Object_Record_Type = -1;
1233 }
1234
1235 \f
1236 /*
1237 * Declare a particular type of object file record
1238 */
1239 Set_VMS_Object_File_Record(Type)
1240 int Type;
1241 {
1242 /*
1243 * If the type matches, we are done
1244 */
1245 if (Type == Current_Object_Record_Type) return;
1246 /*
1247 * Otherwise: flush the buffer
1248 */
1249 Flush_VMS_Object_Record_Buffer();
1250 /*
1251 * Set the new type
1252 */
1253 Current_Object_Record_Type = Type;
1254 }
1255
1256 \f
1257 /*
1258 * Flush the object record buffer to the object file
1259 */
1260 Flush_VMS_Object_Record_Buffer()
1261 {
1262 int i;
1263
1264 /*
1265 * If the buffer is empty, we are done
1266 */
1267 if (Object_Record_Offset == 0) return;
1268 /*
1269 * Write the data to the file
1270 */
1271 i= write(VMS_Object_File_FD,
1272 Object_Record_Buffer,
1273 Object_Record_Offset);
1274 if (i != Object_Record_Offset)
1275 error("I/O error writing VMS object file");
1276 /*
1277 * The buffer is now empty
1278 */
1279 Object_Record_Offset = 0;
1280 }
1281
1282 \f
1283 /*
1284 * Close the VMS Object file
1285 */
1286 Close_VMS_Object_File()
1287 {
1288 close(VMS_Object_File_FD);
1289 }
1290
1291 \f
1292 /*
1293 * Write the MHD (Module Header) records
1294 */
1295 Write_VMS_MHD_Records()
1296 {
1297 register char *cp,*cp1;
1298 register int i;
1299 struct {int Size; char *Ptr;} Descriptor;
1300 char Module_Name[256];
1301 char Now[17];
1302
1303 /*
1304 * We are writing a module header record
1305 */
1306 Set_VMS_Object_File_Record(OBJ$C_HDR);
1307 /*
1308 * ***************************
1309 * *MAIN MODULE HEADER RECORD*
1310 * ***************************
1311 *
1312 * Store record type and header type
1313 */
1314 PUT_CHAR(OBJ$C_HDR);
1315 PUT_CHAR(MHD$C_MHD);
1316 /*
1317 * Structure level is 0
1318 */
1319 PUT_CHAR(OBJ$C_STRLVL);
1320 /*
1321 * Maximum record size is size of the object record buffer
1322 */
1323 PUT_SHORT(sizeof(Object_Record_Buffer));
1324 /*
1325 * Get module name (the FILENAME part of the object file)
1326 */
1327 cp = out_file_name;
1328 cp1 = Module_Name;
1329 while(*cp) {
1330 if ((*cp == ']') || (*cp == '>') ||
1331 (*cp == ':') || (*cp == '/')) {
1332 cp1 = Module_Name;
1333 cp++;
1334 continue;
1335 }
1336 *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
1337 }
1338 *cp1 = 0;
1339 /*
1340 * Limit it to 31 characters and store in the object record
1341 */
1342 while(--cp1 >= Module_Name)
1343 if (*cp1 == '.') *cp1 = 0;
1344 if (strlen(Module_Name) > 31) {
1345 if(flagseen['+'])
1346 printf("%s: Module name truncated: %s\n", myname, Module_Name);
1347 Module_Name[31] = 0;
1348 }
1349 PUT_COUNTED_STRING(Module_Name);
1350 /*
1351 * Module Version is "V1.0"
1352 */
1353 PUT_COUNTED_STRING("V1.0");
1354 /*
1355 * Creation time is "now" (17 chars of time string)
1356 */
1357 Descriptor.Size = 17;
1358 Descriptor.Ptr = Now;
1359 sys$asctim(0,&Descriptor,0,0);
1360 for(i = 0; i < 17; i++) PUT_CHAR(Now[i]);
1361 /*
1362 * Patch time is "never" (17 zeros)
1363 */
1364 for(i = 0; i < 17; i++) PUT_CHAR(0);
1365 /*
1366 * Flush the record
1367 */
1368 Flush_VMS_Object_Record_Buffer();
1369 /*
1370 * *************************
1371 * *LANGUAGE PROCESSOR NAME*
1372 * *************************
1373 *
1374 * Store record type and header type
1375 */
1376 PUT_CHAR(OBJ$C_HDR);
1377 PUT_CHAR(MHD$C_LNM);
1378 /*
1379 * Store language processor name and version
1380 * (not a counted string!)
1381 */
1382 cp = compiler_version_string;
1383 if (cp == 0) {
1384 cp ="GNU AS V";
1385 while(*cp) PUT_CHAR(*cp++);
1386 cp = strchr(&version_string,'.');
1387 while(*cp != ' ') cp--; cp++;
1388 };
1389 while(*cp >= 32) PUT_CHAR(*cp++);
1390 /*
1391 * Flush the record
1392 */
1393 Flush_VMS_Object_Record_Buffer();
1394 }
1395
1396 \f
1397 /*
1398 * Write the EOM (End Of Module) record
1399 */
1400 Write_VMS_EOM_Record(Psect, Offset)
1401 int Psect;
1402 int Offset;
1403 {
1404 /*
1405 * We are writing an end-of-module record
1406 */
1407 Set_VMS_Object_File_Record(OBJ$C_EOM);
1408 /*
1409 * Store record Type
1410 */
1411 PUT_CHAR(OBJ$C_EOM);
1412 /*
1413 * Store the error severity (0)
1414 */
1415 PUT_CHAR(0);
1416 /*
1417 * Store the entry point, if it exists
1418 */
1419 if (Psect >= 0) {
1420 /*
1421 * Store the entry point Psect
1422 */
1423 PUT_CHAR(Psect);
1424 /*
1425 * Store the entry point Psect offset
1426 */
1427 PUT_LONG(Offset);
1428 }
1429 /*
1430 * Flush the record
1431 */
1432 Flush_VMS_Object_Record_Buffer();
1433 }
1434
1435 \f
1436 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
1437
1438 static int
1439 hash_string (ptr)
1440 unsigned char *ptr;
1441 {
1442 register unsigned char *p = ptr;
1443 register unsigned char *end = p + strlen(ptr);
1444 register unsigned char c;
1445 register int hash = 0;
1446
1447 while (p != end)
1448 {
1449 c = *p++;
1450 hash = ((hash<<3) + (hash<<15) + (hash>>28) + c);
1451 }
1452 return hash;
1453 }
1454
1455 /*
1456 * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
1457 */
1458 VMS_Case_Hack_Symbol(In,Out)
1459 register char *In;
1460 register char *Out;
1461 {
1462 long int init = 0;
1463 long int result;
1464 char *pnt;
1465 char *new_name;
1466 char *old_name;
1467 register int i;
1468 int destructor = 0; /*hack to allow for case sens in a destructor*/
1469 int truncate = 0;
1470 int Case_Hack_Bits = 0;
1471 int Saw_Dollar = 0;
1472 static char Hex_Table[16] =
1473 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1474
1475 /*
1476 * Kill any leading "_"
1477 */
1478 if (*In == '_') In++;
1479
1480 new_name=Out; /* save this for later*/
1481
1482 if((In[0]=='_')&&(In[1]=='$')&&(In[2]=='_'))
1483 destructor=1;
1484
1485 /* We may need to truncate the symbol, save the hash for later*/
1486 if(strlen(In)>23) result = hash_string(In);
1487 /*
1488 * Is there a Psect Attribute to skip??
1489 */
1490 if (HAS_PSECT_ATTRIBUTES(In)) {
1491 /*
1492 * Yes: Skip it
1493 */
1494 In += PSECT_ATTRIBUTES_STRING_LENGTH;
1495 while(*In) {
1496 if ((In[0] == '$') && (In[1] == '$')) {
1497 In += 2;
1498 break;
1499 }
1500 In++;
1501 }
1502 }
1503
1504 old_name=In;
1505 /* if(strlen(In) > 31 && flagseen['+'])
1506 printf("%s: Symbol name truncated: %s\n",myname,In);*/
1507 /*
1508 * Do the case conversion
1509 */
1510 i = 23; /* Maximum of 23 chars */
1511 while(*In && (--i >= 0)) {
1512 Case_Hack_Bits <<= 1;
1513 if (*In == '$') Saw_Dollar = 1;
1514 if ((destructor==1)&&(i==21)) Saw_Dollar = 0;
1515 if (isupper(*In)) {
1516 *Out++ = *In++;
1517 Case_Hack_Bits |= 1;
1518 } else {
1519 *Out++ = islower(*In) ? toupper(*In++) : *In++;
1520 }
1521 }
1522 /*
1523 * If we saw a dollar sign, we don't do case hacking
1524 */
1525 if(flagseen['h'] || Saw_Dollar)
1526 Case_Hack_Bits = 0;
1527
1528 /*
1529 * If we have more than 23 characters and everything is lowercase
1530 * we can insert the full 31 characters
1531 */
1532 if (*In) {
1533 /*
1534 * We have more than 23 characters
1535 * If we must add the case hack, then we have truncated the str
1536 */
1537 pnt=Out;
1538 truncate=1;
1539 if (Case_Hack_Bits == 0) {
1540 /*
1541 * And so far they are all lower case:
1542 * Check up to 8 more characters
1543 * and ensure that they are lowercase
1544 */
1545 if(flagseen['h'])
1546 i=8;
1547 else
1548 for(i = 0; (In[i] != 0) && (i < 8); i++)
1549 if (isupper(In[i]) && !Saw_Dollar)
1550 break;
1551 if(In[i]==0)
1552 truncate=0;
1553
1554 if ((i >= 8) || (In[i] == 0)) {
1555 /*
1556 * They are: Copy up to 31 characters
1557 * to the output string
1558 */
1559 i = 8;
1560 while((--i >= 0) && (*In))
1561 *Out++ = islower(*In) ?
1562 toupper(*In++) :
1563 *In++;
1564 }
1565 }
1566 }
1567 /*
1568 * If there were any uppercase characters in the name we
1569 * take on the case hacking string
1570 */
1571
1572 /* Old behavior for regular GNU-C compiler */
1573 if (!flagseen['+'])
1574 truncate=0;
1575 if ((Case_Hack_Bits != 0)||(truncate==1)) {
1576 if(truncate==0) {
1577 *Out++ = '_';
1578 for(i = 0; i < 6; i++) {
1579 *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
1580 Case_Hack_Bits >>= 4;
1581 }
1582 *Out++ = 'X';
1583 } else {
1584 Out=pnt; /*Cut back to 23 characters maximum */
1585 *Out++ = '_';
1586 for( i=0; i < 7; i++) {
1587 init = result & 0x01f;
1588 if (init < 10)
1589 *Out++='0'+init;
1590 else
1591 *Out++ = 'A'+init-10;
1592 result = result >> 5;
1593 }
1594 }
1595 } /*Case Hack */
1596 /*
1597 * Done
1598 */
1599 *Out = 0;
1600 if( truncate==1 && flagseen['+'] && flagseen['H'])
1601 printf("%s: Symbol %s replaced by %s\n",myname,old_name,new_name);
1602 }
1603
1604 \f
1605 /*
1606 * Scan a symbol name for a psect attribute specification
1607 */
1608 VMS_Modify_Psect_Attributes(Name, Attribute_Pointer)
1609 char *Name;
1610 int *Attribute_Pointer;
1611 {
1612 register int i;
1613 register char *cp;
1614 int Negate;
1615 static struct {
1616 char *Name;
1617 int Value;
1618 } Attributes[] = {
1619 {"PIC", GPS$M_PIC},
1620 {"LIB", GPS$M_LIB},
1621 {"OVR", GPS$M_OVR},
1622 {"REL", GPS$M_REL},
1623 {"GBL", GPS$M_GBL},
1624 {"SHR", GPS$M_SHR},
1625 {"EXE", GPS$M_EXE},
1626 {"RD", GPS$M_RD},
1627 {"WRT", GPS$M_WRT},
1628 {"VEC", GPS$M_VEC},
1629 {0, 0}};
1630
1631 /*
1632 * Kill leading "_"
1633 */
1634 if (*Name == '_') Name++;
1635 /*
1636 * Check for a PSECT attribute list
1637 */
1638 if (!HAS_PSECT_ATTRIBUTES(Name)) return; /* If not, return */
1639 /*
1640 * Skip the attribute list indicator
1641 */
1642 Name += PSECT_ATTRIBUTES_STRING_LENGTH;
1643 /*
1644 * Process the attributes ("_" separated, "$" terminated)
1645 */
1646 while(*Name != '$') {
1647 /*
1648 * Assume not negating
1649 */
1650 Negate = 0;
1651 /*
1652 * Check for "NO"
1653 */
1654 if ((Name[0] == 'N') && (Name[1] == 'O')) {
1655 /*
1656 * We are negating (and skip the NO)
1657 */
1658 Negate = 1;
1659 Name += 2;
1660 }
1661 /*
1662 * Find the token delimiter
1663 */
1664 cp = Name;
1665 while(*cp && (*cp != '_') && (*cp != '$')) cp++;
1666 /*
1667 * Look for the token in the attribute list
1668 */
1669 for(i = 0; Attributes[i].Name; i++) {
1670 /*
1671 * If the strings match, set/clear the attr.
1672 */
1673 if (strncmp(Name, Attributes[i].Name, cp - Name) == 0) {
1674 /*
1675 * Set or clear
1676 */
1677 if (Negate)
1678 *Attribute_Pointer &=
1679 ~Attributes[i].Value;
1680 else
1681 *Attribute_Pointer |=
1682 Attributes[i].Value;
1683 /*
1684 * Done
1685 */
1686 break;
1687 }
1688 }
1689 /*
1690 * Now skip the attribute
1691 */
1692 Name = cp;
1693 if (*Name == '_') Name++;
1694 }
1695 /*
1696 * Done
1697 */
1698 return;
1699 }
1700
1701 \f
1702 /*
1703 * Define a psect
1704 */
1705 VMS_Psect_Spec(Name, Size, Type)
1706 char *Name;
1707 int Size;
1708 char *Type;
1709 {
1710 char Local[32];
1711 int Psect_Attributes;
1712
1713 /*
1714 * We are writing a GSD record
1715 */
1716 Set_VMS_Object_File_Record(OBJ$C_GSD);
1717 /*
1718 * If the buffer is empty we must insert the GSD record type
1719 */
1720 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
1721 /*
1722 * We are writing a PSECT definition subrecord
1723 */
1724 PUT_CHAR(GSD$C_PSC);
1725 /*
1726 * Psects are always LONGWORD aligned
1727 */
1728 PUT_CHAR(2);
1729 /*
1730 * Generate the appropriate PSECT flags given the PSECT type
1731 */
1732 if (strcmp(Type,"COMMON") == 0) {
1733 /*
1734 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
1735 */
1736 Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
1737 GPS$M_SHR|GPS$M_RD|GPS$M_WRT);
1738 } else if (strcmp(Type,"CONST") == 0) {
1739 /*
1740 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD
1741 */
1742 Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
1743 GPS$M_SHR|GPS$M_RD);
1744 } else if (strcmp(Type,"DATA") == 0) {
1745 /*
1746 * The Data psects are PIC,REL,RD,WRT
1747 */
1748 Psect_Attributes =
1749 (GPS$M_PIC|GPS$M_REL|GPS$M_RD|GPS$M_WRT);
1750 } else if (strcmp(Type,"TEXT") == 0) {
1751 /*
1752 * The Text psects are PIC,REL,SHR,EXE,RD
1753 */
1754 Psect_Attributes =
1755 (GPS$M_PIC|GPS$M_REL|GPS$M_SHR|
1756 GPS$M_EXE|GPS$M_RD);
1757 } else {
1758 /*
1759 * Error: Unknown psect type
1760 */
1761 error("Unknown VMS psect type");
1762 }
1763 /*
1764 * Modify the psect attributes according to any attribute string
1765 */
1766 if (HAS_PSECT_ATTRIBUTES(Name))
1767 VMS_Modify_Psect_Attributes(Name,&Psect_Attributes);
1768 /*
1769 * Specify the psect attributes
1770 */
1771 PUT_SHORT(Psect_Attributes);
1772 /*
1773 * Specify the allocation
1774 */
1775 PUT_LONG(Size);
1776 /*
1777 * Finally, the psect name
1778 */
1779 VMS_Case_Hack_Symbol(Name,Local);
1780 PUT_COUNTED_STRING(Local);
1781 /*
1782 * Flush the buffer if it is more than 75% full
1783 */
1784 if (Object_Record_Offset >
1785 (sizeof(Object_Record_Buffer)*3/4))
1786 Flush_VMS_Object_Record_Buffer();
1787 }
1788
1789 \f
1790 /*
1791 * Define a global symbol
1792 */
1793 VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined)
1794 char *Name;
1795 int Psect_Number;
1796 int Psect_Offset;
1797 {
1798 char Local[32];
1799
1800 /*
1801 * We are writing a GSD record
1802 */
1803 Set_VMS_Object_File_Record(OBJ$C_GSD);
1804 /*
1805 * If the buffer is empty we must insert the GSD record type
1806 */
1807 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
1808 /*
1809 * We are writing a Global symbol definition subrecord
1810 */
1811 if (Psect_Number <= 255) {
1812 PUT_CHAR(GSD$C_SYM);
1813 } else {
1814 PUT_CHAR(GSD$C_SYMW);
1815 }
1816 /*
1817 * Data type is undefined
1818 */
1819 PUT_CHAR(0);
1820 /*
1821 * Switch on Definition/Reference
1822 */
1823 if (Defined) {
1824 /*
1825 * Definition:
1826 * Flags = "RELOCATABLE" and "DEFINED"
1827 */
1828 PUT_SHORT(GSY$M_DEF|GSY$M_REL);
1829 /*
1830 * Psect Number
1831 */
1832 if (Psect_Number <= 255) {
1833 PUT_CHAR(Psect_Number);
1834 } else {
1835 PUT_SHORT(Psect_Number);
1836 }
1837 /*
1838 * Offset
1839 */
1840 PUT_LONG(Psect_Offset);
1841 } else {
1842 /*
1843 * Reference:
1844 * Flags = "RELOCATABLE"
1845 */
1846 PUT_SHORT(GSY$M_REL);
1847 }
1848 /*
1849 * Finally, the global symbol name
1850 */
1851 VMS_Case_Hack_Symbol(Name,Local);
1852 PUT_COUNTED_STRING(Local);
1853 /*
1854 * Flush the buffer if it is more than 75% full
1855 */
1856 if (Object_Record_Offset >
1857 (sizeof(Object_Record_Buffer)*3/4))
1858 Flush_VMS_Object_Record_Buffer();
1859 }
1860
1861 \f
1862 /*
1863 * Define a procedure entry pt/mask
1864 */
1865 VMS_Procedure_Entry_Pt(Name, Psect_Number, Psect_Offset, Entry_Mask)
1866 char *Name;
1867 int Psect_Number;
1868 int Psect_Offset;
1869 int Entry_Mask;
1870 {
1871 char Local[32];
1872
1873 /*
1874 * We are writing a GSD record
1875 */
1876 Set_VMS_Object_File_Record(OBJ$C_GSD);
1877 /*
1878 * If the buffer is empty we must insert the GSD record type
1879 */
1880 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
1881 /*
1882 * We are writing a Procedure Entry Pt/Mask subrecord
1883 */
1884 if (Psect_Number <= 255) {
1885 PUT_CHAR(GSD$C_EPM);
1886 } else {
1887 PUT_CHAR(GSD$C_EPMW);
1888 }
1889 /*
1890 * Data type is undefined
1891 */
1892 PUT_CHAR(0);
1893 /*
1894 * Flags = "RELOCATABLE" and "DEFINED"
1895 */
1896 PUT_SHORT(GSY$M_DEF|GSY$M_REL);
1897 /*
1898 * Psect Number
1899 */
1900 if (Psect_Number <= 255) {
1901 PUT_CHAR(Psect_Number);
1902 } else {
1903 PUT_SHORT(Psect_Number);
1904 }
1905 /*
1906 * Offset
1907 */
1908 PUT_LONG(Psect_Offset);
1909 /*
1910 * Entry mask
1911 */
1912 PUT_SHORT(Entry_Mask);
1913 /*
1914 * Finally, the global symbol name
1915 */
1916 VMS_Case_Hack_Symbol(Name,Local);
1917 PUT_COUNTED_STRING(Local);
1918 /*
1919 * Flush the buffer if it is more than 75% full
1920 */
1921 if (Object_Record_Offset >
1922 (sizeof(Object_Record_Buffer)*3/4))
1923 Flush_VMS_Object_Record_Buffer();
1924 }
1925
1926 \f
1927 /*
1928 * Set the current location counter to a particular Psect and Offset
1929 */
1930 VMS_Set_Psect(Psect_Index, Offset, Record_Type)
1931 int Psect_Index;
1932 int Offset;
1933 int Record_Type;
1934 {
1935 /*
1936 * We are writing a "Record_Type" record
1937 */
1938 Set_VMS_Object_File_Record(Record_Type);
1939 /*
1940 * If the buffer is empty we must insert the record type
1941 */
1942 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
1943 /*
1944 * Stack the Psect base + Longword Offset
1945 */
1946 if (Psect_Index < 255) {
1947 PUT_CHAR(TIR$C_STA_PL);
1948 PUT_CHAR(Psect_Index);
1949 } else {
1950 PUT_CHAR(TIR$C_STA_WPL);
1951 PUT_SHORT(Psect_Index);
1952 }
1953 PUT_LONG(Offset);
1954 /*
1955 * Set relocation base
1956 */
1957 PUT_CHAR(TIR$C_CTL_SETRB);
1958 /*
1959 * Flush the buffer if it is more than 75% full
1960 */
1961 if (Object_Record_Offset >
1962 (sizeof(Object_Record_Buffer)*3/4))
1963 Flush_VMS_Object_Record_Buffer();
1964 }
1965
1966 /*
1967 * Make a data reference
1968 */
1969 VMS_Set_Data(Psect_Index, Offset, Record_Type,Force)
1970 int Psect_Index;
1971 int Offset;
1972 int Record_Type;
1973 int Force;
1974 {
1975 /*
1976 * We are writing a "Record_Type" record
1977 */
1978 Set_VMS_Object_File_Record(Record_Type);
1979 /*
1980 * If the buffer is empty we must insert the record type
1981 */
1982 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
1983 /*
1984 * Stack the Psect base + Longword Offset
1985 */
1986 if(Force==1){
1987 if(Psect_Index>127){
1988 PUT_CHAR(TIR$C_STA_WPL);
1989 PUT_SHORT(Psect_Index);
1990 PUT_LONG(Offset);}
1991 else {
1992 PUT_CHAR(TIR$C_STA_PL);
1993 PUT_CHAR(Psect_Index);
1994 PUT_LONG(Offset);}
1995 } else {if(Offset>32767){
1996 PUT_CHAR(TIR$C_STA_WPL);
1997 PUT_SHORT(Psect_Index);
1998 PUT_LONG(Offset);}
1999 else if(Offset>127){
2000 PUT_CHAR(TIR$C_STA_WPW);
2001 PUT_SHORT(Psect_Index);
2002 PUT_SHORT(Offset);}
2003 else{
2004 PUT_CHAR(TIR$C_STA_WPB);
2005 PUT_SHORT(Psect_Index);
2006 PUT_CHAR(Offset);};};
2007 /*
2008 * Set relocation base
2009 */
2010 PUT_CHAR(TIR$C_STO_PIDR);
2011 /*
2012 * Flush the buffer if it is more than 75% full
2013 */
2014 if (Object_Record_Offset >
2015 (sizeof(Object_Record_Buffer)*3/4))
2016 Flush_VMS_Object_Record_Buffer();
2017 }
2018
2019 /*
2020 * Make a debugger reference to a struct, union or enum.
2021 */
2022 VMS_Store_Struct(int Struct_Index)
2023 {
2024 /*
2025 * We are writing a "OBJ$C_DBG" record
2026 */
2027 Set_VMS_Object_File_Record(OBJ$C_DBG);
2028 /*
2029 * If the buffer is empty we must insert the record type
2030 */
2031 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2032 PUT_CHAR(TIR$C_STA_UW);
2033 PUT_SHORT(Struct_Index);
2034 PUT_CHAR(TIR$C_CTL_STKDL);
2035 PUT_CHAR(TIR$C_STO_L);
2036 /*
2037 * Flush the buffer if it is more than 75% full
2038 */
2039 if (Object_Record_Offset >
2040 (sizeof(Object_Record_Buffer)*3/4))
2041 Flush_VMS_Object_Record_Buffer();
2042 }
2043
2044 /*
2045 * Make a debugger reference to partially define a struct, union or enum.
2046 */
2047 VMS_Def_Struct(int Struct_Index)
2048 {
2049 /*
2050 * We are writing a "OBJ$C_DBG" record
2051 */
2052 Set_VMS_Object_File_Record(OBJ$C_DBG);
2053 /*
2054 * If the buffer is empty we must insert the record type
2055 */
2056 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2057 PUT_CHAR(TIR$C_STA_UW);
2058 PUT_SHORT(Struct_Index);
2059 PUT_CHAR(TIR$C_CTL_DFLOC);
2060 /*
2061 * Flush the buffer if it is more than 75% full
2062 */
2063 if (Object_Record_Offset >
2064 (sizeof(Object_Record_Buffer)*3/4))
2065 Flush_VMS_Object_Record_Buffer();
2066 }
2067
2068 VMS_Set_Struct(int Struct_Index)
2069 {/* see previous functions for comments */
2070 Set_VMS_Object_File_Record(OBJ$C_DBG);
2071 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2072 PUT_CHAR(TIR$C_STA_UW);
2073 PUT_SHORT(Struct_Index);
2074 PUT_CHAR(TIR$C_CTL_STLOC);
2075 if (Object_Record_Offset >
2076 (sizeof(Object_Record_Buffer)*3/4))
2077 Flush_VMS_Object_Record_Buffer();
2078 }
2079 \f
2080 /*
2081 * Store immediate data in current Psect
2082 */
2083 VMS_Store_Immediate_Data(Pointer, Size, Record_Type)
2084 register char *Pointer;
2085 int Size;
2086 int Record_Type;
2087 {
2088 register int i;
2089
2090 /*
2091 * We are writing a "Record_Type" record
2092 */
2093 Set_VMS_Object_File_Record(Record_Type);
2094 /*
2095 * We can only store 128 bytes at a time
2096 */
2097 while(Size > 0) {
2098 /*
2099 * Store a maximum of 128 bytes
2100 */
2101 i = (Size > 128) ? 128 : Size;
2102 Size -= i;
2103 /*
2104 * If we cannot accommodate this record, flush the
2105 * buffer.
2106 */
2107 if ((Object_Record_Offset + i + 1) >=
2108 sizeof(Object_Record_Buffer))
2109 Flush_VMS_Object_Record_Buffer();
2110 /*
2111 * If the buffer is empty we must insert record type
2112 */
2113 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2114 /*
2115 * Store the count
2116 */
2117 PUT_CHAR(-i & 0xff);
2118 /*
2119 * Store the data
2120 */
2121 while(--i >= 0) PUT_CHAR(*Pointer++);
2122 /*
2123 * Flush the buffer if it is more than 75% full
2124 */
2125 if (Object_Record_Offset >
2126 (sizeof(Object_Record_Buffer)*3/4))
2127 Flush_VMS_Object_Record_Buffer();
2128 }
2129 }
2130
2131 \f
2132 /*
2133 * Store repeated immediate data in current Psect
2134 */
2135 VMS_Store_Repeated_Data(Repeat_Count,Pointer, Size, Record_Type)
2136 int Repeat_Count;
2137 register char *Pointer;
2138 int Size;
2139 int Record_Type;
2140 {
2141
2142 /*
2143 * Ignore zero bytes/words/longwords
2144 */
2145 if ((Size == sizeof(char)) && (*Pointer == 0)) return;
2146 if ((Size == sizeof(short)) && (*(short *)Pointer == 0)) return;
2147 if ((Size == sizeof(long)) && (*(long *)Pointer == 0)) return;
2148 /*
2149 * If the data is too big for a TIR$C_STO_RIVB sub-record
2150 * then we do it manually
2151 */
2152 if (Size > 255) {
2153 while(--Repeat_Count >= 0)
2154 VMS_Store_Immediate_Data(Pointer,Size,Record_Type);
2155 return;
2156 }
2157 /*
2158 * We are writing a "Record_Type" record
2159 */
2160 Set_VMS_Object_File_Record(Record_Type);
2161 /*
2162 * If the buffer is empty we must insert record type
2163 */
2164 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2165 /*
2166 * Stack the repeat count
2167 */
2168 PUT_CHAR(TIR$C_STA_LW);
2169 PUT_LONG(Repeat_Count);
2170 /*
2171 * And now the command and its data
2172 */
2173 PUT_CHAR(TIR$C_STO_RIVB);
2174 PUT_CHAR(Size);
2175 while(--Size >= 0) PUT_CHAR(*Pointer++);
2176 /*
2177 * Flush the buffer if it is more than 75% full
2178 */
2179 if (Object_Record_Offset >
2180 (sizeof(Object_Record_Buffer)*3/4))
2181 Flush_VMS_Object_Record_Buffer();
2182 }
2183
2184 \f
2185 /*
2186 * Store a Position Independent Reference
2187 */
2188 VMS_Store_PIC_Symbol_Reference(Symbol, Offset, PC_Relative,
2189 Psect, Psect_Offset, Record_Type)
2190 struct symbol *Symbol;
2191 int Offset;
2192 int PC_Relative;
2193 int Psect;
2194 int Psect_Offset;
2195 int Record_Type;
2196 {
2197 register struct VMS_Symbol *vsp =
2198 (struct VMS_Symbol *)(Symbol->sy_number);
2199 char Local[32];
2200
2201 /*
2202 * We are writing a "Record_Type" record
2203 */
2204 Set_VMS_Object_File_Record(Record_Type);
2205 /*
2206 * If the buffer is empty we must insert record type
2207 */
2208 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2209 /*
2210 * Set to the appropriate offset in the Psect
2211 */
2212 if (PC_Relative) {
2213 /*
2214 * For a Code reference we need to fix the operand
2215 * specifier as well (so back up 1 byte)
2216 */
2217 VMS_Set_Psect(Psect, Psect_Offset - 1, Record_Type);
2218 } else {
2219 /*
2220 * For a Data reference we just store HERE
2221 */
2222 VMS_Set_Psect(Psect, Psect_Offset, Record_Type);
2223 }
2224 /*
2225 * Make sure we are still generating a "Record Type" record
2226 */
2227 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2228 /*
2229 * Dispatch on symbol type (so we can stack its value)
2230 */
2231 switch(Symbol->sy_nlist.n_type) {
2232 /*
2233 * Global symbol
2234 */
2235 #ifdef NOT_VAX_11_C_COMPATIBLE
2236 case N_UNDF | N_EXT:
2237 case N_DATA | N_EXT:
2238 #endif NOT_VAX_11_C_COMPATIBLE
2239 case N_UNDF:
2240 case N_TEXT | N_EXT:
2241 /*
2242 * Get the symbol name (case hacked)
2243 */
2244 VMS_Case_Hack_Symbol(Symbol->sy_nlist.n_un.n_name,Local);
2245 /*
2246 * Stack the global symbol value
2247 */
2248 PUT_CHAR(TIR$C_STA_GBL);
2249 PUT_COUNTED_STRING(Local);
2250 if (Offset) {
2251 /*
2252 * Stack the longword offset
2253 */
2254 PUT_CHAR(TIR$C_STA_LW);
2255 PUT_LONG(Offset);
2256 /*
2257 * Add the two, leaving the result on the stack
2258 */
2259 PUT_CHAR(TIR$C_OPR_ADD);
2260 }
2261 break;
2262 /*
2263 * Uninitialized local data
2264 */
2265 case N_BSS:
2266 /*
2267 * Stack the Psect (+offset)
2268 */
2269 if (vsp->Psect_Index < 255) {
2270 PUT_CHAR(TIR$C_STA_PL);
2271 PUT_CHAR(vsp->Psect_Index);
2272 } else {
2273 PUT_CHAR(TIR$C_STA_WPL);
2274 PUT_SHORT(vsp->Psect_Index);
2275 }
2276 PUT_LONG(vsp->Psect_Offset + Offset);
2277 break;
2278 /*
2279 * Local text
2280 */
2281 case N_TEXT:
2282 /*
2283 * Stack the Psect (+offset)
2284 */
2285 if (vsp->Psect_Index < 255) {
2286 PUT_CHAR(TIR$C_STA_PL);
2287 PUT_CHAR(vsp->Psect_Index);
2288 } else {
2289 PUT_CHAR(TIR$C_STA_WPL);
2290 PUT_SHORT(vsp->Psect_Index);
2291 }
2292 PUT_LONG(Symbol->sy_nlist.n_value);
2293 break;
2294 /*
2295 * Initialized local or global data
2296 */
2297 case N_DATA:
2298 #ifndef NOT_VAX_11_C_COMPATIBLE
2299 case N_UNDF | N_EXT:
2300 case N_DATA | N_EXT:
2301 #endif NOT_VAX_11_C_COMPATIBLE
2302 /*
2303 * Stack the Psect (+offset)
2304 */
2305 if (vsp->Psect_Index < 255) {
2306 PUT_CHAR(TIR$C_STA_PL);
2307 PUT_CHAR(vsp->Psect_Index);
2308 } else {
2309 PUT_CHAR(TIR$C_STA_WPL);
2310 PUT_SHORT(vsp->Psect_Index);
2311 }
2312 PUT_LONG(vsp->Psect_Offset + Offset);
2313 break;
2314 }
2315 /*
2316 * Store either a code or data reference
2317 */
2318 PUT_CHAR(PC_Relative ? TIR$C_STO_PICR : TIR$C_STO_PIDR);
2319 /*
2320 * Flush the buffer if it is more than 75% full
2321 */
2322 if (Object_Record_Offset >
2323 (sizeof(Object_Record_Buffer)*3/4))
2324 Flush_VMS_Object_Record_Buffer();
2325 }
2326
2327 \f
2328 /*
2329 * Check in the text area for an indirect pc-relative reference
2330 * and fix it up with addressing mode 0xff [PC indirect]
2331 *
2332 * THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
2333 * PIC CODE GENERATING FIXUP ROUTINE.
2334 */
2335 VMS_Fix_Indirect_Reference(Text_Psect, Offset, fragP, text_frag_root)
2336 int Text_Psect;
2337 int Offset;
2338 register fragS *fragP;
2339 struct frag *text_frag_root;
2340 {
2341 /*
2342 * The addressing mode byte is 1 byte before the address
2343 */
2344 Offset--;
2345 /*
2346 * Is it in THIS frag??
2347 */
2348 if ((Offset < fragP->fr_address) ||
2349 (Offset >= (fragP->fr_address + fragP->fr_fix))) {
2350 /*
2351 * We need to search for the fragment containing this
2352 * Offset
2353 */
2354 for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
2355 if ((Offset >= fragP->fr_address) &&
2356 (Offset < (fragP->fr_address + fragP->fr_fix)))
2357 break;
2358 }
2359 /*
2360 * If we couldn't find the frag, things are BAD!!
2361 */
2362 if (fragP == 0)
2363 error("Couldn't find fixup fragment when checking for indirect reference");
2364 }
2365 /*
2366 * Check for indirect PC relative addressing mode
2367 */
2368 if (fragP->fr_literal[Offset - fragP->fr_address] == (char)0xff) {
2369 static char Address_Mode = 0xff;
2370
2371 /*
2372 * Yes: Store the indirect mode back into the image
2373 * to fix up the damage done by STO_PICR
2374 */
2375 VMS_Set_Psect(Text_Psect,Offset,OBJ$C_TIR);
2376 VMS_Store_Immediate_Data(&Address_Mode,1,OBJ$C_TIR);
2377 }
2378 }
2379
2380 \f
2381 /*
2382 * Write the Traceback Module Begin record
2383 */
2384 VMS_TBT_Module_Begin()
2385 {
2386 register char *cp,*cp1;
2387 int Size;
2388 char Module_Name[256];
2389 char Local[256];
2390
2391 /*
2392 * Get module name (the FILENAME part of the object file)
2393 */
2394 cp = out_file_name;
2395 cp1 = Module_Name;
2396 while(*cp) {
2397 if ((*cp == ']') || (*cp == '>') ||
2398 (*cp == ':') || (*cp == '/')) {
2399 cp1 = Module_Name;
2400 cp++;
2401 continue;
2402 }
2403 *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
2404 }
2405 *cp1 = 0;
2406 /*
2407 * Limit it to 31 characters
2408 */
2409 while(--cp1 >= Module_Name)
2410 if (*cp1 == '.') *cp1 = 0;
2411 if (strlen(Module_Name) > 31) {
2412 if(flagseen['+'])
2413 printf("%s: Module name truncated: %s\n",myname, Module_Name);
2414 Module_Name[31] = 0;
2415 }
2416 /*
2417 * Arrange to store the data locally (leave room for size byte)
2418 */
2419 cp = Local+1;
2420 /*
2421 * Begin module
2422 */
2423 *cp++ = DST$C_MODBEG;
2424 /*
2425 * Unused
2426 */
2427 *cp++ = 0;
2428 /*
2429 * Language type == "C"
2430 */
2431 *(long *)cp = DST$C_C;
2432 cp += sizeof(long);
2433 /*
2434 * Store the module name
2435 */
2436 *cp++ = strlen(Module_Name);
2437 cp1 = Module_Name;
2438 while(*cp1) *cp++ = *cp1++;
2439 /*
2440 * Now we can store the record size
2441 */
2442 Size = (cp - Local);
2443 Local[0] = Size-1;
2444 /*
2445 * Put it into the object record
2446 */
2447 VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
2448 }
2449
2450 \f
2451 /*
2452 * Write the Traceback Module End record
2453 */
2454 VMS_TBT_Module_End()
2455 {
2456 char Local[2];
2457
2458 /*
2459 * End module
2460 */
2461 Local[0] = 1;
2462 Local[1] = DST$C_MODEND;
2463 /*
2464 * Put it into the object record
2465 */
2466 VMS_Store_Immediate_Data(Local, 2, OBJ$C_TBT);
2467 }
2468
2469 \f
2470 /*
2471 * Write the Traceback Routine Begin record
2472 */
2473 VMS_TBT_Routine_Begin(symbolP, Psect)
2474 struct symbol *symbolP;
2475 int Psect;
2476 {
2477 register char *cp,*cp1;
2478 char *Name;
2479 int Offset;
2480 int Size;
2481 char Local[512];
2482
2483 /*
2484 * Strip the leading "_" from the name
2485 */
2486 Name = symbolP->sy_nlist.n_un.n_name;
2487 if (*Name == '_') Name++;
2488 /*
2489 * Get the text psect offset
2490 */
2491 Offset = symbolP->sy_nlist.n_value;
2492 /*
2493 * Calculate the record size
2494 */
2495 Size = 1+1+4+1+strlen(Name);
2496 /*
2497 * Record Size
2498 */
2499 Local[0] = Size;
2500 /*
2501 * Begin Routine
2502 */
2503 Local[1] = DST$C_RTNBEG;
2504 /*
2505 * Uses CallS/CallG
2506 */
2507 Local[2] = 0;
2508 /*
2509 * Store the data so far
2510 */
2511 VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
2512 /*
2513 * Make sure we are still generating a OBJ$C_TBT record
2514 */
2515 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
2516 /*
2517 * Now get the symbol address
2518 */
2519 PUT_CHAR(TIR$C_STA_WPL);
2520 PUT_SHORT(Psect);
2521 PUT_LONG(Offset);
2522 /*
2523 * Store the data reference
2524 */
2525 PUT_CHAR(TIR$C_STO_PIDR);
2526 /*
2527 * Store the counted string as data
2528 */
2529 cp = Local;
2530 cp1 = Name;
2531 Size = strlen(cp1) + 1;
2532 *cp++ = Size - 1;
2533 while(*cp1) *cp++ = *cp1++;
2534 VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
2535 }
2536
2537 \f
2538 /*
2539 * Write the Traceback Routine End record
2540 * We *must* search the symbol table to find the next routine, since
2541 * the assember has a way of reassembling the symbol table OUT OF ORDER
2542 * Thus the next routine in the symbol list is not necessarily the
2543 * next one in memory. For debugging to work correctly we must know the
2544 * size of the routine.
2545 */
2546 VMS_TBT_Routine_End(Max_Size,sp)
2547 int Max_Size;
2548 symbolS *sp;
2549 {
2550 symbolS *symbolP;
2551 int Size = 0x7fffffff;
2552 char Local[16];
2553
2554
2555 for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
2556 if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
2557 if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
2558 if((symbolP->sy_nlist.n_value > sp->sy_nlist.n_value) &&
2559 (symbolP->sy_nlist.n_value < Size ))
2560 Size = symbolP->sy_nlist.n_value;
2561 /* check if gcc_compiled. has size of zero */
2562 if((symbolP->sy_nlist.n_value == sp->sy_nlist.n_value) &&
2563 sp != symbolP &&
2564 !strcmp(sp->sy_nlist.n_un.n_name,"gcc_compiled."))
2565 Size = symbolP->sy_nlist.n_value;
2566
2567 };
2568 };
2569 if(Size == 0x7fffffff) Size = Max_Size;
2570 Size -= sp->sy_nlist.n_value; /* and get the size of the routine */
2571 /*
2572 * Record Size
2573 */
2574 Local[0] = 6;
2575 /*
2576 * End of Routine
2577 */
2578 Local[1] = DST$C_RTNEND;
2579 /*
2580 * Unused
2581 */
2582 Local[2] = 0;
2583 /*
2584 * Size of routine
2585 */
2586 *((long *)(Local+3)) = Size;
2587 /*
2588 * Store the record
2589 */
2590 VMS_Store_Immediate_Data(Local,7, OBJ$C_TBT);
2591 }
2592 /*
2593 * Write the Traceback Block End record
2594 */
2595 VMS_TBT_Block_Begin(symbolP, Psect, Name)
2596 struct symbol *symbolP;
2597 int Psect;
2598 char* Name;
2599 {
2600 register char *cp,*cp1;
2601 int Offset;
2602 int Size;
2603 char Local[512];
2604 /*
2605 * Begin block
2606 */
2607 Size = 1+1+4+1+strlen(Name);
2608 /*
2609 * Record Size
2610 */
2611 Local[0] = Size;
2612 /*
2613 * Begin Block - We simulate with a phony routine
2614 */
2615 Local[1] = DST$C_BLKBEG;
2616 /*
2617 * Uses CallS/CallG
2618 */
2619 Local[2] = 0;
2620 /*
2621 * Store the data so far
2622 */
2623 VMS_Store_Immediate_Data(Local, 3, OBJ$C_DBG);
2624 /*
2625 * Make sure we are still generating a OBJ$C_DBG record
2626 */
2627 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2628 /*
2629 * Now get the symbol address
2630 */
2631 PUT_CHAR(TIR$C_STA_WPL);
2632 PUT_SHORT(Psect);
2633 /*
2634 * Get the text psect offset
2635 */
2636 Offset = symbolP->sy_nlist.n_value;
2637 PUT_LONG(Offset);
2638 /*
2639 * Store the data reference
2640 */
2641 PUT_CHAR(TIR$C_STO_PIDR);
2642 /*
2643 * Store the counted string as data
2644 */
2645 cp = Local;
2646 cp1 = Name;
2647 Size = strlen(cp1) + 1;
2648 *cp++ = Size - 1;
2649 while(*cp1) *cp++ = *cp1++;
2650 VMS_Store_Immediate_Data(Local, Size, OBJ$C_DBG);
2651 }
2652
2653 \f
2654 /*
2655 * Write the Traceback Block End record
2656 */
2657 VMS_TBT_Block_End(int Size)
2658 {
2659 char Local[16];
2660
2661 /*
2662 * End block - simulate with a phony end routine
2663 */
2664 Local[0] = 6;
2665 Local[1] = DST$C_BLKEND;
2666 *((long *)(Local+3)) = Size;
2667 /*
2668 * Unused
2669 */
2670 Local[2] = 0;
2671 VMS_Store_Immediate_Data(Local,7, OBJ$C_DBG);
2672 }
2673
2674
2675 \f
2676 /*
2677 * Write a Line number / PC correlation record
2678 */
2679 VMS_TBT_Line_PC_Correlation(Line_Number, Offset, Psect, Do_Delta)
2680 int Line_Number;
2681 int Offset;
2682 int Psect;
2683 int Do_Delta;
2684 {
2685 register char *cp;
2686 char Local[64];
2687
2688 /*
2689 * If not delta, set our PC/Line number correlation
2690 */
2691 if (Do_Delta == 0) {
2692 /*
2693 * Size
2694 */
2695 Local[0] = 1+1+2+1+4;
2696 /*
2697 * Line Number/PC correlation
2698 */
2699 Local[1] = DST$C_LINE_NUM;
2700 /*
2701 * Set Line number
2702 */
2703 Local[2] = DST$C_SET_LINE_NUM;
2704 *((unsigned short *)(Local+3)) = Line_Number-1;
2705 /*
2706 * Set PC
2707 */
2708 Local[5] = DST$C_SET_ABS_PC;
2709 VMS_Store_Immediate_Data(Local, 6, OBJ$C_TBT);
2710 /*
2711 * Make sure we are still generating a OBJ$C_TBT record
2712 */
2713 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
2714 if (Psect < 255) {
2715 PUT_CHAR(TIR$C_STA_PL);
2716 PUT_CHAR(Psect);
2717 } else {
2718 PUT_CHAR(TIR$C_STA_WPL);
2719 PUT_SHORT(Psect);
2720 }
2721 PUT_LONG(Offset);
2722 PUT_CHAR(TIR$C_STO_PIDR);
2723 /*
2724 * Do a PC offset of 0 to register the line number
2725 */
2726 Local[0] = 2;
2727 Local[1] = DST$C_LINE_NUM;
2728 Local[2] = 0; /* Increment PC by 0 and register line # */
2729 VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
2730 } else {
2731 /*
2732 * If Delta is negative, terminate the line numbers
2733 */
2734 if (Do_Delta < 0) {
2735 Local[0] = 1+1+4;
2736 Local[1] = DST$C_LINE_NUM;
2737 Local[2] = DST$C_TERM_L;
2738 *((long *)(Local+3)) = Offset;
2739 VMS_Store_Immediate_Data(Local, 7, OBJ$C_TBT);
2740 /*
2741 * Done
2742 */
2743 return;
2744 }
2745 /*
2746 * Do a PC/Line delta
2747 */
2748 cp = Local+1;
2749 *cp++ = DST$C_LINE_NUM;
2750 if (Line_Number > 1) {
2751 /*
2752 * We need to increment the line number
2753 */
2754 if (Line_Number-1 <= 255) {
2755 *cp++ = DST$C_INCR_LINUM;
2756 *cp++ = Line_Number-1;
2757 } else {
2758 *cp++ = DST$C_INCR_LINUM_W;
2759 *(short *)cp = Line_Number-1;
2760 cp += sizeof(short);
2761 }
2762 }
2763 /*
2764 * Increment the PC
2765 */
2766 if (Offset <= 128) {
2767 *cp++ = -Offset;
2768 } else {
2769 if (Offset < 0x10000) {
2770 *cp++ = DST$C_DELTA_PC_W;
2771 *(short *)cp = Offset;
2772 cp += sizeof(short);
2773 } else {
2774 *cp++ = DST$C_DELTA_PC_L;
2775 *(long *)cp = Offset;
2776 cp += sizeof(long);
2777 }
2778 }
2779 Local[0] = cp - (Local+1);
2780 VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
2781 }
2782 }
2783
2784 \f
2785 /*
2786 * Describe a source file to the debugger
2787 */
2788 VMS_TBT_Source_File(Filename, ID_Number)
2789 char *Filename;
2790 int ID_Number;
2791 {
2792 register char *cp,*cp1;
2793 int Status,i;
2794 char Local[512];
2795 static struct FAB Fab;
2796 static struct NAM Nam;
2797 static struct XABDAT Date_Xab;
2798 static struct XABFHC File_Header_Xab;
2799 char Es_String[255],Rs_String[255];
2800
2801 /*
2802 * Setup the Fab
2803 */
2804 Fab.fab$b_bid = FAB$C_BID;
2805 Fab.fab$b_bln = sizeof(Fab);
2806 Fab.fab$l_nam = (&Nam);
2807 Fab.fab$l_xab = (struct XAB *)&Date_Xab;
2808 /*
2809 * Setup the Nam block so we can find out the FULL name
2810 * of the source file.
2811 */
2812 Nam.nam$b_bid = NAM$C_BID;
2813 Nam.nam$b_bln = sizeof(Nam);
2814 Nam.nam$l_rsa = Rs_String;
2815 Nam.nam$b_rss = sizeof(Rs_String);
2816 Nam.nam$l_esa = Es_String;
2817 Nam.nam$b_ess = sizeof(Es_String);
2818 /*
2819 * Setup the Date and File Header Xabs
2820 */
2821 Date_Xab.xab$b_cod = XAB$C_DAT;
2822 Date_Xab.xab$b_bln = sizeof(Date_Xab);
2823 Date_Xab.xab$l_nxt = (char *)&File_Header_Xab;
2824 File_Header_Xab.xab$b_cod = XAB$C_FHC;
2825 File_Header_Xab.xab$b_bln = sizeof(File_Header_Xab);
2826 /* ((struct XAB *)&Date_Xab)->xab$b_cod = XAB$C_DAT; */
2827 /* ((struct XAB *)&Date_Xab)->xab$b_bln = sizeof(Date_Xab); */
2828 /* ((struct XAB *)&Date_Xab)->xab$l_nxt = (struct XAB *)&File_Header_Xab; */
2829 /* ((struct XAB *)&File_Header_Xab)->xab$b_cod = XAB$C_FHC; */
2830 /* ((struct XAB *)&File_Header_Xab)->xab$b_bln = sizeof(File_Header_Xab); */
2831 /*
2832 * Get the file information
2833 */
2834 Fab.fab$l_fna = Filename;
2835 Fab.fab$b_fns = strlen(Filename);
2836 Status = sys$open(&Fab);
2837 if (!(Status & 1)) {
2838 printf("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
2839 Filename, Status);
2840 return(0);
2841 }
2842 sys$close(&Fab);
2843 /*
2844 * Calculate the size of the resultant string
2845 */
2846 i = Nam.nam$b_rsl;
2847 /*
2848 * Size of record
2849 */
2850 Local[0] = 1+1+1+1+1+2+8+4+2+1+1+i+1;
2851 /*
2852 * Source declaration
2853 */
2854 Local[1] = DST$C_SOURCE;
2855 /*
2856 * Make formfeeds count as source records
2857 */
2858 Local[2] = DST$C_SRC_FORMFEED;
2859 /*
2860 * Declare source file
2861 */
2862 Local[3] = DST$C_SRC_DECLFILE;
2863 Local[4] = 1+2+8+4+2+1+1+i+1;
2864 cp = Local+5;
2865 /*
2866 * Flags
2867 */
2868 *cp++ = 0;
2869 /*
2870 * File ID
2871 */
2872 *(short *)cp = ID_Number;
2873 cp += sizeof(short);
2874 /*
2875 * Creation Date
2876 */
2877 *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[0];
2878 cp += sizeof(long);
2879 *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[1];
2880 cp += sizeof(long);
2881 /*
2882 * End of file block
2883 */
2884 *(long *)cp = File_Header_Xab.xab$l_ebk;
2885 cp += sizeof(long);
2886 /*
2887 * First free byte
2888 */
2889 *(short *)cp = File_Header_Xab.xab$w_ffb;
2890 cp += sizeof(short);
2891 /*
2892 * Record format
2893 */
2894 *cp++ = File_Header_Xab.xab$b_rfo;
2895 /*
2896 * Filename
2897 */
2898 *cp++ = i;
2899 cp1 = Rs_String;
2900 while(--i >= 0) *cp++ = *cp1++;
2901 /*
2902 * Library module name (none)
2903 */
2904 *cp++ = 0;
2905 /*
2906 * Done
2907 */
2908 VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
2909 }
2910
2911 \f
2912 /*
2913 * Give the number of source lines to the debugger
2914 */
2915 VMS_TBT_Source_Lines(ID_Number,Starting_Line_Number,Number_Of_Lines)
2916 int ID_Number;
2917 int Starting_Line_Number;
2918 int Number_Of_Lines;
2919 {
2920 char *cp,*cp1;
2921 char Local[16];
2922
2923 /*
2924 * Size of record
2925 */
2926 Local[0] = 1+1+2+1+4+1+2;
2927 /*
2928 * Source declaration
2929 */
2930 Local[1] = DST$C_SOURCE;
2931 /*
2932 * Set Source File
2933 */
2934 cp = Local+2;
2935 *cp++ = DST$C_SRC_SETFILE;
2936 /*
2937 * File ID Number
2938 */
2939 *(short *)cp = ID_Number;
2940 cp += sizeof(short);
2941 /*
2942 * Set record number
2943 */
2944 *cp++ = DST$C_SRC_SETREC_L;
2945 *(long *)cp = Starting_Line_Number;
2946 cp += sizeof(long);
2947 /*
2948 * Define lines
2949 */
2950 *cp++ = DST$C_SRC_DEFLINES_W;
2951 *(short *)cp = Number_Of_Lines;
2952 cp += sizeof(short);
2953 /*
2954 * Done
2955 */
2956 VMS_Store_Immediate_Data(Local, cp-Local, OBJ$C_TBT);
2957 }
2958
2959 \f
2960 /*
2961 * Given the pointer to a symbol we calculate how big the data at the
2962 * symbol is. We do this by looking for the next symbol (local or
2963 * global) which will indicate the start of another datum.
2964 */
2965 int VMS_Initialized_Data_Size(sp, End_Of_Data)
2966 register struct symbol *sp;
2967 int End_Of_Data;
2968 {
2969 register struct symbol *sp1,*Next_Symbol;
2970
2971 /*
2972 * Find the next symbol
2973 * it delimits this datum
2974 */
2975 Next_Symbol = 0;
2976 for (sp1 = symbol_rootP; sp1; sp1 = symbol_next(sp1)) {
2977 /*
2978 * The data type must match
2979 */
2980 if ((sp1->sy_nlist.n_type & ~N_EXT) != N_DATA) continue;
2981 /*
2982 * The symbol must be AFTER this symbol
2983 */
2984 if (sp1->sy_nlist.n_value <= sp->sy_nlist.n_value) continue;
2985 /*
2986 * We ignore THIS symbol
2987 */
2988 if (sp1 == sp) continue;
2989 /*
2990 * If there is already a candidate selected for the
2991 * next symbol, see if we are a better candidate
2992 */
2993 if (Next_Symbol) {
2994 /*
2995 * We are a better candidate if we are "closer"
2996 * to the symbol
2997 */
2998 if (sp1->sy_nlist.n_value >
2999 Next_Symbol->sy_nlist.n_value)
3000 continue;
3001 /*
3002 * Win: Make this the candidate
3003 */
3004 Next_Symbol = sp1;
3005 } else {
3006 /*
3007 * This is the 1st candidate
3008 */
3009 Next_Symbol = sp1;
3010 }
3011 }
3012 /*
3013 * Calculate its size
3014 */
3015 return(Next_Symbol ?
3016 (Next_Symbol->sy_nlist.n_value -
3017 sp->sy_nlist.n_value) :
3018 (End_Of_Data - sp->sy_nlist.n_value));
3019 }
3020
3021 \f
3022
3023 /* this routine locates a file in the list of files. If an entry does not
3024 * exist, one is created. For include files, a new entry is always created
3025 * such that inline functions can be properly debugged */
3026 struct input_file *
3027 find_file(sp)
3028 symbolS * sp;
3029 {
3030 struct input_file * same_file;
3031 struct input_file * fpnt;
3032 same_file = (struct input_file*) NULL;
3033 for(fpnt = file_root; fpnt; fpnt = fpnt->next){
3034 if(fpnt == (struct input_file*) NULL) break;
3035 if(fpnt->spnt == sp) return fpnt;
3036 };
3037 for(fpnt = file_root; fpnt; fpnt = fpnt->next){
3038 if(fpnt == (struct input_file*) NULL) break;
3039 if (strcmp(sp->sy_nlist.n_un.n_name,fpnt->name) == 0){
3040 if(fpnt->flag == 1)return fpnt;
3041 same_file = fpnt;
3042 break;
3043 };
3044 };
3045 fpnt = (struct input_file*) malloc(sizeof(struct input_file));
3046 if(file_root == (struct input_file*) NULL) file_root = fpnt;
3047 else {
3048 struct input_file * fpnt1;
3049 for(fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next);
3050 fpnt1->next = fpnt;
3051 };
3052 fpnt->next = (struct input_file*) NULL;
3053 fpnt->name = sp->sy_nlist.n_un.n_name;
3054 fpnt->min_line = 0x7fffffff;
3055 fpnt->max_line = 0;
3056 fpnt->offset = 0;
3057 fpnt->flag = 0;
3058 fpnt->file_number = 0;
3059 fpnt->spnt = sp;
3060 fpnt->same_file_fpnt = same_file;
3061 return fpnt;
3062 }
3063
3064 \f
3065 /*
3066 * This is a hacked _doprnt() for VAX-11 "C". It understands that
3067 * it is ONLY called by as_fatal(Format, Args) with a pointer to the
3068 * "Args" argument. From this we can make it all work right!
3069 */
3070 #ifndef eunice
3071 _doprnt(Format, a, f)
3072 char *Format;
3073 FILE *f;
3074 char **a;
3075 {
3076 int Nargs = ((int *)a)[-2]; /* This understands as_fatal() */
3077
3078 switch(Nargs) {
3079 default: fprintf(f,"_doprnt error on \"%s\"!!",Format); break;
3080 case 1: fprintf(f,Format); break;
3081 case 2: fprintf(f,Format,a[0]); break;
3082 case 3: fprintf(f,Format,a[0],a[1]); break;
3083 case 4: fprintf(f,Format,a[0],a[1],a[2]); break;
3084 case 5: fprintf(f,Format,a[0],a[1],a[2],a[3]); break;
3085 case 6: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4]); break;
3086 case 7: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5]); break;
3087 case 8: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;
3088 case 9: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); break;
3089 case 10: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]); break;
3090 }
3091 }
3092
3093 #endif /* eunice */
3094
3095 #endif /* VMS */
3096
3097 char const_flag = 0;
3098 void s_const();
3099
3100 void
3101 s_const()
3102 {
3103 register int temp;
3104
3105 temp = get_absolute_expression ();
3106 subseg_new (SEG_DATA, (subsegT)temp);
3107 const_flag = 1;
3108 demand_empty_rest_of_line();
3109 }
3110
3111 obj_crawl_symbol_chain() {
3112 /* JF deal with forward references first. . . */
3113 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
3114 if (symbolP->sy_forward) {
3115 symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
3116 #ifdef OBJ_COFF
3117 if(SF_GET_GET_SEGMENT(symbolP) &&
3118 S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
3119 S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
3120 #endif /* OBJ_COFF */
3121 symbolP->sy_forward=0;
3122 } /* if it has a forward reference */
3123 } /* walk the symbol chain */
3124
3125 { /* crawl symbol table */
3126 register int symbol_number = 0;
3127
3128 #if defined(OBJ_COFF)
3129 { /* OBJ_COFF version */
3130 lineno* lineP;
3131 symbolS* symbol_externP = (symbolS*)0;
3132 symbolS* symbol_extern_lastP = (symbolS*)0;
3133
3134 /* The symbol list should be ordered according to the following sequence
3135 * order :
3136 * . .file symbol
3137 * . debug entries for functions
3138 * . fake symbols for .text .data and .bss
3139 * . defined symbols
3140 * . undefined symbols
3141 * But this is not mandatory. The only important point is to put the
3142 * undefined symbols at the end of the list.
3143 */
3144
3145 if (symbol_rootP == NULL
3146 || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
3147 c_dot_file_symbol("fake");
3148 } /* Is there a .file symbol ? If not insert one at the beginning. */
3149
3150 /*
3151 * Build up static symbols for .text, .data and .bss
3152 */
3153 dot_text_symbol = (symbolS*)
3154 c_section_symbol(".text",
3155 0,
3156 H_GET_TEXT_SIZE(&headers),
3157 0/*text_relocation_number*/,
3158 0/*text_lineno_number*/);
3159
3160 dot_data_symbol = (symbolS*)
3161 c_section_symbol(".data",
3162 H_GET_TEXT_SIZE(&headers),
3163 H_GET_DATA_SIZE(&headers),
3164 0/*data_relocation_number*/,
3165 0); /* There are no data lineno
3166 entries */
3167
3168 dot_bss_symbol = (symbolS*)
3169 c_section_symbol(".bss",
3170 H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
3171 H_GET_BSS_SIZE(&headers),
3172 0, /* No relocation for a bss section. */
3173 0); /* There are no bss lineno entries */
3174
3175 /* FIXME late night before delivery, I don't know why the chain is
3176 broken, but I can guess. So! Let's force them to be knit properly
3177 at this point. */
3178
3179 /* as john pointed out, this wasn't right. Instead, we'll check here to
3180 make sure that the list is doubly linked. */
3181
3182 #if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
3183 for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
3184 know(symbolP->sy_next->sy_previous == symbolP);
3185 } /* walk the symbol chain */
3186 #endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
3187 symbolP = symbol_rootP;
3188
3189 if (symbolP) {
3190 while(symbolP) {
3191 /* If the symbol has a tagndx entry, resolve it */
3192 if(SF_GET_TAGGED(symbolP)) {
3193 SA_SET_SYM_TAGNDX(symbolP,
3194 ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
3195 }
3196 /* Debug symbol do not need all this rubbish */
3197 if(!SF_GET_DEBUG(symbolP)) {
3198 symbolS* real_symbolP;
3199 /* L* and C_EFCN symbols never merge. */
3200 if(!SF_GET_LOCAL(symbolP) &&
3201 (real_symbolP =
3202 symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
3203 real_symbolP != symbolP) {
3204 /* FIXME where do dups come from? xoxorich. */
3205 /* Move the debug data from the debug symbol to the
3206 real symbol. Do NOT do the oposite (i.e. move from
3207 real symbol to symbol and remove real symbol from the
3208 list.) Because some pointers refer to the real symbol
3209 whereas no pointers refer to the symbol. */
3210 c_symbol_merge(symbolP, real_symbolP);
3211 /* Replace the current symbol by the real one */
3212 /* The symbols will never be the last or the first
3213 because : 1st symbol is .file and 3 last symbols are
3214 .text, .data, .bss */
3215 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
3216 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
3217 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
3218 symbolP = real_symbolP;
3219 }
3220 if(flagseen['R'] && S_IS_DATA(symbolP))
3221 S_SET_TEXT(symbolP);
3222
3223 symbolP->sy_value += symbolP->sy_frag->fr_address;
3224
3225 if(!S_IS_DEFINED(symbolP))
3226 S_SET_EXTERNAL(symbolP);
3227 else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
3228 S_SET_STORAGE_CLASS(symbolP, C_STAT);
3229
3230 /* Mainly to speed up if not -g */
3231 if(SF_GET_PROCESS(symbolP)) {
3232 /* Handle the nested blocks auxiliary info. */
3233 if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
3234 if(!strcmp(S_GET_NAME(symbolP), ".bb"))
3235 stack_push(block_stack, (char *) &symbolP);
3236 else { /* .eb */
3237 register symbolS* begin_symbolP;
3238 begin_symbolP = *(symbolS**)stack_pop(block_stack);
3239 if(begin_symbolP == (symbolS*)0)
3240 as_warn("mismatched .eb");
3241 else
3242 SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
3243 }
3244 }
3245 /* If we are able to identify the type of a function, and we
3246 are out of a function (last_functionP == 0) then, the
3247 function symbol will be associated with an auxiliary
3248 entry. */
3249 if(last_functionP == (symbolS*)0 &&
3250 SF_GET_FUNCTION(symbolP)) {
3251 last_functionP = symbolP;
3252 S_SET_NUMBER_AUXILIARY(symbolP, 1);
3253 /* Clobber possible stale .dim information. */
3254 memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
3255 }
3256 /* The C_FCN doesn't need any additional information.
3257 I don't even know if this is needed for sdb. But the
3258 standard assembler generates it, so...
3259 */
3260 if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
3261 if(last_functionP == (symbolS*)0)
3262 as_fatal("C_EFCN symbol out of scope");
3263 SA_SET_SYM_FSIZE(last_functionP,
3264 (long)(symbolP->sy_value -
3265 last_functionP->sy_value));
3266 SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
3267 last_functionP = (symbolS*)0;
3268 }
3269 }
3270 } else {
3271 /* First descriptor of a structure must point to the next
3272 slot outside the structure description. */
3273 if(SF_GET_TAG(symbolP))
3274 last_tagP = symbolP;
3275 else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
3276 /* +2 take in account the current symbol */
3277 SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
3278 }
3279
3280 /* We must put the external symbols apart. The loader
3281 does not bomb if we do not. But the references in
3282 the endndx field for a .bb symbol are not corrected
3283 if an external symbol is removed between .bb and .be.
3284 I.e in the following case :
3285 [20] .bb endndx = 22
3286 [21] foo external
3287 [22] .be
3288 ld will move the symbol 21 to the end of the list but
3289 endndx will still be 22 instead of 21. */
3290 {
3291 register symbolS* thisP = symbolP;
3292
3293 symbolP = symbol_next(thisP);
3294 /* remove C_EFCN and LOCAL (L...) symbols */
3295 if (SF_GET_LOCAL(thisP)) {
3296 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3297 } else {
3298 if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
3299 !SF_GET_FUNCTION(thisP)) {
3300 /* Remove from the list */
3301 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3302 symbol_clear_list_pointers(thisP);
3303 /* Move at the end of the list */
3304 if (symbol_extern_lastP == (symbolS*)0)
3305 symbol_externP = thisP;
3306 else
3307 symbol_append(thisP, symbol_extern_lastP);
3308 symbol_extern_lastP = thisP;
3309 } else {
3310 if(SF_GET_STRING(thisP)) {
3311 thisP->sy_name_offset = string_byte_count;
3312 string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
3313 } else
3314 thisP->sy_name_offset = 0;
3315 thisP->sy_number = symbol_number;
3316 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
3317 }
3318 }
3319 }
3320 }
3321
3322 /* this actually appends the entire extern chain */
3323 symbol_append(symbol_externP, symbol_lastP);
3324 symbolP = symbol_externP;
3325 while(symbolP) {
3326 if(SF_GET_STRING(symbolP)) {
3327 symbolP->sy_name_offset = string_byte_count;
3328 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3329 } else
3330 symbolP->sy_name_offset = 0;
3331 symbolP->sy_number = symbol_number;
3332 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
3333 symbolP = symbol_next(symbolP);
3334 }
3335 }
3336
3337 /* FIXME I'm counting line no's here so we know what to put in the section
3338 headers, and I'm resolving the addresses since I'm not sure how to
3339 do it later. I am NOT resolving the linno's representing functions.
3340 Their symbols need a fileptr pointing to this linno when emitted.
3341 Thus, I resolve them on emit. xoxorich. */
3342
3343 for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
3344 if (lineP->line.l_lnno) {
3345 lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
3346 } else {
3347 ;
3348 }
3349 text_lineno_number++;
3350 } /* for each line number */
3351 } /* OBJ_COFF version */
3352 #elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
3353 { /* OBJ_AOUT version */
3354 symbolPP = & symbol_rootP; /* -> last symbol chain link. */
3355 while ((symbolP = *symbolPP) != NULL)
3356 {
3357 if (flagseen['R'] && S_IS_DATA(symbolP)) {
3358 S_SET_TEXT(symbolP);
3359 } /* if pusing data into text */
3360
3361 symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
3362
3363 /* OK, here is how we decide which symbols go out into the
3364 brave new symtab. Symbols that do are:
3365
3366 * symbols with no name (stabd's?)
3367 * symbols with debug info in their N_TYPE
3368
3369 Symbols that don't are:
3370 * symbols that are registers
3371 * symbols with \1 as their 3rd character (numeric labels)
3372 * "local labels" as defined by S_LOCAL_NAME(name)
3373 if the -L switch was passed to gas.
3374
3375 All other symbols are output. We complain if a deleted
3376 symbol was marked external. */
3377
3378
3379 if (1
3380 && !S_IS_REGISTER(symbolP)
3381 #ifndef VMS /* Under VMS we need to keep local symbols */
3382 && ( !S_GET_NAME(symbolP)
3383 || S_IS_DEBUG(symbolP)
3384 #ifdef TC_I960
3385 /* FIXME this ifdef seems highly dubious to me. xoxorich. */
3386 || !S_IS_DEFINED(symbolP)
3387 || S_IS_EXTERNAL(symbolP)
3388 #endif /* TC_I960 */
3389 || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
3390 #endif /* not VMS */
3391 )
3392 {
3393 #ifndef VMS
3394 symbolP->sy_number = symbol_number++;
3395
3396 /* The + 1 after strlen account for the \0 at the
3397 end of each string */
3398 if (!S_IS_STABD(symbolP)) {
3399 /* Ordinary case. */
3400 symbolP->sy_name_offset = string_byte_count;
3401 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3402 }
3403 else /* .Stabd case. */
3404 #endif /* not VMS */
3405 symbolP->sy_name_offset = 0;
3406 symbolPP = &(symbol_next(symbolP));
3407 } else {
3408 if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
3409 as_bad ("Local symbol %s never defined", name);
3410 } /* oops. */
3411
3412 #ifndef VMS
3413 /* Unhook it from the chain */
3414 *symbolPP = symbol_next(symbolP);
3415 #endif /* VMS */
3416 } /* if this symbol should be in the output */
3417 } /* for each symbol */
3418 } /* OBJ_AOUT version */
3419 #else
3420 cant_crawl_symbol_table();
3421 #endif
3422 H_SET_STRING_SIZE(&headers,string_byte_count);
3423 H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
3424 } /* crawl symbol table */
3425
3426 /* JF deal with forward references first. . . */
3427 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
3428 if (symbolP->sy_forward) {
3429 symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
3430 #ifdef OBJ_COFF
3431 if(SF_GET_GET_SEGMENT(symbolP) &&
3432 S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
3433 S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
3434 #endif /* OBJ_COFF */
3435 symbolP->sy_forward=0;
3436 } /* if it has a forward reference */
3437 } /* walk the symbol chain */
3438
3439 { /* crawl symbol table */
3440 register int symbol_number = 0;
3441
3442 #if defined(OBJ_COFF)
3443 { /* OBJ_COFF version */
3444 lineno* lineP;
3445 symbolS* symbol_externP = (symbolS*)0;
3446 symbolS* symbol_extern_lastP = (symbolS*)0;
3447
3448 /* The symbol list should be ordered according to the following sequence
3449 * order :
3450 * . .file symbol
3451 * . debug entries for functions
3452 * . fake symbols for .text .data and .bss
3453 * . defined symbols
3454 * . undefined symbols
3455 * But this is not mandatory. The only important point is to put the
3456 * undefined symbols at the end of the list.
3457 */
3458
3459 if (symbol_rootP == NULL
3460 || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
3461 c_dot_file_symbol("fake");
3462 } /* Is there a .file symbol ? If not insert one at the beginning. */
3463
3464 /*
3465 * Build up static symbols for .text, .data and .bss
3466 */
3467 dot_text_symbol = (symbolS*)
3468 c_section_symbol(".text",
3469 0,
3470 H_GET_TEXT_SIZE(&headers),
3471 0/*text_relocation_number*/,
3472 0/*text_lineno_number*/);
3473
3474 dot_data_symbol = (symbolS*)
3475 c_section_symbol(".data",
3476 H_GET_TEXT_SIZE(&headers),
3477 H_GET_DATA_SIZE(&headers),
3478 0/*data_relocation_number*/,
3479 0); /* There are no data lineno
3480 entries */
3481
3482 dot_bss_symbol = (symbolS*)
3483 c_section_symbol(".bss",
3484 H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
3485 H_GET_BSS_SIZE(&headers),
3486 0, /* No relocation for a bss section. */
3487 0); /* There are no bss lineno entries */
3488
3489 /* FIXME late night before delivery, I don't know why the chain is
3490 broken, but I can guess. So! Let's force them to be knit properly
3491 at this point. */
3492
3493 /* as john pointed out, this wasn't right. Instead, we'll check here to
3494 make sure that the list is doubly linked. */
3495
3496 #if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
3497 for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
3498 know(symbolP->sy_next->sy_previous == symbolP);
3499 } /* walk the symbol chain */
3500 #endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
3501 symbolP = symbol_rootP;
3502
3503 if (symbolP) {
3504 while(symbolP) {
3505 /* If the symbol has a tagndx entry, resolve it */
3506 if(SF_GET_TAGGED(symbolP)) {
3507 SA_SET_SYM_TAGNDX(symbolP,
3508 ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
3509 }
3510 /* Debug symbol do not need all this rubbish */
3511 if(!SF_GET_DEBUG(symbolP)) {
3512 symbolS* real_symbolP;
3513 /* L* and C_EFCN symbols never merge. */
3514 if(!SF_GET_LOCAL(symbolP) &&
3515 (real_symbolP =
3516 symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
3517 real_symbolP != symbolP) {
3518 /* FIXME where do dups come from? xoxorich. */
3519 /* Move the debug data from the debug symbol to the
3520 real symbol. Do NOT do the oposite (i.e. move from
3521 real symbol to symbol and remove real symbol from the
3522 list.) Because some pointers refer to the real symbol
3523 whereas no pointers refer to the symbol. */
3524 c_symbol_merge(symbolP, real_symbolP);
3525 /* Replace the current symbol by the real one */
3526 /* The symbols will never be the last or the first
3527 because : 1st symbol is .file and 3 last symbols are
3528 .text, .data, .bss */
3529 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
3530 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
3531 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
3532 symbolP = real_symbolP;
3533 }
3534 if(flagseen['R'] && S_IS_DATA(symbolP))
3535 S_SET_TEXT(symbolP);
3536
3537 symbolP->sy_value += symbolP->sy_frag->fr_address;
3538
3539 if(!S_IS_DEFINED(symbolP))
3540 S_SET_EXTERNAL(symbolP);
3541 else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
3542 S_SET_STORAGE_CLASS(symbolP, C_STAT);
3543
3544 /* Mainly to speed up if not -g */
3545 if(SF_GET_PROCESS(symbolP)) {
3546 /* Handle the nested blocks auxiliary info. */
3547 if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
3548 if(!strcmp(S_GET_NAME(symbolP), ".bb"))
3549 stack_push(block_stack, (char *) &symbolP);
3550 else { /* .eb */
3551 register symbolS* begin_symbolP;
3552 begin_symbolP = *(symbolS**)stack_pop(block_stack);
3553 if(begin_symbolP == (symbolS*)0)
3554 as_warn("mismatched .eb");
3555 else
3556 SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
3557 }
3558 }
3559 /* If we are able to identify the type of a function, and we
3560 are out of a function (last_functionP == 0) then, the
3561 function symbol will be associated with an auxiliary
3562 entry. */
3563 if(last_functionP == (symbolS*)0 &&
3564 SF_GET_FUNCTION(symbolP)) {
3565 last_functionP = symbolP;
3566 S_SET_NUMBER_AUXILIARY(symbolP, 1);
3567 /* Clobber possible stale .dim information. */
3568 memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
3569 }
3570 /* The C_FCN doesn't need any additional information.
3571 I don't even know if this is needed for sdb. But the
3572 standard assembler generates it, so...
3573 */
3574 if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
3575 if(last_functionP == (symbolS*)0)
3576 as_fatal("C_EFCN symbol out of scope");
3577 SA_SET_SYM_FSIZE(last_functionP,
3578 (long)(symbolP->sy_value -
3579 last_functionP->sy_value));
3580 SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
3581 last_functionP = (symbolS*)0;
3582 }
3583 }
3584 } else {
3585 /* First descriptor of a structure must point to the next
3586 slot outside the structure description. */
3587 if(SF_GET_TAG(symbolP))
3588 last_tagP = symbolP;
3589 else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
3590 /* +2 take in account the current symbol */
3591 SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
3592 }
3593
3594 /* We must put the external symbols apart. The loader
3595 does not bomb if we do not. But the references in
3596 the endndx field for a .bb symbol are not corrected
3597 if an external symbol is removed between .bb and .be.
3598 I.e in the following case :
3599 [20] .bb endndx = 22
3600 [21] foo external
3601 [22] .be
3602 ld will move the symbol 21 to the end of the list but
3603 endndx will still be 22 instead of 21. */
3604 {
3605 register symbolS* thisP = symbolP;
3606
3607 symbolP = symbol_next(thisP);
3608 /* remove C_EFCN and LOCAL (L...) symbols */
3609 if (SF_GET_LOCAL(thisP)) {
3610 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3611 } else {
3612 if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
3613 !SF_GET_FUNCTION(thisP)) {
3614 /* Remove from the list */
3615 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3616 symbol_clear_list_pointers(thisP);
3617 /* Move at the end of the list */
3618 if (symbol_extern_lastP == (symbolS*)0)
3619 symbol_externP = thisP;
3620 else
3621 symbol_append(thisP, symbol_extern_lastP);
3622 symbol_extern_lastP = thisP;
3623 } else {
3624 if(SF_GET_STRING(thisP)) {
3625 thisP->sy_name_offset = string_byte_count;
3626 string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
3627 } else
3628 thisP->sy_name_offset = 0;
3629 thisP->sy_number = symbol_number;
3630 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
3631 }
3632 }
3633 }
3634 }
3635
3636 /* this actually appends the entire extern chain */
3637 symbol_append(symbol_externP, symbol_lastP);
3638 symbolP = symbol_externP;
3639 while(symbolP) {
3640 if(SF_GET_STRING(symbolP)) {
3641 symbolP->sy_name_offset = string_byte_count;
3642 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3643 } else
3644 symbolP->sy_name_offset = 0;
3645 symbolP->sy_number = symbol_number;
3646 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
3647 symbolP = symbol_next(symbolP);
3648 }
3649 }
3650
3651 /* FIXME I'm counting line no's here so we know what to put in the section
3652 headers, and I'm resolving the addresses since I'm not sure how to
3653 do it later. I am NOT resolving the linno's representing functions.
3654 Their symbols need a fileptr pointing to this linno when emitted.
3655 Thus, I resolve them on emit. xoxorich. */
3656
3657 for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
3658 if (lineP->line.l_lnno) {
3659 lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
3660 } else {
3661 ;
3662 }
3663 text_lineno_number++;
3664 } /* for each line number */
3665 } /* OBJ_COFF version */
3666 #elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
3667 { /* OBJ_AOUT version */
3668 symbolPP = & symbol_rootP; /* -> last symbol chain link. */
3669 while ((symbolP = *symbolPP) != NULL)
3670 {
3671 if (flagseen['R'] && S_IS_DATA(symbolP)) {
3672 S_SET_TEXT(symbolP);
3673 } /* if pusing data into text */
3674
3675 symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
3676
3677 /* OK, here is how we decide which symbols go out into the
3678 brave new symtab. Symbols that do are:
3679
3680 * symbols with no name (stabd's?)
3681 * symbols with debug info in their N_TYPE
3682
3683 Symbols that don't are:
3684 * symbols that are registers
3685 * symbols with \1 as their 3rd character (numeric labels)
3686 * "local labels" as defined by S_LOCAL_NAME(name)
3687 if the -L switch was passed to gas.
3688
3689 All other symbols are output. We complain if a deleted
3690 symbol was marked external. */
3691
3692
3693 if (1
3694 && !S_IS_REGISTER(symbolP)
3695 #ifndef VMS /* Under VMS we need to keep local symbols */
3696 && ( !S_GET_NAME(symbolP)
3697 || S_IS_DEBUG(symbolP)
3698 #ifdef TC_I960
3699 /* FIXME this ifdef seems highly dubious to me. xoxorich. */
3700 || !S_IS_DEFINED(symbolP)
3701 || S_IS_EXTERNAL(symbolP)
3702 #endif /* TC_I960 */
3703 || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
3704 #endif /* not VMS */
3705 )
3706 {
3707 #ifndef VMS
3708 symbolP->sy_number = symbol_number++;
3709
3710 /* The + 1 after strlen account for the \0 at the
3711 end of each string */
3712 if (!S_IS_STABD(symbolP)) {
3713 /* Ordinary case. */
3714 symbolP->sy_name_offset = string_byte_count;
3715 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3716 }
3717 else /* .Stabd case. */
3718 #endif /* not VMS */
3719 symbolP->sy_name_offset = 0;
3720 symbolPP = &(symbol_next(symbolP));
3721 } else {
3722 if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
3723 as_bad ("Local symbol %s never defined", name);
3724 } /* oops. */
3725
3726 #ifndef VMS
3727 /* Unhook it from the chain */
3728 *symbolPP = symbol_next(symbolP);
3729 #endif /* VMS */
3730 } /* if this symbol should be in the output */
3731 } /* for each symbol */
3732 } /* OBJ_AOUT version */
3733 #else
3734 cant_crawl_symbol_table();
3735 #endif
3736 H_SET_STRING_SIZE(&headers,string_byte_count);
3737 H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
3738 } /* crawl symbol table */
3739
3740 } /* obj_crawl_symbol_chain() */
3741
3742 /* end of vms.c */