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