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