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