vms stuff from fsf version - untested
[deliverable/binutils-gdb.git] / gas / config / obj-vms.c
1 /* vms.c -- Write out a VAX/VMS object file
2 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* Written by David L. Kashtan */
21 /* Modified by Eric Youngdale to write VMS debug records for program
22 variables */
23 #include "as.h"
24 #include "subsegs.h"
25 #include "obstack.h"
26
27 /* What we do if there is a goof. */
28 #define error as_fatal
29
30 #ifdef HO_VMS /* These are of no use if we are cross assembling. */
31 #include <fab.h> /* Define File Access Block */
32 #include <nam.h> /* Define NAM Block */
33 #include <xab.h> /* Define XAB - all different types*/
34 #endif
35 /*
36 * Version string of the compiler that produced the code we are
37 * assembling. (And this assembler, if we do not have compiler info.)
38 */
39 extern const char version_string[];
40 char *compiler_version_string;
41
42 /* Flag that determines how we map names. This takes several values, and
43 * is set with the -h switch. A value of zero implies names should be
44 * upper case, and the presence of the -h switch inhibits the case hack.
45 * No -h switch at all sets vms_name_mapping to 0, and allows case hacking.
46 * A value of 2 (set with -h2) implies names should be
47 * all lower case, with no case hack. A value of 3 (set with -h3) implies
48 * that case should be preserved. */
49
50 /* If the -+ switch is given, then the hash is appended to any name that is
51 * longer than 31 characters, irregardless of the setting of the -h switch.
52 */
53
54 char vms_name_mapping = 0;
55
56
57 extern char *strchr ();
58 extern char *myname;
59 static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
60
61 /*
62 * We augment the "gas" symbol structure with this
63 */
64 struct VMS_Symbol
65 {
66 struct VMS_Symbol *Next;
67 struct symbol *Symbol;
68 int Size;
69 int Psect_Index;
70 int Psect_Offset;
71 };
72 struct VMS_Symbol *VMS_Symbols = 0;
73
74 /* We need this to keep track of the various input files, so that we can
75 * give the debugger the correct source line.
76 */
77
78 struct input_file
79 {
80 struct input_file *next;
81 struct input_file *same_file_fpnt;
82 int file_number;
83 int max_line;
84 int min_line;
85 int offset;
86 char flag;
87 char *name;
88 symbolS *spnt;
89 };
90
91 static struct input_file *file_root = (struct input_file *) NULL;
92
93
94 static struct input_file *find_file (symbolS *);
95
96 /*
97 * This enum is used to keep track of the various types of variables that
98 * may be present.
99 */
100
101 enum advanced_type
102 {
103 BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, UNKNOWN
104 };
105
106 /*
107 * This structure contains the information from the stabs directives, and the
108 * information is filled in by VMS_typedef_parse. Everything that is needed
109 * to generate the debugging record for a given symbol is present here.
110 * This could be done more efficiently, using nested struct/unions, but for now
111 * I am happy that it works.
112 */
113 struct VMS_DBG_Symbol
114 {
115 struct VMS_DBG_Symbol *next;
116 enum advanced_type advanced; /* description of what this is */
117 int dbx_type; /* this record is for this type */
118 int type2; /* For advanced types this is the type referred to.
119 i.e. the type a pointer points to, or the type
120 of object that makes up an array */
121 int VMS_type; /* Use this type when generating a variable def */
122 int index_min; /* used for arrays - this will be present for all */
123 int index_max; /* entries, but will be meaningless for non-arrays */
124 int data_size; /* size in bytes of the data type. For an array, this
125 is the size of one element in the array */
126 int struc_numb; /* Number of the structure/union/enum - used for ref */
127 };
128
129 struct VMS_DBG_Symbol *VMS_Symbol_type_list =
130 {(struct VMS_DBG_Symbol *) NULL};
131
132 /*
133 * We need this structure to keep track of forward references to
134 * struct/union/enum that have not been defined yet. When they are ultimately
135 * defined, then we can go back and generate the TIR commands to make a back
136 * reference.
137 */
138
139 struct forward_ref
140 {
141 struct forward_ref *next;
142 int dbx_type;
143 int struc_numb;
144 char resolved;
145 };
146
147 struct forward_ref *f_ref_root =
148 {(struct forward_ref *) NULL};
149
150 /*
151 * This routine is used to compare the names of certain types to various
152 * fixed types that are known by the debugger.
153 */
154 #define type_check(x) !strcmp( symbol_name , x )
155
156 /*
157 * This variable is used to keep track of the name of the symbol we are
158 * working on while we are parsing the stabs directives.
159 */
160 static char *symbol_name;
161
162 /* We use this counter to assign numbers to all of the structures, unions
163 * and enums that we define. When we actually declare a variable to the
164 * debugger, we can simply do it by number, rather than describing the
165 * whole thing each time.
166 */
167
168 static structure_count = 0;
169
170 /* This variable is used to keep track of the current structure number
171 * for a given variable. If this is < 0, that means that the structure
172 * has not yet been defined to the debugger. This is still cool, since
173 * the VMS object language has ways of fixing things up after the fact,
174 * so we just make a note of this, and generate fixups at the end.
175 */
176 static int struct_number;
177
178
179 /*
180 * Variable descriptors are used tell the debugger the data types of certain
181 * more complicated variables (basically anything involving a structure,
182 * union, enum, array or pointer). Some non-pointer variables of the
183 * basic types that the debugger knows about do not require a variable
184 * descriptor.
185 *
186 * Since it is impossible to have a variable descriptor longer than 128
187 * bytes by virtue of the way that the VMS object language is set up,
188 * it makes not sense to make the arrays any longer than this, or worrying
189 * about dynamic sizing of the array.
190 *
191 * These are the arrays and counters that we use to build a variable
192 * descriptor.
193 */
194
195 #define MAX_DEBUG_RECORD 128
196 static char Local[MAX_DEBUG_RECORD]; /* buffer for variable descriptor */
197 static char Asuffix[MAX_DEBUG_RECORD]; /* buffer for array descriptor */
198 static int Lpnt; /* index into Local */
199 static int Apoint; /* index into Asuffix */
200 static char overflow; /* flag to indicate we have written too much*/
201 static int total_len; /* used to calculate the total length of variable
202 descriptor plus array descriptor - used for len byte*/
203
204 /* Flag if we have told user about finding global constants in the text
205 section. */
206 static gave_compiler_message = 0;
207
208 /* A pointer to the current routine that we are working on. */
209
210 static symbolS *Current_Routine;
211
212 /* The psect number for $code a.k.a. the text section. */
213
214 static int Text_Psect;
215
216
217 /*
218 * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
219 */
220 static int VMS_Object_File_FD; /* File Descriptor for object file */
221 static char Object_Record_Buffer[512]; /* Buffer for object file records */
222 static int Object_Record_Offset;/* Offset to end of data */
223 static int Current_Object_Record_Type; /* Type of record in above */
224
225 /*
226 * Macros for placing data into the object record buffer
227 */
228
229 #define PUT_LONG(val) \
230 { md_number_to_chars(Object_Record_Buffer + \
231 Object_Record_Offset, val, 4); \
232 Object_Record_Offset += 4; }
233
234 #define PUT_SHORT(val) \
235 { md_number_to_chars(Object_Record_Buffer + \
236 Object_Record_Offset, val, 2); \
237 Object_Record_Offset += 2; }
238
239 #define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val
240
241 #define PUT_COUNTED_STRING(cp) {\
242 register char *p = cp; \
243 PUT_CHAR(strlen(p)); \
244 while (*p) PUT_CHAR(*p++);}
245
246 /*
247 * Macro for determining if a Name has psect attributes attached
248 * to it.
249 */
250 #define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
251 #define PSECT_ATTRIBUTES_STRING_LENGTH 18
252
253 #define HAS_PSECT_ATTRIBUTES(Name) \
254 (strncmp((Name[0] == '_' ? Name + 1 : Name), \
255 PSECT_ATTRIBUTES_STRING, \
256 PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
257 \f
258
259 /* in: segT out: N_TYPE bits */
260 const short seg_N_TYPE[] =
261 {
262 N_ABS,
263 N_TEXT,
264 N_DATA,
265 N_BSS,
266 N_UNDF, /* unknown */
267 N_UNDF, /* absent */
268 N_UNDF, /* pass1 */
269 N_UNDF, /* error */
270 N_UNDF, /* bignum/flonum */
271 N_UNDF, /* difference */
272 N_UNDF, /* debug */
273 N_UNDF, /* ntv */
274 N_UNDF, /* ptv */
275 N_REGISTER, /* register */
276 };
277
278 const segT N_TYPE_seg[N_TYPE + 2] =
279 { /* N_TYPE == 0x1E = 32-2 */
280 SEG_UNKNOWN, /* N_UNDF == 0 */
281 SEG_GOOF,
282 SEG_ABSOLUTE, /* N_ABS == 2 */
283 SEG_GOOF,
284 SEG_TEXT, /* N_TEXT == 4 */
285 SEG_GOOF,
286 SEG_DATA, /* N_DATA == 6 */
287 SEG_GOOF,
288 SEG_BSS, /* N_BSS == 8 */
289 SEG_GOOF,
290 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
291 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
292 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
293 SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
294 SEG_GOOF,
295 };
296 \f
297
298 /* The following code defines the special types of pseudo-ops that we
299 * use with VMS.
300 */
301
302 char const_flag = 0;
303
304 void
305 s_const ()
306 {
307 register int temp;
308
309 temp = get_absolute_expression ();
310 subseg_new (SEG_DATA, (subsegT) temp);
311 const_flag = 1;
312 demand_empty_rest_of_line ();
313 }
314
315 /*
316 * stab()
317 *
318 * Handle .stabX directives, which used to be open-coded.
319 * So much creeping featurism overloaded the semantics that we decided
320 * to put all .stabX thinking in one place. Here.
321 *
322 * We try to make any .stabX directive legal. Other people's AS will often
323 * do assembly-time consistency checks: eg assigning meaning to n_type bits
324 * and "protecting" you from setting them to certain values. (They also zero
325 * certain bits before emitting symbols. Tut tut.)
326 *
327 * If an expression is not absolute we either gripe or use the relocation
328 * information. Other people's assemblers silently forget information they
329 * don't need and invent information they need that you didn't supply.
330 *
331 * .stabX directives always make a symbol table entry. It may be junk if
332 * the rest of your .stabX directive is malformed.
333 */
334 static void
335 obj_aout_stab (what)
336 int what;
337 {
338 register symbolS *symbolP = 0;
339 register char *string;
340 int saved_type = 0;
341 int length;
342 int goof; /* TRUE if we have aborted. */
343 long longint;
344
345 /*
346 * Enter with input_line_pointer pointing past .stabX and any following
347 * whitespace.
348 */
349 goof = 0; /* JF who forgot this?? */
350 if (what == 's')
351 {
352 string = demand_copy_C_string (&length);
353 SKIP_WHITESPACE ();
354 if (*input_line_pointer == ',')
355 input_line_pointer++;
356 else
357 {
358 as_bad ("I need a comma after symbol's name");
359 goof = 1;
360 }
361 }
362 else
363 string = "";
364
365 /*
366 * Input_line_pointer->after ','. String->symbol name.
367 */
368 if (!goof)
369 {
370 symbolP = symbol_new (string,
371 SEG_UNKNOWN,
372 0,
373 (struct frag *) 0);
374 switch (what)
375 {
376 case 'd':
377 S_SET_NAME (symbolP, NULL); /* .stabd feature. */
378 S_SET_VALUE (symbolP, obstack_next_free (&frags) - frag_now->fr_literal);
379 symbolP->sy_frag = frag_now;
380 break;
381
382 case 'n':
383 symbolP->sy_frag = &zero_address_frag;
384 break;
385
386 case 's':
387 symbolP->sy_frag = &zero_address_frag;
388 break;
389
390 default:
391 BAD_CASE (what);
392 break;
393 }
394
395 if (get_absolute_expression_and_terminator (&longint) == ',')
396 symbolP->sy_symbol.n_type = saved_type = longint;
397 else
398 {
399 as_bad ("I want a comma after the n_type expression");
400 goof = 1;
401 input_line_pointer--; /* Backup over a non-',' char. */
402 }
403 }
404
405 if (!goof)
406 {
407 if (get_absolute_expression_and_terminator (&longint) == ',')
408 S_SET_OTHER (symbolP, longint);
409 else
410 {
411 as_bad ("I want a comma after the n_other expression");
412 goof = 1;
413 input_line_pointer--; /* Backup over a non-',' char. */
414 }
415 }
416
417 if (!goof)
418 {
419 S_SET_DESC (symbolP, get_absolute_expression ());
420 if (what == 's' || what == 'n')
421 {
422 if (*input_line_pointer != ',')
423 {
424 as_bad ("I want a comma after the n_desc expression");
425 goof = 1;
426 }
427 else
428 {
429 input_line_pointer++;
430 }
431 }
432 }
433
434 if ((!goof) && (what == 's' || what == 'n'))
435 {
436 pseudo_set (symbolP);
437 symbolP->sy_symbol.n_type = saved_type;
438 }
439
440 if (goof)
441 ignore_rest_of_line ();
442 else
443 demand_empty_rest_of_line ();
444 } /* obj_aout_stab() */
445
446 const pseudo_typeS obj_pseudo_table[] =
447 {
448 {"stabd", obj_aout_stab, 'd'},/* stabs */
449 {"stabn", obj_aout_stab, 'n'},/* stabs */
450 {"stabs", obj_aout_stab, 's'},/* stabs */
451 {"const", s_const, 0},
452 {0, 0, 0},
453
454 }; /* obj_pseudo_table */
455
456 void
457 obj_read_begin_hook ()
458 {
459 return;
460 } /* obj_read_begin_hook() */
461
462 void
463 obj_crawl_symbol_chain (headers)
464 object_headers *headers;
465 {
466 symbolS *symbolP;
467 symbolS **symbolPP;
468 int symbol_number = 0;
469
470 /* JF deal with forward references first... */
471 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
472 {
473 if (symbolP->sy_forward)
474 {
475 S_SET_VALUE (symbolP, S_GET_VALUE (symbolP)
476 + S_GET_VALUE (symbolP->sy_forward)
477 + symbolP->sy_forward->sy_frag->fr_address);
478 symbolP->sy_forward = 0;
479 } /* if it has a forward reference */
480 } /* walk the symbol chain */
481
482 { /* crawl symbol table */
483 register int symbol_number = 0;
484
485 {
486 symbolPP = &symbol_rootP; /* -> last symbol chain link. */
487 while ((symbolP = *symbolPP) != NULL)
488 {
489 S_GET_VALUE (symbolP) += symbolP->sy_frag->fr_address;
490
491 /* OK, here is how we decide which symbols go out into the
492 brave new symtab. Symbols that do are:
493
494 * symbols with no name (stabd's?)
495 * symbols with debug info in their N_TYPE
496
497 Symbols that don't are:
498 * symbols that are registers
499 * symbols with \1 as their 3rd character (numeric labels)
500 * "local labels" as defined by S_LOCAL_NAME(name)
501 if the -L switch was passed to gas.
502
503 All other symbols are output. We complain if a deleted
504 symbol was marked external. */
505
506
507 if (!S_IS_REGISTER (symbolP))
508 {
509 symbolP->sy_name_offset = 0;
510 symbolPP = &(symbol_next (symbolP));
511 }
512 else
513 {
514 if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
515 {
516 as_bad ("Local symbol %s never defined", S_GET_NAME (symbolP));
517 } /* oops. */
518
519 } /* if this symbol should be in the output */
520 } /* for each symbol */
521 }
522 H_SET_STRING_SIZE (headers, string_byte_count);
523 H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
524 } /* crawl symbol table */
525
526 } /* obj_crawl_symbol_chain() */
527 \f
528
529 /****** VMS OBJECT FILE HACKING ROUTINES *******/
530
531
532 /*
533 * Create the VMS object file
534 */
535 static
536 Create_VMS_Object_File ()
537 {
538 #if defined(eunice) || !defined(HO_VMS)
539 VMS_Object_File_FD = creat (out_file_name, 0777, "var");
540 #else /* eunice */
541 VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var",
542 "mbc=16", "deq=64", "fop=tef", "shr=nil");
543 #endif /* eunice */
544 /*
545 * Deal with errors
546 */
547 if (VMS_Object_File_FD < 0)
548 {
549 char Error_Line[256];
550
551 sprintf (Error_Line, "Couldn't create VMS object file \"%s\"",
552 out_file_name);
553 error (Error_Line);
554 }
555 /*
556 * Initialize object file hacking variables
557 */
558 Object_Record_Offset = 0;
559 Current_Object_Record_Type = -1;
560 }
561 \f
562
563 /*
564 * Flush the object record buffer to the object file
565 */
566 static
567 Flush_VMS_Object_Record_Buffer ()
568 {
569 int i;
570 short int zero;
571 /*
572 * If the buffer is empty, we are done
573 */
574 if (Object_Record_Offset == 0)
575 return;
576 /*
577 * Write the data to the file
578 */
579 #ifndef HO_VMS /* For cross-assembly purposes. */
580 i = write (VMS_Object_File_FD, &Object_Record_Offset, 2);
581 #endif /* not HO_VMS */
582 i = write (VMS_Object_File_FD,
583 Object_Record_Buffer,
584 Object_Record_Offset);
585 if (i != Object_Record_Offset)
586 error ("I/O error writing VMS object file");
587 #ifndef HO_VMS /* When cross-assembling, we need to pad the record to an even
588 number of bytes. */
589 /* pad it if needed */
590 zero = 0;
591 if (Object_Record_Offset & 1 != 0)
592 write (VMS_Object_File_FD, &zero, 1);
593 #endif /* not HO_VMS */
594 /*
595 * The buffer is now empty
596 */
597 Object_Record_Offset = 0;
598 }
599 \f
600
601 /*
602 * Declare a particular type of object file record
603 */
604 static
605 Set_VMS_Object_File_Record (Type)
606 int Type;
607 {
608 /*
609 * If the type matches, we are done
610 */
611 if (Type == Current_Object_Record_Type)
612 return;
613 /*
614 * Otherwise: flush the buffer
615 */
616 Flush_VMS_Object_Record_Buffer ();
617 /*
618 * Set the new type
619 */
620 Current_Object_Record_Type = Type;
621 }
622 \f
623
624
625 /*
626 * Close the VMS Object file
627 */
628 static
629 Close_VMS_Object_File ()
630 {
631 short int m_one = -1;
632 #ifndef HO_VMS /* For cross-assembly purposes. */
633 /* Write a 0xffff into the file, which means "End of File" */
634 write (VMS_Object_File_FD, &m_one, 2);
635 #endif /* not HO_VMS */
636 close (VMS_Object_File_FD);
637 }
638 \f
639
640 /*
641 * Store immediate data in current Psect
642 */
643 static
644 VMS_Store_Immediate_Data (Pointer, Size, Record_Type)
645 register char *Pointer;
646 int Size;
647 int Record_Type;
648 {
649 register int i;
650
651 /*
652 * We are writing a "Record_Type" record
653 */
654 Set_VMS_Object_File_Record (Record_Type);
655 /*
656 * We can only store 128 bytes at a time
657 */
658 while (Size > 0)
659 {
660 /*
661 * Store a maximum of 128 bytes
662 */
663 i = (Size > 128) ? 128 : Size;
664 Size -= i;
665 /*
666 * If we cannot accommodate this record, flush the
667 * buffer.
668 */
669 if ((Object_Record_Offset + i + 1) >=
670 sizeof (Object_Record_Buffer))
671 Flush_VMS_Object_Record_Buffer ();
672 /*
673 * If the buffer is empty we must insert record type
674 */
675 if (Object_Record_Offset == 0)
676 PUT_CHAR (Record_Type);
677 /*
678 * Store the count
679 */
680 PUT_CHAR (-i & 0xff);
681 /*
682 * Store the data
683 */
684 while (--i >= 0)
685 PUT_CHAR (*Pointer++);
686 /*
687 * Flush the buffer if it is more than 75% full
688 */
689 if (Object_Record_Offset >
690 (sizeof (Object_Record_Buffer) * 3 / 4))
691 Flush_VMS_Object_Record_Buffer ();
692 }
693 }
694
695 /*
696 * Make a data reference
697 */
698 static
699 VMS_Set_Data (Psect_Index, Offset, Record_Type, Force)
700 int Psect_Index;
701 int Offset;
702 int Record_Type;
703 int Force;
704 {
705 /*
706 * We are writing a "Record_Type" record
707 */
708 Set_VMS_Object_File_Record (Record_Type);
709 /*
710 * If the buffer is empty we must insert the record type
711 */
712 if (Object_Record_Offset == 0)
713 PUT_CHAR (Record_Type);
714 /*
715 * Stack the Psect base + Longword Offset
716 */
717 if (Force == 1)
718 {
719 if (Psect_Index > 127)
720 {
721 PUT_CHAR (TIR_S_C_STA_WPL);
722 PUT_SHORT (Psect_Index);
723 PUT_LONG (Offset);
724 }
725 else
726 {
727 PUT_CHAR (TIR_S_C_STA_PL);
728 PUT_CHAR (Psect_Index);
729 PUT_LONG (Offset);
730 }
731 }
732 else
733 {
734 if (Offset > 32767)
735 {
736 PUT_CHAR (TIR_S_C_STA_WPL);
737 PUT_SHORT (Psect_Index);
738 PUT_LONG (Offset);
739 }
740 else if (Offset > 127)
741 {
742 PUT_CHAR (TIR_S_C_STA_WPW);
743 PUT_SHORT (Psect_Index);
744 PUT_SHORT (Offset);
745 }
746 else
747 {
748 PUT_CHAR (TIR_S_C_STA_WPB);
749 PUT_SHORT (Psect_Index);
750 PUT_CHAR (Offset);
751 };
752 };
753 /*
754 * Set relocation base
755 */
756 PUT_CHAR (TIR_S_C_STO_PIDR);
757 /*
758 * Flush the buffer if it is more than 75% full
759 */
760 if (Object_Record_Offset >
761 (sizeof (Object_Record_Buffer) * 3 / 4))
762 Flush_VMS_Object_Record_Buffer ();
763 }
764
765 /*
766 * Make a debugger reference to a struct, union or enum.
767 */
768 static
769 VMS_Store_Struct (int Struct_Index)
770 {
771 /*
772 * We are writing a "OBJ_S_C_DBG" record
773 */
774 Set_VMS_Object_File_Record (OBJ_S_C_DBG);
775 /*
776 * If the buffer is empty we must insert the record type
777 */
778 if (Object_Record_Offset == 0)
779 PUT_CHAR (OBJ_S_C_DBG);
780 PUT_CHAR (TIR_S_C_STA_UW);
781 PUT_SHORT (Struct_Index);
782 PUT_CHAR (TIR_S_C_CTL_STKDL);
783 PUT_CHAR (TIR_S_C_STO_L);
784 /*
785 * Flush the buffer if it is more than 75% full
786 */
787 if (Object_Record_Offset >
788 (sizeof (Object_Record_Buffer) * 3 / 4))
789 Flush_VMS_Object_Record_Buffer ();
790 }
791
792 /*
793 * Make a debugger reference to partially define a struct, union or enum.
794 */
795 static
796 VMS_Def_Struct (int Struct_Index)
797 {
798 /*
799 * We are writing a "OBJ_S_C_DBG" record
800 */
801 Set_VMS_Object_File_Record (OBJ_S_C_DBG);
802 /*
803 * If the buffer is empty we must insert the record type
804 */
805 if (Object_Record_Offset == 0)
806 PUT_CHAR (OBJ_S_C_DBG);
807 PUT_CHAR (TIR_S_C_STA_UW);
808 PUT_SHORT (Struct_Index);
809 PUT_CHAR (TIR_S_C_CTL_DFLOC);
810 /*
811 * Flush the buffer if it is more than 75% full
812 */
813 if (Object_Record_Offset >
814 (sizeof (Object_Record_Buffer) * 3 / 4))
815 Flush_VMS_Object_Record_Buffer ();
816 }
817
818 static
819 VMS_Set_Struct (int Struct_Index)
820 { /* see previous functions for comments */
821 Set_VMS_Object_File_Record (OBJ_S_C_DBG);
822 if (Object_Record_Offset == 0)
823 PUT_CHAR (OBJ_S_C_DBG);
824 PUT_CHAR (TIR_S_C_STA_UW);
825 PUT_SHORT (Struct_Index);
826 PUT_CHAR (TIR_S_C_CTL_STLOC);
827 if (Object_Record_Offset >
828 (sizeof (Object_Record_Buffer) * 3 / 4))
829 Flush_VMS_Object_Record_Buffer ();
830 }
831 \f
832 /*
833 * Write the Traceback Module Begin record
834 */
835 static
836 VMS_TBT_Module_Begin ()
837 {
838 register char *cp, *cp1;
839 int Size;
840 char Module_Name[256];
841 char Local[256];
842
843 /*
844 * Get module name (the FILENAME part of the object file)
845 */
846 cp = out_file_name;
847 cp1 = Module_Name;
848 while (*cp)
849 {
850 if ((*cp == ']') || (*cp == '>') ||
851 (*cp == ':') || (*cp == '/'))
852 {
853 cp1 = Module_Name;
854 cp++;
855 continue;
856 }
857 *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++;
858 }
859 *cp1 = 0;
860 /*
861 * Limit it to 31 characters
862 */
863 while (--cp1 >= Module_Name)
864 if (*cp1 == '.')
865 *cp1 = 0;
866 if (strlen (Module_Name) > 31)
867 {
868 if (flagseen['+'])
869 printf ("%s: Module name truncated: %s\n", myname, Module_Name);
870 Module_Name[31] = 0;
871 }
872 /*
873 * Arrange to store the data locally (leave room for size byte)
874 */
875 cp = Local + 1;
876 /*
877 * Begin module
878 */
879 *cp++ = DST_S_C_MODBEG;
880 /*
881 * Unused
882 */
883 *cp++ = 0;
884 /*
885 * Language type == "C"
886 */
887 *(long *) cp = DST_S_C_C;
888 cp += sizeof (long);
889 /*
890 * Store the module name
891 */
892 *cp++ = strlen (Module_Name);
893 cp1 = Module_Name;
894 while (*cp1)
895 *cp++ = *cp1++;
896 /*
897 * Now we can store the record size
898 */
899 Size = (cp - Local);
900 Local[0] = Size - 1;
901 /*
902 * Put it into the object record
903 */
904 VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
905 }
906 \f
907
908 /*
909 * Write the Traceback Module End record
910 */
911 static
912 VMS_TBT_Module_End ()
913 {
914 char Local[2];
915
916 /*
917 * End module
918 */
919 Local[0] = 1;
920 Local[1] = DST_S_C_MODEND;
921 /*
922 * Put it into the object record
923 */
924 VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT);
925 }
926 \f
927
928 /*
929 * Write the Traceback Routine Begin record
930 */
931 static
932 VMS_TBT_Routine_Begin (symbolP, Psect)
933 struct symbol *symbolP;
934 int Psect;
935 {
936 register char *cp, *cp1;
937 char *Name;
938 int Offset;
939 int Size;
940 char Local[512];
941
942 /*
943 * Strip the leading "_" from the name
944 */
945 Name = S_GET_NAME (symbolP);
946 if (*Name == '_')
947 Name++;
948 /*
949 * Get the text psect offset
950 */
951 Offset = S_GET_VALUE (symbolP);
952 /*
953 * Calculate the record size
954 */
955 Size = 1 + 1 + 4 + 1 + strlen (Name);
956 /*
957 * Record Size
958 */
959 Local[0] = Size;
960 /*
961 * Begin Routine
962 */
963 Local[1] = DST_S_C_RTNBEG;
964 /*
965 * Uses CallS/CallG
966 */
967 Local[2] = 0;
968 /*
969 * Store the data so far
970 */
971 VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
972 /*
973 * Make sure we are still generating a OBJ_S_C_TBT record
974 */
975 if (Object_Record_Offset == 0)
976 PUT_CHAR (OBJ_S_C_TBT);
977 /*
978 * Now get the symbol address
979 */
980 PUT_CHAR (TIR_S_C_STA_WPL);
981 PUT_SHORT (Psect);
982 PUT_LONG (Offset);
983 /*
984 * Store the data reference
985 */
986 PUT_CHAR (TIR_S_C_STO_PIDR);
987 /*
988 * Store the counted string as data
989 */
990 cp = Local;
991 cp1 = Name;
992 Size = strlen (cp1) + 1;
993 *cp++ = Size - 1;
994 while (*cp1)
995 *cp++ = *cp1++;
996 VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
997 }
998 \f
999
1000 /*
1001 * Write the Traceback Routine End record
1002 * We *must* search the symbol table to find the next routine, since
1003 * the assember has a way of reassembling the symbol table OUT OF ORDER
1004 * Thus the next routine in the symbol list is not necessarily the
1005 * next one in memory. For debugging to work correctly we must know the
1006 * size of the routine.
1007 */
1008 static
1009 VMS_TBT_Routine_End (Max_Size, sp)
1010 int Max_Size;
1011 symbolS *sp;
1012 {
1013 symbolS *symbolP;
1014 int Size = 0x7fffffff;
1015 char Local[16];
1016
1017
1018 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
1019 {
1020 if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
1021 {
1022 if (*S_GET_NAME (symbolP) == 'L')
1023 continue;
1024 if ((S_GET_VALUE (symbolP) > S_GET_VALUE (sp)) &&
1025 (S_GET_VALUE (symbolP) < Size))
1026 Size = S_GET_VALUE (symbolP);
1027 /* check if gcc_compiled. has size of zero */
1028 if ((S_GET_VALUE (symbolP) == S_GET_VALUE (sp)) &&
1029 sp != symbolP &&
1030 (!strcmp (S_GET_NAME (sp), "gcc_compiled.") ||
1031 !strcmp (S_GET_NAME (sp), "gcc2_compiled.")))
1032 Size = S_GET_VALUE (symbolP);
1033
1034 };
1035 };
1036 if (Size == 0x7fffffff)
1037 Size = Max_Size;
1038 Size -= S_GET_VALUE (sp); /* and get the size of the routine */
1039 /*
1040 * Record Size
1041 */
1042 Local[0] = 6;
1043 /*
1044 * End of Routine
1045 */
1046 Local[1] = DST_S_C_RTNEND;
1047 /*
1048 * Unused
1049 */
1050 Local[2] = 0;
1051 /*
1052 * Size of routine
1053 */
1054 *((long *) (Local + 3)) = Size;
1055 /*
1056 * Store the record
1057 */
1058 VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
1059 }
1060
1061 /*
1062 * Write the Traceback Block End record
1063 */
1064 static
1065 VMS_TBT_Block_Begin (symbolP, Psect, Name)
1066 struct symbol *symbolP;
1067 int Psect;
1068 char *Name;
1069 {
1070 register char *cp, *cp1;
1071 int Offset;
1072 int Size;
1073 char Local[512];
1074 /*
1075 * Begin block
1076 */
1077 Size = 1 + 1 + 4 + 1 + strlen (Name);
1078 /*
1079 * Record Size
1080 */
1081 Local[0] = Size;
1082 /*
1083 * Begin Block - We simulate with a phony routine
1084 */
1085 Local[1] = DST_S_C_BLKBEG;
1086 /*
1087 * Uses CallS/CallG
1088 */
1089 Local[2] = 0;
1090 /*
1091 * Store the data so far
1092 */
1093 VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG);
1094 /*
1095 * Make sure we are still generating a OBJ_S_C_DBG record
1096 */
1097 if (Object_Record_Offset == 0)
1098 PUT_CHAR (OBJ_S_C_DBG);
1099 /*
1100 * Now get the symbol address
1101 */
1102 PUT_CHAR (TIR_S_C_STA_WPL);
1103 PUT_SHORT (Psect);
1104 /*
1105 * Get the text psect offset
1106 */
1107 Offset = S_GET_VALUE (symbolP);
1108 PUT_LONG (Offset);
1109 /*
1110 * Store the data reference
1111 */
1112 PUT_CHAR (TIR_S_C_STO_PIDR);
1113 /*
1114 * Store the counted string as data
1115 */
1116 cp = Local;
1117 cp1 = Name;
1118 Size = strlen (cp1) + 1;
1119 *cp++ = Size - 1;
1120 while (*cp1)
1121 *cp++ = *cp1++;
1122 VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG);
1123 }
1124 \f
1125
1126 /*
1127 * Write the Traceback Block End record
1128 */
1129 static
1130 VMS_TBT_Block_End (int Size)
1131 {
1132 char Local[16];
1133
1134 /*
1135 * End block - simulate with a phony end routine
1136 */
1137 Local[0] = 6;
1138 Local[1] = DST_S_C_BLKEND;
1139 *((long *) (Local + 3)) = Size;
1140 /*
1141 * Unused
1142 */
1143 Local[2] = 0;
1144 VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG);
1145 }
1146 \f
1147
1148
1149 /*
1150 * Write a Line number / PC correlation record
1151 */
1152 static
1153 VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
1154 int Line_Number;
1155 int Offset;
1156 int Psect;
1157 int Do_Delta;
1158 {
1159 register char *cp;
1160 char Local[64];
1161
1162 /*
1163 * If not delta, set our PC/Line number correlation
1164 */
1165 if (Do_Delta == 0)
1166 {
1167 /*
1168 * Size
1169 */
1170 Local[0] = 1 + 1 + 2 + 1 + 4;
1171 /*
1172 * Line Number/PC correlation
1173 */
1174 Local[1] = DST_S_C_LINE_NUM;
1175 /*
1176 * Set Line number
1177 */
1178 Local[2] = DST_S_C_SET_LINE_NUM;
1179 *((unsigned short *) (Local + 3)) = Line_Number - 1;
1180 /*
1181 * Set PC
1182 */
1183 Local[5] = DST_S_C_SET_ABS_PC;
1184 VMS_Store_Immediate_Data (Local, 6, OBJ_S_C_TBT);
1185 /*
1186 * Make sure we are still generating a OBJ_S_C_TBT record
1187 */
1188 if (Object_Record_Offset == 0)
1189 PUT_CHAR (OBJ_S_C_TBT);
1190 if (Psect < 255)
1191 {
1192 PUT_CHAR (TIR_S_C_STA_PL);
1193 PUT_CHAR (Psect);
1194 }
1195 else
1196 {
1197 PUT_CHAR (TIR_S_C_STA_WPL);
1198 PUT_SHORT (Psect);
1199 }
1200 PUT_LONG (Offset);
1201 PUT_CHAR (TIR_S_C_STO_PIDR);
1202 /*
1203 * Do a PC offset of 0 to register the line number
1204 */
1205 Local[0] = 2;
1206 Local[1] = DST_S_C_LINE_NUM;
1207 Local[2] = 0; /* Increment PC by 0 and register line # */
1208 VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
1209 }
1210 else
1211 {
1212 /*
1213 * If Delta is negative, terminate the line numbers
1214 */
1215 if (Do_Delta < 0)
1216 {
1217 Local[0] = 1 + 1 + 4;
1218 Local[1] = DST_S_C_LINE_NUM;
1219 Local[2] = DST_S_C_TERM_L;
1220 *((long *) (Local + 3)) = Offset;
1221 VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
1222 /*
1223 * Done
1224 */
1225 return;
1226 }
1227 /*
1228 * Do a PC/Line delta
1229 */
1230 cp = Local + 1;
1231 *cp++ = DST_S_C_LINE_NUM;
1232 if (Line_Number > 1)
1233 {
1234 /*
1235 * We need to increment the line number
1236 */
1237 if (Line_Number - 1 <= 255)
1238 {
1239 *cp++ = DST_S_C_INCR_LINUM;
1240 *cp++ = Line_Number - 1;
1241 }
1242 else
1243 {
1244 *cp++ = DST_S_C_INCR_LINUM_W;
1245 *(short *) cp = Line_Number - 1;
1246 cp += sizeof (short);
1247 }
1248 }
1249 /*
1250 * Increment the PC
1251 */
1252 if (Offset <= 128)
1253 {
1254 *cp++ = -Offset;
1255 }
1256 else
1257 {
1258 if (Offset < 0x10000)
1259 {
1260 *cp++ = DST_S_C_DELTA_PC_W;
1261 *(short *) cp = Offset;
1262 cp += sizeof (short);
1263 }
1264 else
1265 {
1266 *cp++ = DST_S_C_DELTA_PC_L;
1267 *(long *) cp = Offset;
1268 cp += sizeof (long);
1269 }
1270 }
1271 Local[0] = cp - (Local + 1);
1272 VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
1273 }
1274 }
1275 \f
1276
1277 /*
1278 * Describe a source file to the debugger
1279 */
1280 static
1281 VMS_TBT_Source_File (Filename, ID_Number)
1282 char *Filename;
1283 int ID_Number;
1284 {
1285 register char *cp, *cp1;
1286 int Status, i;
1287 char Local[512];
1288 #ifndef HO_VMS /* Used for cross-assembly */
1289 i = strlen (Filename);
1290 #else /* HO_VMS */
1291 static struct FAB Fab;
1292 static struct NAM Nam;
1293 static struct XABDAT Date_Xab;
1294 static struct XABFHC File_Header_Xab;
1295 char Es_String[255], Rs_String[255];
1296
1297 /*
1298 * Setup the Fab
1299 */
1300 Fab.fab$b_bid = FAB$C_BID;
1301 Fab.fab$b_bln = sizeof (Fab);
1302 Fab.fab$l_nam = (&Nam);
1303 Fab.fab$l_xab = (char *) &Date_Xab;
1304 /*
1305 * Setup the Nam block so we can find out the FULL name
1306 * of the source file.
1307 */
1308 Nam.nam$b_bid = NAM$C_BID;
1309 Nam.nam$b_bln = sizeof (Nam);
1310 Nam.nam$l_rsa = Rs_String;
1311 Nam.nam$b_rss = sizeof (Rs_String);
1312 Nam.nam$l_esa = Es_String;
1313 Nam.nam$b_ess = sizeof (Es_String);
1314 /*
1315 * Setup the Date and File Header Xabs
1316 */
1317 Date_Xab.xab$b_cod = XAB$C_DAT;
1318 Date_Xab.xab$b_bln = sizeof (Date_Xab);
1319 Date_Xab.xab$l_nxt = (char *) &File_Header_Xab;
1320 File_Header_Xab.xab$b_cod = XAB$C_FHC;
1321 File_Header_Xab.xab$b_bln = sizeof (File_Header_Xab);
1322 /*
1323 * Get the file information
1324 */
1325 Fab.fab$l_fna = Filename;
1326 Fab.fab$b_fns = strlen (Filename);
1327 Status = sys$open (&Fab);
1328 if (!(Status & 1))
1329 {
1330 printf ("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
1331 Filename, Status);
1332 return (0);
1333 }
1334 sys$close (&Fab);
1335 /*
1336 * Calculate the size of the resultant string
1337 */
1338 i = Nam.nam$b_rsl;
1339 #endif /* HO_VMS */
1340 /*
1341 * Size of record
1342 */
1343 Local[0] = 1 + 1 + 1 + 1 + 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1;
1344 /*
1345 * Source declaration
1346 */
1347 Local[1] = DST_S_C_SOURCE;
1348 /*
1349 * Make formfeeds count as source records
1350 */
1351 Local[2] = DST_S_C_SRC_FORMFEED;
1352 /*
1353 * Declare source file
1354 */
1355 Local[3] = DST_S_C_SRC_DECLFILE;
1356 Local[4] = 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1;
1357 cp = Local + 5;
1358 /*
1359 * Flags
1360 */
1361 *cp++ = 0;
1362 /*
1363 * File ID
1364 */
1365 *(short *) cp = ID_Number;
1366 cp += sizeof (short);
1367 #ifndef HO_VMS
1368 /*
1369 * Creation Date. Unknown, so we fill with zeroes.
1370 */
1371 *(long *) cp = 0;
1372 cp += sizeof (long);
1373 *(long *) cp = 0;
1374 cp += sizeof (long);
1375 /*
1376 * End of file block
1377 */
1378 *(long *) cp = 0;
1379 cp += sizeof (long);
1380 /*
1381 * First free byte
1382 */
1383 *(short *) cp = 0;
1384 cp += sizeof (short);
1385 /*
1386 * Record format
1387 */
1388 *cp++ = 0;
1389 /*
1390 * Filename
1391 */
1392 *cp++ = i;
1393 cp1 = Filename;
1394 #else /* Use this code when assembling for VMS on a VMS system */
1395 /*
1396 * Creation Date
1397 */
1398 *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[0];
1399 cp += sizeof (long);
1400 *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[1];
1401 cp += sizeof (long);
1402 /*
1403 * End of file block
1404 */
1405 *(long *) cp = File_Header_Xab.xab$l_ebk;
1406 cp += sizeof (long);
1407 /*
1408 * First free byte
1409 */
1410 *(short *) cp = File_Header_Xab.xab$w_ffb;
1411 cp += sizeof (short);
1412 /*
1413 * Record format
1414 */
1415 *cp++ = File_Header_Xab.xab$b_rfo;
1416 /*
1417 * Filename
1418 */
1419 *cp++ = i;
1420 cp1 = Rs_String;
1421 #endif /* HO_VMS */
1422 while (--i >= 0)
1423 *cp++ = *cp1++;
1424 /*
1425 * Library module name (none)
1426 */
1427 *cp++ = 0;
1428 /*
1429 * Done
1430 */
1431 VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
1432 return 1;
1433 }
1434 \f
1435
1436 /*
1437 * Give the number of source lines to the debugger
1438 */
1439 static
1440 VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines)
1441 int ID_Number;
1442 int Starting_Line_Number;
1443 int Number_Of_Lines;
1444 {
1445 char *cp, *cp1;
1446 char Local[16];
1447
1448 /*
1449 * Size of record
1450 */
1451 Local[0] = 1 + 1 + 2 + 1 + 4 + 1 + 2;
1452 /*
1453 * Source declaration
1454 */
1455 Local[1] = DST_S_C_SOURCE;
1456 /*
1457 * Set Source File
1458 */
1459 cp = Local + 2;
1460 *cp++ = DST_S_C_SRC_SETFILE;
1461 /*
1462 * File ID Number
1463 */
1464 *(short *) cp = ID_Number;
1465 cp += sizeof (short);
1466 /*
1467 * Set record number
1468 */
1469 *cp++ = DST_S_C_SRC_SETREC_L;
1470 *(long *) cp = Starting_Line_Number;
1471 cp += sizeof (long);
1472 /*
1473 * Define lines
1474 */
1475 *cp++ = DST_S_C_SRC_DEFLINES_W;
1476 *(short *) cp = Number_Of_Lines;
1477 cp += sizeof (short);
1478 /*
1479 * Done
1480 */
1481 VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
1482 }
1483 \f
1484
1485
1486
1487 /* This routine locates a file in the list of files. If an entry does not
1488 * exist, one is created. For include files, a new entry is always created
1489 * such that inline functions can be properly debugged. */
1490 static struct input_file *
1491 find_file (sp)
1492 symbolS *sp;
1493 {
1494 struct input_file *same_file;
1495 struct input_file *fpnt;
1496 same_file = (struct input_file *) NULL;
1497 for (fpnt = file_root; fpnt; fpnt = fpnt->next)
1498 {
1499 if (fpnt == (struct input_file *) NULL)
1500 break;
1501 if (fpnt->spnt == sp)
1502 return fpnt;
1503 };
1504 for (fpnt = file_root; fpnt; fpnt = fpnt->next)
1505 {
1506 if (fpnt == (struct input_file *) NULL)
1507 break;
1508 if (strcmp (S_GET_NAME (sp), fpnt->name) == 0)
1509 {
1510 if (fpnt->flag == 1)
1511 return fpnt;
1512 same_file = fpnt;
1513 break;
1514 };
1515 };
1516 fpnt = (struct input_file *) malloc (sizeof (struct input_file));
1517 if (file_root == (struct input_file *) NULL)
1518 file_root = fpnt;
1519 else
1520 {
1521 struct input_file *fpnt1;
1522 for (fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next) ;
1523 fpnt1->next = fpnt;
1524 };
1525 fpnt->next = (struct input_file *) NULL;
1526 fpnt->name = S_GET_NAME (sp);
1527 fpnt->min_line = 0x7fffffff;
1528 fpnt->max_line = 0;
1529 fpnt->offset = 0;
1530 fpnt->flag = 0;
1531 fpnt->file_number = 0;
1532 fpnt->spnt = sp;
1533 fpnt->same_file_fpnt = same_file;
1534 return fpnt;
1535 }
1536 \f
1537 /*
1538 * The following functions and definitions are used to generate object records
1539 * that will describe program variables to the VMS debugger.
1540 *
1541 * This file contains many of the routines needed to output debugging info into
1542 * the object file that the VMS debugger needs to understand symbols. These
1543 * routines are called very late in the assembly process, and thus we can be
1544 * fairly lax about changing things, since the GSD and the TIR sections have
1545 * already been output.
1546 */
1547
1548
1549 /* This routine converts a number string into an integer, and stops when it
1550 * sees an invalid character the return value is the address of the character
1551 * just past the last character read. No error is generated.
1552 */
1553 static char *
1554 cvt_integer (str, rtn)
1555 char *str;
1556 int *rtn;
1557 {
1558 int ival, neg;
1559 neg = *str == '-' ? ++str, -1 : 1;
1560 ival = 0; /* first get the number of the type for dbx */
1561 while ((*str <= '9') && (*str >= '0'))
1562 ival = 10 * ival + *str++ - '0';
1563 *rtn = neg * ival;
1564 return str;
1565 }
1566
1567 /* this routine fixes the names that are generated by C++, ".this" is a good
1568 * example. The period does not work for the debugger, since it looks like
1569 * the syntax for a structure element, and thus it gets mightily confused
1570 *
1571 * We also use this to strip the PsectAttribute hack from the name before we
1572 * write a debugger record */
1573
1574 static char *
1575 fix_name (pnt)
1576 char *pnt;
1577 {
1578 char *pnt1;
1579 /*
1580 * Kill any leading "_"
1581 */
1582 if (*pnt == '_')
1583 pnt++;
1584 /*
1585 * Is there a Psect Attribute to skip??
1586 */
1587 if (HAS_PSECT_ATTRIBUTES (pnt))
1588 {
1589 /*
1590 * Yes: Skip it
1591 */
1592 pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
1593 while (*pnt)
1594 {
1595 if ((pnt[0] == '$') && (pnt[1] == '$'))
1596 {
1597 pnt += 2;
1598 break;
1599 }
1600 pnt++;
1601 }
1602 }
1603 /* Here we fix the .this -> $this conversion */
1604 for (pnt1 = pnt; *pnt1 != 0; pnt1++)
1605 {
1606 if (*pnt1 == '.')
1607 *pnt1 = '$';
1608 };
1609 return pnt;
1610 }
1611
1612 /* When defining a structure, this routine is called to find the name of
1613 * the actual structure. It is assumed that str points to the equal sign
1614 * in the definition, and it moves backward until it finds the start of the
1615 * name. If it finds a 0, then it knows that this structure def is in the
1616 * outermost level, and thus symbol_name points to the symbol name.
1617 */
1618 static char *
1619 get_struct_name (str)
1620 char *str;
1621 {
1622 char *pnt;
1623 pnt = str;
1624 while ((*pnt != ':') && (*pnt != '\0'))
1625 pnt--;
1626 if (*pnt == '\0')
1627 return symbol_name;
1628 *pnt-- = '\0';
1629 while ((*pnt != ';') && (*pnt != '='))
1630 pnt--;
1631 if (*pnt == ';')
1632 return pnt + 1;
1633 while ((*pnt < '0') || (*pnt > '9'))
1634 pnt++;
1635 while ((*pnt >= '0') && (*pnt <= '9'))
1636 pnt++;
1637 return pnt;
1638 }
1639
1640 /* search symbol list for type number dbx_type. Return a pointer to struct */
1641 static struct VMS_DBG_Symbol *
1642 find_symbol (dbx_type)
1643 int dbx_type;
1644 {
1645 struct VMS_DBG_Symbol *spnt;
1646 spnt = VMS_Symbol_type_list;
1647 while (spnt != (struct VMS_DBG_Symbol *) NULL)
1648 {
1649 if (spnt->dbx_type == dbx_type)
1650 break;
1651 spnt = spnt->next;
1652 };
1653 if (spnt == (struct VMS_DBG_Symbol *) NULL)
1654 return 0; /*Dunno what this is*/
1655 return spnt;
1656 }
1657
1658
1659 /* this routine puts info into either Local or Asuffix, depending on the sign
1660 * of size. The reason is that it is easier to build the variable descriptor
1661 * backwards, while the array descriptor is best built forwards. In the end
1662 * they get put together, if there is not a struct/union/enum along the way
1663 */
1664 static
1665 push (value, size)
1666 int value, size;
1667 {
1668 char *pnt;
1669 int i;
1670 int size1;
1671 long int val;
1672 val = value;
1673 pnt = (char *) &val;
1674 size1 = size;
1675 if (size < 0)
1676 {
1677 size1 = -size;
1678 pnt += size1 - 1;
1679 };
1680 if (size < 0)
1681 for (i = 0; i < size1; i++)
1682 {
1683 Local[Lpnt--] = *pnt--;
1684 if (Lpnt < 0)
1685 {
1686 overflow = 1;
1687 Lpnt = 1;
1688 };
1689 }
1690 else
1691 for (i = 0; i < size1; i++)
1692 {
1693 Asuffix[Apoint++] = *pnt++;
1694 if (Apoint >= MAX_DEBUG_RECORD)
1695 {
1696 overflow = 1;
1697 Apoint = MAX_DEBUG_RECORD - 1;
1698 };
1699 }
1700 }
1701
1702 /* this routine generates the array descriptor for a given array */
1703 static
1704 array_suffix (spnt2)
1705 struct VMS_DBG_Symbol *spnt2;
1706 {
1707 struct VMS_DBG_Symbol *spnt;
1708 struct VMS_DBG_Symbol *spnt1;
1709 int rank;
1710 int total_size;
1711 int i;
1712 rank = 0;
1713 spnt = spnt2;
1714 while (spnt->advanced != ARRAY)
1715 {
1716 spnt = find_symbol (spnt->type2);
1717 if (spnt == (struct VMS_DBG_Symbol *) NULL)
1718 return;
1719 };
1720 spnt1 = spnt;
1721 spnt1 = spnt;
1722 total_size = 1;
1723 while (spnt1->advanced == ARRAY)
1724 {
1725 rank++;
1726 total_size *= (spnt1->index_max - spnt1->index_min + 1);
1727 spnt1 = find_symbol (spnt1->type2);
1728 };
1729 total_size = total_size * spnt1->data_size;
1730 push (spnt1->data_size, 2);
1731 if (spnt1->VMS_type == 0xa3)
1732 push (0, 1);
1733 else
1734 push (spnt1->VMS_type, 1);
1735 push (4, 1);
1736 for (i = 0; i < 6; i++)
1737 push (0, 1);
1738 push (0xc0, 1);
1739 push (rank, 1);
1740 push (total_size, 4);
1741 push (0, 4);
1742 spnt1 = spnt;
1743 while (spnt1->advanced == ARRAY)
1744 {
1745 push (spnt1->index_max - spnt1->index_min + 1, 4);
1746 spnt1 = find_symbol (spnt1->type2);
1747 };
1748 spnt1 = spnt;
1749 while (spnt1->advanced == ARRAY)
1750 {
1751 push (spnt1->index_min, 4);
1752 push (spnt1->index_max, 4);
1753 spnt1 = find_symbol (spnt1->type2);
1754 };
1755 }
1756
1757 /* this routine generates the start of a variable descriptor based upon
1758 * a struct/union/enum that has yet to be defined. We define this spot as
1759 * a new location, and save four bytes for the address. When the struct is
1760 * finally defined, then we can go back and plug in the correct address
1761 */
1762 static
1763 new_forward_ref (dbx_type)
1764 int dbx_type;
1765 {
1766 struct forward_ref *fpnt;
1767 fpnt = (struct forward_ref *) malloc (sizeof (struct forward_ref));
1768 fpnt->next = f_ref_root;
1769 f_ref_root = fpnt;
1770 fpnt->dbx_type = dbx_type;
1771 fpnt->struc_numb = ++structure_count;
1772 fpnt->resolved = 'N';
1773 push (3, -1);
1774 total_len = 5;
1775 push (total_len, -2);
1776 struct_number = -fpnt->struc_numb;
1777 }
1778
1779 /* this routine generates the variable descriptor used to describe non-basic
1780 * variables. It calls itself recursively until it gets to the bottom of it
1781 * all, and then builds the descriptor backwards. It is easiest to do it this
1782 *way since we must periodically write length bytes, and it is easiest if we know
1783 *the value when it is time to write it.
1784 */
1785 static int
1786 gen1 (spnt, array_suffix_len)
1787 struct VMS_DBG_Symbol *spnt;
1788 int array_suffix_len;
1789 {
1790 struct VMS_DBG_Symbol *spnt1;
1791 int i;
1792 switch (spnt->advanced)
1793 {
1794 case VOID:
1795 push (DBG_S_C_VOID, -1);
1796 total_len += 1;
1797 push (total_len, -2);
1798 return 0;
1799 case BASIC:
1800 case FUNCTION:
1801 if (array_suffix_len == 0)
1802 {
1803 push (spnt->VMS_type, -1);
1804 push (DBG_S_C_BASIC, -1);
1805 total_len = 2;
1806 push (total_len, -2);
1807 return 1;
1808 };
1809 push (0, -4);
1810 push (0xfa02, -2);
1811 total_len = -2;
1812 return 1;
1813 case STRUCT:
1814 case UNION:
1815 case ENUM:
1816 struct_number = spnt->struc_numb;
1817 if (struct_number < 0)
1818 {
1819 new_forward_ref (spnt->dbx_type);
1820 return 1;
1821 }
1822 push (DBG_S_C_STRUCT, -1);
1823 total_len = 5;
1824 push (total_len, -2);
1825 return 1;
1826 case POINTER:
1827 spnt1 = find_symbol (spnt->type2);
1828 i = 1;
1829 if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
1830 new_forward_ref (spnt->type2);
1831 else
1832 i = gen1 (spnt1, 0);
1833 if (i)
1834 { /* (*void) is a special case, do not put pointer suffix*/
1835 push (DBG_S_C_POINTER, -1);
1836 total_len += 3;
1837 push (total_len, -2);
1838 };
1839 return 1;
1840 case ARRAY:
1841 spnt1 = spnt;
1842 while (spnt1->advanced == ARRAY)
1843 {
1844 spnt1 = find_symbol (spnt1->type2);
1845 if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
1846 {
1847 printf ("gcc-as warning(debugger output):");
1848 printf ("Forward reference error, dbx type %d\n",
1849 spnt->type2);
1850 return;
1851 }
1852 };
1853 /* It is too late to generate forward references, so the user gets a message.
1854 * This should only happen on a compiler error */
1855 i = gen1 (spnt1, 1);
1856 i = Apoint;
1857 array_suffix (spnt);
1858 array_suffix_len = Apoint - i;
1859 switch (spnt1->advanced)
1860 {
1861 case BASIC:
1862 case FUNCTION:
1863 break;
1864 default:
1865 push (0, -2);
1866 total_len += 2;
1867 push (total_len, -2);
1868 push (0xfa, -1);
1869 push (0x0101, -2);
1870 push (DBG_S_C_COMPLEX_ARRAY, -1);
1871 };
1872 total_len += array_suffix_len + 8;
1873 push (total_len, -2);
1874 };
1875 }
1876
1877 /* This generates a suffix for a variable. If it is not a defined type yet,
1878 * then dbx_type contains the type we are expecting so we can generate a
1879 * forward reference. This calls gen1 to build most of the descriptor, and
1880 * then it puts the icing on at the end. It then dumps whatever is needed
1881 * to get a complete descriptor (i.e. struct reference, array suffix ).
1882 */
1883 static
1884 generate_suffix (spnt, dbx_type)
1885 struct VMS_DBG_Symbol *spnt;
1886 int dbx_type;
1887 {
1888 int ilen;
1889 int i;
1890 char pvoid[6] =
1891 {5, 0xaf, 0, 1, 0, 5};
1892 struct VMS_DBG_Symbol *spnt1;
1893 Apoint = 0;
1894 Lpnt = MAX_DEBUG_RECORD - 1;
1895 total_len = 0;
1896 struct_number = 0;
1897 overflow = 0;
1898 if (spnt == (struct VMS_DBG_Symbol *) NULL)
1899 new_forward_ref (dbx_type);
1900 else
1901 {
1902 if (spnt->VMS_type != 0xa3)
1903 return 0; /* no suffix needed */
1904 gen1 (spnt, 0);
1905 };
1906 push (0x00af, -2);
1907 total_len += 4;
1908 push (total_len, -1);
1909 /* if the variable descriptor overflows the record, output a descriptor for
1910 * a pointer to void.
1911 */
1912 if ((total_len >= MAX_DEBUG_RECORD) || overflow)
1913 {
1914 printf (" Variable descriptor %d too complicated. Defined as *void ", spnt->dbx_type);
1915 VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG);
1916 return;
1917 };
1918 i = 0;
1919 while (Lpnt < MAX_DEBUG_RECORD - 1)
1920 Local[i++] = Local[++Lpnt];
1921 Lpnt = i;
1922 /* we use this for a reference to a structure that has already been defined */
1923 if (struct_number > 0)
1924 {
1925 VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
1926 Lpnt = 0;
1927 VMS_Store_Struct (struct_number);
1928 };
1929 /* we use this for a forward reference to a structure that has yet to be
1930 *defined. We store four bytes of zero to make room for the actual address once
1931 * it is known
1932 */
1933 if (struct_number < 0)
1934 {
1935 struct_number = -struct_number;
1936 VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
1937 Lpnt = 0;
1938 VMS_Def_Struct (struct_number);
1939 for (i = 0; i < 4; i++)
1940 Local[Lpnt++] = 0;
1941 VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
1942 Lpnt = 0;
1943 };
1944 i = 0;
1945 while (i < Apoint)
1946 Local[Lpnt++] = Asuffix[i++];
1947 if (Lpnt != 0)
1948 VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
1949 Lpnt = 0;
1950 }
1951
1952 /* This routine generates a symbol definition for a C sybmol for the debugger.
1953 * It takes a psect and offset for global symbols - if psect < 0, then this is
1954 * a local variable and the offset is relative to FP. In this case it can
1955 * be either a variable (Offset < 0) or a parameter (Offset > 0).
1956 */
1957 static
1958 VMS_DBG_record (spnt, Psect, Offset, Name)
1959 struct VMS_DBG_Symbol *spnt;
1960 int Psect;
1961 int Offset;
1962 char *Name;
1963 {
1964 char *pnt;
1965 char *Name_pnt;
1966 int j;
1967 int maxlen;
1968 int i = 0;
1969 Name_pnt = fix_name (Name); /* if there are bad characters in name, convert them */
1970 if (Psect < 0)
1971 { /* this is a local variable, referenced to SP */
1972 maxlen = 7 + strlen (Name_pnt);
1973 Local[i++] = maxlen;
1974 Local[i++] = spnt->VMS_type;
1975 if (Offset > 0)
1976 Local[i++] = DBG_S_C_FUNCTION_PARAMETER;
1977 else
1978 Local[i++] = DBG_S_C_LOCAL_SYM;
1979 pnt = (char *) &Offset;
1980 for (j = 0; j < 4; j++)
1981 Local[i++] = *pnt++; /* copy the offset */
1982 }
1983 else
1984 {
1985 maxlen = 7 + strlen (Name_pnt); /* symbols fixed in memory */
1986 Local[i++] = 7 + strlen (Name_pnt);
1987 Local[i++] = spnt->VMS_type;
1988 Local[i++] = 1;
1989 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
1990 i = 0;
1991 VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0);
1992 }
1993 Local[i++] = strlen (Name_pnt);
1994 while (*Name_pnt != '\0')
1995 Local[i++] = *Name_pnt++;
1996 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
1997 if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
1998 generate_suffix (spnt, 0);
1999 }
2000
2001
2002 /* This routine parses the stabs entries in order to make the definition
2003 * for the debugger of local symbols and function parameters
2004 */
2005 static int
2006 VMS_local_stab_Parse (sp)
2007 symbolS *sp;
2008 {
2009 char *pnt;
2010 char *pnt1;
2011 char *str;
2012 struct VMS_DBG_Symbol *spnt;
2013 struct VMS_Symbol *vsp;
2014 int dbx_type;
2015 int VMS_type;
2016 dbx_type = 0;
2017 str = S_GET_NAME (sp);
2018 pnt = (char *) strchr (str, ':');
2019 if (pnt == (char *) NULL)
2020 return; /* no colon present */
2021 pnt1 = pnt++; /* save this for later, and skip colon */
2022 if (*pnt == 'c')
2023 return 0; /* ignore static constants */
2024 /* there is one little catch that we must be aware of. Sometimes function
2025 * parameters are optimized into registers, and the compiler, in its infiite
2026 * wisdom outputs stabs records for *both*. In general we want to use the
2027 * register if it is present, so we must search the rest of the symbols for
2028 * this function to see if this parameter is assigned to a register.
2029 */
2030 {
2031 char *str1;
2032 char *pnt2;
2033 symbolS *sp1;
2034 if (*pnt == 'p')
2035 {
2036 for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
2037 {
2038 if (!S_IS_DEBUG (sp1))
2039 continue;
2040 if (S_GET_RAW_TYPE (sp1) == N_FUN)
2041 {
2042 char * pnt3=(char*) strchr (S_GET_NAME (sp1), ':') + 1;
2043 if (*pnt3 == 'F' || *pnt3 == 'f') break;
2044 };
2045 if (S_GET_RAW_TYPE (sp1) != N_RSYM)
2046 continue;
2047 str1 = S_GET_NAME (sp1); /* and get the name */
2048 pnt2 = str;
2049 while (*pnt2 != ':')
2050 {
2051 if (*pnt2 != *str1)
2052 break;
2053 pnt2++;
2054 str1++;
2055 };
2056 if ((*str1 != ':') || (*pnt2 != ':'))
2057 continue;
2058 return; /* they are the same! lets skip this one */
2059 }; /* for */
2060 /* first find the dbx symbol type from list, and then find VMS type */
2061 pnt++; /* skip p in case no register */
2062 }; /* if */
2063 }; /* p block */
2064 pnt = cvt_integer (pnt, &dbx_type);
2065 spnt = find_symbol (dbx_type);
2066 if (spnt == (struct VMS_DBG_Symbol *) NULL)
2067 return 0; /*Dunno what this is*/
2068 *pnt1 = '\0';
2069 VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str);
2070 *pnt1 = ':'; /* and restore the string */
2071 return 1;
2072 }
2073
2074 /* This routine parses a stabs entry to find the information required to define
2075 * a variable. It is used for global and static variables.
2076 * Basically we need to know the address of the symbol. With older versions
2077 * of the compiler, const symbols are
2078 * treated differently, in that if they are global they are written into the
2079 * text psect. The global symbol entry for such a const is actually written
2080 * as a program entry point (Yuk!!), so if we cannot find a symbol in the list
2081 * of psects, we must search the entry points as well. static consts are even
2082 * harder, since they are never assigned a memory address. The compiler passes
2083 * a stab to tell us the value, but I am not sure what to do with it.
2084 */
2085
2086 static
2087 VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
2088 symbolS *sp;
2089 char expected_type;
2090 int type1, type2, Text_Psect;
2091 {
2092 char *pnt;
2093 char *pnt1;
2094 char *str;
2095 symbolS *sp1;
2096 struct VMS_DBG_Symbol *spnt;
2097 struct VMS_Symbol *vsp;
2098 int dbx_type;
2099 int VMS_type;
2100 dbx_type = 0;
2101 str = S_GET_NAME (sp);
2102 pnt = (char *) strchr (str, ':');
2103 if (pnt == (char *) NULL)
2104 return; /* no colon present */
2105 pnt1 = pnt; /* save this for later*/
2106 pnt++;
2107 if (*pnt == expected_type)
2108 {
2109 pnt = cvt_integer (pnt + 1, &dbx_type);
2110 spnt = find_symbol (dbx_type);
2111 if (spnt == (struct VMS_DBG_Symbol *) NULL)
2112 return 0; /*Dunno what this is*/
2113 /* now we need to search the symbol table to find the psect and offset for
2114 * this variable.
2115 */
2116 *pnt1 = '\0';
2117 vsp = VMS_Symbols;
2118 while (vsp != (struct VMS_Symbol *) NULL)
2119 {
2120 pnt = S_GET_NAME (vsp->Symbol);
2121 if (pnt != (char *) NULL)
2122 if (*pnt++ == '_')
2123 /* make sure name is the same, and make sure correct symbol type */
2124 if ((strlen (pnt) == strlen (str)) && (strcmp (pnt, str) == 0)
2125 && ((S_GET_RAW_TYPE (vsp->Symbol) == type1) ||
2126 (S_GET_RAW_TYPE (vsp->Symbol) == type2)))
2127 break;
2128 vsp = vsp->Next;
2129 };
2130 if (vsp != (struct VMS_Symbol *) NULL)
2131 {
2132 VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
2133 *pnt1 = ':'; /* and restore the string */
2134 return 1;
2135 };
2136 /* the symbol was not in the symbol list, but it may be an "entry point"
2137 if it was a constant */
2138 for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
2139 {
2140 /*
2141 * Dispatch on STAB type
2142 */
2143 if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT))
2144 continue;
2145 pnt = S_GET_NAME (sp1);
2146 if (*pnt == '_')
2147 pnt++;
2148 if (strcmp (pnt, str) == 0)
2149 {
2150 if (!gave_compiler_message && expected_type == 'G')
2151 {
2152 printf ("***Warning - the assembly code generated by the compiler has placed\n");
2153 printf ("global constant(s) in the text psect. These will not be available to\n");
2154 printf ("other modules, since this is not the correct way to handle this. You\n");
2155 printf ("have two options: 1) get a patched compiler that does not put global\n");
2156 printf ("constants in the text psect, or 2) remove the 'const' keyword from\n");
2157 printf ("definitions of global variables in your source module(s). Don't say\n");
2158 printf ("I didn't warn you!");
2159 gave_compiler_message = 1;
2160 };
2161 VMS_DBG_record (spnt,
2162 Text_Psect,
2163 S_GET_VALUE (sp1),
2164 str);
2165 *pnt1 = ':';
2166 *S_GET_NAME (sp1) = 'L';
2167 /* fool assembler to not output this
2168 * as a routine in the TBT */
2169 return 1;
2170 };
2171 };
2172 };
2173 *pnt1 = ':'; /* and restore the string */
2174 return 0;
2175 }
2176
2177 static
2178 VMS_GSYM_Parse (sp, Text_Psect)
2179 symbolS *sp;
2180 int Text_Psect;
2181 { /* Global variables */
2182 VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect);
2183 }
2184
2185
2186 static
2187 VMS_LCSYM_Parse (sp, Text_Psect)
2188 symbolS *sp;
2189 int Text_Psect;
2190 { /* Static symbols - uninitialized */
2191 VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect);
2192 }
2193
2194 static
2195 VMS_STSYM_Parse (sp, Text_Psect)
2196 symbolS *sp;
2197 int Text_Psect;
2198 { /* Static symbols - initialized */
2199 VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect);
2200 }
2201
2202
2203 /* for register symbols, we must figure out what range of addresses within the
2204 * psect are valid. We will use the brackets in the stab directives to give us
2205 * guidance as to the PC range that this variable is in scope. I am still not
2206 * completely comfortable with this but as I learn more, I seem to get a better
2207 * handle on what is going on.
2208 * Caveat Emptor.
2209 */
2210 static
2211 VMS_RSYM_Parse (sp, Current_Routine, Text_Psect)
2212 symbolS *sp, *Current_Routine;
2213 int Text_Psect;
2214 {
2215 char *pnt;
2216 char *pnt1;
2217 char *str;
2218 int dbx_type;
2219 struct VMS_DBG_Symbol *spnt;
2220 int j;
2221 int maxlen;
2222 int i = 0;
2223 int bcnt = 0;
2224 int Min_Offset = -1; /* min PC of validity */
2225 int Max_Offset = 0; /* max PC of validity */
2226 symbolS *symbolP;
2227 for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP))
2228 {
2229 /*
2230 * Dispatch on STAB type
2231 */
2232 switch (S_GET_RAW_TYPE (symbolP))
2233 {
2234 case N_LBRAC:
2235 if (bcnt++ == 0)
2236 Min_Offset = S_GET_VALUE (symbolP);
2237 break;
2238 case N_RBRAC:
2239 if (--bcnt == 0)
2240 Max_Offset =
2241 S_GET_VALUE (symbolP) - 1;
2242 break;
2243 }
2244 if ((Min_Offset != -1) && (bcnt == 0))
2245 break;
2246 if (S_GET_RAW_TYPE (symbolP) == N_FUN)
2247 {
2248 pnt=(char*) strchr (S_GET_NAME (symbolP), ':') + 1;
2249 if (*pnt == 'F' || *pnt == 'f') break;
2250 };
2251 }
2252 /* check to see that the addresses were defined. If not, then there were no
2253 * brackets in the function, and we must try to search for the next function
2254 * Since functions can be in any order, we should search all of the symbol list
2255 * to find the correct ending address. */
2256 if (Min_Offset == -1)
2257 {
2258 int Max_Source_Offset;
2259 int This_Offset;
2260 Min_Offset = S_GET_VALUE (sp);
2261 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
2262 {
2263 /*
2264 * Dispatch on STAB type
2265 */
2266 This_Offset = S_GET_VALUE (symbolP);
2267 switch (S_GET_RAW_TYPE (symbolP))
2268 {
2269 case N_TEXT | N_EXT:
2270 if ((This_Offset > Min_Offset) && (This_Offset < Max_Offset))
2271 Max_Offset = This_Offset;
2272 break;
2273 case N_SLINE:
2274 if (This_Offset > Max_Source_Offset)
2275 Max_Source_Offset = This_Offset;
2276 }
2277 }
2278 /* if this is the last routine, then we use the PC of the last source line
2279 * as a marker of the max PC for which this reg is valid */
2280 if (Max_Offset == 0x7fffffff)
2281 Max_Offset = Max_Source_Offset;
2282 };
2283 dbx_type = 0;
2284 str = S_GET_NAME (sp);
2285 pnt = (char *) strchr (str, ':');
2286 if (pnt == (char *) NULL)
2287 return; /* no colon present */
2288 pnt1 = pnt; /* save this for later*/
2289 pnt++;
2290 if (*pnt != 'r')
2291 return 0;
2292 pnt = cvt_integer (pnt + 1, &dbx_type);
2293 spnt = find_symbol (dbx_type);
2294 if (spnt == (struct VMS_DBG_Symbol *) NULL)
2295 return 0; /*Dunno what this is yet*/
2296 *pnt1 = '\0';
2297 pnt = fix_name (S_GET_NAME (sp)); /* if there are bad characters in name, convert them */
2298 maxlen = 25 + strlen (pnt);
2299 Local[i++] = maxlen;
2300 Local[i++] = spnt->VMS_type;
2301 Local[i++] = 0xfb;
2302 Local[i++] = strlen (pnt) + 1;
2303 Local[i++] = 0x00;
2304 Local[i++] = 0x00;
2305 Local[i++] = 0x00;
2306 Local[i++] = strlen (pnt);
2307 while (*pnt != '\0')
2308 Local[i++] = *pnt++;
2309 Local[i++] = 0xfd;
2310 Local[i++] = 0x0f;
2311 Local[i++] = 0x00;
2312 Local[i++] = 0x03;
2313 Local[i++] = 0x01;
2314 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2315 i = 0;
2316 VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1);
2317 VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1);
2318 Local[i++] = 0x03;
2319 Local[i++] = S_GET_VALUE (sp);
2320 Local[i++] = 0x00;
2321 Local[i++] = 0x00;
2322 Local[i++] = 0x00;
2323 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2324 *pnt1 = ':';
2325 if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
2326 generate_suffix (spnt, 0);
2327 }
2328
2329 /* this function examines a structure definition, checking all of the elements
2330 * to make sure that all of them are fully defined. The only thing that we
2331 * kick out are arrays of undefined structs, since we do not know how big
2332 * they are. All others we can handle with a normal forward reference.
2333 */
2334 static int
2335 forward_reference (pnt)
2336 char *pnt;
2337 {
2338 int i;
2339 struct VMS_DBG_Symbol *spnt;
2340 struct VMS_DBG_Symbol *spnt1;
2341 pnt = cvt_integer (pnt + 1, &i);
2342 if (*pnt == ';')
2343 return 0; /* no forward references */
2344 do
2345 {
2346 pnt = (char *) strchr (pnt, ':');
2347 pnt = cvt_integer (pnt + 1, &i);
2348 spnt = find_symbol (i);
2349 if (spnt == (struct VMS_DBG_Symbol *) NULL)
2350 return 0;
2351 while ((spnt->advanced == POINTER) || (spnt->advanced == ARRAY))
2352 {
2353 i = spnt->type2;
2354 spnt1 = find_symbol (spnt->type2);
2355 if ((spnt->advanced == ARRAY) &&
2356 (spnt1 == (struct VMS_DBG_Symbol *) NULL))
2357 return 1;
2358 if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
2359 break;
2360 spnt = spnt1;
2361 };
2362 pnt = cvt_integer (pnt + 1, &i);
2363 pnt = cvt_integer (pnt + 1, &i);
2364 } while (*++pnt != ';');
2365 return 0; /* no forward refences found */
2366 }
2367
2368 /* This routine parses the stabs directives to find any definitions of dbx type
2369 * numbers. It makes a note of all of them, creating a structure element
2370 * of VMS_DBG_Symbol that describes it. This also generates the info for the
2371 * debugger that describes the struct/union/enum, so that further references
2372 * to these data types will be by number
2373 * We have to process pointers right away, since there can be references
2374 * to them later in the same stabs directive. We cannot have forward
2375 * references to pointers, (but we can have a forward reference to a pointer to
2376 * a structure/enum/union) and this is why we process them immediately.
2377 * After we process the pointer, then we search for defs that are nested even
2378 * deeper.
2379 */
2380 static int
2381 VMS_typedef_parse (str)
2382 char *str;
2383 {
2384 char *pnt;
2385 char *pnt1;
2386 char *pnt2;
2387 int i;
2388 int dtype;
2389 struct forward_ref *fpnt;
2390 int i1, i2, i3;
2391 int convert_integer;
2392 struct VMS_DBG_Symbol *spnt;
2393 struct VMS_DBG_Symbol *spnt1;
2394 /* check for any nested def's */
2395 pnt = (char *) strchr (str + 1, '=');
2396 if ((pnt != (char *) NULL) && (*(str + 1) != '*'))
2397 if (VMS_typedef_parse (pnt) == 1)
2398 return 1;
2399 /* now find dbx_type of entry */
2400 pnt = str - 1;
2401 if (*pnt == 'c')
2402 { /* check for static constants */
2403 *str = '\0'; /* for now we ignore them */
2404 return 0;
2405 };
2406 while ((*pnt <= '9') && (*pnt >= '0'))
2407 pnt--;
2408 pnt++; /* and get back to the number */
2409 cvt_integer (pnt, &i1);
2410 spnt = find_symbol (i1);
2411 /* first we see if this has been defined already, due to a forward reference*/
2412 if (spnt == (struct VMS_DBG_Symbol *) NULL)
2413 {
2414 if (VMS_Symbol_type_list == (struct VMS_DBG_Symbol *) NULL)
2415 {
2416 spnt = (struct VMS_DBG_Symbol *) malloc (sizeof (struct VMS_DBG_Symbol));
2417 spnt->next = (struct VMS_DBG_Symbol *) NULL;
2418 VMS_Symbol_type_list = spnt;
2419 }
2420 else
2421 {
2422 spnt = (struct VMS_DBG_Symbol *) malloc (sizeof (struct VMS_DBG_Symbol));
2423 spnt->next = VMS_Symbol_type_list;
2424 VMS_Symbol_type_list = spnt;
2425 };
2426 spnt->dbx_type = i1; /* and save the type */
2427 };
2428 /* for structs and unions, do a partial parse, otherwise we sometimes get
2429 * circular definitions that are impossible to resolve. We read enough info
2430 * so that any reference to this type has enough info to be resolved
2431 */
2432 pnt = str + 1; /* point to character past equal sign */
2433 if ((*pnt == 'u') || (*pnt == 's'))
2434 {
2435 };
2436 if ((*pnt <= '9') && (*pnt >= '0'))
2437 {
2438 if (type_check ("void"))
2439 { /* this is the void symbol */
2440 *str = '\0';
2441 spnt->advanced = VOID;
2442 return 0;
2443 };
2444 if (type_check ("unknown type"))
2445 { /* this is the void symbol */
2446 *str = '\0';
2447 spnt->advanced = UNKNOWN;
2448 return 0;
2449 };
2450 printf ("gcc-as warning(debugger output):");
2451 printf (" %d is an unknown untyped variable.\n", spnt->dbx_type);
2452 return 1; /* do not know what this is */
2453 };
2454 /* now define this module*/
2455 pnt = str + 1; /* point to character past equal sign */
2456 switch (*pnt)
2457 {
2458 case 'r':
2459 spnt->advanced = BASIC;
2460 if (type_check ("int"))
2461 {
2462 spnt->VMS_type = DBG_S_C_SLINT;
2463 spnt->data_size = 4;
2464 }
2465 else if (type_check ("long int"))
2466 {
2467 spnt->VMS_type = DBG_S_C_SLINT;
2468 spnt->data_size = 4;
2469 }
2470 else if (type_check ("unsigned int"))
2471 {
2472 spnt->VMS_type = DBG_S_C_ULINT;
2473 spnt->data_size = 4;
2474 }
2475 else if (type_check ("long unsigned int"))
2476 {
2477 spnt->VMS_type = DBG_S_C_ULINT;
2478 spnt->data_size = 4;
2479 }
2480 else if (type_check ("short int"))
2481 {
2482 spnt->VMS_type = DBG_S_C_SSINT;
2483 spnt->data_size = 2;
2484 }
2485 else if (type_check ("short unsigned int"))
2486 {
2487 spnt->VMS_type = DBG_S_C_USINT;
2488 spnt->data_size = 2;
2489 }
2490 else if (type_check ("char"))
2491 {
2492 spnt->VMS_type = DBG_S_C_SCHAR;
2493 spnt->data_size = 1;
2494 }
2495 else if (type_check ("signed char"))
2496 {
2497 spnt->VMS_type = DBG_S_C_SCHAR;
2498 spnt->data_size = 1;
2499 }
2500 else if (type_check ("unsigned char"))
2501 {
2502 spnt->VMS_type = DBG_S_C_UCHAR;
2503 spnt->data_size = 1;
2504 }
2505 else if (type_check ("float"))
2506 {
2507 spnt->VMS_type = DBG_S_C_REAL4;
2508 spnt->data_size = 4;
2509 }
2510 else if (type_check ("double"))
2511 {
2512 spnt->VMS_type = DBG_S_C_REAL8;
2513 spnt->data_size = 8;
2514 }
2515 pnt1 = (char *) strchr (str, ';') + 1;
2516 break;
2517 case 's':
2518 case 'u':
2519 if (*pnt == 's')
2520 spnt->advanced = STRUCT;
2521 else
2522 spnt->advanced = UNION;
2523 spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
2524 pnt1 = cvt_integer (pnt + 1, &spnt->data_size);
2525 if (forward_reference (pnt))
2526 {
2527 spnt->struc_numb = -1;
2528 return 1;
2529 }
2530 spnt->struc_numb = ++structure_count;
2531 pnt1--;
2532 pnt = get_struct_name (str);
2533 VMS_Def_Struct (spnt->struc_numb);
2534 fpnt = f_ref_root;
2535 while (fpnt != (struct forward_ref *) NULL)
2536 {
2537 if (fpnt->dbx_type == spnt->dbx_type)
2538 {
2539 fpnt->resolved = 'Y';
2540 VMS_Set_Struct (fpnt->struc_numb);
2541 VMS_Store_Struct (spnt->struc_numb);
2542 };
2543 fpnt = fpnt->next;
2544 };
2545 VMS_Set_Struct (spnt->struc_numb);
2546 i = 0;
2547 Local[i++] = 11 + strlen (pnt);
2548 Local[i++] = DBG_S_C_STRUCT_START;
2549 Local[i++] = 0x80;
2550 for (i1 = 0; i1 < 4; i1++)
2551 Local[i++] = 0x00;
2552 Local[i++] = strlen (pnt);
2553 pnt2 = pnt;
2554 while (*pnt2 != '\0')
2555 Local[i++] = *pnt2++;
2556 i2 = spnt->data_size * 8; /* number of bits */
2557 pnt2 = (char *) &i2;
2558 for (i1 = 0; i1 < 4; i1++)
2559 Local[i++] = *pnt2++;
2560 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2561 i = 0;
2562 if (pnt != symbol_name)
2563 {
2564 pnt += strlen (pnt);
2565 *pnt = ':';
2566 }; /* replace colon for later */
2567 while (*++pnt1 != ';')
2568 {
2569 pnt = (char *) strchr (pnt1, ':');
2570 *pnt = '\0';
2571 pnt2 = pnt1;
2572 pnt1 = cvt_integer (pnt + 1, &dtype);
2573 pnt1 = cvt_integer (pnt1 + 1, &i2);
2574 pnt1 = cvt_integer (pnt1 + 1, &i3);
2575 if ((dtype == 1) && (i3 != 32))
2576 { /* bitfield */
2577 Apoint = 0;
2578 push (19 + strlen (pnt2), 1);
2579 push (0xfa22, 2);
2580 push (1 + strlen (pnt2), 4);
2581 push (strlen (pnt2), 1);
2582 while (*pnt2 != '\0')
2583 push (*pnt2++, 1);
2584 push (i3, 2); /* size of bitfield */
2585 push (0x0d22, 2);
2586 push (0x00, 4);
2587 push (i2, 4); /* start position */
2588 VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG);
2589 Apoint = 0;
2590 }
2591 else
2592 {
2593 Local[i++] = 7 + strlen (pnt2);
2594 spnt1 = find_symbol (dtype);
2595 /* check if this is a forward reference */
2596 if (spnt1 != (struct VMS_DBG_Symbol *) NULL)
2597 Local[i++] = spnt1->VMS_type;
2598 else
2599 Local[i++] = DBG_S_C_ADVANCED_TYPE;
2600 Local[i++] = DBG_S_C_STRUCT_ITEM;
2601 pnt = (char *) &i2;
2602 for (i1 = 0; i1 < 4; i1++)
2603 Local[i++] = *pnt++;
2604 Local[i++] = strlen (pnt2);
2605 while (*pnt2 != '\0')
2606 Local[i++] = *pnt2++;
2607 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2608 i = 0;
2609 if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
2610 generate_suffix (spnt1, dtype);
2611 else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
2612 generate_suffix (spnt1, 0);
2613 };
2614 };
2615 pnt1++;
2616 Local[i++] = 0x01; /* length byte */
2617 Local[i++] = DBG_S_C_STRUCT_END;
2618 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2619 i = 0;
2620 break;
2621 case 'e':
2622 spnt->advanced = ENUM;
2623 spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
2624 spnt->struc_numb = ++structure_count;
2625 spnt->data_size = 4;
2626 VMS_Def_Struct (spnt->struc_numb);
2627 fpnt = f_ref_root;
2628 while (fpnt != (struct forward_ref *) NULL)
2629 {
2630 if (fpnt->dbx_type == spnt->dbx_type)
2631 {
2632 fpnt->resolved = 'Y';
2633 VMS_Set_Struct (fpnt->struc_numb);
2634 VMS_Store_Struct (spnt->struc_numb);
2635 };
2636 fpnt = fpnt->next;
2637 };
2638 VMS_Set_Struct (spnt->struc_numb);
2639 i = 0;
2640 Local[i++] = 3 + strlen (symbol_name);
2641 Local[i++] = DBG_S_C_ENUM_START;
2642 Local[i++] = 0x20;
2643 Local[i++] = strlen (symbol_name);
2644 pnt2 = symbol_name;
2645 while (*pnt2 != '\0')
2646 Local[i++] = *pnt2++;
2647 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2648 i = 0;
2649 while (*++pnt != ';')
2650 {
2651 pnt1 = (char *) strchr (pnt, ':');
2652 *pnt1++ = '\0';
2653 pnt1 = cvt_integer (pnt1, &i1);
2654 Local[i++] = 7 + strlen (pnt);
2655 Local[i++] = DBG_S_C_ENUM_ITEM;
2656 Local[i++] = 0x00;
2657 pnt2 = (char *) &i1;
2658 for (i2 = 0; i2 < 4; i2++)
2659 Local[i++] = *pnt2++;
2660 Local[i++] = strlen (pnt);
2661 pnt2 = pnt;
2662 while (*pnt != '\0')
2663 Local[i++] = *pnt++;
2664 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2665 i = 0;
2666 pnt = pnt1; /* Skip final semicolon */
2667 };
2668 Local[i++] = 0x01; /* len byte */
2669 Local[i++] = DBG_S_C_ENUM_END;
2670 VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
2671 i = 0;
2672 pnt1 = pnt + 1;
2673 break;
2674 case 'a':
2675 spnt->advanced = ARRAY;
2676 spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
2677 pnt = (char *) strchr (pnt, ';');
2678 if (pnt == (char *) NULL)
2679 return 1;
2680 pnt1 = cvt_integer (pnt + 1, &spnt->index_min);
2681 pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max);
2682 pnt1 = cvt_integer (pnt1 + 1, &spnt->type2);
2683 break;
2684 case 'f':
2685 spnt->advanced = FUNCTION;
2686 spnt->VMS_type = DBG_S_C_FUNCTION_ADDR;
2687 /* this masquerades as a basic type*/
2688 spnt->data_size = 4;
2689 pnt1 = cvt_integer (pnt + 1, &spnt->type2);
2690 break;
2691 case '*':
2692 spnt->advanced = POINTER;
2693 spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
2694 spnt->data_size = 4;
2695 pnt1 = cvt_integer (pnt + 1, &spnt->type2);
2696 pnt = (char *) strchr (str + 1, '=');
2697 if ((pnt != (char *) NULL))
2698 if (VMS_typedef_parse (pnt) == 1)
2699 return 1;
2700 break;
2701 default:
2702 spnt->advanced = UNKNOWN;
2703 spnt->VMS_type = 0;
2704 printf ("gcc-as warning(debugger output):");
2705 printf (" %d is an unknown type of variable.\n", spnt->dbx_type);
2706 return 1; /* unable to decipher */
2707 };
2708 /* this removes the evidence of the definition so that the outer levels of
2709 parsing do not have to worry about it */
2710 pnt = str;
2711 while (*pnt1 != '\0')
2712 *pnt++ = *pnt1++;
2713 *pnt = '\0';
2714 return 0;
2715 }
2716
2717
2718 /*
2719 * This is the root routine that parses the stabs entries for definitions.
2720 * it calls VMS_typedef_parse, which can in turn call itself.
2721 * We need to be careful, since sometimes there are forward references to
2722 * other symbol types, and these cannot be resolved until we have completed
2723 * the parse.
2724 */
2725 static int
2726 VMS_LSYM_Parse ()
2727 {
2728 char *pnt;
2729 char *pnt1;
2730 char *pnt2;
2731 char *str;
2732 char fixit[10];
2733 int incomplete, i, pass, incom1;
2734 struct VMS_DBG_Symbol *spnt;
2735 struct VMS_Symbol *vsp;
2736 struct forward_ref *fpnt;
2737 symbolS *sp;
2738 pass = 0;
2739 incomplete = 0;
2740 do
2741 {
2742 incom1 = incomplete;
2743 incomplete = 0;
2744 for (sp = symbol_rootP; sp; sp = symbol_next (sp))
2745 {
2746 /*
2747 * Deal with STAB symbols
2748 */
2749 if (S_IS_DEBUG (sp))
2750 {
2751 /*
2752 * Dispatch on STAB type
2753 */
2754 switch (S_GET_RAW_TYPE (sp))
2755 {
2756 case N_GSYM:
2757 case N_LCSYM:
2758 case N_STSYM:
2759 case N_PSYM:
2760 case N_RSYM:
2761 case N_LSYM:
2762 case N_FUN: /*sometimes these contain typedefs*/
2763 str = S_GET_NAME (sp);
2764 symbol_name = str;
2765 pnt = (char *) strchr (str, ':');
2766 if (pnt == (char *) NULL)
2767 break;
2768 *pnt = '\0';
2769 pnt1 = pnt + 1;
2770 pnt2 = (char *) strchr (pnt1, '=');
2771 if (pnt2 == (char *) NULL)
2772 {
2773 *pnt = ':'; /* replace colon */
2774 break;
2775 }; /* no symbol here */
2776 incomplete += VMS_typedef_parse (pnt2);
2777 *pnt = ':'; /* put back colon so variable def code finds dbx_type*/
2778 break;
2779 } /*switch*/
2780 } /* if */
2781 } /*for*/
2782 pass++;
2783 } while ((incomplete != 0) && (incomplete != incom1));
2784 /* repeat until all refs resolved if possible */
2785 /* if (pass > 1) printf(" Required %d passes\n",pass);*/
2786 if (incomplete != 0)
2787 {
2788 printf ("gcc-as warning(debugger output):");
2789 printf ("Unable to resolve %d circular references.\n", incomplete);
2790 };
2791 fpnt = f_ref_root;
2792 symbol_name = "\0";
2793 while (fpnt != (struct forward_ref *) NULL)
2794 {
2795 if (fpnt->resolved != 'Y')
2796 {
2797 if (find_symbol (fpnt->dbx_type) !=
2798 (struct VMS_DBG_Symbol *) NULL)
2799 {
2800 printf ("gcc-as warning(debugger output):");
2801 printf ("Forward reference error, dbx type %d\n",
2802 fpnt->dbx_type);
2803 break;
2804 };
2805 fixit[0] = 0;
2806 sprintf (&fixit[1], "%d=s4;", fpnt->dbx_type);
2807 pnt2 = (char *) strchr (&fixit[1], '=');
2808 VMS_typedef_parse (pnt2);
2809 };
2810 fpnt = fpnt->next;
2811 };
2812 }
2813
2814 static
2815 Define_Local_Symbols (s1, s2)
2816 symbolS *s1, *s2;
2817 {
2818 symbolS *symbolP1;
2819 for (symbolP1 = symbol_next (s1); symbolP1 != s2; symbolP1 = symbol_next (symbolP1))
2820 {
2821 if (symbolP1 == (symbolS *) NULL)
2822 return;
2823 if (S_GET_RAW_TYPE (symbolP1) == N_FUN)
2824 {
2825 char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1;
2826 if (*pnt == 'F' || *pnt == 'f') break;
2827 };
2828 /*
2829 * Deal with STAB symbols
2830 */
2831 if (S_IS_DEBUG (symbolP1))
2832 {
2833 /*
2834 * Dispatch on STAB type
2835 */
2836 switch (S_GET_RAW_TYPE (symbolP1))
2837 {
2838 case N_LSYM:
2839 case N_PSYM:
2840 VMS_local_stab_Parse (symbolP1);
2841 break;
2842 case N_RSYM:
2843 VMS_RSYM_Parse (symbolP1, Current_Routine, Text_Psect);
2844 break;
2845 } /*switch*/
2846 } /* if */
2847 } /* for */
2848 }
2849
2850 \f
2851 /* This function crawls the symbol chain searching for local symbols that need
2852 * to be described to the debugger. When we enter a new scope with a "{", it
2853 * creates a new "block", which helps the debugger keep track of which scope
2854 * we are currently in.
2855 */
2856
2857 static symbolS *
2858 Define_Routine (symbolP, Level)
2859 symbolS *symbolP;
2860 int Level;
2861 {
2862 symbolS *sstart;
2863 symbolS *symbolP1;
2864 char str[10];
2865 int rcount = 0;
2866 int Offset;
2867 sstart = symbolP;
2868 for (symbolP1 = symbol_next (symbolP); symbolP1; symbolP1 = symbol_next (symbolP1))
2869 {
2870 if (S_GET_RAW_TYPE (symbolP1) == N_FUN)
2871 {
2872 char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1;
2873 if (*pnt == 'F' || *pnt == 'f') break;
2874 };
2875 /*
2876 * Deal with STAB symbols
2877 */
2878 if (S_IS_DEBUG (symbolP1))
2879 {
2880 /*
2881 * Dispatch on STAB type
2882 */
2883 switch (S_GET_RAW_TYPE (symbolP1))
2884 {
2885 case N_LBRAC:
2886 if (Level != 0)
2887 {
2888 sprintf (str, "$%d", rcount++);
2889 VMS_TBT_Block_Begin (symbolP1, Text_Psect, str);
2890 };
2891 Offset = S_GET_VALUE (symbolP1);
2892 Define_Local_Symbols (sstart, symbolP1);
2893 symbolP1 =
2894 Define_Routine (symbolP1, Level + 1);
2895 if (Level != 0)
2896 VMS_TBT_Block_End (S_GET_VALUE (symbolP1) -
2897 Offset);
2898 sstart = symbolP1;
2899 break;
2900 case N_RBRAC:
2901 return symbolP1;
2902 } /*switch*/
2903 } /* if */
2904 } /* for */
2905 /* we end up here if there were no brackets in this function. Define
2906 everything */
2907 Define_Local_Symbols (sstart, (symbolS *) 0);
2908 return symbolP1;
2909 }
2910 \f
2911
2912 static
2913 VMS_DBG_Define_Routine (symbolP, Curr_Routine, Txt_Psect)
2914 symbolS *symbolP;
2915 symbolS *Curr_Routine;
2916 int Txt_Psect;
2917 {
2918 Current_Routine = Curr_Routine;
2919 Text_Psect = Txt_Psect;
2920 Define_Routine (symbolP, 0);
2921 }
2922 \f
2923
2924
2925
2926 #ifndef HO_VMS
2927 #include <sys/types.h>
2928 #include <time.h>
2929
2930 /* Manufacure a VMS like time on a unix based system. */
2931 get_VMS_time_on_unix (char *Now)
2932 {
2933 char *pnt;
2934 time_t timeb;
2935 time (&timeb);
2936 pnt = ctime (&timeb);
2937 pnt[3] = 0;
2938 pnt[7] = 0;
2939 pnt[10] = 0;
2940 pnt[16] = 0;
2941 pnt[24] = 0;
2942 sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11);
2943 }
2944
2945 #endif /* not HO_VMS */
2946 /*
2947 * Write the MHD (Module Header) records
2948 */
2949 static
2950 Write_VMS_MHD_Records ()
2951 {
2952 register char *cp, *cp1;
2953 register int i;
2954 struct
2955 {
2956 int Size;
2957 char *Ptr;
2958 } Descriptor;
2959 char Module_Name[256];
2960 char Now[18];
2961
2962 /*
2963 * We are writing a module header record
2964 */
2965 Set_VMS_Object_File_Record (OBJ_S_C_HDR);
2966 /*
2967 * ***************************
2968 * *MAIN MODULE HEADER RECORD*
2969 * ***************************
2970 *
2971 * Store record type and header type
2972 */
2973 PUT_CHAR (OBJ_S_C_HDR);
2974 PUT_CHAR (MHD_S_C_MHD);
2975 /*
2976 * Structure level is 0
2977 */
2978 PUT_CHAR (OBJ_S_C_STRLVL);
2979 /*
2980 * Maximum record size is size of the object record buffer
2981 */
2982 PUT_SHORT (sizeof (Object_Record_Buffer));
2983 /*
2984 * Get module name (the FILENAME part of the object file)
2985 */
2986 cp = out_file_name;
2987 cp1 = Module_Name;
2988 while (*cp)
2989 {
2990 if ((*cp == ']') || (*cp == '>') ||
2991 (*cp == ':') || (*cp == '/'))
2992 {
2993 cp1 = Module_Name;
2994 cp++;
2995 continue;
2996 }
2997 *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++;
2998 }
2999 *cp1 = 0;
3000 /*
3001 * Limit it to 31 characters and store in the object record
3002 */
3003 while (--cp1 >= Module_Name)
3004 if (*cp1 == '.')
3005 *cp1 = 0;
3006 if (strlen (Module_Name) > 31)
3007 {
3008 if (flagseen['+'])
3009 printf ("%s: Module name truncated: %s\n", myname, Module_Name);
3010 Module_Name[31] = 0;
3011 }
3012 PUT_COUNTED_STRING (Module_Name);
3013 /*
3014 * Module Version is "V1.0"
3015 */
3016 PUT_COUNTED_STRING ("V1.0");
3017 /*
3018 * Creation time is "now" (17 chars of time string)
3019 */
3020 #ifndef HO_VMS
3021 get_VMS_time_on_unix (&Now[0]);
3022 #else /* HO_VMS */
3023 Descriptor.Size = 17;
3024 Descriptor.Ptr = Now;
3025 sys$asctim (0, &Descriptor, 0, 0);
3026 #endif /* HO_VMS */
3027 for (i = 0; i < 17; i++)
3028 PUT_CHAR (Now[i]);
3029 /*
3030 * Patch time is "never" (17 zeros)
3031 */
3032 for (i = 0; i < 17; i++)
3033 PUT_CHAR (0);
3034 /*
3035 * Flush the record
3036 */
3037 Flush_VMS_Object_Record_Buffer ();
3038 /*
3039 * *************************
3040 * *LANGUAGE PROCESSOR NAME*
3041 * *************************
3042 *
3043 * Store record type and header type
3044 */
3045 PUT_CHAR (OBJ_S_C_HDR);
3046 PUT_CHAR (MHD_S_C_LNM);
3047 /*
3048 * Store language processor name and version
3049 * (not a counted string!)
3050 */
3051 cp = compiler_version_string;
3052 if (cp == 0)
3053 {
3054 cp = "GNU AS V";
3055 while (*cp)
3056 PUT_CHAR (*cp++);
3057 cp = strchr (&version_string, '.');
3058 while (*cp != ' ')
3059 cp--;
3060 cp++;
3061 };
3062 while (*cp >= 32)
3063 PUT_CHAR (*cp++);
3064 /*
3065 * Flush the record
3066 */
3067 Flush_VMS_Object_Record_Buffer ();
3068 }
3069 \f
3070
3071 /*
3072 * Write the EOM (End Of Module) record
3073 */
3074 static
3075 Write_VMS_EOM_Record (Psect, Offset)
3076 int Psect;
3077 int Offset;
3078 {
3079 /*
3080 * We are writing an end-of-module record
3081 */
3082 Set_VMS_Object_File_Record (OBJ_S_C_EOM);
3083 /*
3084 * Store record Type
3085 */
3086 PUT_CHAR (OBJ_S_C_EOM);
3087 /*
3088 * Store the error severity (0)
3089 */
3090 PUT_CHAR (0);
3091 /*
3092 * Store the entry point, if it exists
3093 */
3094 if (Psect >= 0)
3095 {
3096 /*
3097 * Store the entry point Psect
3098 */
3099 PUT_CHAR (Psect);
3100 /*
3101 * Store the entry point Psect offset
3102 */
3103 PUT_LONG (Offset);
3104 }
3105 /*
3106 * Flush the record
3107 */
3108 Flush_VMS_Object_Record_Buffer ();
3109 }
3110 \f
3111
3112 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
3113
3114 static int
3115 hash_string (ptr)
3116 unsigned char *ptr;
3117 {
3118 register unsigned char *p = ptr;
3119 register unsigned char *end = p + strlen (ptr);
3120 register unsigned char c;
3121 register int hash = 0;
3122
3123 while (p != end)
3124 {
3125 c = *p++;
3126 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
3127 }
3128 return hash;
3129 }
3130
3131 /*
3132 * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
3133 */
3134 static
3135 VMS_Case_Hack_Symbol (In, Out)
3136 register char *In;
3137 register char *Out;
3138 {
3139 long int init = 0;
3140 long int result;
3141 char *pnt;
3142 char *new_name;
3143 char *old_name;
3144 register int i;
3145 int destructor = 0; /*hack to allow for case sens in a destructor*/
3146 int truncate = 0;
3147 int Case_Hack_Bits = 0;
3148 int Saw_Dollar = 0;
3149 static char Hex_Table[16] =
3150 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
3151
3152 /*
3153 * Kill any leading "_"
3154 */
3155 if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0')))
3156 In++;
3157
3158 new_name = Out; /* save this for later*/
3159
3160 #if barfoo /* Dead code */
3161 if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_'))
3162 destructor = 1;
3163 #endif
3164
3165 /* We may need to truncate the symbol, save the hash for later*/
3166 if (strlen (In) > 23)
3167 result = hash_string (In);
3168 /*
3169 * Is there a Psect Attribute to skip??
3170 */
3171 if (HAS_PSECT_ATTRIBUTES (In))
3172 {
3173 /*
3174 * Yes: Skip it
3175 */
3176 In += PSECT_ATTRIBUTES_STRING_LENGTH;
3177 while (*In)
3178 {
3179 if ((In[0] == '$') && (In[1] == '$'))
3180 {
3181 In += 2;
3182 break;
3183 }
3184 In++;
3185 }
3186 }
3187
3188 old_name = In;
3189 /* if (strlen(In) > 31 && flagseen['+'])
3190 printf("%s: Symbol name truncated: %s\n",myname,In);*/
3191 /*
3192 * Do the case conversion
3193 */
3194 i = 23; /* Maximum of 23 chars */
3195 while (*In && (--i >= 0))
3196 {
3197 Case_Hack_Bits <<= 1;
3198 if (*In == '$')
3199 Saw_Dollar = 1;
3200 if ((destructor == 1) && (i == 21))
3201 Saw_Dollar = 0;
3202 switch (vms_name_mapping)
3203 {
3204 case 0:
3205 if (isupper(*In)) {
3206 *Out++ = *In++;
3207 Case_Hack_Bits |= 1;
3208 } else {
3209 *Out++ = islower(*In) ? toupper(*In++) : *In++;
3210 }
3211 break;
3212 case 3: *Out++ = *In++;
3213 break;
3214 case 2:
3215 if (islower(*In)) {
3216 *Out++ = *In++;
3217 } else {
3218 *Out++ = isupper(*In) ? tolower(*In++) : *In++;
3219 }
3220 break;
3221 };
3222 }
3223 /*
3224 * If we saw a dollar sign, we don't do case hacking
3225 */
3226 if (flagseen['h'] || Saw_Dollar)
3227 Case_Hack_Bits = 0;
3228
3229 /*
3230 * If we have more than 23 characters and everything is lowercase
3231 * we can insert the full 31 characters
3232 */
3233 if (*In)
3234 {
3235 /*
3236 * We have more than 23 characters
3237 * If we must add the case hack, then we have truncated the str
3238 */
3239 pnt = Out;
3240 truncate = 1;
3241 if (Case_Hack_Bits == 0)
3242 {
3243 /*
3244 * And so far they are all lower case:
3245 * Check up to 8 more characters
3246 * and ensure that they are lowercase
3247 */
3248 for (i = 0; (In[i] != 0) && (i < 8); i++)
3249 if (isupper(In[i]) && !Saw_Dollar && !flagseen['h'])
3250 break;
3251
3252 if (In[i] == 0)
3253 truncate = 0;
3254
3255 if ((i == 8) || (In[i] == 0))
3256 {
3257 /*
3258 * They are: Copy up to 31 characters
3259 * to the output string
3260 */
3261 i = 8;
3262 while ((--i >= 0) && (*In))
3263 switch (vms_name_mapping){
3264 case 0: *Out++ = islower(*In) ?
3265 toupper (*In++) :
3266 *In++;
3267 break;
3268 case 3: *Out++ = *In++;
3269 break;
3270 case 2: *Out++ = isupper(*In) ?
3271 tolower(*In++) :
3272 *In++;
3273 break;
3274 };
3275 }
3276 }
3277 }
3278 /*
3279 * If there were any uppercase characters in the name we
3280 * take on the case hacking string
3281 */
3282
3283 /* Old behavior for regular GNU-C compiler */
3284 if (!flagseen['+'])
3285 truncate = 0;
3286 if ((Case_Hack_Bits != 0) || (truncate == 1))
3287 {
3288 if (truncate == 0)
3289 {
3290 *Out++ = '_';
3291 for (i = 0; i < 6; i++)
3292 {
3293 *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
3294 Case_Hack_Bits >>= 4;
3295 }
3296 *Out++ = 'X';
3297 }
3298 else
3299 {
3300 Out = pnt; /*Cut back to 23 characters maximum */
3301 *Out++ = '_';
3302 for (i = 0; i < 7; i++)
3303 {
3304 init = result & 0x01f;
3305 if (init < 10)
3306 *Out++ = '0' + init;
3307 else
3308 *Out++ = 'A' + init - 10;
3309 result = result >> 5;
3310 }
3311 }
3312 } /*Case Hack */
3313 /*
3314 * Done
3315 */
3316 *Out = 0;
3317 if (truncate == 1 && flagseen['+'] && flagseen['H'])
3318 printf ("%s: Symbol %s replaced by %s\n", myname, old_name, new_name);
3319 }
3320 \f
3321
3322 /*
3323 * Scan a symbol name for a psect attribute specification
3324 */
3325 #define GLOBALSYMBOL_BIT 0x10000
3326 #define GLOBALVALUE_BIT 0x20000
3327
3328
3329 static
3330 VMS_Modify_Psect_Attributes (Name, Attribute_Pointer)
3331 char *Name;
3332 int *Attribute_Pointer;
3333 {
3334 register int i;
3335 register char *cp;
3336 int Negate;
3337 static struct
3338 {
3339 char *Name;
3340 int Value;
3341 } Attributes[] =
3342 {
3343 {"PIC", GPS_S_M_PIC},
3344 {"LIB", GPS_S_M_LIB},
3345 {"OVR", GPS_S_M_OVR},
3346 {"REL", GPS_S_M_REL},
3347 {"GBL", GPS_S_M_GBL},
3348 {"SHR", GPS_S_M_SHR},
3349 {"EXE", GPS_S_M_EXE},
3350 {"RD", GPS_S_M_RD},
3351 {"WRT", GPS_S_M_WRT},
3352 {"VEC", GPS_S_M_VEC},
3353 {"GLOBALSYMBOL", GLOBALSYMBOL_BIT},
3354 {"GLOBALVALUE", GLOBALVALUE_BIT},
3355 {0, 0}
3356 };
3357
3358 /*
3359 * Kill leading "_"
3360 */
3361 if (*Name == '_')
3362 Name++;
3363 /*
3364 * Check for a PSECT attribute list
3365 */
3366 if (!HAS_PSECT_ATTRIBUTES (Name))
3367 return; /* If not, return */
3368 /*
3369 * Skip the attribute list indicator
3370 */
3371 Name += PSECT_ATTRIBUTES_STRING_LENGTH;
3372 /*
3373 * Process the attributes ("_" separated, "$" terminated)
3374 */
3375 while (*Name != '$')
3376 {
3377 /*
3378 * Assume not negating
3379 */
3380 Negate = 0;
3381 /*
3382 * Check for "NO"
3383 */
3384 if ((Name[0] == 'N') && (Name[1] == 'O'))
3385 {
3386 /*
3387 * We are negating (and skip the NO)
3388 */
3389 Negate = 1;
3390 Name += 2;
3391 }
3392 /*
3393 * Find the token delimiter
3394 */
3395 cp = Name;
3396 while (*cp && (*cp != '_') && (*cp != '$'))
3397 cp++;
3398 /*
3399 * Look for the token in the attribute list
3400 */
3401 for (i = 0; Attributes[i].Name; i++)
3402 {
3403 /*
3404 * If the strings match, set/clear the attr.
3405 */
3406 if (strncmp (Name, Attributes[i].Name, cp - Name) == 0)
3407 {
3408 /*
3409 * Set or clear
3410 */
3411 if (Negate)
3412 *Attribute_Pointer &=
3413 ~Attributes[i].Value;
3414 else
3415 *Attribute_Pointer |=
3416 Attributes[i].Value;
3417 /*
3418 * Done
3419 */
3420 break;
3421 }
3422 }
3423 /*
3424 * Now skip the attribute
3425 */
3426 Name = cp;
3427 if (*Name == '_')
3428 Name++;
3429 }
3430 /*
3431 * Done
3432 */
3433 return;
3434 }
3435 \f
3436
3437 /*
3438 * Define a global symbol
3439 */
3440 static
3441 VMS_Global_Symbol_Spec (Name, Psect_Number, Psect_Offset, Defined)
3442 char *Name;
3443 int Psect_Number;
3444 int Psect_Offset;
3445 {
3446 char Local[32];
3447
3448 /*
3449 * We are writing a GSD record
3450 */
3451 Set_VMS_Object_File_Record (OBJ_S_C_GSD);
3452 /*
3453 * If the buffer is empty we must insert the GSD record type
3454 */
3455 if (Object_Record_Offset == 0)
3456 PUT_CHAR (OBJ_S_C_GSD);
3457 /*
3458 * We are writing a Global symbol definition subrecord
3459 */
3460 if (Psect_Number <= 255)
3461 {
3462 PUT_CHAR (GSD_S_C_SYM);
3463 }
3464 else
3465 {
3466 PUT_CHAR (GSD_S_C_SYMW);
3467 }
3468 /*
3469 * Data type is undefined
3470 */
3471 PUT_CHAR (0);
3472 /*
3473 * Switch on Definition/Reference
3474 */
3475 if ((Defined & 1) != 0)
3476 {
3477 /*
3478 * Definition:
3479 * Flags = "RELOCATABLE" and "DEFINED" for regular symbol
3480 * = "DEFINED" for globalvalue (Defined & 2 == 1)
3481 */
3482 if ((Defined & 2) == 0)
3483 {
3484 PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
3485 }
3486 else
3487 {
3488 PUT_SHORT (GSY_S_M_DEF);
3489 };
3490 /*
3491 * Psect Number
3492 */
3493 if (Psect_Number <= 255)
3494 {
3495 PUT_CHAR (Psect_Number);
3496 }
3497 else
3498 {
3499 PUT_SHORT (Psect_Number);
3500 }
3501 /*
3502 * Offset
3503 */
3504 PUT_LONG (Psect_Offset);
3505 }
3506 else
3507 {
3508 /*
3509 * Reference:
3510 * Flags = "RELOCATABLE" for regular symbol,
3511 * = "" for globalvalue (Defined & 2 == 1)
3512 */
3513 if ((Defined & 2) == 0)
3514 {
3515 PUT_SHORT (GSY_S_M_REL);
3516 }
3517 else
3518 {
3519 PUT_SHORT (0);
3520 };
3521 }
3522 /*
3523 * Finally, the global symbol name
3524 */
3525 VMS_Case_Hack_Symbol (Name, Local);
3526 PUT_COUNTED_STRING (Local);
3527 /*
3528 * Flush the buffer if it is more than 75% full
3529 */
3530 if (Object_Record_Offset >
3531 (sizeof (Object_Record_Buffer) * 3 / 4))
3532 Flush_VMS_Object_Record_Buffer ();
3533 }
3534 \f
3535
3536 /*
3537 * Define a psect
3538 */
3539 static int
3540 VMS_Psect_Spec (Name, Size, Type, vsp)
3541 char *Name;
3542 int Size;
3543 char *Type;
3544 struct VMS_Symbol *vsp;
3545 {
3546 char Local[32];
3547 int Psect_Attributes;
3548
3549 /*
3550 * Generate the appropriate PSECT flags given the PSECT type
3551 */
3552 if (strcmp (Type, "COMMON") == 0)
3553 {
3554 /*
3555 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
3556 */
3557 Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL |
3558 GPS_S_M_SHR | GPS_S_M_RD | GPS_S_M_WRT);
3559 }
3560 else if (strcmp (Type, "CONST") == 0)
3561 {
3562 /*
3563 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD
3564 */
3565 Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL |
3566 GPS_S_M_SHR | GPS_S_M_RD);
3567 }
3568 else if (strcmp (Type, "DATA") == 0)
3569 {
3570 /*
3571 * The Data psects are PIC,REL,RD,WRT
3572 */
3573 Psect_Attributes =
3574 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT);
3575 }
3576 else if (strcmp (Type, "TEXT") == 0)
3577 {
3578 /*
3579 * The Text psects are PIC,REL,SHR,EXE,RD
3580 */
3581 Psect_Attributes =
3582 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR |
3583 GPS_S_M_EXE | GPS_S_M_RD);
3584 }
3585 else
3586 {
3587 /*
3588 * Error: Unknown psect type
3589 */
3590 error ("Unknown VMS psect type");
3591 }
3592 /*
3593 * Modify the psect attributes according to any attribute string
3594 */
3595 if (HAS_PSECT_ATTRIBUTES (Name))
3596 VMS_Modify_Psect_Attributes (Name, &Psect_Attributes);
3597 /*
3598 * Check for globalref/def/val.
3599 */
3600 if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
3601 {
3602 /*
3603 * globalvalue symbols were generated before. This code
3604 * prevents unsightly psect buildup, and makes sure that
3605 * fixup references are emitted correctly.
3606 */
3607 vsp->Psect_Index = -1; /* to catch errors */
3608 S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF; /* make refs work */
3609 return 1; /* decrement psect counter */
3610 };
3611
3612 if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0)
3613 {
3614 switch (S_GET_RAW_TYPE (vsp->Symbol))
3615 {
3616 case N_UNDF | N_EXT:
3617 VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
3618 vsp->Psect_Offset, 0);
3619 vsp->Psect_Index = -1;
3620 S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF;
3621 return 1; /* return and indicate no psect */
3622 case N_DATA | N_EXT:
3623 VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
3624 vsp->Psect_Offset, 1);
3625 /* In this case we still generate the psect */
3626 break;
3627 default:
3628 {
3629 char Error_Line[256];
3630 sprintf (Error_Line, "Globalsymbol attribute for"
3631 " symbol %s was unexpected.\n", Name);
3632 error (Error_Line);
3633 break;
3634 };
3635 }; /* switch */
3636 };
3637
3638 Psect_Attributes &= 0xffff; /* clear out the globalref/def stuff */
3639 /*
3640 * We are writing a GSD record
3641 */
3642 Set_VMS_Object_File_Record (OBJ_S_C_GSD);
3643 /*
3644 * If the buffer is empty we must insert the GSD record type
3645 */
3646 if (Object_Record_Offset == 0)
3647 PUT_CHAR (OBJ_S_C_GSD);
3648 /*
3649 * We are writing a PSECT definition subrecord
3650 */
3651 PUT_CHAR (GSD_S_C_PSC);
3652 /*
3653 * Psects are always LONGWORD aligned
3654 */
3655 PUT_CHAR (2);
3656 /*
3657 * Specify the psect attributes
3658 */
3659 PUT_SHORT (Psect_Attributes);
3660 /*
3661 * Specify the allocation
3662 */
3663 PUT_LONG (Size);
3664 /*
3665 * Finally, the psect name
3666 */
3667 VMS_Case_Hack_Symbol (Name, Local);
3668 PUT_COUNTED_STRING (Local);
3669 /*
3670 * Flush the buffer if it is more than 75% full
3671 */
3672 if (Object_Record_Offset >
3673 (sizeof (Object_Record_Buffer) * 3 / 4))
3674 Flush_VMS_Object_Record_Buffer ();
3675 return 0;
3676 }
3677 \f
3678
3679 /*
3680 * Given the pointer to a symbol we calculate how big the data at the
3681 * symbol is. We do this by looking for the next symbol (local or
3682 * global) which will indicate the start of another datum.
3683 */
3684 static int
3685 VMS_Initialized_Data_Size (sp, End_Of_Data)
3686 register struct symbol *sp;
3687 int End_Of_Data;
3688 {
3689 register struct symbol *sp1, *Next_Symbol;
3690
3691 /*
3692 * Find the next symbol
3693 * it delimits this datum
3694 */
3695 Next_Symbol = 0;
3696 for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
3697 {
3698 /*
3699 * The data type must match
3700 */
3701 if (S_GET_TYPE (sp1) != N_DATA)
3702 continue;
3703 /*
3704 * The symbol must be AFTER this symbol
3705 */
3706 if (S_GET_VALUE (sp1) <= S_GET_VALUE (sp))
3707 continue;
3708 /*
3709 * We ignore THIS symbol
3710 */
3711 if (sp1 == sp)
3712 continue;
3713 /*
3714 * If there is already a candidate selected for the
3715 * next symbol, see if we are a better candidate
3716 */
3717 if (Next_Symbol)
3718 {
3719 /*
3720 * We are a better candidate if we are "closer"
3721 * to the symbol
3722 */
3723 if (S_GET_VALUE (sp1) >
3724 S_GET_VALUE (Next_Symbol))
3725 continue;
3726 /*
3727 * Win: Make this the candidate
3728 */
3729 Next_Symbol = sp1;
3730 }
3731 else
3732 {
3733 /*
3734 * This is the 1st candidate
3735 */
3736 Next_Symbol = sp1;
3737 }
3738 }
3739 /*
3740 * Calculate its size
3741 */
3742 return (Next_Symbol ?
3743 (S_GET_VALUE (Next_Symbol) -
3744 S_GET_VALUE (sp)) :
3745 (End_Of_Data - S_GET_VALUE (sp)));
3746 }
3747 \f
3748 /*
3749 * Check symbol names for the Psect hack with a globalvalue, and then
3750 * generate globalvalues for those that have it.
3751 */
3752 static
3753 VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment)
3754 unsigned text_siz;
3755 unsigned data_siz;
3756 char *Data_Segment;
3757 {
3758 register symbolS *sp;
3759 char *stripped_name, *Name;
3760 int Size;
3761 int Psect_Attributes;
3762 int globalvalue;
3763
3764 /*
3765 * Scan the symbol table for globalvalues, and emit def/ref when
3766 * required. These will be caught again later and converted to
3767 * N_UNDF
3768 */
3769 for (sp = symbol_rootP; sp; sp = sp->sy_next)
3770 {
3771 /*
3772 * See if this is something we want to look at.
3773 */
3774 if ((S_GET_RAW_TYPE (sp) != (N_DATA | N_EXT)) &&
3775 (S_GET_RAW_TYPE (sp) != (N_UNDF | N_EXT)))
3776 continue;
3777 /*
3778 * See if this has globalvalue specification.
3779 */
3780 Name = S_GET_NAME (sp);
3781
3782 if (!HAS_PSECT_ATTRIBUTES (Name))
3783 continue;
3784
3785 stripped_name = (char *) malloc (strlen (Name) + 1);
3786 strcpy (stripped_name, Name);
3787 Psect_Attributes = 0;
3788 VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes);
3789
3790 if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
3791 {
3792 switch (S_GET_RAW_TYPE (sp))
3793 {
3794 case N_UNDF | N_EXT:
3795 VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2);
3796 break;
3797 case N_DATA | N_EXT:
3798 Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
3799 if (Size > 4)
3800 error ("Invalid data type for globalvalue");
3801 globalvalue = 0;
3802
3803 memcpy (&globalvalue, Data_Segment + S_GET_VALUE (sp) -
3804 text_siz, Size);
3805 /* Three times for good luck. The linker seems to get confused
3806 if there are fewer than three */
3807 VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2);
3808 VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3);
3809 VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3);
3810 break;
3811 default:
3812 printf (" Invalid globalvalue of %s\n", stripped_name);
3813 break;
3814 }; /* switch */
3815 }; /* if */
3816 free (stripped_name); /* clean up */
3817 }; /* for */
3818
3819 }
3820 \f
3821
3822 /*
3823 * Define a procedure entry pt/mask
3824 */
3825 static
3826 VMS_Procedure_Entry_Pt (Name, Psect_Number, Psect_Offset, Entry_Mask)
3827 char *Name;
3828 int Psect_Number;
3829 int Psect_Offset;
3830 int Entry_Mask;
3831 {
3832 char Local[32];
3833
3834 /*
3835 * We are writing a GSD record
3836 */
3837 Set_VMS_Object_File_Record (OBJ_S_C_GSD);
3838 /*
3839 * If the buffer is empty we must insert the GSD record type
3840 */
3841 if (Object_Record_Offset == 0)
3842 PUT_CHAR (OBJ_S_C_GSD);
3843 /*
3844 * We are writing a Procedure Entry Pt/Mask subrecord
3845 */
3846 if (Psect_Number <= 255)
3847 {
3848 PUT_CHAR (GSD_S_C_EPM);
3849 }
3850 else
3851 {
3852 PUT_CHAR (GSD_S_C_EPMW);
3853 }
3854 /*
3855 * Data type is undefined
3856 */
3857 PUT_CHAR (0);
3858 /*
3859 * Flags = "RELOCATABLE" and "DEFINED"
3860 */
3861 PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
3862 /*
3863 * Psect Number
3864 */
3865 if (Psect_Number <= 255)
3866 {
3867 PUT_CHAR (Psect_Number);
3868 }
3869 else
3870 {
3871 PUT_SHORT (Psect_Number);
3872 }
3873 /*
3874 * Offset
3875 */
3876 PUT_LONG (Psect_Offset);
3877 /*
3878 * Entry mask
3879 */
3880 PUT_SHORT (Entry_Mask);
3881 /*
3882 * Finally, the global symbol name
3883 */
3884 VMS_Case_Hack_Symbol (Name, Local);
3885 PUT_COUNTED_STRING (Local);
3886 /*
3887 * Flush the buffer if it is more than 75% full
3888 */
3889 if (Object_Record_Offset >
3890 (sizeof (Object_Record_Buffer) * 3 / 4))
3891 Flush_VMS_Object_Record_Buffer ();
3892 }
3893 \f
3894
3895 /*
3896 * Set the current location counter to a particular Psect and Offset
3897 */
3898 static
3899 VMS_Set_Psect (Psect_Index, Offset, Record_Type)
3900 int Psect_Index;
3901 int Offset;
3902 int Record_Type;
3903 {
3904 /*
3905 * We are writing a "Record_Type" record
3906 */
3907 Set_VMS_Object_File_Record (Record_Type);
3908 /*
3909 * If the buffer is empty we must insert the record type
3910 */
3911 if (Object_Record_Offset == 0)
3912 PUT_CHAR (Record_Type);
3913 /*
3914 * Stack the Psect base + Longword Offset
3915 */
3916 if (Psect_Index < 255)
3917 {
3918 PUT_CHAR (TIR_S_C_STA_PL);
3919 PUT_CHAR (Psect_Index);
3920 }
3921 else
3922 {
3923 PUT_CHAR (TIR_S_C_STA_WPL);
3924 PUT_SHORT (Psect_Index);
3925 }
3926 PUT_LONG (Offset);
3927 /*
3928 * Set relocation base
3929 */
3930 PUT_CHAR (TIR_S_C_CTL_SETRB);
3931 /*
3932 * Flush the buffer if it is more than 75% full
3933 */
3934 if (Object_Record_Offset >
3935 (sizeof (Object_Record_Buffer) * 3 / 4))
3936 Flush_VMS_Object_Record_Buffer ();
3937 }
3938 \f
3939
3940 /*
3941 * Store repeated immediate data in current Psect
3942 */
3943 static
3944 VMS_Store_Repeated_Data (Repeat_Count, Pointer, Size, Record_Type)
3945 int Repeat_Count;
3946 register char *Pointer;
3947 int Size;
3948 int Record_Type;
3949 {
3950
3951 /*
3952 * Ignore zero bytes/words/longwords
3953 */
3954 if ((Size == sizeof (char)) && (*Pointer == 0))
3955 return;
3956 if ((Size == sizeof (short)) && (*(short *) Pointer == 0))
3957 return;
3958 if ((Size == sizeof (long)) && (*(long *) Pointer == 0))
3959 return;
3960 /*
3961 * If the data is too big for a TIR_S_C_STO_RIVB sub-record
3962 * then we do it manually
3963 */
3964 if (Size > 255)
3965 {
3966 while (--Repeat_Count >= 0)
3967 VMS_Store_Immediate_Data (Pointer, Size, Record_Type);
3968 return;
3969 }
3970 /*
3971 * We are writing a "Record_Type" record
3972 */
3973 Set_VMS_Object_File_Record (Record_Type);
3974 /*
3975 * If the buffer is empty we must insert record type
3976 */
3977 if (Object_Record_Offset == 0)
3978 PUT_CHAR (Record_Type);
3979 /*
3980 * Stack the repeat count
3981 */
3982 PUT_CHAR (TIR_S_C_STA_LW);
3983 PUT_LONG (Repeat_Count);
3984 /*
3985 * And now the command and its data
3986 */
3987 PUT_CHAR (TIR_S_C_STO_RIVB);
3988 PUT_CHAR (Size);
3989 while (--Size >= 0)
3990 PUT_CHAR (*Pointer++);
3991 /*
3992 * Flush the buffer if it is more than 75% full
3993 */
3994 if (Object_Record_Offset >
3995 (sizeof (Object_Record_Buffer) * 3 / 4))
3996 Flush_VMS_Object_Record_Buffer ();
3997 }
3998 \f
3999
4000 /*
4001 * Store a Position Independent Reference
4002 */
4003 static
4004 VMS_Store_PIC_Symbol_Reference (Symbol, Offset, PC_Relative,
4005 Psect, Psect_Offset, Record_Type)
4006 struct symbol *Symbol;
4007 int Offset;
4008 int PC_Relative;
4009 int Psect;
4010 int Psect_Offset;
4011 int Record_Type;
4012 {
4013 register struct VMS_Symbol *vsp =
4014 (struct VMS_Symbol *) (Symbol->sy_number);
4015 char Local[32];
4016
4017 /*
4018 * We are writing a "Record_Type" record
4019 */
4020 Set_VMS_Object_File_Record (Record_Type);
4021 /*
4022 * If the buffer is empty we must insert record type
4023 */
4024 if (Object_Record_Offset == 0)
4025 PUT_CHAR (Record_Type);
4026 /*
4027 * Set to the appropriate offset in the Psect
4028 */
4029 if (PC_Relative)
4030 {
4031 /*
4032 * For a Code reference we need to fix the operand
4033 * specifier as well (so back up 1 byte)
4034 */
4035 VMS_Set_Psect (Psect, Psect_Offset - 1, Record_Type);
4036 }
4037 else
4038 {
4039 /*
4040 * For a Data reference we just store HERE
4041 */
4042 VMS_Set_Psect (Psect, Psect_Offset, Record_Type);
4043 }
4044 /*
4045 * Make sure we are still generating a "Record Type" record
4046 */
4047 if (Object_Record_Offset == 0)
4048 PUT_CHAR (Record_Type);
4049 /*
4050 * Dispatch on symbol type (so we can stack its value)
4051 */
4052 switch (S_GET_RAW_TYPE (Symbol))
4053 {
4054 /*
4055 * Global symbol
4056 */
4057 #ifdef NOT_VAX_11_C_COMPATIBLE
4058 case N_UNDF | N_EXT:
4059 case N_DATA | N_EXT:
4060 #endif /* NOT_VAX_11_C_COMPATIBLE */
4061 case N_UNDF:
4062 case N_TEXT | N_EXT:
4063 /*
4064 * Get the symbol name (case hacked)
4065 */
4066 VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local);
4067 /*
4068 * Stack the global symbol value
4069 */
4070 PUT_CHAR (TIR_S_C_STA_GBL);
4071 PUT_COUNTED_STRING (Local);
4072 if (Offset)
4073 {
4074 /*
4075 * Stack the longword offset
4076 */
4077 PUT_CHAR (TIR_S_C_STA_LW);
4078 PUT_LONG (Offset);
4079 /*
4080 * Add the two, leaving the result on the stack
4081 */
4082 PUT_CHAR (TIR_S_C_OPR_ADD);
4083 }
4084 break;
4085 /*
4086 * Uninitialized local data
4087 */
4088 case N_BSS:
4089 /*
4090 * Stack the Psect (+offset)
4091 */
4092 if (vsp->Psect_Index < 255)
4093 {
4094 PUT_CHAR (TIR_S_C_STA_PL);
4095 PUT_CHAR (vsp->Psect_Index);
4096 }
4097 else
4098 {
4099 PUT_CHAR (TIR_S_C_STA_WPL);
4100 PUT_SHORT (vsp->Psect_Index);
4101 }
4102 PUT_LONG (vsp->Psect_Offset + Offset);
4103 break;
4104 /*
4105 * Local text
4106 */
4107 case N_TEXT:
4108 /*
4109 * Stack the Psect (+offset)
4110 */
4111 if (vsp->Psect_Index < 255)
4112 {
4113 PUT_CHAR (TIR_S_C_STA_PL);
4114 PUT_CHAR (vsp->Psect_Index);
4115 }
4116 else
4117 {
4118 PUT_CHAR (TIR_S_C_STA_WPL);
4119 PUT_SHORT (vsp->Psect_Index);
4120 }
4121 PUT_LONG (S_GET_VALUE (Symbol) + Offset);
4122 break;
4123 /*
4124 * Initialized local or global data
4125 */
4126 case N_DATA:
4127 #ifndef NOT_VAX_11_C_COMPATIBLE
4128 case N_UNDF | N_EXT:
4129 case N_DATA | N_EXT:
4130 #endif /* NOT_VAX_11_C_COMPATIBLE */
4131 /*
4132 * Stack the Psect (+offset)
4133 */
4134 if (vsp->Psect_Index < 255)
4135 {
4136 PUT_CHAR (TIR_S_C_STA_PL);
4137 PUT_CHAR (vsp->Psect_Index);
4138 }
4139 else
4140 {
4141 PUT_CHAR (TIR_S_C_STA_WPL);
4142 PUT_SHORT (vsp->Psect_Index);
4143 }
4144 PUT_LONG (vsp->Psect_Offset + Offset);
4145 break;
4146 }
4147 /*
4148 * Store either a code or data reference
4149 */
4150 PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR);
4151 /*
4152 * Flush the buffer if it is more than 75% full
4153 */
4154 if (Object_Record_Offset >
4155 (sizeof (Object_Record_Buffer) * 3 / 4))
4156 Flush_VMS_Object_Record_Buffer ();
4157 }
4158 \f
4159
4160 /*
4161 * Check in the text area for an indirect pc-relative reference
4162 * and fix it up with addressing mode 0xff [PC indirect]
4163 *
4164 * THIS SHOULD BE REPLACED BY THE USE OF TIR_S_C_STO_PIRR IN THE
4165 * PIC CODE GENERATING FIXUP ROUTINE.
4166 */
4167 static
4168 VMS_Fix_Indirect_Reference (Text_Psect, Offset, fragP, text_frag_root)
4169 int Text_Psect;
4170 int Offset;
4171 register fragS *fragP;
4172 struct frag *text_frag_root;
4173 {
4174 /*
4175 * The addressing mode byte is 1 byte before the address
4176 */
4177 Offset--;
4178 /*
4179 * Is it in THIS frag??
4180 */
4181 if ((Offset < fragP->fr_address) ||
4182 (Offset >= (fragP->fr_address + fragP->fr_fix)))
4183 {
4184 /*
4185 * We need to search for the fragment containing this
4186 * Offset
4187 */
4188 for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
4189 {
4190 if ((Offset >= fragP->fr_address) &&
4191 (Offset < (fragP->fr_address + fragP->fr_fix)))
4192 break;
4193 }
4194 /*
4195 * If we couldn't find the frag, things are BAD!!
4196 */
4197 if (fragP == 0)
4198 error ("Couldn't find fixup fragment when checking for indirect reference");
4199 }
4200 /*
4201 * Check for indirect PC relative addressing mode
4202 */
4203 if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff)
4204 {
4205 static char Address_Mode = 0xff;
4206
4207 /*
4208 * Yes: Store the indirect mode back into the image
4209 * to fix up the damage done by STO_PICR
4210 */
4211 VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR);
4212 VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR);
4213 }
4214 }
4215 \f
4216
4217
4218 /*
4219 * This is a hacked _doprnt() for VAX-11 "C". It understands that
4220 * it is ONLY called by as_fatal(Format, Args) with a pointer to the
4221 * "Args" argument. From this we can make it all work right!
4222 */
4223 #if !defined(eunice) && defined(HO_VMS)
4224 _doprnt (Format, a, f)
4225 char *Format;
4226 FILE *f;
4227 char **a;
4228 {
4229 int Nargs = ((int *) a)[-2]; /* This understands as_fatal() */
4230
4231 switch (Nargs)
4232 {
4233 default:
4234 fprintf (f, "_doprnt error on \"%s\"!!", Format);
4235 break;
4236 case 1:
4237 fprintf (f, Format);
4238 break;
4239 case 2:
4240 fprintf (f, Format, a[0]);
4241 break;
4242 case 3:
4243 fprintf (f, Format, a[0], a[1]);
4244 break;
4245 case 4:
4246 fprintf (f, Format, a[0], a[1], a[2]);
4247 break;
4248 case 5:
4249 fprintf (f, Format, a[0], a[1], a[2], a[3]);
4250 break;
4251 case 6:
4252 fprintf (f, Format, a[0], a[1], a[2], a[3], a[4]);
4253 break;
4254 case 7:
4255 fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5]);
4256 break;
4257 case 8:
4258 fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5], a[6]);
4259 break;
4260 case 9:
4261 fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
4262 break;
4263 case 10:
4264 fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
4265 break;
4266 }
4267 }
4268
4269 #endif /* eunice */
4270 \f
4271
4272 /*
4273 * If the procedure "main()" exists we have to add the instruction
4274 * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
4275 */
4276 VMS_Check_For_Main ()
4277 {
4278 register symbolS *symbolP;
4279 #ifdef HACK_DEC_C_STARTUP /* JF */
4280 register struct frchain *frchainP;
4281 register fragS *fragP;
4282 register fragS **prev_fragPP;
4283 register struct fix *fixP;
4284 register fragS *New_Frag;
4285 int i;
4286 #endif /* HACK_DEC_C_STARTUP */
4287
4288 symbolP = (struct symbol *) symbol_find ("_main");
4289 if (symbolP && !S_IS_DEBUG (symbolP) &&
4290 S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
4291 {
4292 #ifdef HACK_DEC_C_STARTUP
4293 if (!flagseen['+'])
4294 {
4295 #endif
4296 /*
4297 * Remember the entry point symbol
4298 */
4299 Entry_Point_Symbol = symbolP;
4300 #ifdef HACK_DEC_C_STARTUP
4301 }
4302 else
4303 {
4304 /*
4305 * Scan all the fragment chains for the one with "_main"
4306 * (Actually we know the fragment from the symbol, but we need
4307 * the previous fragment so we can change its pointer)
4308 */
4309 frchainP = frchain_root;
4310 while (frchainP)
4311 {
4312 /*
4313 * Scan all the fragments in this chain, remembering
4314 * the "previous fragment"
4315 */
4316 prev_fragPP = &frchainP->frch_root;
4317 fragP = frchainP->frch_root;
4318 while (fragP && (fragP != frchainP->frch_last))
4319 {
4320 /*
4321 * Is this the fragment?
4322 */
4323 if (fragP == symbolP->sy_frag)
4324 {
4325 /*
4326 * Yes: Modify the fragment by replacing
4327 * it with a new fragment.
4328 */
4329 New_Frag = (fragS *)
4330 xmalloc (sizeof (*New_Frag) +
4331 fragP->fr_fix +
4332 fragP->fr_var +
4333 5);
4334 /*
4335 * The fragments are the same except
4336 * that the "fixed" area is larger
4337 */
4338 *New_Frag = *fragP;
4339 New_Frag->fr_fix += 6;
4340 /*
4341 * Copy the literal data opening a hole
4342 * 2 bytes after "_main" (i.e. just after
4343 * the entry mask). Into which we place
4344 * the JSB instruction.
4345 */
4346 New_Frag->fr_literal[0] = fragP->fr_literal[0];
4347 New_Frag->fr_literal[1] = fragP->fr_literal[1];
4348 New_Frag->fr_literal[2] = 0x16; /* Jsb */
4349 New_Frag->fr_literal[3] = 0xef;
4350 New_Frag->fr_literal[4] = 0;
4351 New_Frag->fr_literal[5] = 0;
4352 New_Frag->fr_literal[6] = 0;
4353 New_Frag->fr_literal[7] = 0;
4354 for (i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
4355 New_Frag->fr_literal[i + 6] =
4356 fragP->fr_literal[i];
4357 /*
4358 * Now replace the old fragment with the
4359 * newly generated one.
4360 */
4361 *prev_fragPP = New_Frag;
4362 /*
4363 * Remember the entry point symbol
4364 */
4365 Entry_Point_Symbol = symbolP;
4366 /*
4367 * Scan the text area fixup structures
4368 * as offsets in the fragment may have
4369 * changed
4370 */
4371 for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
4372 {
4373 /*
4374 * Look for references to this
4375 * fragment.
4376 */
4377 if (fixP->fx_frag == fragP)
4378 {
4379 /*
4380 * Change the fragment
4381 * pointer
4382 */
4383 fixP->fx_frag = New_Frag;
4384 /*
4385 * If the offset is after
4386 * the entry mask we need
4387 * to account for the JSB
4388 * instruction we just
4389 * inserted.
4390 */
4391 if (fixP->fx_where >= 2)
4392 fixP->fx_where += 6;
4393 }
4394 }
4395 /*
4396 * Scan the symbols as offsets in the
4397 * fragment may have changed
4398 */
4399 for (symbolP = symbol_rootP;
4400 symbolP;
4401 symbolP = symbol_next (symbolP))
4402 {
4403 /*
4404 * Look for references to this
4405 * fragment.
4406 */
4407 if (symbolP->sy_frag == fragP)
4408 {
4409 /*
4410 * Change the fragment
4411 * pointer
4412 */
4413 symbolP->sy_frag = New_Frag;
4414 /*
4415 * If the offset is after
4416 * the entry mask we need
4417 * to account for the JSB
4418 * instruction we just
4419 * inserted.
4420 */
4421 if (S_GET_VALUE (symbolP) >= 2)
4422 S_GET_VALUE (symbolP) += 6;
4423 }
4424 }
4425 /*
4426 * Make a symbol reference to
4427 * "_c$main_args" so we can get
4428 * its address inserted into the
4429 * JSB instruction.
4430 */
4431 symbolP = (symbolS *) xmalloc (sizeof (*symbolP));
4432 S_GET_NAME (symbolP) = "_c$main_args";
4433 S_SET_TYPE (symbolP, N_UNDF);
4434 S_GET_OTHER (symbolP) = 0;
4435 S_GET_DESC (symbolP) = 0;
4436 S_GET_VALUE (symbolP) = 0;
4437 symbolP->sy_name_offset = 0;
4438 symbolP->sy_number = 0;
4439 symbolP->sy_frag = New_Frag;
4440 symbolP->sy_forward = 0;
4441 /* this actually inserts at the beginning of the list */
4442 symbol_append (symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP);
4443
4444 symbol_rootP = symbolP;
4445 /*
4446 * Generate a text fixup structure
4447 * to get "_c$main_args" stored into the
4448 * JSB instruction.
4449 */
4450 fixP = (struct fix *) xmalloc (sizeof (*fixP));
4451 fixP->fx_frag = New_Frag;
4452 fixP->fx_where = 4;
4453 fixP->fx_addsy = symbolP;
4454 fixP->fx_subsy = 0;
4455 fixP->fx_offset = 0;
4456 fixP->fx_size = sizeof (long);
4457 fixP->fx_pcrel = 1;
4458 fixP->fx_next = text_fix_root;
4459 text_fix_root = fixP;
4460 /*
4461 * Now make sure we exit from the loop
4462 */
4463 frchainP = 0;
4464 break;
4465 }
4466 /*
4467 * Try the next fragment
4468 */
4469 prev_fragPP = &fragP->fr_next;
4470 fragP = fragP->fr_next;
4471 }
4472 /*
4473 * Try the next fragment chain
4474 */
4475 if (frchainP)
4476 frchainP = frchainP->frch_next;
4477 }
4478 }
4479 #endif /* HACK_DEC_C_STARTUP */
4480 }
4481 }
4482 \f
4483 /*
4484 * Write a VAX/VMS object file (everything else has been done!)
4485 */
4486 VMS_write_object_file (text_siz, data_siz, text_frag_root, data_frag_root)
4487 unsigned text_siz;
4488 unsigned data_siz;
4489 struct frag *text_frag_root;
4490 struct frag *data_frag_root;
4491 {
4492 register fragS *fragP;
4493 register symbolS *symbolP;
4494 register symbolS *sp;
4495 register struct fix *fixP;
4496 register struct VMS_Symbol *vsp;
4497 char *Data_Segment;
4498 int Local_Initialized_Data_Size = 0;
4499 int Globalref;
4500 int Psect_Number = 0; /* Psect Index Number */
4501 int Text_Psect = -1; /* Text Psect Index */
4502 int Data_Psect = -2; /* Data Psect Index JF: Was -1 */
4503 int Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */
4504
4505 /*
4506 * Create the VMS object file
4507 */
4508 Create_VMS_Object_File ();
4509 /*
4510 * Write the module header records
4511 */
4512 Write_VMS_MHD_Records ();
4513 \f
4514 /*
4515 * Store the Data segment:
4516 *
4517 * Since this is REALLY hard to do any other way,
4518 * we actually manufacture the data segment and
4519 * the store the appropriate values out of it.
4520 * We need to generate this early, so that globalvalues
4521 * can be properly emitted.
4522 */
4523 if (data_siz > 0)
4524 {
4525 /*
4526 * Allocate the data segment
4527 */
4528 Data_Segment = (char *) xmalloc (data_siz);
4529 /*
4530 * Run through the data fragments, filling in the segment
4531 */
4532 for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
4533 {
4534 register long int count;
4535 register char *fill_literal;
4536 register long int fill_size;
4537 int i;
4538
4539 i = fragP->fr_address - text_siz;
4540 if (fragP->fr_fix)
4541 memcpy (Data_Segment + i,
4542 fragP->fr_literal,
4543 fragP->fr_fix);
4544 i += fragP->fr_fix;
4545
4546 fill_literal = fragP->fr_literal + fragP->fr_fix;
4547 fill_size = fragP->fr_var;
4548 for (count = fragP->fr_offset; count; count--)
4549 {
4550 if (fill_size)
4551 memcpy (Data_Segment + i, fill_literal, fill_size);
4552 i += fill_size;
4553 }
4554 }
4555 }
4556
4557
4558 /*
4559 * Generate the VMS object file records
4560 * 1st GSD then TIR records
4561 */
4562
4563 /******* Global Symbol Dictionary *******/
4564 /*
4565 * Emit globalvalues now. We must do this before the text psect
4566 * is defined, or we will get linker warnings about multiply defined
4567 * symbols. All of the globalvalues "reference" psect 0, although
4568 * it really does not have anything to do with it.
4569 */
4570 VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
4571 /*
4572 * Define the Text Psect
4573 */
4574 Text_Psect = Psect_Number++;
4575 VMS_Psect_Spec ("$code", text_siz, "TEXT", 0);
4576 /*
4577 * Define the BSS Psect
4578 */
4579 if (local_bss_counter > 0)
4580 {
4581 Bss_Psect = Psect_Number++;
4582 VMS_Psect_Spec ("$uninitialized_data", local_bss_counter, "DATA",
4583 0);
4584 }
4585 #ifndef gxx_bug_fixed
4586 /*
4587 * The g++ compiler does not write out external references to vtables
4588 * correctly. Check for this and holler if we see it happening.
4589 * If that compiler bug is ever fixed we can remove this.
4590 */
4591 for (sp = symbol_rootP; sp; sp = symbol_next (sp))
4592 {
4593 /*
4594 * Dispatch on symbol type
4595 */
4596 switch (S_GET_RAW_TYPE (sp)) {
4597 /*
4598 * Global Reference
4599 */
4600 case N_UNDF:
4601 /*
4602 * Make a GSD global symbol reference
4603 * record.
4604 */
4605 if (strncmp (S_GET_NAME (sp),"__vt.",5) == 0)
4606 {
4607 S_GET_RAW_TYPE (sp) = N_UNDF | N_EXT;
4608 as_warn("g++ wrote an extern reference to %s as a routine.",
4609 S_GET_NAME (sp));
4610 as_warn("I will fix it, but I hope that it was not really a routine");
4611 };
4612 break;
4613 default:
4614 break;
4615 }
4616 }
4617 #endif /* gxx_bug_fixed */
4618 /*
4619 * Now scan the symbols and emit the appropriate GSD records
4620 */
4621 for (sp = symbol_rootP; sp; sp = symbol_next (sp))
4622 {
4623 /*
4624 * Dispatch on symbol type
4625 */
4626 switch (S_GET_RAW_TYPE (sp))
4627 {
4628 /*
4629 * Global uninitialized data
4630 */
4631 case N_UNDF | N_EXT:
4632 /*
4633 * Make a VMS data symbol entry
4634 */
4635 vsp = (struct VMS_Symbol *)
4636 xmalloc (sizeof (*vsp));
4637 vsp->Symbol = sp;
4638 vsp->Size = S_GET_VALUE (sp);
4639 vsp->Psect_Index = Psect_Number++;
4640 vsp->Psect_Offset = 0;
4641 vsp->Next = VMS_Symbols;
4642 VMS_Symbols = vsp;
4643 sp->sy_number = (int) vsp;
4644 /*
4645 * Make the psect for this data
4646 */
4647 if (S_GET_OTHER (sp))
4648 Globalref = VMS_Psect_Spec (
4649 S_GET_NAME (sp),
4650 vsp->Size,
4651 "CONST",
4652 vsp);
4653 else
4654 Globalref = VMS_Psect_Spec (
4655 S_GET_NAME (sp),
4656 vsp->Size,
4657 "COMMON",
4658 vsp);
4659 if (Globalref)
4660 Psect_Number--;
4661 #ifdef NOT_VAX_11_C_COMPATIBLE
4662 /*
4663 * Place a global symbol at the
4664 * beginning of the Psect
4665 */
4666 VMS_Global_Symbol_Spec (S_GET_NAME (sp),
4667 vsp->Psect_Index,
4668 0,
4669 1);
4670 #endif /* NOT_VAX_11_C_COMPATIBLE */
4671 break;
4672 /*
4673 * Local uninitialized data
4674 */
4675 case N_BSS:
4676 /*
4677 * Make a VMS data symbol entry
4678 */
4679 vsp = (struct VMS_Symbol *)
4680 xmalloc (sizeof (*vsp));
4681 vsp->Symbol = sp;
4682 vsp->Size = 0;
4683 vsp->Psect_Index = Bss_Psect;
4684 vsp->Psect_Offset =
4685 S_GET_VALUE (sp) -
4686 bss_address_frag.fr_address;
4687 vsp->Next = VMS_Symbols;
4688 VMS_Symbols = vsp;
4689 sp->sy_number = (int) vsp;
4690 break;
4691 /*
4692 * Global initialized data
4693 */
4694 case N_DATA | N_EXT:
4695 /*
4696 * Make a VMS data symbol entry
4697 */
4698 vsp = (struct VMS_Symbol *)
4699 xmalloc (sizeof (*vsp));
4700 vsp->Symbol = sp;
4701 vsp->Size = VMS_Initialized_Data_Size (sp,
4702 text_siz + data_siz);
4703 vsp->Psect_Index = Psect_Number++;
4704 vsp->Psect_Offset = 0;
4705 vsp->Next = VMS_Symbols;
4706 VMS_Symbols = vsp;
4707 sp->sy_number = (int) vsp;
4708 /*
4709 * Make its psect
4710 */
4711 if (S_GET_OTHER (sp))
4712 Globalref = VMS_Psect_Spec (
4713 S_GET_NAME (sp),
4714 vsp->Size,
4715 "CONST",
4716 vsp);
4717 else
4718 Globalref = VMS_Psect_Spec (
4719 S_GET_NAME (sp),
4720 vsp->Size,
4721 "COMMON",
4722 vsp);
4723 if (Globalref)
4724 Psect_Number--;
4725 #ifdef NOT_VAX_11_C_COMPATIBLE
4726 /*
4727 * Place a global symbol at the
4728 * beginning of the Psect
4729 */
4730 VMS_Global_Symbol_Spec (S_GET_NAME (sp),
4731 vsp->Psect_Index,
4732 0,
4733 1);
4734 #endif /* NOT_VAX_11_C_COMPATIBLE */
4735 break;
4736 /*
4737 * Local initialized data
4738 */
4739 case N_DATA:
4740 /*
4741 * Make a VMS data symbol entry
4742 */
4743 vsp = (struct VMS_Symbol *)
4744 xmalloc (sizeof (*vsp));
4745 vsp->Symbol = sp;
4746 vsp->Size =
4747 VMS_Initialized_Data_Size (sp,
4748 text_siz + data_siz);
4749 vsp->Psect_Index = Data_Psect;
4750 vsp->Psect_Offset =
4751 Local_Initialized_Data_Size;
4752 Local_Initialized_Data_Size += vsp->Size;
4753 vsp->Next = VMS_Symbols;
4754 VMS_Symbols = vsp;
4755 sp->sy_number = (int) vsp;
4756 break;
4757 /*
4758 * Global Text definition
4759 */
4760 case N_TEXT | N_EXT:
4761 {
4762 unsigned short Entry_Mask;
4763
4764 /*
4765 * Get the entry mask
4766 */
4767 fragP = sp->sy_frag;
4768 Entry_Mask = (fragP->fr_literal[0] & 0xff) +
4769 ((fragP->fr_literal[1] & 0xff)
4770 << 8);
4771 /*
4772 * Define the Procedure entry pt.
4773 */
4774 VMS_Procedure_Entry_Pt (S_GET_NAME (sp),
4775 Text_Psect,
4776 S_GET_VALUE (sp),
4777 Entry_Mask);
4778 break;
4779 }
4780 /*
4781 * Local Text definition
4782 */
4783 case N_TEXT:
4784 /*
4785 * Make a VMS data symbol entry
4786 */
4787 if (Text_Psect != -1)
4788 {
4789 vsp = (struct VMS_Symbol *)
4790 xmalloc (sizeof (*vsp));
4791 vsp->Symbol = sp;
4792 vsp->Size = 0;
4793 vsp->Psect_Index = Text_Psect;
4794 vsp->Psect_Offset = S_GET_VALUE (sp);
4795 vsp->Next = VMS_Symbols;
4796 VMS_Symbols = vsp;
4797 sp->sy_number = (int) vsp;
4798 }
4799 break;
4800 /*
4801 * Global Reference
4802 */
4803 case N_UNDF:
4804 /*
4805 * Make a GSD global symbol reference
4806 * record.
4807 */
4808 VMS_Global_Symbol_Spec (S_GET_NAME (sp),
4809 0,
4810 0,
4811 0);
4812 break;
4813 /*
4814 * Anything else
4815 */
4816 default:
4817 /*
4818 * Ignore STAB symbols
4819 * Including .stabs emitted by g++
4820 */
4821 if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22))
4822 break;
4823 /*
4824 * Error
4825 */
4826 if (S_GET_TYPE (sp) != 22)
4827 printf (" ERROR, unknown type (%d)\n",
4828 S_GET_TYPE (sp));
4829 break;
4830 }
4831 }
4832 /*
4833 * Define the Data Psect
4834 */
4835 if ((data_siz > 0) && (Local_Initialized_Data_Size > 0))
4836 {
4837 /*
4838 * Do it
4839 */
4840 Data_Psect = Psect_Number++;
4841 VMS_Psect_Spec ("$data",
4842 Local_Initialized_Data_Size,
4843 "DATA", 0);
4844 /*
4845 * Scan the VMS symbols and fill in the data psect
4846 */
4847 for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
4848 {
4849 /*
4850 * Only look for undefined psects
4851 */
4852 if (vsp->Psect_Index < 0)
4853 {
4854 /*
4855 * And only initialized data
4856 */
4857 if ((S_GET_TYPE (vsp->Symbol) == N_DATA) && !S_IS_EXTERNAL (vsp->Symbol))
4858 vsp->Psect_Index = Data_Psect;
4859 }
4860 }
4861 }
4862 \f
4863 /******* Text Information and Relocation Records *******/
4864 /*
4865 * Write the text segment data
4866 */
4867 if (text_siz > 0)
4868 {
4869 /*
4870 * Scan the text fragments
4871 */
4872 for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
4873 {
4874 /*
4875 * Stop if we get to the data fragments
4876 */
4877 if (fragP == data_frag_root)
4878 break;
4879 /*
4880 * Ignore fragments with no data
4881 */
4882 if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
4883 continue;
4884 /*
4885 * Go the the appropriate offset in the
4886 * Text Psect.
4887 */
4888 VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
4889 /*
4890 * Store the "fixed" part
4891 */
4892 if (fragP->fr_fix)
4893 VMS_Store_Immediate_Data (fragP->fr_literal,
4894 fragP->fr_fix,
4895 OBJ_S_C_TIR);
4896 /*
4897 * Store the "variable" part
4898 */
4899 if (fragP->fr_var && fragP->fr_offset)
4900 VMS_Store_Repeated_Data (fragP->fr_offset,
4901 fragP->fr_literal +
4902 fragP->fr_fix,
4903 fragP->fr_var,
4904 OBJ_S_C_TIR);
4905 }
4906 /*
4907 * Now we go through the text segment fixups and
4908 * generate TIR records to fix up addresses within
4909 * the Text Psect
4910 */
4911 for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
4912 {
4913 /*
4914 * We DO handle the case of "Symbol - Symbol" as
4915 * long as it is in the same segment.
4916 */
4917 if (fixP->fx_subsy && fixP->fx_addsy)
4918 {
4919 int i;
4920
4921 /*
4922 * They need to be in the same segment
4923 */
4924 if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
4925 S_GET_RAW_TYPE (fixP->fx_addsy))
4926 error ("Fixup data addsy and subsy didn't have the same type");
4927 /*
4928 * And they need to be in one that we
4929 * can check the psect on
4930 */
4931 if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
4932 (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
4933 error ("Fixup data addsy and subsy didn't have an appropriate type");
4934 /*
4935 * This had better not be PC relative!
4936 */
4937 if (fixP->fx_pcrel)
4938 error ("Fixup data was erroneously \"pcrel\"");
4939 /*
4940 * Subtract their values to get the
4941 * difference.
4942 */
4943 i = S_GET_VALUE (fixP->fx_addsy) -
4944 S_GET_VALUE (fixP->fx_subsy);
4945 /*
4946 * Now generate the fixup object records
4947 * Set the psect and store the data
4948 */
4949 VMS_Set_Psect (Text_Psect,
4950 fixP->fx_where +
4951 fixP->fx_frag->fr_address,
4952 OBJ_S_C_TIR);
4953 VMS_Store_Immediate_Data (&i,
4954 fixP->fx_size,
4955 OBJ_S_C_TIR);
4956 /*
4957 * Done
4958 */
4959 continue;
4960 }
4961 /*
4962 * Size will HAVE to be "long"
4963 */
4964 if (fixP->fx_size != sizeof (long))
4965 error ("Fixup datum was not a longword");
4966 /*
4967 * Symbol must be "added" (if it is ever
4968 * subtracted we can
4969 * fix this assumption)
4970 */
4971 if (fixP->fx_addsy == 0)
4972 error ("Fixup datum was not \"fixP->fx_addsy\"");
4973 /*
4974 * Store the symbol value in a PIC fashion
4975 */
4976 VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
4977 fixP->fx_offset,
4978 fixP->fx_pcrel,
4979 Text_Psect,
4980 fixP->fx_where +
4981 fixP->fx_frag->fr_address,
4982 OBJ_S_C_TIR);
4983 /*
4984 * Check for indirect address reference,
4985 * which has to be fixed up (as the linker
4986 * will screw it up with TIR_S_C_STO_PICR).
4987 */
4988 if (fixP->fx_pcrel)
4989 VMS_Fix_Indirect_Reference (Text_Psect,
4990 fixP->fx_where +
4991 fixP->fx_frag->fr_address,
4992 fixP->fx_frag,
4993 text_frag_root);
4994 }
4995 }
4996 /*
4997 * Store the Data segment:
4998 *
4999 * Since this is REALLY hard to do any other way,
5000 * we actually manufacture the data segment and
5001 * the store the appropriate values out of it.
5002 * The segment was manufactured before, now we just
5003 * dump it into the appropriate psects.
5004 */
5005 if (data_siz > 0)
5006 {
5007
5008 /*
5009 * Now we can run through all the data symbols
5010 * and store the data
5011 */
5012 for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
5013 {
5014 /*
5015 * Ignore anything other than data symbols
5016 */
5017 if (S_GET_TYPE (vsp->Symbol) != N_DATA)
5018 continue;
5019 /*
5020 * Set the Psect + Offset
5021 */
5022 VMS_Set_Psect (vsp->Psect_Index,
5023 vsp->Psect_Offset,
5024 OBJ_S_C_TIR);
5025 /*
5026 * Store the data
5027 */
5028 VMS_Store_Immediate_Data (Data_Segment +
5029 S_GET_VALUE (vsp->Symbol) -
5030 text_siz,
5031 vsp->Size,
5032 OBJ_S_C_TIR);
5033 }
5034 /*
5035 * Now we go through the data segment fixups and
5036 * generate TIR records to fix up addresses within
5037 * the Data Psects
5038 */
5039 for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
5040 {
5041 /*
5042 * Find the symbol for the containing datum
5043 */
5044 for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
5045 {
5046 /*
5047 * Only bother with Data symbols
5048 */
5049 sp = vsp->Symbol;
5050 if (S_GET_TYPE (sp) != N_DATA)
5051 continue;
5052 /*
5053 * Ignore symbol if After fixup
5054 */
5055 if (S_GET_VALUE (sp) >
5056 (fixP->fx_where +
5057 fixP->fx_frag->fr_address))
5058 continue;
5059 /*
5060 * See if the datum is here
5061 */
5062 if ((S_GET_VALUE (sp) + vsp->Size) <=
5063 (fixP->fx_where +
5064 fixP->fx_frag->fr_address))
5065 continue;
5066 /*
5067 * We DO handle the case of "Symbol - Symbol" as
5068 * long as it is in the same segment.
5069 */
5070 if (fixP->fx_subsy && fixP->fx_addsy)
5071 {
5072 int i;
5073
5074 /*
5075 * They need to be in the same segment
5076 */
5077 if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
5078 S_GET_RAW_TYPE (fixP->fx_addsy))
5079 error ("Fixup data addsy and subsy didn't have the same type");
5080 /*
5081 * And they need to be in one that we
5082 * can check the psect on
5083 */
5084 if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
5085 (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
5086 error ("Fixup data addsy and subsy didn't have an appropriate type");
5087 /*
5088 * This had better not be PC relative!
5089 */
5090 if (fixP->fx_pcrel)
5091 error ("Fixup data was erroneously \"pcrel\"");
5092 /*
5093 * Subtract their values to get the
5094 * difference.
5095 */
5096 i = S_GET_VALUE (fixP->fx_addsy) -
5097 S_GET_VALUE (fixP->fx_subsy);
5098 /*
5099 * Now generate the fixup object records
5100 * Set the psect and store the data
5101 */
5102 VMS_Set_Psect (vsp->Psect_Index,
5103 fixP->fx_frag->fr_address +
5104 fixP->fx_where -
5105 S_GET_VALUE (vsp->Symbol) +
5106 vsp->Psect_Offset,
5107 OBJ_S_C_TIR);
5108 VMS_Store_Immediate_Data (&i,
5109 fixP->fx_size,
5110 OBJ_S_C_TIR);
5111 /*
5112 * Done
5113 */
5114 break;
5115 }
5116 /*
5117 * Size will HAVE to be "long"
5118 */
5119 if (fixP->fx_size != sizeof (long))
5120 error ("Fixup datum was not a longword");
5121 /*
5122 * Symbol must be "added" (if it is ever
5123 * subtracted we can
5124 * fix this assumption)
5125 */
5126 if (fixP->fx_addsy == 0)
5127 error ("Fixup datum was not \"fixP->fx_addsy\"");
5128 /*
5129 * Store the symbol value in a PIC fashion
5130 */
5131 VMS_Store_PIC_Symbol_Reference (
5132 fixP->fx_addsy,
5133 fixP->fx_offset,
5134 fixP->fx_pcrel,
5135 vsp->Psect_Index,
5136 fixP->fx_frag->fr_address +
5137 fixP->fx_where -
5138 S_GET_VALUE (vsp->Symbol) +
5139 vsp->Psect_Offset,
5140 OBJ_S_C_TIR);
5141 /*
5142 * Done
5143 */
5144 break;
5145 }
5146
5147 }
5148 }
5149 \f
5150 /*
5151 * Write the Traceback Begin Module record
5152 */
5153 VMS_TBT_Module_Begin ();
5154 /*
5155 * Scan the symbols and write out the routines
5156 * (this makes the assumption that symbols are in
5157 * order of ascending text segment offset)
5158 */
5159 {
5160 struct symbol *Current_Routine = 0;
5161 int Current_Line_Number = 0;
5162 int Current_Offset = -1;
5163 struct input_file *Current_File;
5164
5165 /* Output debugging info for global variables and static variables that are not
5166 * specific to one routine. We also need to examine all stabs directives, to
5167 * find the definitions to all of the advanced data types, and this is done by
5168 * VMS_LSYM_Parse. This needs to be done before any definitions are output to
5169 * the object file, since there can be forward references in the stabs
5170 * directives. When through with parsing, the text of the stabs directive
5171 * is altered, with the definitions removed, so that later passes will see
5172 * directives as they would be written if the type were already defined.
5173 *
5174 * We also look for files and include files, and make a list of them. We
5175 * examine the source file numbers to establish the actual lines that code was
5176 * generated from, and then generate offsets.
5177 */
5178 VMS_LSYM_Parse ();
5179 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
5180 {
5181 /*
5182 * Deal with STAB symbols
5183 */
5184 if (S_IS_DEBUG (symbolP))
5185 {
5186 /*
5187 * Dispatch on STAB type
5188 */
5189 switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
5190 {
5191 case N_SLINE:
5192 if (S_GET_DESC (symbolP) > Current_File->max_line)
5193 Current_File->max_line = S_GET_DESC (symbolP);
5194 if (S_GET_DESC (symbolP) < Current_File->min_line)
5195 Current_File->min_line = S_GET_DESC (symbolP);
5196 break;
5197 case N_SO:
5198 Current_File = find_file (symbolP);
5199 Current_File->flag = 1;
5200 Current_File->min_line = 1;
5201 break;
5202 case N_SOL:
5203 Current_File = find_file (symbolP);
5204 break;
5205 case N_GSYM:
5206 VMS_GSYM_Parse (symbolP, Text_Psect);
5207 break;
5208 case N_LCSYM:
5209 VMS_LCSYM_Parse (symbolP, Text_Psect);
5210 break;
5211 case N_FUN: /* For static constant symbols */
5212 case N_STSYM:
5213 VMS_STSYM_Parse (symbolP, Text_Psect);
5214 break;
5215 }
5216 }
5217 }
5218
5219 /* now we take a quick sweep through the files and assign offsets
5220 to each one. This will essentially be the starting line number to the
5221 debugger for each file. Output the info for the debugger to specify the
5222 files, and then tell it how many lines to use */
5223 {
5224 int File_Number = 0;
5225 int Debugger_Offset = 0;
5226 int file_available;
5227 Current_File = file_root;
5228 for (Current_File = file_root; Current_File; Current_File = Current_File->next)
5229 {
5230 if (Current_File == (struct input_file *) NULL)
5231 break;
5232 if (Current_File->max_line == 0)
5233 continue;
5234 if ((strncmp (Current_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
5235 !flagseen['D'])
5236 continue;
5237 if ((strncmp (Current_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
5238 !flagseen['D'])
5239 continue;
5240 /* show a few extra lines at the start of the region selected */
5241 if (Current_File->min_line > 2)
5242 Current_File->min_line -= 2;
5243 Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
5244 Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
5245 if (Current_File->same_file_fpnt != (struct input_file *) NULL)
5246 Current_File->file_number = Current_File->same_file_fpnt->file_number;
5247 else
5248 {
5249 Current_File->file_number = ++File_Number;
5250 file_available = VMS_TBT_Source_File (Current_File->name,
5251 Current_File->file_number);
5252 if (!file_available)
5253 {
5254 Current_File->file_number = 0;
5255 File_Number--;
5256 continue;
5257 };
5258 };
5259 VMS_TBT_Source_Lines (Current_File->file_number,
5260 Current_File->min_line,
5261 Current_File->max_line - Current_File->min_line + 1);
5262 }; /* for */
5263 }; /* scope */
5264 Current_File = (struct input_file *) NULL;
5265
5266 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
5267 {
5268 /*
5269 * Deal with text symbols
5270 */
5271 if (!S_IS_DEBUG (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
5272 {
5273 /*
5274 * Ignore symbols starting with "L",
5275 * as they are local symbols
5276 */
5277 if (*S_GET_NAME (symbolP) == 'L')
5278 continue;
5279 /*
5280 * If there is a routine start defined,
5281 * terminate it.
5282 */
5283 if (Current_Routine)
5284 {
5285 /*
5286 * End the routine
5287 */
5288 VMS_TBT_Routine_End (text_siz, Current_Routine);
5289 }
5290 /*
5291 * Store the routine begin traceback info
5292 */
5293 if (Text_Psect != -1)
5294 {
5295 VMS_TBT_Routine_Begin (symbolP, Text_Psect);
5296 Current_Routine = symbolP;
5297 }
5298 /* Output local symbols, i.e. all symbols that are associated with a specific
5299 * routine. We output them now so the debugger recognizes them as local to
5300 * this routine.
5301 */
5302 {
5303 symbolS *symbolP1;
5304 char *pnt;
5305 char *pnt1;
5306 for (symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next (symbolP1))
5307 {
5308 if (!S_IS_DEBUG (symbolP1))
5309 continue;
5310 if (S_GET_RAW_TYPE (symbolP1) != N_FUN)
5311 continue;
5312 pnt = S_GET_NAME (symbolP);
5313 pnt1 = S_GET_NAME (symbolP1);
5314 if (*pnt++ != '_')
5315 continue;
5316 while (*pnt++ == *pnt1++)
5317 {
5318 };
5319 if (*pnt1 != 'F' && *pnt1 != 'f') continue;
5320 if ((*(--pnt) == '\0') && (*(--pnt1) == ':'))
5321 break;
5322 };
5323 if (symbolP1 != (symbolS *) NULL)
5324 VMS_DBG_Define_Routine (symbolP1, Current_Routine, Text_Psect);
5325 } /* local symbol block */
5326 /*
5327 * Done
5328 */
5329 continue;
5330 }
5331 /*
5332 * Deal with STAB symbols
5333 */
5334 if (S_IS_DEBUG (symbolP))
5335 {
5336 /*
5337 * Dispatch on STAB type
5338 */
5339 switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
5340 {
5341 /*
5342 * Line number
5343 */
5344 case N_SLINE:
5345 /* Offset the line into the correct portion
5346 * of the file */
5347 if (Current_File->file_number == 0)
5348 break;
5349 /* Sometimes the same offset gets several source
5350 * lines assigned to it.
5351 * We should be selective about which lines
5352 * we allow, we should prefer lines that are
5353 * in the main source file when debugging
5354 * inline functions. */
5355 if ((Current_File->file_number != 1) &&
5356 S_GET_VALUE (symbolP) ==
5357 Current_Offset)
5358 break;
5359 /* calculate actual debugger source line */
5360 S_GET_DESC (symbolP)
5361 += Current_File->offset;
5362 /*
5363 * If this is the 1st N_SLINE, setup
5364 * PC/Line correlation. Otherwise
5365 * do the delta PC/Line. If the offset
5366 * for the line number is not +ve we need
5367 * to do another PC/Line correlation
5368 * setup
5369 */
5370 if (Current_Offset == -1)
5371 {
5372 VMS_TBT_Line_PC_Correlation (
5373 S_GET_DESC (symbolP),
5374 S_GET_VALUE (symbolP),
5375 Text_Psect,
5376 0);
5377 }
5378 else
5379 {
5380 if ((S_GET_DESC (symbolP) -
5381 Current_Line_Number) <= 0)
5382 {
5383 /*
5384 * Line delta is not +ve, we
5385 * need to close the line and
5386 * start a new PC/Line
5387 * correlation.
5388 */
5389 VMS_TBT_Line_PC_Correlation (0,
5390 S_GET_VALUE (symbolP) -
5391 Current_Offset,
5392 0,
5393 -1);
5394 VMS_TBT_Line_PC_Correlation (
5395 S_GET_DESC (symbolP),
5396 S_GET_VALUE (symbolP),
5397 Text_Psect,
5398 0);
5399 }
5400 else
5401 {
5402 /*
5403 * Line delta is +ve, all is well
5404 */
5405 VMS_TBT_Line_PC_Correlation (
5406 S_GET_DESC (symbolP) -
5407 Current_Line_Number,
5408 S_GET_VALUE (symbolP) -
5409 Current_Offset,
5410 0,
5411 1);
5412 }
5413 }
5414 /*
5415 * Update the current line/PC
5416 */
5417 Current_Line_Number = S_GET_DESC (symbolP);
5418 Current_Offset = S_GET_VALUE (symbolP);
5419 /*
5420 * Done
5421 */
5422 break;
5423 /*
5424 * Source file
5425 */
5426 case N_SO:
5427 /*
5428 * Remember that we had a source file
5429 * and emit the source file debugger
5430 * record
5431 */
5432 Current_File =
5433 find_file (symbolP);
5434 break;
5435 /* We need to make sure that we are really in the actual source file when
5436 * we compute the maximum line number. Otherwise the debugger gets really
5437 * confused */
5438 case N_SOL:
5439 Current_File =
5440 find_file (symbolP);
5441 break;
5442 }
5443 }
5444 }
5445 /*
5446 * If there is a routine start defined,
5447 * terminate it (and the line numbers)
5448 */
5449 if (Current_Routine)
5450 {
5451 /*
5452 * Terminate the line numbers
5453 */
5454 VMS_TBT_Line_PC_Correlation (0,
5455 text_siz - S_GET_VALUE (Current_Routine),
5456 0,
5457 -1);
5458 /*
5459 * Terminate the routine
5460 */
5461 VMS_TBT_Routine_End (text_siz, Current_Routine);
5462 }
5463 }
5464 /*
5465 * Write the Traceback End Module TBT record
5466 */
5467 VMS_TBT_Module_End ();
5468 \f
5469 /*
5470 * Write the End Of Module record
5471 */
5472 if (Entry_Point_Symbol == 0)
5473 Write_VMS_EOM_Record (-1, 0);
5474 else
5475 Write_VMS_EOM_Record (Text_Psect,
5476 S_GET_VALUE (Entry_Point_Symbol));
5477 \f
5478 /*
5479 * All done, close the object file
5480 */
5481 Close_VMS_Object_File ();
5482 }
5483
5484 /* end of obj-vms.c */
This page took 0.134844 seconds and 5 git commands to generate.