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