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