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