force all files to end in "/* end of filename"
[deliverable/binutils-gdb.git] / gas / config / vms / vms.c
CommitLineData
0e39a8bb
RP
1/* vms.c -- Write out a VAX/VMS object file
2 Copyright (C) 1987, 1988 Free Software Foundation, Inc.
8b228fe9
RP
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
0e39a8bb
RP
19
20/* Written by David L. Kashtan */
21#include <ctype.h>
22#include <stdio.h>
23
24#include "as.h"
25#include "subsegs.h"
26#include "obstack.h"
27#include "struc-symbol.h"
28#include "write.h"
29#include "symbols.h"
30
31#ifdef VMS /* THIS MODULE IS FOR VMS ONLY */
32
33#include <stab.h>
34#include "objrecdef.h" /* Define VMS Object record lang. */
35#include <vms/fabdef.h> /* Define File Access Block */
36#include <vms/namdef.h> /* Define NAM Block */
37#include <vms/xabdef.h> /* Define XAB */
38#include <vms/xabdatdef.h> /* Define Date XAB */
39#include <vms/xabfhcdef.h> /* Define File Header XAB */
40
41const pseudo_typeS obj_pseudo_table[] = {
8b228fe9
RP
42{ "const", s_const, 0 },
43
0e39a8bb
RP
44}; /* obj_pseudo_table */
45
46/*
47 * Version string of the compiler that produced the code we are
48 * assembling. (And this assembler, if we do not have compiler info.)
49 */
50extern char version_string[];
51char *compiler_version_string;
52
53extern char *myname;
54static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
55
56/*
57 * We augment the "gas" symbol structure with this
58 */
59struct VMS_Symbol {
8b228fe9
RP
60 struct VMS_Symbol *Next;
61struct symbol *Symbol;
62int Size;
63int Psect_Index;
64int Psect_Offset;
65};
0e39a8bb
RP
66struct VMS_Symbol *VMS_Symbols = 0;
67
68/* we need this to keep track of the various input files, so that we can
69 * give the debugger the correct source line
70 */
71
72struct input_file{
8b228fe9
RP
73 struct input_file* next;
74struct input_file* same_file_fpnt;
75int file_number;
76int max_line;
77int min_line;
78int offset;
79char flag;
80char * name;
81symbolS * spnt;
82};
0e39a8bb
RP
83
84static struct input_file * file_root = (struct input_file*)NULL;
8b228fe9
RP
85
86 struct input_file * find_file(symbolS *);
87
88 \f
89 /*
90 * If the procedure "main()" exists we have to add the instruction
91 * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
92 */
93 VMS_Check_For_Main()
0e39a8bb 94{
8b228fe9 95 register symbolS *symbolP;
0e39a8bb 96#ifdef HACK_DEC_C_STARTUP /* JF */
8b228fe9
RP
97 register struct frchain *frchainP;
98 register fragS *fragP;
99 register fragS **prev_fragPP;
100 register struct fix *fixP;
101 register fragS *New_Frag;
102 int i;
0e39a8bb 103#endif HACK_DEC_C_STARTUP
8b228fe9
RP
104
105 symbolP = (struct symbol *)symbol_find("_main");
106 if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {
0e39a8bb
RP
107#ifdef HACK_DEC_C_STARTUP
108 if( !flagseen['+']) {
109#endif
8b228fe9
RP
110 /*
111 * Remember the entry point symbol
112 */
113 Entry_Point_Symbol = symbolP;
0e39a8bb
RP
114#ifdef HACK_DEC_C_STARTUP
115 } else {
8b228fe9
RP
116 /*
117 * Scan all the fragment chains for the one with "_main"
118 * (Actually we know the fragment from the symbol, but we need
119 * the previous fragment so we can change its pointer)
120 */
121 frchainP = frchain_root;
122 while(frchainP) {
0e39a8bb 123 /*
8b228fe9
RP
124 * Scan all the fragments in this chain, remembering
125 * the "previous fragment"
0e39a8bb 126 */
8b228fe9
RP
127 prev_fragPP = &frchainP->frch_root;
128 fragP = frchainP->frch_root;
129 while(fragP && (fragP != frchainP->frch_last)) {
130 /*
131 * Is this the fragment?
132 */
133 if (fragP == symbolP->sy_frag) {
0e39a8bb 134 /*
8b228fe9
RP
135 * Yes: Modify the fragment by replacing
136 * it with a new fragment.
0e39a8bb 137 */
8b228fe9
RP
138 New_Frag = (fragS *)
139 xmalloc(sizeof(*New_Frag) +
140 fragP->fr_fix +
141 fragP->fr_var +
142 5);
0e39a8bb 143 /*
8b228fe9
RP
144 * The fragments are the same except
145 * that the "fixed" area is larger
0e39a8bb 146 */
8b228fe9
RP
147 *New_Frag = *fragP;
148 New_Frag->fr_fix += 6;
0e39a8bb 149 /*
8b228fe9
RP
150 * Copy the literal data opening a hole
151 * 2 bytes after "_main" (i.e. just after
152 * the entry mask). Into which we place
153 * the JSB instruction.
0e39a8bb 154 */
8b228fe9
RP
155 New_Frag->fr_literal[0] = fragP->fr_literal[0];
156 New_Frag->fr_literal[1] = fragP->fr_literal[1];
157 New_Frag->fr_literal[2] = 0x16; /* Jsb */
158 New_Frag->fr_literal[3] = 0xef;
159 New_Frag->fr_literal[4] = 0;
160 New_Frag->fr_literal[5] = 0;
161 New_Frag->fr_literal[6] = 0;
162 New_Frag->fr_literal[7] = 0;
163 for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
164 New_Frag->fr_literal[i+6] =
165 fragP->fr_literal[i];
0e39a8bb 166 /*
8b228fe9
RP
167 * Now replace the old fragment with the
168 * newly generated one.
0e39a8bb 169 */
8b228fe9 170 *prev_fragPP = New_Frag;
0e39a8bb 171 /*
8b228fe9 172 * Remember the entry point symbol
0e39a8bb 173 */
8b228fe9 174 Entry_Point_Symbol = symbolP;
0e39a8bb 175 /*
8b228fe9
RP
176 * Scan the text area fixup structures
177 * as offsets in the fragment may have
178 * changed
0e39a8bb 179 */
8b228fe9
RP
180 for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
181 /*
182 * Look for references to this
183 * fragment.
184 */
185 if (fixP->fx_frag == fragP) {
186 /*
187 * Change the fragment
188 * pointer
189 */
190 fixP->fx_frag = New_Frag;
0e39a8bb 191 /*
8b228fe9
RP
192 * If the offset is after
193 * the entry mask we need
194 * to account for the JSB
195 * instruction we just
196 * inserted.
0e39a8bb 197 */
8b228fe9
RP
198 if (fixP->fx_where >= 2)
199 fixP->fx_where += 6;
200 }
201 }
0e39a8bb 202 /*
8b228fe9
RP
203 * Scan the symbols as offsets in the
204 * fragment may have changed
0e39a8bb 205 */
8b228fe9
RP
206 for(symbolP = symbol_rootP;
207 symbolP;
208 symbolP = symbol_next(symbolP)) {
209 /*
210 * Look for references to this
211 * fragment.
212 */
213 if (symbolP->sy_frag == fragP) {
0e39a8bb 214 /*
8b228fe9
RP
215 * Change the fragment
216 * pointer
0e39a8bb 217 */
8b228fe9 218 symbolP->sy_frag = New_Frag;
0e39a8bb 219 /*
8b228fe9
RP
220 * If the offset is after
221 * the entry mask we need
222 * to account for the JSB
223 * instruction we just
224 * inserted.
0e39a8bb 225 */
8b228fe9
RP
226 if (symbolP->sy_nlist.n_value >= 2)
227 symbolP->sy_nlist.n_value += 6;
228 }
0e39a8bb
RP
229 }
230 /*
8b228fe9
RP
231 * Make a symbol reference to
232 * "_c$main_args" so we can get
233 * its address inserted into the
234 * JSB instruction.
0e39a8bb 235 */
8b228fe9
RP
236 symbolP = (symbolS *)xmalloc(sizeof(*symbolP));
237 symbolP->sy_nlist.n_un.n_name = "_c$main_args";
238 symbolP->sy_nlist.n_type = N_UNDF;
239 symbolP->sy_nlist.n_other = 0;
240 symbolP->sy_nlist.n_desc = 0;
241 symbolP->sy_nlist.n_value = 0;
242 symbolP->sy_name_offset = 0;
243 symbolP->sy_number = 0;
244 symbolP->sy_frag = New_Frag;
245 symbolP->sy_forward = 0;
246 /* this actually inserts at the beginning of the list */
247 symbol_append(symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP);
248
249 symbol_rootP = symbolP;
0e39a8bb 250 /*
8b228fe9
RP
251 * Generate a text fixup structure
252 * to get "_c$main_args" stored into the
253 * JSB instruction.
0e39a8bb 254 */
8b228fe9
RP
255 fixP = (struct fix *)xmalloc(sizeof(*fixP));
256 fixP->fx_frag = New_Frag;
257 fixP->fx_where = 4;
258 fixP->fx_addsy = symbolP;
259 fixP->fx_subsy = 0;
260 fixP->fx_offset = 0;
261 fixP->fx_size = sizeof(long);
262 fixP->fx_pcrel = 1;
263 fixP->fx_next = text_fix_root;
264 text_fix_root = fixP;
0e39a8bb 265 /*
8b228fe9 266 * Now make sure we exit from the loop
0e39a8bb 267 */
8b228fe9
RP
268 frchainP = 0;
269 break;
270 }
271 /*
272 * Try the next fragment
273 */
274 prev_fragPP = &fragP->fr_next;
275 fragP = fragP->fr_next;
0e39a8bb 276 }
8b228fe9
RP
277 /*
278 * Try the next fragment chain
279 */
280 if (frchainP) frchainP=frchainP->frch_next;
281 }
282 }
283#endif /* HACK_DEC_C_STARTUP */
284 }
285}
286\f
287/*
288 * Write a VAX/VMS object file (everything else has been done!)
289 */
290VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)
291 unsigned text_siz;
292 unsigned data_siz;
293 struct frag *text_frag_root;
294 struct frag *data_frag_root;
295{
296 register fragS * fragP;
297 register symbolS * symbolP;
298 register symbolS * sp;
299 register struct fix * fixP;
300 register struct VMS_Symbol * vsp;
301 int Local_Initialized_Data_Size = 0;
302 int Psect_Number = 0; /* Psect Index Number */
303 int Text_Psect = -1; /* Text Psect Index */
304 int Data_Psect = -2; /* Data Psect Index JF: Was -1 */
305 int Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */
306
307 /*
308 * Create the VMS object file
309 */
310 Create_VMS_Object_File();
311 /*
312 * Write the module header records
313 */
314 Write_VMS_MHD_Records();
315 \f
316 /*
317 * Generate the VMS object file records
318 * 1st GSD then TIR records
319 */
320
321 /******* Global Symbol Dictionary *******/
322 /*
323 * Define the Text Psect
324 */
325 if (text_siz > 0) {
326 Text_Psect = Psect_Number++;
327 VMS_Psect_Spec("$code",text_siz,"TEXT");
328 }
329 /*
330 * Define the BSS Psect
331 */
332 if (local_bss_counter > 0) {
333 Bss_Psect = Psect_Number++;
334 VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA");
335 }
336 /*
337 * Now scan the symbols and emit the appropriate GSD records
338 */
339 for (sp = symbol_rootP; sp; sp = symbol_next(sp)) {
340 /*
341 * Dispatch on symbol type
342 */
343 switch(sp->sy_type) {
344 /*
345 * Global uninitialized data
346 */
347 case N_UNDF | N_EXT:
348 /*
349 * Make a VMS data symbol entry
350 */
351 vsp = (struct VMS_Symbol *)
352 xmalloc(sizeof(*vsp));
353 vsp->Symbol = sp;
354 vsp->Size = sp->sy_nlist.n_value;
355 vsp->Psect_Index = Psect_Number++;
356 vsp->Psect_Offset = 0;
357 vsp->Next = VMS_Symbols;
358 VMS_Symbols = vsp;
359 sp->sy_number = (int)vsp;
360 /*
361 * Make the psect for this data
362 */
363 if(sp->sy_nlist.n_other)
364 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
365 vsp->Size,
366 "CONST");
367 else
368 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
369 vsp->Size,
370 "COMMON");
371#ifdef NOT_VAX_11_C_COMPATIBLE
372 /*
373 * Place a global symbol at the
374 * beginning of the Psect
375 */
376 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
377 vsp->Psect_Index,
378 0,
379 1);
380#endif NOT_VAX_11_C_COMPATIBLE
381 break;
382 /*
383 * Local uninitialized data
384 */
385 case N_BSS:
386 /*
387 * Make a VMS data symbol entry
388 */
389 vsp = (struct VMS_Symbol *)
390 xmalloc(sizeof(*vsp));
391 vsp->Symbol = sp;
392 vsp->Size = 0;
393 vsp->Psect_Index = Bss_Psect;
394 vsp->Psect_Offset =
395 sp->sy_nlist.n_value -
396 bss_address_frag . fr_address;
397 vsp->Next = VMS_Symbols;
398 VMS_Symbols = vsp;
399 sp->sy_number = (int)vsp;
400 break;
401 /*
402 * Global initialized data
403 */
404 case N_DATA | N_EXT:
405 /*
406 * Make a VMS data symbol entry
407 */
408 vsp = (struct VMS_Symbol *)
409 xmalloc(sizeof(*vsp));
410 vsp->Symbol = sp;
411 vsp->Size = VMS_Initialized_Data_Size(sp,
412 text_siz + data_siz);
413 vsp->Psect_Index = Psect_Number++;
414 vsp->Psect_Offset = 0;
415 vsp->Next = VMS_Symbols;
416 VMS_Symbols = vsp;
417 sp->sy_number = (int)vsp;
418 /*
419 * Make its psect
420 */
421 if(sp->sy_nlist.n_other)
422 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
423 vsp->Size,
424 "CONST");
425 else
426 VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
427 vsp->Size,
428 "COMMON");
429#ifdef NOT_VAX_11_C_COMPATIBLE
430 /*
431 * Place a global symbol at the
432 * beginning of the Psect
433 */
434 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
435 vsp->Psect_Index,
436 0,
437 1);
438#endif NOT_VAX_11_C_COMPATIBLE
439 break;
440 /*
441 * Local initialized data
442 */
443 case N_DATA:
444 /*
445 * Make a VMS data symbol entry
446 */
447 vsp = (struct VMS_Symbol *)
448 xmalloc(sizeof(*vsp));
449 vsp->Symbol = sp;
450 vsp->Size =
451 VMS_Initialized_Data_Size(sp,
452 text_siz + data_siz);
453 vsp->Psect_Index = Data_Psect;
454 vsp->Psect_Offset =
455 Local_Initialized_Data_Size;
456 Local_Initialized_Data_Size += vsp->Size;
457 vsp->Next = VMS_Symbols;
458 VMS_Symbols = vsp;
459 sp->sy_number = (int)vsp;
460 break;
461 /*
462 * Global Text definition
463 */
464 case N_TEXT | N_EXT: {
465 unsigned short Entry_Mask;
466
467 /*
468 * Get the entry mask
469 */
470 fragP = sp->sy_frag;
471 Entry_Mask = (fragP->fr_literal[0] & 0xff) +
472 ((fragP->fr_literal[1] & 0xff)
473 << 8);
474 /*
475 * Define the Procedure entry pt.
476 */
477 VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,
478 Text_Psect,
479 sp->sy_nlist.n_value,
480 Entry_Mask);
481 break;
0e39a8bb 482 }
8b228fe9
RP
483 /*
484 * Local Text definition
485 */
486 case N_TEXT:
487 /*
488 * Make a VMS data symbol entry
489 */
490 if(Text_Psect != -1) {
491 vsp = (struct VMS_Symbol *)
492 xmalloc(sizeof(*vsp));
493 vsp->Symbol = sp;
494 vsp->Size = 0;
495 vsp->Psect_Index = Text_Psect;
496 vsp->Psect_Offset = sp->sy_nlist.n_value;
497 vsp->Next = VMS_Symbols;
498 VMS_Symbols = vsp;
499 sp->sy_number = (int)vsp;
500 }
501 break;
502 /*
503 * Global Reference
504 */
505 case N_UNDF:
506 /*
507 * Make a GSD global symbol reference
508 * record.
509 */
510 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
511 0,
512 0,
513 0);
514 break;
515 /*
516 * Anything else
517 */
518 default:
519 /*
520 * Ignore STAB symbols
521 * Including .stabs emitted by g++
522 */
523 if ((sp->sy_type & N_STAB) != 0 || sp->sy_nlist.n_type==22)
524 break;
525 /*
526 * Error
527 */
528 if(sp->sy_nlist.n_type !=22)
529 printf(" ERROR, unknown type (%d)\n",
530 sp->sy_nlist.n_type);
531 break;
532 }
533 }
534 /*
535 * Define the Data Psect
536 */
537 if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {
0e39a8bb 538 /*
8b228fe9 539 * Do it
0e39a8bb 540 */
8b228fe9
RP
541 Data_Psect = Psect_Number++;
542 VMS_Psect_Spec("$data",
543 Local_Initialized_Data_Size,
544 "DATA");
545 /*
546 * Scan the VMS symbols and fill in the data psect
547 */
548 for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
549 /*
550 * Only look for undefined psects
551 */
552 if (vsp->Psect_Index < 0) {
0e39a8bb 553 /*
8b228fe9 554 * And only initialized data
0e39a8bb 555 */
8b228fe9
RP
556 if (vsp->Symbol->sy_nlist.n_type == N_DATA)
557 vsp->Psect_Index = Data_Psect;
558 }
559 }
560 }
561 \f
562 /******* Text Information and Relocation Records *******/
563 /*
564 * Write the text segment data
565 */
566 if (text_siz > 0) {
567 /*
568 * Scan the text fragments
569 */
570 for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
571 /*
572 * Stop if we get to the data fragments
573 */
574 if (fragP == data_frag_root) break;
575 /*
576 * Ignore fragments with no data
577 */
578 if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
579 continue;
580 /*
581 * Go the the appropriate offset in the
582 * Text Psect.
583 */
584 VMS_Set_Psect(Text_Psect,fragP->fr_address,OBJ$C_TIR);
585 /*
586 * Store the "fixed" part
587 */
588 if (fragP->fr_fix)
589 VMS_Store_Immediate_Data(fragP->fr_literal,
590 fragP->fr_fix,
591 OBJ$C_TIR);
592 /*
593 * Store the "variable" part
594 */
595 if (fragP->fr_var && fragP->fr_offset)
596 VMS_Store_Repeated_Data(fragP->fr_offset,
597 fragP->fr_literal+
598 fragP->fr_fix,
599 fragP->fr_var,
600 OBJ$C_TIR);
0e39a8bb 601 }
0e39a8bb 602 /*
8b228fe9
RP
603 * Now we go through the text segment fixups and
604 * generate TIR records to fix up addresses within
605 * the Text Psect
606 */
607 for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
608 /*
609 * We DO handle the case of "Symbol - Symbol" as
610 * long as it is in the same segment.
611 */
612 if (fixP->fx_subsy && fixP->fx_addsy) {
613 int i;
614
0e39a8bb 615 /*
8b228fe9 616 * They need to be in the same segment
0e39a8bb 617 */
8b228fe9
RP
618 if (fixP->fx_subsy->sy_type !=
619 fixP->fx_addsy->sy_type)
620 error("Fixup data addsy and subsy didn't have the same type");
0e39a8bb 621 /*
8b228fe9
RP
622 * And they need to be in one that we
623 * can check the psect on
0e39a8bb 624 */
8b228fe9
RP
625 if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
626 ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
627 error("Fixup data addsy and subsy didn't have an appropriate type");
0e39a8bb 628 /*
8b228fe9 629 * This had better not be PC relative!
0e39a8bb 630 */
8b228fe9
RP
631 if (fixP->fx_pcrel)
632 error("Fixup data was erroneously \"pcrel\"");
0e39a8bb 633 /*
8b228fe9
RP
634 * Subtract their values to get the
635 * difference.
0e39a8bb 636 */
8b228fe9
RP
637 i = fixP->fx_addsy->sy_value -
638 fixP->fx_subsy->sy_value;
0e39a8bb 639 /*
8b228fe9
RP
640 * Now generate the fixup object records
641 * Set the psect and store the data
0e39a8bb 642 */
8b228fe9
RP
643 VMS_Set_Psect(Text_Psect,
644 fixP->fx_where +
645 fixP->fx_frag->fr_address,
646 OBJ$C_TIR);
647 VMS_Store_Immediate_Data(&i,
648 fixP->fx_size,
649 OBJ$C_TIR);
0e39a8bb 650 /*
8b228fe9 651 * Done
0e39a8bb 652 */
8b228fe9
RP
653 continue;
654 }
655 /*
656 * Size will HAVE to be "long"
657 */
658 if (fixP->fx_size != sizeof(long))
659 error("Fixup datum was not a longword");
660 /*
661 * Symbol must be "added" (if it is ever
662 * subtracted we can
663 * fix this assumption)
664 */
665 if (fixP->fx_addsy == 0)
666 error("Fixup datum was not \"fixP->fx_addsy\"");
667 /*
668 * Store the symbol value in a PIC fashion
669 */
670 VMS_Store_PIC_Symbol_Reference(fixP->fx_addsy,
671 fixP->fx_offset,
672 fixP->fx_pcrel,
673 Text_Psect,
674 fixP->fx_where +
675 fixP->fx_frag->fr_address,
676 OBJ$C_TIR);
677 /*
678 * Check for indirect address reference,
679 * which has to be fixed up (as the linker
680 * will screw it up with TIR$C_STO_PICR).
681 */
682 if (fixP->fx_pcrel)
683 VMS_Fix_Indirect_Reference(Text_Psect,
684 fixP->fx_where +
685 fixP->fx_frag->fr_address,
686 fixP->fx_frag,
687 text_frag_root);
688 }
689 }
690 /*
691 * Store the Data segment:
692 *
693 * Since this is REALLY hard to do any other way,
694 * we actually manufacture the data segment and
695 * the store the appropriate values out of it.
696 */
697 if (data_siz > 0) {
698 char *Data_Segment;
699
700 /*
701 * Allocate the data segment
702 */
703 Data_Segment = (char *)xmalloc(data_siz);
704 /*
705 * Run through the data fragments, filling in the segment
706 */
707 for(fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
708 register long int count;
709 register char * fill_literal;
710 register long int fill_size;
711 int i;
712
713 i = fragP->fr_address - text_siz;
714 if (fragP->fr_fix)
715 bcopy(fragP->fr_literal,
716 Data_Segment + i,
717 fragP->fr_fix);
718 i += fragP->fr_fix;
719
720 fill_literal= fragP -> fr_literal + fragP -> fr_fix;
721 fill_size = fragP -> fr_var;
722 for (count = fragP -> fr_offset; count; count --) {
723 if (fill_size)
724 bcopy(fill_literal,
725 Data_Segment + i,
726 fill_size);
727 i += fill_size;
728 }
0e39a8bb 729 }
0e39a8bb 730 /*
8b228fe9
RP
731 * Now we can run through all the data symbols
732 * and store the data
733 */
734 for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
735 /*
736 * Ignore anything other than data symbols
737 */
738 if ((vsp->Symbol->sy_nlist.n_type & ~N_EXT) != N_DATA)
739 continue;
740 /*
741 * Set the Psect + Offset
742 */
743 VMS_Set_Psect(vsp->Psect_Index,
744 vsp->Psect_Offset,
745 OBJ$C_TIR);
746 /*
747 * Store the data
748 */
749 VMS_Store_Immediate_Data(Data_Segment +
750 vsp->Symbol->sy_nlist.n_value -
751 text_siz,
752 vsp->Size,
753 OBJ$C_TIR);
754 }
0e39a8bb 755 /*
8b228fe9
RP
756 * Now we go through the data segment fixups and
757 * generate TIR records to fix up addresses within
758 * the Data Psects
0e39a8bb 759 */
8b228fe9
RP
760 for(fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
761 /*
762 * Find the symbol for the containing datum
763 */
764 for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
765 /*
766 * Only bother with Data symbols
767 */
768 sp = vsp->Symbol;
769 if ((sp->sy_nlist.n_type & ~N_EXT) != N_DATA)
770 continue;
771 /*
772 * Ignore symbol if After fixup
773 */
774 if (sp->sy_nlist.n_value >
775 (fixP->fx_where +
776 fixP->fx_frag->fr_address))
777 continue;
778 /*
779 * See if the datum is here
780 */
781 if ((sp->sy_nlist.n_value + vsp->Size) <=
782 (fixP->fx_where +
783 fixP->fx_frag->fr_address))
784 continue;
0e39a8bb 785 /*
8b228fe9
RP
786 * We DO handle the case of "Symbol - Symbol" as
787 * long as it is in the same segment.
0e39a8bb 788 */
8b228fe9
RP
789 if (fixP->fx_subsy && fixP->fx_addsy) {
790 int i;
791
792 /*
793 * They need to be in the same segment
794 */
795 if (fixP->fx_subsy->sy_type !=
796 fixP->fx_addsy->sy_type)
797 error("Fixup data addsy and subsy didn't have the same type");
798 /*
799 * And they need to be in one that we
800 * can check the psect on
801 */
802 if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
803 ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
804 error("Fixup data addsy and subsy didn't have an appropriate type");
805 /*
806 * This had better not be PC relative!
807 */
808 if (fixP->fx_pcrel)
809 error("Fixup data was erroneously \"pcrel\"");
810 /*
811 * Subtract their values to get the
812 * difference.
813 */
814 i = fixP->fx_addsy->sy_value -
815 fixP->fx_subsy->sy_value;
816 /*
817 * Now generate the fixup object records
818 * Set the psect and store the data
819 */
820 VMS_Set_Psect(vsp->Psect_Index,
821 fixP->fx_frag->fr_address +
822 fixP->fx_where -
823 vsp->Symbol->sy_value +
824 vsp->Psect_Offset,
825 OBJ$C_TIR);
826 VMS_Store_Immediate_Data(&i,
827 fixP->fx_size,
828 OBJ$C_TIR);
829 /*
830 * Done
831 */
832 break;
0e39a8bb 833 }
8b228fe9
RP
834 /*
835 * Size will HAVE to be "long"
836 */
837 if (fixP->fx_size != sizeof(long))
838 error("Fixup datum was not a longword");
839 /*
840 * Symbol must be "added" (if it is ever
841 * subtracted we can
842 * fix this assumption)
843 */
844 if (fixP->fx_addsy == 0)
845 error("Fixup datum was not \"fixP->fx_addsy\"");
846 /*
847 * Store the symbol value in a PIC fashion
848 */
849 VMS_Store_PIC_Symbol_Reference(
850 fixP->fx_addsy,
851 fixP->fx_offset,
852 fixP->fx_pcrel,
853 vsp->Psect_Index,
854 fixP->fx_frag->fr_address +
855 fixP->fx_where -
856 vsp->Symbol->sy_value +
857 vsp->Psect_Offset,
858 OBJ$C_TIR);
859 /*
860 * Done
861 */
862 break;
863 }
864
865 }
866 }
867 \f
868 /*
869 * Write the Traceback Begin Module record
870 */
871 VMS_TBT_Module_Begin();
872 /*
873 * Scan the symbols and write out the routines
874 * (this makes the assumption that symbols are in
875 * order of ascending text segment offset)
876 */
877{
878 struct symbol *Current_Routine = 0;
879 int Current_Line_Number = 0;
880 int Current_Offset = -1;
881 struct input_file * Current_File;
882
883 /* Output debugging info for global variables and static variables that are not
884 * specific to one routine. We also need to examine all stabs directives, to
885 * find the definitions to all of the advanced data types, and this is done by
886 * VMS_LSYM_Parse. This needs to be done before any definitions are output to
887 * the object file, since there can be forward references in the stabs
888 * directives. When through with parsing, the text of the stabs directive
889 * is altered, with the definitions removed, so that later passes will see
890 * directives as they would be written if the type were already defined.
891 *
892 * We also look for files and include files, and make a list of them. We
893 * examine the source file numbers to establish the actual lines that code was
894 * generated from, and then generate offsets.
895 */
896 VMS_LSYM_Parse();
897 for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
898 /*
899 * Deal with STAB symbols
900 */
901 if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
902 /*
903 * Dispatch on STAB type
904 */
905 switch((unsigned char)symbolP->sy_nlist.n_type) {
906 case N_SLINE:
907 if(symbolP->sy_nlist.n_desc > Current_File->max_line)
908 Current_File->max_line = symbolP->sy_nlist.n_desc;
909 if(symbolP->sy_nlist.n_desc < Current_File->min_line)
910 Current_File->min_line = symbolP->sy_nlist.n_desc;
911 break;
912 case N_SO:
913 Current_File =find_file(symbolP);
914 Current_File->flag = 1;
915 Current_File->min_line = 1;
916 break;
917 case N_SOL:
918 Current_File = find_file(symbolP);
919 break;
920 case N_GSYM:
921 VMS_GSYM_Parse(symbolP,Text_Psect);
922 break;
923 case N_LCSYM:
924 VMS_LCSYM_Parse(symbolP,Text_Psect);
925 break;
926 case N_FUN: /* For static constant symbols */
927 case N_STSYM:
928 VMS_STSYM_Parse(symbolP,Text_Psect);
929 break;
930 }
931 }
932 }
933
934 /* now we take a quick sweep through the files and assign offsets
935 to each one. This will essentially be the starting line number to the
0e39a8bb
RP
936 debugger for each file. Output the info for the debugger to specify the
937 files, and then tell it how many lines to use */
8b228fe9
RP
938{
939 int File_Number = 0;
940 int Debugger_Offset = 0;
941 int file_available;
942 Current_File = file_root;
943 for(Current_File = file_root; Current_File; Current_File = Current_File->next){
944 if(Current_File == (struct input_file*) NULL) break;
945 if(Current_File->max_line == 0) continue;
946 if((strncmp(Current_File->name,"GNU_GXX_INCLUDE:",16) == 0) &&
947 !flagseen['D']) continue;
948 if((strncmp(Current_File->name,"GNU_CC_INCLUDE:",15) == 0) &&
949 !flagseen['D']) continue;
950 /* show a few extra lines at the start of the region selected */
951 if(Current_File->min_line > 2) Current_File->min_line -= 2;
952 Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
953 Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
954 if(Current_File->same_file_fpnt != (struct input_file *) NULL)
955 Current_File->file_number =Current_File->same_file_fpnt->file_number;
956 else {
0e39a8bb
RP
957 Current_File->file_number = ++File_Number;
958 file_available = VMS_TBT_Source_File(Current_File->name,
8b228fe9 959 Current_File->file_number);
0e39a8bb 960 if(!file_available) {Current_File->file_number = 0;
8b228fe9
RP
961 File_Number--;
962 continue;};
963 };
964 VMS_TBT_Source_Lines(Current_File->file_number,
965 Current_File->min_line,
966 Current_File->max_line-Current_File->min_line+1);
967 }; /* for */
968}; /* scope */
969Current_File = (struct input_file*) NULL;
970
971 for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
972 /*
973 * Deal with text symbols
974 */
975 if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
976 /*
977 * Ignore symbols starting with "L",
978 * as they are local symbols
979 */
980 if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
981 /*
982 * If there is a routine start defined,
983 * terminate it.
984 */
985 if (Current_Routine) {
0e39a8bb 986 /*
8b228fe9 987 * End the routine
0e39a8bb 988 */
8b228fe9
RP
989 VMS_TBT_Routine_End(text_siz,Current_Routine);
990 }
991 /*
992 * Store the routine begin traceback info
993 */
994 if(Text_Psect != -1) {
995 VMS_TBT_Routine_Begin(symbolP,Text_Psect);
996 Current_Routine = symbolP;
997 }
998 /* Output local symbols, i.e. all symbols that are associated with a specific
999 * routine. We output them now so the debugger recognizes them as local to
1000 * this routine.
1001 */
0e39a8bb
RP
1002 { symbolS * symbolP1;
1003 char* pnt;
1004 char* pnt1;
8b228fe9
RP
1005 for(symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next(symbolP1)) {
1006 if ((symbolP1->sy_nlist.n_type & N_STAB) == 0) continue;
1007 if (symbolP1->sy_nlist.n_type != N_FUN) continue;
1008 pnt=symbolP->sy_nlist.n_un.n_name;
1009 pnt1=symbolP1->sy_nlist.n_un.n_name;
1010 if(*pnt++ != '_') continue;
1011 while(*pnt++ == *pnt1++) {};
1012 if((*(--pnt) == '\0') && (*(--pnt1) == ':')) break;
1013 };
0e39a8bb 1014 if(symbolP1 != (symbolS *) NULL)
8b228fe9
RP
1015 VMS_DBG_Define_Routine(symbolP1,Current_Routine,Text_Psect);
1016 } /* local symbol block */
1017 /*
1018 * Done
1019 */
1020 continue;
1021 }
1022 /*
1023 * Deal with STAB symbols
1024 */
1025 if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
1026 /*
1027 * Dispatch on STAB type
1028 */
1029 switch((unsigned char)symbolP->sy_nlist.n_type) {
0e39a8bb 1030 /*
8b228fe9 1031 * Line number
0e39a8bb 1032 */
8b228fe9
RP
1033 case N_SLINE:
1034 /* Offset the line into the correct portion
1035 * of the file */
1036 if(Current_File->file_number == 0) break;
1037 /* Sometimes the same offset gets several source
1038 * lines assigned to it.
1039 * We should be selective about which lines
1040 * we allow, we should prefer lines that are
1041 * in the main source file when debugging
1042 * inline functions. */
1043 if((Current_File->file_number != 1) &&
1044 symbolP->sy_nlist.n_value ==
1045 Current_Offset) break;
1046 /* calculate actual debugger source line */
1047 symbolP->sy_nlist.n_desc
1048 += Current_File->offset;
1049 /*
1050 * If this is the 1st N_SLINE, setup
1051 * PC/Line correlation. Otherwise
1052 * do the delta PC/Line. If the offset
1053 * for the line number is not +ve we need
1054 * to do another PC/Line correlation
1055 * setup
1056 */
1057 if (Current_Offset == -1) {
1058 VMS_TBT_Line_PC_Correlation(
0e39a8bb
RP
1059 symbolP->sy_nlist.n_desc,
1060 symbolP->sy_nlist.n_value,
1061 Text_Psect,
1062 0);
8b228fe9
RP
1063 } else {
1064 if ((symbolP->sy_nlist.n_desc -
1065 Current_Line_Number) <= 0) {
0e39a8bb 1066 /*
8b228fe9
RP
1067 * Line delta is not +ve, we
1068 * need to close the line and
1069 * start a new PC/Line
1070 * correlation.
0e39a8bb 1071 */
8b228fe9
RP
1072 VMS_TBT_Line_PC_Correlation(0,
1073 symbolP->sy_nlist.n_value -
1074 Current_Offset,
1075 0,
1076 -1);
1077 VMS_TBT_Line_PC_Correlation(
1078 symbolP->sy_nlist.n_desc,
1079 symbolP->sy_nlist.n_value,
1080 Text_Psect,
1081 0);
1082 } else {
1083 /*
1084 * Line delta is +ve, all is well
1085 */
1086 VMS_TBT_Line_PC_Correlation(
1087 symbolP->sy_nlist.n_desc -
1088 Current_Line_Number,
1089 symbolP->sy_nlist.n_value -
1090 Current_Offset,
1091 0,
1092 1);
1093 }
0e39a8bb 1094 }
0e39a8bb 1095 /*
8b228fe9 1096 * Update the current line/PC
0e39a8bb 1097 */
8b228fe9
RP
1098 Current_Line_Number = symbolP->sy_nlist.n_desc;
1099 Current_Offset = symbolP->sy_nlist.n_value;
0e39a8bb 1100 /*
8b228fe9 1101 * Done
0e39a8bb 1102 */
8b228fe9
RP
1103 break;
1104 /*
1105 * Source file
1106 */
1107 case N_SO:
1108 /*
1109 * Remember that we had a source file
1110 * and emit the source file debugger
1111 * record
1112 */
1113 Current_File =
1114 find_file(symbolP);
1115 break;
1116 /* We need to make sure that we are really in the actual source file when
1117 * we compute the maximum line number. Otherwise the debugger gets really
1118 * confused */
1119 case N_SOL:
1120 Current_File =
1121 find_file(symbolP);
1122 break;
1123 }
0e39a8bb 1124 }
8b228fe9
RP
1125 }
1126 /*
1127 * If there is a routine start defined,
1128 * terminate it (and the line numbers)
1129 */
1130 if (Current_Routine) {
0e39a8bb 1131 /*
8b228fe9 1132 * Terminate the line numbers
0e39a8bb 1133 */
8b228fe9
RP
1134 VMS_TBT_Line_PC_Correlation(0,
1135 text_siz - Current_Routine->sy_nlist.n_value,
1136 0,
1137 -1);
0e39a8bb 1138 /*
8b228fe9 1139 * Terminate the routine
0e39a8bb 1140 */
8b228fe9
RP
1141 VMS_TBT_Routine_End(text_siz,Current_Routine);
1142 }
1143}
1144/*
1145 * Write the Traceback End Module TBT record
1146 */
1147VMS_TBT_Module_End();
1148\f
1149/*
1150 * Write the End Of Module record
1151 */
1152if (Entry_Point_Symbol == 0)
1153 Write_VMS_EOM_Record(-1,0);
1154else
1155 Write_VMS_EOM_Record(Text_Psect,
1156 Entry_Point_Symbol->sy_nlist.n_value);
0e39a8bb 1157\f
8b228fe9
RP
1158/*
1159 * All done, close the object file
1160 */
1161Close_VMS_Object_File();
0e39a8bb
RP
1162}
1163
1164\f
8b228fe9 1165/****** VMS OBJECT FILE HACKING ROUTINES *******/
0e39a8bb
RP
1166
1167
1168/*
1169 * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
1170 */
1171static int VMS_Object_File_FD; /* File Descriptor for object file */
1172static char Object_Record_Buffer[512]; /* Buffer for object file records */
1173static int Object_Record_Offset; /* Offset to end of data */
1174static int Current_Object_Record_Type; /* Type of record in above */
1175
1176/*
1177 * Macros for placing data into the object record buffer
1178 */
1179#define PUT_LONG(val) *((long *)(Object_Record_Buffer + \
8b228fe9
RP
1180 Object_Record_Offset)) = val; \
1181 Object_Record_Offset += sizeof(long)
0e39a8bb
RP
1182
1183#define PUT_SHORT(val) *((short *)(Object_Record_Buffer + \
8b228fe9
RP
1184 Object_Record_Offset)) = val; \
1185 Object_Record_Offset += sizeof(short)
0e39a8bb
RP
1186
1187#define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val
1188
1189#define PUT_COUNTED_STRING(cp) {\
8b228fe9
RP
1190 register char *p = cp; \
1191 PUT_CHAR(strlen(p)); \
1192 while(*p) PUT_CHAR(*p++);}
0e39a8bb
RP
1193
1194/*
1195 * Macro for determining if a Name has psect attributes attached
1196 * to it.
1197 */
1198#define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
1199#define PSECT_ATTRIBUTES_STRING_LENGTH 18
1200
1201#define HAS_PSECT_ATTRIBUTES(Name) \
8b228fe9
RP
1202(strncmp((Name[0] == '_' ? Name + 1 : Name), \
1203 PSECT_ATTRIBUTES_STRING, \
1204 PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
0e39a8bb
RP
1205
1206\f
1207/*
1208 * Create the VMS object file
1209 */
1210Create_VMS_Object_File()
1211{
1212#ifdef eunice
8b228fe9 1213 VMS_Object_File_FD = creat(out_file_name, 0777, "var");
0e39a8bb 1214#else eunice
8b228fe9 1215 VMS_Object_File_FD = creat(out_file_name, 0, "rfm=var");
0e39a8bb 1216#endif eunice
8b228fe9
RP
1217 /*
1218 * Deal with errors
1219 */
1220 if (VMS_Object_File_FD < 0) {
1221 char Error_Line[256];
1222
1223 sprintf(Error_Line,"Couldn't create VMS object file \"%s\"",
1224 out_file_name);
1225 error(Error_Line);
1226 }
1227 /*
1228 * Initialize object file hacking variables
1229 */
1230 Object_Record_Offset = 0;
1231 Current_Object_Record_Type = -1;
0e39a8bb
RP
1232}
1233
1234\f
1235/*
1236 * Declare a particular type of object file record
1237 */
1238Set_VMS_Object_File_Record(Type)
8b228fe9 1239 int Type;
0e39a8bb 1240{
8b228fe9
RP
1241 /*
1242 * If the type matches, we are done
1243 */
1244 if (Type == Current_Object_Record_Type) return;
1245 /*
1246 * Otherwise: flush the buffer
1247 */
1248 Flush_VMS_Object_Record_Buffer();
1249 /*
1250 * Set the new type
1251 */
1252 Current_Object_Record_Type = Type;
0e39a8bb
RP
1253}
1254
1255\f
1256/*
1257 * Flush the object record buffer to the object file
1258 */
1259Flush_VMS_Object_Record_Buffer()
1260{
8b228fe9
RP
1261 int i;
1262
1263 /*
1264 * If the buffer is empty, we are done
1265 */
1266 if (Object_Record_Offset == 0) return;
1267 /*
1268 * Write the data to the file
1269 */
1270 i= write(VMS_Object_File_FD,
1271 Object_Record_Buffer,
1272 Object_Record_Offset);
1273 if (i != Object_Record_Offset)
1274 error("I/O error writing VMS object file");
1275 /*
1276 * The buffer is now empty
1277 */
1278 Object_Record_Offset = 0;
0e39a8bb
RP
1279}
1280
1281\f
1282/*
1283 * Close the VMS Object file
1284 */
1285Close_VMS_Object_File()
1286{
8b228fe9 1287 close(VMS_Object_File_FD);
0e39a8bb
RP
1288}
1289
1290\f
1291/*
1292 * Write the MHD (Module Header) records
1293 */
1294Write_VMS_MHD_Records()
1295{
8b228fe9
RP
1296 register char *cp,*cp1;
1297 register int i;
1298 struct {int Size; char *Ptr;} Descriptor;
1299 char Module_Name[256];
1300 char Now[17];
1301
1302 /*
1303 * We are writing a module header record
1304 */
1305 Set_VMS_Object_File_Record(OBJ$C_HDR);
1306 /*
1307 * ***************************
1308 * *MAIN MODULE HEADER RECORD*
1309 * ***************************
1310 *
1311 * Store record type and header type
1312 */
1313 PUT_CHAR(OBJ$C_HDR);
1314 PUT_CHAR(MHD$C_MHD);
1315 /*
1316 * Structure level is 0
1317 */
1318 PUT_CHAR(OBJ$C_STRLVL);
1319 /*
1320 * Maximum record size is size of the object record buffer
1321 */
1322 PUT_SHORT(sizeof(Object_Record_Buffer));
1323 /*
1324 * Get module name (the FILENAME part of the object file)
1325 */
1326 cp = out_file_name;
1327 cp1 = Module_Name;
1328 while(*cp) {
1329 if ((*cp == ']') || (*cp == '>') ||
1330 (*cp == ':') || (*cp == '/')) {
1331 cp1 = Module_Name;
1332 cp++;
1333 continue;
0e39a8bb 1334 }
8b228fe9
RP
1335 *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
1336 }
1337 *cp1 = 0;
1338 /*
1339 * Limit it to 31 characters and store in the object record
1340 */
1341 while(--cp1 >= Module_Name)
1342 if (*cp1 == '.') *cp1 = 0;
1343 if (strlen(Module_Name) > 31) {
1344 if(flagseen['+'])
1345 printf("%s: Module name truncated: %s\n", myname, Module_Name);
1346 Module_Name[31] = 0;
1347 }
1348 PUT_COUNTED_STRING(Module_Name);
1349 /*
1350 * Module Version is "V1.0"
1351 */
1352 PUT_COUNTED_STRING("V1.0");
1353 /*
1354 * Creation time is "now" (17 chars of time string)
1355 */
1356 Descriptor.Size = 17;
1357 Descriptor.Ptr = Now;
1358 sys$asctim(0,&Descriptor,0,0);
1359 for(i = 0; i < 17; i++) PUT_CHAR(Now[i]);
1360 /*
1361 * Patch time is "never" (17 zeros)
1362 */
1363 for(i = 0; i < 17; i++) PUT_CHAR(0);
1364 /*
1365 * Flush the record
1366 */
1367 Flush_VMS_Object_Record_Buffer();
1368 /*
1369 * *************************
1370 * *LANGUAGE PROCESSOR NAME*
1371 * *************************
1372 *
1373 * Store record type and header type
1374 */
1375 PUT_CHAR(OBJ$C_HDR);
1376 PUT_CHAR(MHD$C_LNM);
1377 /*
1378 * Store language processor name and version
1379 * (not a counted string!)
1380 */
1381 cp = compiler_version_string;
1382 if (cp == 0) {
1383 cp ="GNU AS V";
1384 while(*cp) PUT_CHAR(*cp++);
1385 cp = strchr(&version_string,'.');
1386 while(*cp != ' ') cp--; cp++;
1387 };
1388 while(*cp >= 32) PUT_CHAR(*cp++);
1389 /*
1390 * Flush the record
1391 */
1392 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
1393}
1394
1395\f
1396/*
1397 * Write the EOM (End Of Module) record
1398 */
1399Write_VMS_EOM_Record(Psect, Offset)
8b228fe9
RP
1400 int Psect;
1401 int Offset;
0e39a8bb 1402{
8b228fe9
RP
1403 /*
1404 * We are writing an end-of-module record
1405 */
1406 Set_VMS_Object_File_Record(OBJ$C_EOM);
1407 /*
1408 * Store record Type
1409 */
1410 PUT_CHAR(OBJ$C_EOM);
1411 /*
1412 * Store the error severity (0)
1413 */
1414 PUT_CHAR(0);
1415 /*
1416 * Store the entry point, if it exists
1417 */
1418 if (Psect >= 0) {
0e39a8bb 1419 /*
8b228fe9 1420 * Store the entry point Psect
0e39a8bb 1421 */
8b228fe9 1422 PUT_CHAR(Psect);
0e39a8bb 1423 /*
8b228fe9 1424 * Store the entry point Psect offset
0e39a8bb 1425 */
8b228fe9
RP
1426 PUT_LONG(Offset);
1427 }
1428 /*
1429 * Flush the record
1430 */
1431 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
1432}
1433
1434\f
1435/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
1436
1437static int
8b228fe9
RP
1438 hash_string (ptr)
1439unsigned char *ptr;
0e39a8bb 1440{
8b228fe9
RP
1441 register unsigned char *p = ptr;
1442 register unsigned char *end = p + strlen(ptr);
1443 register unsigned char c;
1444 register int hash = 0;
1445
1446 while (p != end)
0e39a8bb 1447 {
8b228fe9
RP
1448 c = *p++;
1449 hash = ((hash<<3) + (hash<<15) + (hash>>28) + c);
0e39a8bb 1450 }
8b228fe9 1451 return hash;
0e39a8bb
RP
1452}
1453
1454/*
1455 * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
1456 */
1457VMS_Case_Hack_Symbol(In,Out)
8b228fe9
RP
1458 register char *In;
1459 register char *Out;
0e39a8bb 1460{
8b228fe9
RP
1461 long int init = 0;
1462 long int result;
1463 char *pnt;
1464 char *new_name;
1465 char *old_name;
1466 register int i;
1467 int destructor = 0; /*hack to allow for case sens in a destructor*/
1468 int truncate = 0;
1469 int Case_Hack_Bits = 0;
1470 int Saw_Dollar = 0;
1471 static char Hex_Table[16] =
1472 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1473
1474 /*
1475 * Kill any leading "_"
1476 */
1477 if (*In == '_') In++;
1478
1479 new_name=Out; /* save this for later*/
1480
1481 if((In[0]=='_')&&(In[1]=='$')&&(In[2]=='_'))
1482 destructor=1;
1483
1484 /* We may need to truncate the symbol, save the hash for later*/
1485 if(strlen(In)>23) result = hash_string(In);
1486 /*
1487 * Is there a Psect Attribute to skip??
1488 */
1489 if (HAS_PSECT_ATTRIBUTES(In)) {
0e39a8bb 1490 /*
8b228fe9 1491 * Yes: Skip it
0e39a8bb 1492 */
8b228fe9
RP
1493 In += PSECT_ATTRIBUTES_STRING_LENGTH;
1494 while(*In) {
1495 if ((In[0] == '$') && (In[1] == '$')) {
1496 In += 2;
1497 break;
1498 }
1499 In++;
0e39a8bb 1500 }
8b228fe9
RP
1501 }
1502
1503 old_name=In;
1504 /* if(strlen(In) > 31 && flagseen['+'])
1505 printf("%s: Symbol name truncated: %s\n",myname,In);*/
1506 /*
1507 * Do the case conversion
1508 */
1509 i = 23; /* Maximum of 23 chars */
1510 while(*In && (--i >= 0)) {
1511 Case_Hack_Bits <<= 1;
1512 if (*In == '$') Saw_Dollar = 1;
1513 if ((destructor==1)&&(i==21)) Saw_Dollar = 0;
1514 if (isupper(*In)) {
1515 *Out++ = *In++;
1516 Case_Hack_Bits |= 1;
1517 } else {
1518 *Out++ = islower(*In) ? toupper(*In++) : *In++;
0e39a8bb 1519 }
8b228fe9
RP
1520 }
1521 /*
1522 * If we saw a dollar sign, we don't do case hacking
1523 */
1524 if(flagseen['h'] || Saw_Dollar)
1525 Case_Hack_Bits = 0;
1526
1527 /*
1528 * If we have more than 23 characters and everything is lowercase
1529 * we can insert the full 31 characters
1530 */
1531 if (*In) {
1532 /*
1533 * We have more than 23 characters
1534 * If we must add the case hack, then we have truncated the str
1535 */
1536 pnt=Out;
1537 truncate=1;
1538 if (Case_Hack_Bits == 0) {
1539 /*
1540 * And so far they are all lower case:
1541 * Check up to 8 more characters
1542 * and ensure that they are lowercase
1543 */
1544 if(flagseen['h'])
1545 i=8;
1546 else
1547 for(i = 0; (In[i] != 0) && (i < 8); i++)
1548 if (isupper(In[i]) && !Saw_Dollar)
1549 break;
1550 if(In[i]==0)
1551 truncate=0;
1552
1553 if ((i >= 8) || (In[i] == 0)) {
0e39a8bb 1554 /*
8b228fe9
RP
1555 * They are: Copy up to 31 characters
1556 * to the output string
0e39a8bb 1557 */
8b228fe9
RP
1558 i = 8;
1559 while((--i >= 0) && (*In))
1560 *Out++ = islower(*In) ?
1561 toupper(*In++) :
1562 *In++;
1563 }
0e39a8bb 1564 }
8b228fe9
RP
1565 }
1566 /*
1567 * If there were any uppercase characters in the name we
1568 * take on the case hacking string
1569 */
1570
1571 /* Old behavior for regular GNU-C compiler */
1572 if (!flagseen['+'])
1573 truncate=0;
1574 if ((Case_Hack_Bits != 0)||(truncate==1)) {
1575 if(truncate==0) {
1576 *Out++ = '_';
1577 for(i = 0; i < 6; i++) {
1578 *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
1579 Case_Hack_Bits >>= 4;
1580 }
1581 *Out++ = 'X';
1582 } else {
1583 Out=pnt; /*Cut back to 23 characters maximum */
1584 *Out++ = '_';
1585 for( i=0; i < 7; i++) {
1586 init = result & 0x01f;
1587 if (init < 10)
1588 *Out++='0'+init;
1589 else
1590 *Out++ = 'A'+init-10;
1591 result = result >> 5;
1592 }
1593 }
1594 } /*Case Hack */
1595 /*
1596 * Done
1597 */
1598 *Out = 0;
1599 if( truncate==1 && flagseen['+'] && flagseen['H'])
1600 printf("%s: Symbol %s replaced by %s\n",myname,old_name,new_name);
0e39a8bb
RP
1601}
1602
1603\f
1604/*
1605 * Scan a symbol name for a psect attribute specification
1606 */
1607VMS_Modify_Psect_Attributes(Name, Attribute_Pointer)
8b228fe9
RP
1608 char *Name;
1609 int *Attribute_Pointer;
0e39a8bb 1610{
8b228fe9
RP
1611 register int i;
1612 register char *cp;
1613 int Negate;
1614 static struct {
1615 char *Name;
1616 int Value;
1617 } Attributes[] = {
1618 {"PIC", GPS$M_PIC},
1619{"LIB", GPS$M_LIB},
1620{"OVR", GPS$M_OVR},
1621{"REL", GPS$M_REL},
1622{"GBL", GPS$M_GBL},
1623{"SHR", GPS$M_SHR},
1624{"EXE", GPS$M_EXE},
1625{"RD", GPS$M_RD},
1626{"WRT", GPS$M_WRT},
1627{"VEC", GPS$M_VEC},
1628{0, 0}};
0e39a8bb 1629
8b228fe9
RP
1630/*
1631 * Kill leading "_"
1632 */
1633if (*Name == '_') Name++;
1634 /*
1635 * Check for a PSECT attribute list
1636 */
1637 if (!HAS_PSECT_ATTRIBUTES(Name)) return; /* If not, return */
1638 /*
1639 * Skip the attribute list indicator
1640 */
1641 Name += PSECT_ATTRIBUTES_STRING_LENGTH;
1642 /*
1643 * Process the attributes ("_" separated, "$" terminated)
1644 */
1645 while(*Name != '$') {
0e39a8bb 1646 /*
8b228fe9 1647 * Assume not negating
0e39a8bb 1648 */
8b228fe9
RP
1649 Negate = 0;
1650 /*
1651 * Check for "NO"
1652 */
1653 if ((Name[0] == 'N') && (Name[1] == 'O')) {
0e39a8bb 1654 /*
8b228fe9 1655 * We are negating (and skip the NO)
0e39a8bb 1656 */
8b228fe9
RP
1657 Negate = 1;
1658 Name += 2;
1659 }
1660 /*
1661 * Find the token delimiter
1662 */
1663 cp = Name;
1664 while(*cp && (*cp != '_') && (*cp != '$')) cp++;
1665 /*
1666 * Look for the token in the attribute list
1667 */
1668 for(i = 0; Attributes[i].Name; i++) {
1669 /*
1670 * If the strings match, set/clear the attr.
1671 */
1672 if (strncmp(Name, Attributes[i].Name, cp - Name) == 0) {
1673 /*
1674 * Set or clear
1675 */
1676 if (Negate)
1677 *Attribute_Pointer &=
1678 ~Attributes[i].Value;
1679 else
1680 *Attribute_Pointer |=
1681 Attributes[i].Value;
1682 /*
1683 * Done
1684 */
1685 break;
0e39a8bb 1686 }
8b228fe9
RP
1687 }
1688 /*
1689 * Now skip the attribute
1690 */
1691 Name = cp;
1692 if (*Name == '_') Name++;
1693}
1694/*
1695 * Done
1696 */
1697return;
0e39a8bb
RP
1698}
1699
1700\f
1701/*
1702 * Define a psect
1703 */
1704VMS_Psect_Spec(Name, Size, Type)
8b228fe9
RP
1705 char *Name;
1706 int Size;
1707 char *Type;
0e39a8bb 1708{
8b228fe9
RP
1709 char Local[32];
1710 int Psect_Attributes;
1711
1712 /*
1713 * We are writing a GSD record
1714 */
1715 Set_VMS_Object_File_Record(OBJ$C_GSD);
1716 /*
1717 * If the buffer is empty we must insert the GSD record type
1718 */
1719 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
1720 /*
1721 * We are writing a PSECT definition subrecord
1722 */
1723 PUT_CHAR(GSD$C_PSC);
1724 /*
1725 * Psects are always LONGWORD aligned
1726 */
1727 PUT_CHAR(2);
1728 /*
1729 * Generate the appropriate PSECT flags given the PSECT type
1730 */
1731 if (strcmp(Type,"COMMON") == 0) {
0e39a8bb 1732 /*
8b228fe9 1733 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
0e39a8bb 1734 */
8b228fe9
RP
1735 Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
1736 GPS$M_SHR|GPS$M_RD|GPS$M_WRT);
1737 } else if (strcmp(Type,"CONST") == 0) {
0e39a8bb 1738 /*
8b228fe9 1739 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD
0e39a8bb 1740 */
8b228fe9
RP
1741 Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
1742 GPS$M_SHR|GPS$M_RD);
1743 } else if (strcmp(Type,"DATA") == 0) {
0e39a8bb 1744 /*
8b228fe9 1745 * The Data psects are PIC,REL,RD,WRT
0e39a8bb 1746 */
8b228fe9
RP
1747 Psect_Attributes =
1748 (GPS$M_PIC|GPS$M_REL|GPS$M_RD|GPS$M_WRT);
1749 } else if (strcmp(Type,"TEXT") == 0) {
0e39a8bb 1750 /*
8b228fe9 1751 * The Text psects are PIC,REL,SHR,EXE,RD
0e39a8bb 1752 */
8b228fe9
RP
1753 Psect_Attributes =
1754 (GPS$M_PIC|GPS$M_REL|GPS$M_SHR|
1755 GPS$M_EXE|GPS$M_RD);
1756 } else {
0e39a8bb 1757 /*
8b228fe9 1758 * Error: Unknown psect type
0e39a8bb 1759 */
8b228fe9
RP
1760 error("Unknown VMS psect type");
1761 }
1762 /*
1763 * Modify the psect attributes according to any attribute string
1764 */
1765 if (HAS_PSECT_ATTRIBUTES(Name))
1766 VMS_Modify_Psect_Attributes(Name,&Psect_Attributes);
1767 /*
1768 * Specify the psect attributes
1769 */
1770 PUT_SHORT(Psect_Attributes);
1771 /*
1772 * Specify the allocation
1773 */
1774 PUT_LONG(Size);
1775 /*
1776 * Finally, the psect name
1777 */
1778 VMS_Case_Hack_Symbol(Name,Local);
1779 PUT_COUNTED_STRING(Local);
1780 /*
1781 * Flush the buffer if it is more than 75% full
1782 */
1783 if (Object_Record_Offset >
1784 (sizeof(Object_Record_Buffer)*3/4))
1785 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
1786}
1787
1788\f
1789/*
1790 * Define a global symbol
1791 */
1792VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined)
8b228fe9
RP
1793 char *Name;
1794 int Psect_Number;
1795 int Psect_Offset;
0e39a8bb 1796{
8b228fe9
RP
1797 char Local[32];
1798
1799 /*
1800 * We are writing a GSD record
1801 */
1802 Set_VMS_Object_File_Record(OBJ$C_GSD);
1803 /*
1804 * If the buffer is empty we must insert the GSD record type
1805 */
1806 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
1807 /*
1808 * We are writing a Global symbol definition subrecord
1809 */
1810 if (Psect_Number <= 255) {
1811 PUT_CHAR(GSD$C_SYM);
1812 } else {
1813 PUT_CHAR(GSD$C_SYMW);
1814 }
1815 /*
1816 * Data type is undefined
1817 */
1818 PUT_CHAR(0);
1819 /*
1820 * Switch on Definition/Reference
1821 */
1822 if (Defined) {
0e39a8bb 1823 /*
8b228fe9
RP
1824 * Definition:
1825 * Flags = "RELOCATABLE" and "DEFINED"
0e39a8bb 1826 */
8b228fe9 1827 PUT_SHORT(GSY$M_DEF|GSY$M_REL);
0e39a8bb 1828 /*
8b228fe9 1829 * Psect Number
0e39a8bb
RP
1830 */
1831 if (Psect_Number <= 255) {
8b228fe9 1832 PUT_CHAR(Psect_Number);
0e39a8bb 1833 } else {
8b228fe9 1834 PUT_SHORT(Psect_Number);
0e39a8bb
RP
1835 }
1836 /*
8b228fe9 1837 * Offset
0e39a8bb 1838 */
8b228fe9
RP
1839 PUT_LONG(Psect_Offset);
1840 } else {
0e39a8bb 1841 /*
8b228fe9
RP
1842 * Reference:
1843 * Flags = "RELOCATABLE"
0e39a8bb 1844 */
8b228fe9
RP
1845 PUT_SHORT(GSY$M_REL);
1846 }
1847 /*
1848 * Finally, the global symbol name
1849 */
1850 VMS_Case_Hack_Symbol(Name,Local);
1851 PUT_COUNTED_STRING(Local);
1852 /*
1853 * Flush the buffer if it is more than 75% full
1854 */
1855 if (Object_Record_Offset >
1856 (sizeof(Object_Record_Buffer)*3/4))
1857 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
1858}
1859
1860\f
1861/*
1862 * Define a procedure entry pt/mask
1863 */
1864VMS_Procedure_Entry_Pt(Name, Psect_Number, Psect_Offset, Entry_Mask)
8b228fe9
RP
1865 char *Name;
1866 int Psect_Number;
1867 int Psect_Offset;
1868 int Entry_Mask;
0e39a8bb 1869{
8b228fe9
RP
1870 char Local[32];
1871
1872 /*
1873 * We are writing a GSD record
1874 */
1875 Set_VMS_Object_File_Record(OBJ$C_GSD);
1876 /*
1877 * If the buffer is empty we must insert the GSD record type
1878 */
1879 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
1880 /*
1881 * We are writing a Procedure Entry Pt/Mask subrecord
1882 */
1883 if (Psect_Number <= 255) {
1884 PUT_CHAR(GSD$C_EPM);
1885 } else {
1886 PUT_CHAR(GSD$C_EPMW);
1887 }
1888 /*
1889 * Data type is undefined
1890 */
1891 PUT_CHAR(0);
1892 /*
1893 * Flags = "RELOCATABLE" and "DEFINED"
1894 */
1895 PUT_SHORT(GSY$M_DEF|GSY$M_REL);
1896 /*
1897 * Psect Number
1898 */
1899 if (Psect_Number <= 255) {
1900 PUT_CHAR(Psect_Number);
1901 } else {
1902 PUT_SHORT(Psect_Number);
1903 }
1904 /*
1905 * Offset
1906 */
1907 PUT_LONG(Psect_Offset);
1908 /*
1909 * Entry mask
1910 */
1911 PUT_SHORT(Entry_Mask);
1912 /*
1913 * Finally, the global symbol name
1914 */
1915 VMS_Case_Hack_Symbol(Name,Local);
1916 PUT_COUNTED_STRING(Local);
1917 /*
1918 * Flush the buffer if it is more than 75% full
1919 */
1920 if (Object_Record_Offset >
1921 (sizeof(Object_Record_Buffer)*3/4))
1922 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
1923}
1924
1925\f
1926/*
1927 * Set the current location counter to a particular Psect and Offset
1928 */
1929VMS_Set_Psect(Psect_Index, Offset, Record_Type)
8b228fe9
RP
1930 int Psect_Index;
1931 int Offset;
1932 int Record_Type;
0e39a8bb 1933{
8b228fe9
RP
1934 /*
1935 * We are writing a "Record_Type" record
1936 */
1937 Set_VMS_Object_File_Record(Record_Type);
1938 /*
1939 * If the buffer is empty we must insert the record type
1940 */
1941 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
1942 /*
1943 * Stack the Psect base + Longword Offset
1944 */
1945 if (Psect_Index < 255) {
1946 PUT_CHAR(TIR$C_STA_PL);
1947 PUT_CHAR(Psect_Index);
1948 } else {
1949 PUT_CHAR(TIR$C_STA_WPL);
1950 PUT_SHORT(Psect_Index);
1951 }
1952 PUT_LONG(Offset);
1953 /*
1954 * Set relocation base
1955 */
1956 PUT_CHAR(TIR$C_CTL_SETRB);
1957 /*
1958 * Flush the buffer if it is more than 75% full
1959 */
1960 if (Object_Record_Offset >
1961 (sizeof(Object_Record_Buffer)*3/4))
1962 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
1963}
1964
1965/*
1966 * Make a data reference
1967 */
1968VMS_Set_Data(Psect_Index, Offset, Record_Type,Force)
8b228fe9
RP
1969 int Psect_Index;
1970 int Offset;
1971 int Record_Type;
1972 int Force;
0e39a8bb 1973{
8b228fe9
RP
1974 /*
1975 * We are writing a "Record_Type" record
1976 */
1977 Set_VMS_Object_File_Record(Record_Type);
1978 /*
1979 * If the buffer is empty we must insert the record type
1980 */
1981 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
1982 /*
1983 * Stack the Psect base + Longword Offset
1984 */
1985 if(Force==1){
1986 if(Psect_Index>127){
1987 PUT_CHAR(TIR$C_STA_WPL);
1988 PUT_SHORT(Psect_Index);
1989 PUT_LONG(Offset);}
1990 else {
1991 PUT_CHAR(TIR$C_STA_PL);
1992 PUT_CHAR(Psect_Index);
1993 PUT_LONG(Offset);}
1994 } else {if(Offset>32767){
1995 PUT_CHAR(TIR$C_STA_WPL);
1996 PUT_SHORT(Psect_Index);
1997 PUT_LONG(Offset);}
1998 else if(Offset>127){
1999 PUT_CHAR(TIR$C_STA_WPW);
2000 PUT_SHORT(Psect_Index);
2001 PUT_SHORT(Offset);}
2002 else{
2003 PUT_CHAR(TIR$C_STA_WPB);
2004 PUT_SHORT(Psect_Index);
2005 PUT_CHAR(Offset);};};
2006 /*
2007 * Set relocation base
2008 */
2009 PUT_CHAR(TIR$C_STO_PIDR);
2010 /*
2011 * Flush the buffer if it is more than 75% full
2012 */
2013 if (Object_Record_Offset >
2014 (sizeof(Object_Record_Buffer)*3/4))
2015 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
2016}
2017
2018/*
2019 * Make a debugger reference to a struct, union or enum.
2020 */
2021VMS_Store_Struct(int Struct_Index)
2022{
8b228fe9
RP
2023 /*
2024 * We are writing a "OBJ$C_DBG" record
2025 */
2026 Set_VMS_Object_File_Record(OBJ$C_DBG);
2027 /*
2028 * If the buffer is empty we must insert the record type
2029 */
2030 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2031 PUT_CHAR(TIR$C_STA_UW);
2032 PUT_SHORT(Struct_Index);
2033 PUT_CHAR(TIR$C_CTL_STKDL);
2034 PUT_CHAR(TIR$C_STO_L);
2035 /*
2036 * Flush the buffer if it is more than 75% full
2037 */
2038 if (Object_Record_Offset >
2039 (sizeof(Object_Record_Buffer)*3/4))
2040 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
2041}
2042
2043/*
2044 * Make a debugger reference to partially define a struct, union or enum.
2045 */
2046VMS_Def_Struct(int Struct_Index)
2047{
8b228fe9
RP
2048 /*
2049 * We are writing a "OBJ$C_DBG" record
2050 */
2051 Set_VMS_Object_File_Record(OBJ$C_DBG);
2052 /*
2053 * If the buffer is empty we must insert the record type
2054 */
2055 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2056 PUT_CHAR(TIR$C_STA_UW);
2057 PUT_SHORT(Struct_Index);
2058 PUT_CHAR(TIR$C_CTL_DFLOC);
2059 /*
2060 * Flush the buffer if it is more than 75% full
2061 */
2062 if (Object_Record_Offset >
2063 (sizeof(Object_Record_Buffer)*3/4))
2064 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
2065}
2066
2067VMS_Set_Struct(int Struct_Index)
2068{/* see previous functions for comments */
8b228fe9
RP
2069 Set_VMS_Object_File_Record(OBJ$C_DBG);
2070 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2071 PUT_CHAR(TIR$C_STA_UW);
2072 PUT_SHORT(Struct_Index);
2073 PUT_CHAR(TIR$C_CTL_STLOC);
2074 if (Object_Record_Offset >
2075 (sizeof(Object_Record_Buffer)*3/4))
2076 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
2077}
2078\f
2079/*
2080 * Store immediate data in current Psect
2081 */
2082VMS_Store_Immediate_Data(Pointer, Size, Record_Type)
8b228fe9
RP
2083 register char *Pointer;
2084 int Size;
2085 int Record_Type;
0e39a8bb 2086{
8b228fe9
RP
2087 register int i;
2088
2089 /*
2090 * We are writing a "Record_Type" record
2091 */
2092 Set_VMS_Object_File_Record(Record_Type);
2093 /*
2094 * We can only store 128 bytes at a time
2095 */
2096 while(Size > 0) {
0e39a8bb 2097 /*
8b228fe9 2098 * Store a maximum of 128 bytes
0e39a8bb 2099 */
8b228fe9
RP
2100 i = (Size > 128) ? 128 : Size;
2101 Size -= i;
0e39a8bb 2102 /*
8b228fe9
RP
2103 * If we cannot accommodate this record, flush the
2104 * buffer.
0e39a8bb 2105 */
8b228fe9
RP
2106 if ((Object_Record_Offset + i + 1) >=
2107 sizeof(Object_Record_Buffer))
2108 Flush_VMS_Object_Record_Buffer();
2109 /*
2110 * If the buffer is empty we must insert record type
2111 */
2112 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2113 /*
2114 * Store the count
2115 */
2116 PUT_CHAR(-i & 0xff);
2117 /*
2118 * Store the data
2119 */
2120 while(--i >= 0) PUT_CHAR(*Pointer++);
2121 /*
2122 * Flush the buffer if it is more than 75% full
2123 */
2124 if (Object_Record_Offset >
2125 (sizeof(Object_Record_Buffer)*3/4))
2126 Flush_VMS_Object_Record_Buffer();
2127 }
0e39a8bb
RP
2128}
2129
2130\f
2131/*
2132 * Store repeated immediate data in current Psect
2133 */
2134VMS_Store_Repeated_Data(Repeat_Count,Pointer, Size, Record_Type)
8b228fe9
RP
2135 int Repeat_Count;
2136 register char *Pointer;
2137 int Size;
2138 int Record_Type;
0e39a8bb 2139{
8b228fe9
RP
2140
2141 /*
2142 * Ignore zero bytes/words/longwords
2143 */
2144 if ((Size == sizeof(char)) && (*Pointer == 0)) return;
2145 if ((Size == sizeof(short)) && (*(short *)Pointer == 0)) return;
2146 if ((Size == sizeof(long)) && (*(long *)Pointer == 0)) return;
2147 /*
2148 * If the data is too big for a TIR$C_STO_RIVB sub-record
2149 * then we do it manually
2150 */
2151 if (Size > 255) {
2152 while(--Repeat_Count >= 0)
2153 VMS_Store_Immediate_Data(Pointer,Size,Record_Type);
2154 return;
2155 }
2156 /*
2157 * We are writing a "Record_Type" record
2158 */
2159 Set_VMS_Object_File_Record(Record_Type);
2160 /*
2161 * If the buffer is empty we must insert record type
2162 */
2163 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2164 /*
2165 * Stack the repeat count
2166 */
2167 PUT_CHAR(TIR$C_STA_LW);
2168 PUT_LONG(Repeat_Count);
2169 /*
2170 * And now the command and its data
2171 */
2172 PUT_CHAR(TIR$C_STO_RIVB);
2173 PUT_CHAR(Size);
2174 while(--Size >= 0) PUT_CHAR(*Pointer++);
2175 /*
2176 * Flush the buffer if it is more than 75% full
2177 */
2178 if (Object_Record_Offset >
2179 (sizeof(Object_Record_Buffer)*3/4))
2180 Flush_VMS_Object_Record_Buffer();
2181}
0e39a8bb 2182
8b228fe9
RP
2183\f
2184/*
2185 * Store a Position Independent Reference
2186 */
2187VMS_Store_PIC_Symbol_Reference(Symbol, Offset, PC_Relative,
2188 Psect, Psect_Offset, Record_Type)
2189 struct symbol *Symbol;
2190 int Offset;
2191 int PC_Relative;
2192 int Psect;
2193 int Psect_Offset;
2194 int Record_Type;
2195{
2196 register struct VMS_Symbol *vsp =
2197 (struct VMS_Symbol *)(Symbol->sy_number);
2198 char Local[32];
2199
2200 /*
2201 * We are writing a "Record_Type" record
2202 */
2203 Set_VMS_Object_File_Record(Record_Type);
2204 /*
2205 * If the buffer is empty we must insert record type
2206 */
2207 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2208 /*
2209 * Set to the appropriate offset in the Psect
2210 */
2211 if (PC_Relative) {
0e39a8bb 2212 /*
8b228fe9
RP
2213 * For a Code reference we need to fix the operand
2214 * specifier as well (so back up 1 byte)
0e39a8bb 2215 */
8b228fe9
RP
2216 VMS_Set_Psect(Psect, Psect_Offset - 1, Record_Type);
2217 } else {
0e39a8bb 2218 /*
8b228fe9 2219 * For a Data reference we just store HERE
0e39a8bb 2220 */
8b228fe9
RP
2221 VMS_Set_Psect(Psect, Psect_Offset, Record_Type);
2222 }
2223 /*
2224 * Make sure we are still generating a "Record Type" record
2225 */
2226 if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
2227 /*
2228 * Dispatch on symbol type (so we can stack its value)
2229 */
2230 switch(Symbol->sy_nlist.n_type) {
0e39a8bb 2231 /*
8b228fe9 2232 * Global symbol
0e39a8bb 2233 */
8b228fe9
RP
2234#ifdef NOT_VAX_11_C_COMPATIBLE
2235 case N_UNDF | N_EXT:
2236 case N_DATA | N_EXT:
2237#endif NOT_VAX_11_C_COMPATIBLE
2238 case N_UNDF:
2239 case N_TEXT | N_EXT:
0e39a8bb 2240 /*
8b228fe9 2241 * Get the symbol name (case hacked)
0e39a8bb 2242 */
8b228fe9 2243 VMS_Case_Hack_Symbol(Symbol->sy_nlist.n_un.n_name,Local);
0e39a8bb 2244 /*
8b228fe9 2245 * Stack the global symbol value
0e39a8bb 2246 */
8b228fe9
RP
2247 PUT_CHAR(TIR$C_STA_GBL);
2248 PUT_COUNTED_STRING(Local);
2249 if (Offset) {
2250 /*
2251 * Stack the longword offset
2252 */
2253 PUT_CHAR(TIR$C_STA_LW);
2254 PUT_LONG(Offset);
2255 /*
2256 * Add the two, leaving the result on the stack
2257 */
2258 PUT_CHAR(TIR$C_OPR_ADD);
2259 }
2260 break;
0e39a8bb 2261 /*
8b228fe9 2262 * Uninitialized local data
0e39a8bb 2263 */
8b228fe9 2264 case N_BSS:
0e39a8bb 2265 /*
8b228fe9 2266 * Stack the Psect (+offset)
0e39a8bb 2267 */
8b228fe9
RP
2268 if (vsp->Psect_Index < 255) {
2269 PUT_CHAR(TIR$C_STA_PL);
2270 PUT_CHAR(vsp->Psect_Index);
2271 } else {
2272 PUT_CHAR(TIR$C_STA_WPL);
2273 PUT_SHORT(vsp->Psect_Index);
2274 }
2275 PUT_LONG(vsp->Psect_Offset + Offset);
2276 break;
0e39a8bb 2277 /*
8b228fe9 2278 * Local text
0e39a8bb 2279 */
8b228fe9 2280 case N_TEXT:
0e39a8bb 2281 /*
8b228fe9 2282 * Stack the Psect (+offset)
0e39a8bb 2283 */
8b228fe9
RP
2284 if (vsp->Psect_Index < 255) {
2285 PUT_CHAR(TIR$C_STA_PL);
2286 PUT_CHAR(vsp->Psect_Index);
0e39a8bb 2287 } else {
8b228fe9
RP
2288 PUT_CHAR(TIR$C_STA_WPL);
2289 PUT_SHORT(vsp->Psect_Index);
0e39a8bb 2290 }
8b228fe9
RP
2291 PUT_LONG(Symbol->sy_nlist.n_value);
2292 break;
0e39a8bb 2293 /*
8b228fe9 2294 * Initialized local or global data
0e39a8bb 2295 */
8b228fe9 2296 case N_DATA:
0e39a8bb 2297#ifndef NOT_VAX_11_C_COMPATIBLE
8b228fe9
RP
2298 case N_UNDF | N_EXT:
2299 case N_DATA | N_EXT:
0e39a8bb 2300#endif NOT_VAX_11_C_COMPATIBLE
0e39a8bb 2301 /*
8b228fe9 2302 * Stack the Psect (+offset)
0e39a8bb 2303 */
8b228fe9
RP
2304 if (vsp->Psect_Index < 255) {
2305 PUT_CHAR(TIR$C_STA_PL);
2306 PUT_CHAR(vsp->Psect_Index);
2307 } else {
2308 PUT_CHAR(TIR$C_STA_WPL);
2309 PUT_SHORT(vsp->Psect_Index);
2310 }
2311 PUT_LONG(vsp->Psect_Offset + Offset);
2312 break;
2313 }
2314 /*
2315 * Store either a code or data reference
2316 */
2317 PUT_CHAR(PC_Relative ? TIR$C_STO_PICR : TIR$C_STO_PIDR);
2318 /*
2319 * Flush the buffer if it is more than 75% full
2320 */
2321 if (Object_Record_Offset >
2322 (sizeof(Object_Record_Buffer)*3/4))
2323 Flush_VMS_Object_Record_Buffer();
0e39a8bb
RP
2324}
2325
2326\f
2327/*
2328 * Check in the text area for an indirect pc-relative reference
2329 * and fix it up with addressing mode 0xff [PC indirect]
2330 *
2331 * THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
2332 * PIC CODE GENERATING FIXUP ROUTINE.
2333 */
2334VMS_Fix_Indirect_Reference(Text_Psect, Offset, fragP, text_frag_root)
8b228fe9
RP
2335 int Text_Psect;
2336 int Offset;
2337 register fragS *fragP;
2338 struct frag *text_frag_root;
0e39a8bb 2339{
8b228fe9
RP
2340 /*
2341 * The addressing mode byte is 1 byte before the address
2342 */
2343 Offset--;
2344 /*
2345 * Is it in THIS frag??
2346 */
2347 if ((Offset < fragP->fr_address) ||
2348 (Offset >= (fragP->fr_address + fragP->fr_fix))) {
0e39a8bb 2349 /*
8b228fe9
RP
2350 * We need to search for the fragment containing this
2351 * Offset
0e39a8bb 2352 */
8b228fe9
RP
2353 for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
2354 if ((Offset >= fragP->fr_address) &&
2355 (Offset < (fragP->fr_address + fragP->fr_fix)))
2356 break;
2357 }
0e39a8bb 2358 /*
8b228fe9 2359 * If we couldn't find the frag, things are BAD!!
0e39a8bb 2360 */
8b228fe9
RP
2361 if (fragP == 0)
2362 error("Couldn't find fixup fragment when checking for indirect reference");
2363 }
2364 /*
2365 * Check for indirect PC relative addressing mode
2366 */
2367 if (fragP->fr_literal[Offset - fragP->fr_address] == (char)0xff) {
2368 static char Address_Mode = 0xff;
2369
0e39a8bb 2370 /*
8b228fe9
RP
2371 * Yes: Store the indirect mode back into the image
2372 * to fix up the damage done by STO_PICR
0e39a8bb 2373 */
8b228fe9
RP
2374 VMS_Set_Psect(Text_Psect,Offset,OBJ$C_TIR);
2375 VMS_Store_Immediate_Data(&Address_Mode,1,OBJ$C_TIR);
2376 }
0e39a8bb
RP
2377}
2378
2379\f
2380/*
2381 * Write the Traceback Module Begin record
2382 */
2383VMS_TBT_Module_Begin()
2384{
8b228fe9
RP
2385 register char *cp,*cp1;
2386 int Size;
2387 char Module_Name[256];
2388 char Local[256];
2389
2390 /*
2391 * Get module name (the FILENAME part of the object file)
2392 */
2393 cp = out_file_name;
2394 cp1 = Module_Name;
2395 while(*cp) {
2396 if ((*cp == ']') || (*cp == '>') ||
2397 (*cp == ':') || (*cp == '/')) {
2398 cp1 = Module_Name;
2399 cp++;
2400 continue;
0e39a8bb 2401 }
8b228fe9
RP
2402 *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
2403 }
2404 *cp1 = 0;
2405 /*
2406 * Limit it to 31 characters
2407 */
2408 while(--cp1 >= Module_Name)
2409 if (*cp1 == '.') *cp1 = 0;
2410 if (strlen(Module_Name) > 31) {
2411 if(flagseen['+'])
2412 printf("%s: Module name truncated: %s\n",myname, Module_Name);
2413 Module_Name[31] = 0;
2414 }
2415 /*
2416 * Arrange to store the data locally (leave room for size byte)
2417 */
2418 cp = Local+1;
2419 /*
2420 * Begin module
2421 */
2422 *cp++ = DST$C_MODBEG;
2423 /*
2424 * Unused
2425 */
2426 *cp++ = 0;
2427 /*
2428 * Language type == "C"
2429 */
2430 *(long *)cp = DST$C_C;
2431 cp += sizeof(long);
2432 /*
2433 * Store the module name
2434 */
2435 *cp++ = strlen(Module_Name);
2436 cp1 = Module_Name;
2437 while(*cp1) *cp++ = *cp1++;
2438 /*
2439 * Now we can store the record size
2440 */
2441 Size = (cp - Local);
2442 Local[0] = Size-1;
2443 /*
2444 * Put it into the object record
2445 */
2446 VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
0e39a8bb
RP
2447}
2448
2449\f
2450/*
2451 * Write the Traceback Module End record
8b228fe9 2452 */
0e39a8bb
RP
2453VMS_TBT_Module_End()
2454{
8b228fe9
RP
2455 char Local[2];
2456
2457 /*
2458 * End module
2459 */
2460 Local[0] = 1;
2461 Local[1] = DST$C_MODEND;
2462 /*
2463 * Put it into the object record
2464 */
2465 VMS_Store_Immediate_Data(Local, 2, OBJ$C_TBT);
0e39a8bb
RP
2466}
2467
2468\f
2469/*
2470 * Write the Traceback Routine Begin record
2471 */
2472VMS_TBT_Routine_Begin(symbolP, Psect)
8b228fe9
RP
2473 struct symbol *symbolP;
2474 int Psect;
0e39a8bb 2475{
8b228fe9
RP
2476 register char *cp,*cp1;
2477 char *Name;
2478 int Offset;
2479 int Size;
2480 char Local[512];
2481
2482 /*
2483 * Strip the leading "_" from the name
2484 */
2485 Name = symbolP->sy_nlist.n_un.n_name;
2486 if (*Name == '_') Name++;
2487 /*
2488 * Get the text psect offset
2489 */
2490 Offset = symbolP->sy_nlist.n_value;
2491 /*
2492 * Calculate the record size
2493 */
2494 Size = 1+1+4+1+strlen(Name);
2495 /*
2496 * Record Size
2497 */
2498 Local[0] = Size;
2499 /*
2500 * Begin Routine
2501 */
2502 Local[1] = DST$C_RTNBEG;
2503 /*
2504 * Uses CallS/CallG
2505 */
2506 Local[2] = 0;
2507 /*
2508 * Store the data so far
2509 */
2510 VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
2511 /*
2512 * Make sure we are still generating a OBJ$C_TBT record
2513 */
2514 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
2515 /*
2516 * Now get the symbol address
2517 */
2518 PUT_CHAR(TIR$C_STA_WPL);
2519 PUT_SHORT(Psect);
2520 PUT_LONG(Offset);
2521 /*
2522 * Store the data reference
2523 */
2524 PUT_CHAR(TIR$C_STO_PIDR);
2525 /*
2526 * Store the counted string as data
2527 */
2528 cp = Local;
2529 cp1 = Name;
2530 Size = strlen(cp1) + 1;
2531 *cp++ = Size - 1;
2532 while(*cp1) *cp++ = *cp1++;
2533 VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
0e39a8bb
RP
2534}
2535
2536\f
2537/*
2538 * Write the Traceback Routine End record
2539 * We *must* search the symbol table to find the next routine, since
2540 * the assember has a way of reassembling the symbol table OUT OF ORDER
2541 * Thus the next routine in the symbol list is not necessarily the
2542 * next one in memory. For debugging to work correctly we must know the
2543 * size of the routine.
2544 */
2545VMS_TBT_Routine_End(Max_Size,sp)
8b228fe9
RP
2546 int Max_Size;
2547 symbolS *sp;
0e39a8bb 2548{
8b228fe9
RP
2549 symbolS *symbolP;
2550 int Size = 0x7fffffff;
2551 char Local[16];
2552
2553
2554 for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
2555 if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
0e39a8bb
RP
2556 if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
2557 if((symbolP->sy_nlist.n_value > sp->sy_nlist.n_value) &&
8b228fe9 2558 (symbolP->sy_nlist.n_value < Size ))
0e39a8bb 2559 Size = symbolP->sy_nlist.n_value;
8b228fe9 2560 /* check if gcc_compiled. has size of zero */
0e39a8bb 2561 if((symbolP->sy_nlist.n_value == sp->sy_nlist.n_value) &&
8b228fe9
RP
2562 sp != symbolP &&
2563 !strcmp(sp->sy_nlist.n_un.n_name,"gcc_compiled."))
0e39a8bb 2564 Size = symbolP->sy_nlist.n_value;
8b228fe9 2565
0e39a8bb 2566 };
8b228fe9
RP
2567 };
2568 if(Size == 0x7fffffff) Size = Max_Size;
2569 Size -= sp->sy_nlist.n_value; /* and get the size of the routine */
2570 /*
2571 * Record Size
2572 */
2573 Local[0] = 6;
2574 /*
2575 * End of Routine
2576 */
2577 Local[1] = DST$C_RTNEND;
2578 /*
2579 * Unused
2580 */
2581 Local[2] = 0;
2582 /*
2583 * Size of routine
2584 */
2585 *((long *)(Local+3)) = Size;
2586 /*
2587 * Store the record
2588 */
2589 VMS_Store_Immediate_Data(Local,7, OBJ$C_TBT);
0e39a8bb
RP
2590}
2591/*
2592 * Write the Traceback Block End record
2593 */
2594VMS_TBT_Block_Begin(symbolP, Psect, Name)
8b228fe9
RP
2595 struct symbol *symbolP;
2596 int Psect;
2597 char* Name;
0e39a8bb 2598{
8b228fe9
RP
2599 register char *cp,*cp1;
2600 int Offset;
2601 int Size;
2602 char Local[512];
2603 /*
2604 * Begin block
2605 */
2606 Size = 1+1+4+1+strlen(Name);
2607 /*
2608 * Record Size
2609 */
2610 Local[0] = Size;
2611 /*
2612 * Begin Block - We simulate with a phony routine
2613 */
2614 Local[1] = DST$C_BLKBEG;
2615 /*
2616 * Uses CallS/CallG
2617 */
2618 Local[2] = 0;
2619 /*
2620 * Store the data so far
2621 */
2622 VMS_Store_Immediate_Data(Local, 3, OBJ$C_DBG);
2623 /*
2624 * Make sure we are still generating a OBJ$C_DBG record
2625 */
2626 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
2627 /*
2628 * Now get the symbol address
2629 */
2630 PUT_CHAR(TIR$C_STA_WPL);
2631 PUT_SHORT(Psect);
2632 /*
2633 * Get the text psect offset
2634 */
2635 Offset = symbolP->sy_nlist.n_value;
2636 PUT_LONG(Offset);
2637 /*
2638 * Store the data reference
2639 */
2640 PUT_CHAR(TIR$C_STO_PIDR);
2641 /*
2642 * Store the counted string as data
2643 */
2644 cp = Local;
2645 cp1 = Name;
2646 Size = strlen(cp1) + 1;
2647 *cp++ = Size - 1;
2648 while(*cp1) *cp++ = *cp1++;
2649 VMS_Store_Immediate_Data(Local, Size, OBJ$C_DBG);
0e39a8bb
RP
2650}
2651
2652\f
2653/*
2654 * Write the Traceback Block End record
2655 */
2656VMS_TBT_Block_End(int Size)
2657{
8b228fe9
RP
2658 char Local[16];
2659
2660 /*
2661 * End block - simulate with a phony end routine
2662 */
2663 Local[0] = 6;
2664 Local[1] = DST$C_BLKEND;
2665 *((long *)(Local+3)) = Size;
2666 /*
2667 * Unused
2668 */
2669 Local[2] = 0;
2670 VMS_Store_Immediate_Data(Local,7, OBJ$C_DBG);
0e39a8bb
RP
2671}
2672
2673
2674\f
2675/*
2676 * Write a Line number / PC correlation record
2677 */
2678VMS_TBT_Line_PC_Correlation(Line_Number, Offset, Psect, Do_Delta)
8b228fe9
RP
2679 int Line_Number;
2680 int Offset;
2681 int Psect;
2682 int Do_Delta;
0e39a8bb 2683{
8b228fe9
RP
2684 register char *cp;
2685 char Local[64];
2686
2687 /*
2688 * If not delta, set our PC/Line number correlation
2689 */
2690 if (Do_Delta == 0) {
0e39a8bb 2691 /*
8b228fe9 2692 * Size
0e39a8bb 2693 */
8b228fe9 2694 Local[0] = 1+1+2+1+4;
0e39a8bb 2695 /*
8b228fe9 2696 * Line Number/PC correlation
0e39a8bb 2697 */
8b228fe9 2698 Local[1] = DST$C_LINE_NUM;
0e39a8bb 2699 /*
8b228fe9 2700 * Set Line number
0e39a8bb 2701 */
8b228fe9
RP
2702 Local[2] = DST$C_SET_LINE_NUM;
2703 *((unsigned short *)(Local+3)) = Line_Number-1;
0e39a8bb 2704 /*
8b228fe9 2705 * Set PC
0e39a8bb 2706 */
8b228fe9
RP
2707 Local[5] = DST$C_SET_ABS_PC;
2708 VMS_Store_Immediate_Data(Local, 6, OBJ$C_TBT);
0e39a8bb 2709 /*
8b228fe9 2710 * Make sure we are still generating a OBJ$C_TBT record
0e39a8bb 2711 */
8b228fe9
RP
2712 if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
2713 if (Psect < 255) {
2714 PUT_CHAR(TIR$C_STA_PL);
2715 PUT_CHAR(Psect);
2716 } else {
2717 PUT_CHAR(TIR$C_STA_WPL);
2718 PUT_SHORT(Psect);
2719 }
2720 PUT_LONG(Offset);
2721 PUT_CHAR(TIR$C_STO_PIDR);
0e39a8bb 2722 /*
8b228fe9 2723 * Do a PC offset of 0 to register the line number
0e39a8bb 2724 */
8b228fe9
RP
2725 Local[0] = 2;
2726 Local[1] = DST$C_LINE_NUM;
2727 Local[2] = 0; /* Increment PC by 0 and register line # */
2728 VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
2729 } else {
2730 /*
2731 * If Delta is negative, terminate the line numbers
2732 */
2733 if (Do_Delta < 0) {
2734 Local[0] = 1+1+4;
2735 Local[1] = DST$C_LINE_NUM;
2736 Local[2] = DST$C_TERM_L;
2737 *((long *)(Local+3)) = Offset;
2738 VMS_Store_Immediate_Data(Local, 7, OBJ$C_TBT);
2739 /*
2740 * Done
2741 */
2742 return;
2743 }
0e39a8bb 2744 /*
8b228fe9 2745 * Do a PC/Line delta
0e39a8bb 2746 */
8b228fe9
RP
2747 cp = Local+1;
2748 *cp++ = DST$C_LINE_NUM;
2749 if (Line_Number > 1) {
2750 /*
2751 * We need to increment the line number
2752 */
2753 if (Line_Number-1 <= 255) {
2754 *cp++ = DST$C_INCR_LINUM;
2755 *cp++ = Line_Number-1;
2756 } else {
2757 *cp++ = DST$C_INCR_LINUM_W;
2758 *(short *)cp = Line_Number-1;
2759 cp += sizeof(short);
2760 }
2761 }
0e39a8bb 2762 /*
8b228fe9 2763 * Increment the PC
0e39a8bb 2764 */
8b228fe9
RP
2765 if (Offset <= 128) {
2766 *cp++ = -Offset;
2767 } else {
2768 if (Offset < 0x10000) {
2769 *cp++ = DST$C_DELTA_PC_W;
2770 *(short *)cp = Offset;
2771 cp += sizeof(short);
2772 } else {
2773 *cp++ = DST$C_DELTA_PC_L;
2774 *(long *)cp = Offset;
2775 cp += sizeof(long);
2776 }
2777 }
2778 Local[0] = cp - (Local+1);
0e39a8bb 2779 VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
8b228fe9
RP
2780 }
2781}
2782
2783\f
2784/*
2785 * Describe a source file to the debugger
2786 */
2787VMS_TBT_Source_File(Filename, ID_Number)
2788 char *Filename;
2789 int ID_Number;
2790{
2791 register char *cp,*cp1;
2792 int Status,i;
2793 char Local[512];
2794 static struct FAB Fab;
2795 static struct NAM Nam;
2796 static struct XABDAT Date_Xab;
2797 static struct XABFHC File_Header_Xab;
2798 char Es_String[255],Rs_String[255];
2799
2800 /*
2801 * Setup the Fab
2802 */
2803 Fab.fab$b_bid = FAB$C_BID;
2804 Fab.fab$b_bln = sizeof(Fab);
2805 Fab.fab$l_nam = (&Nam);
2806 Fab.fab$l_xab = (struct XAB *)&Date_Xab;
2807 /*
2808 * Setup the Nam block so we can find out the FULL name
2809 * of the source file.
2810 */
2811 Nam.nam$b_bid = NAM$C_BID;
2812 Nam.nam$b_bln = sizeof(Nam);
2813 Nam.nam$l_rsa = Rs_String;
2814 Nam.nam$b_rss = sizeof(Rs_String);
2815 Nam.nam$l_esa = Es_String;
2816 Nam.nam$b_ess = sizeof(Es_String);
2817 /*
2818 * Setup the Date and File Header Xabs
2819 */
2820 Date_Xab.xab$b_cod = XAB$C_DAT;
2821 Date_Xab.xab$b_bln = sizeof(Date_Xab);
2822 Date_Xab.xab$l_nxt = (char *)&File_Header_Xab;
2823 File_Header_Xab.xab$b_cod = XAB$C_FHC;
2824 File_Header_Xab.xab$b_bln = sizeof(File_Header_Xab);
2825 /* ((struct XAB *)&Date_Xab)->xab$b_cod = XAB$C_DAT; */
2826 /* ((struct XAB *)&Date_Xab)->xab$b_bln = sizeof(Date_Xab); */
2827 /* ((struct XAB *)&Date_Xab)->xab$l_nxt = (struct XAB *)&File_Header_Xab; */
2828 /* ((struct XAB *)&File_Header_Xab)->xab$b_cod = XAB$C_FHC; */
2829 /* ((struct XAB *)&File_Header_Xab)->xab$b_bln = sizeof(File_Header_Xab); */
2830 /*
2831 * Get the file information
2832 */
2833 Fab.fab$l_fna = Filename;
2834 Fab.fab$b_fns = strlen(Filename);
2835 Status = sys$open(&Fab);
2836 if (!(Status & 1)) {
2837 printf("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
2838 Filename, Status);
2839 return(0);
2840 }
2841 sys$close(&Fab);
2842 /*
2843 * Calculate the size of the resultant string
2844 */
2845 i = Nam.nam$b_rsl;
2846 /*
2847 * Size of record
2848 */
2849 Local[0] = 1+1+1+1+1+2+8+4+2+1+1+i+1;
2850 /*
2851 * Source declaration
2852 */
2853 Local[1] = DST$C_SOURCE;
2854 /*
2855 * Make formfeeds count as source records
2856 */
2857 Local[2] = DST$C_SRC_FORMFEED;
2858 /*
2859 * Declare source file
2860 */
2861 Local[3] = DST$C_SRC_DECLFILE;
2862 Local[4] = 1+2+8+4+2+1+1+i+1;
2863 cp = Local+5;
2864 /*
2865 * Flags
2866 */
2867 *cp++ = 0;
2868 /*
2869 * File ID
2870 */
2871 *(short *)cp = ID_Number;
2872 cp += sizeof(short);
2873 /*
2874 * Creation Date
2875 */
2876 *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[0];
2877 cp += sizeof(long);
2878 *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[1];
2879 cp += sizeof(long);
2880 /*
2881 * End of file block
2882 */
2883 *(long *)cp = File_Header_Xab.xab$l_ebk;
2884 cp += sizeof(long);
2885 /*
2886 * First free byte
2887 */
2888 *(short *)cp = File_Header_Xab.xab$w_ffb;
2889 cp += sizeof(short);
2890 /*
2891 * Record format
2892 */
2893 *cp++ = File_Header_Xab.xab$b_rfo;
2894 /*
2895 * Filename
2896 */
2897 *cp++ = i;
2898 cp1 = Rs_String;
2899 while(--i >= 0) *cp++ = *cp1++;
2900 /*
2901 * Library module name (none)
2902 */
2903 *cp++ = 0;
2904 /*
2905 * Done
2906 */
2907 VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
0e39a8bb
RP
2908}
2909
2910\f
2911/*
2912 * Give the number of source lines to the debugger
2913 */
2914VMS_TBT_Source_Lines(ID_Number,Starting_Line_Number,Number_Of_Lines)
8b228fe9
RP
2915 int ID_Number;
2916 int Starting_Line_Number;
2917 int Number_Of_Lines;
0e39a8bb 2918{
8b228fe9
RP
2919 char *cp,*cp1;
2920 char Local[16];
2921
2922 /*
2923 * Size of record
2924 */
2925 Local[0] = 1+1+2+1+4+1+2;
2926 /*
2927 * Source declaration
2928 */
2929 Local[1] = DST$C_SOURCE;
2930 /*
2931 * Set Source File
2932 */
2933 cp = Local+2;
2934 *cp++ = DST$C_SRC_SETFILE;
2935 /*
2936 * File ID Number
2937 */
2938 *(short *)cp = ID_Number;
2939 cp += sizeof(short);
2940 /*
2941 * Set record number
2942 */
2943 *cp++ = DST$C_SRC_SETREC_L;
2944 *(long *)cp = Starting_Line_Number;
2945 cp += sizeof(long);
2946 /*
2947 * Define lines
2948 */
2949 *cp++ = DST$C_SRC_DEFLINES_W;
2950 *(short *)cp = Number_Of_Lines;
2951 cp += sizeof(short);
2952 /*
2953 * Done
2954 */
2955 VMS_Store_Immediate_Data(Local, cp-Local, OBJ$C_TBT);
0e39a8bb
RP
2956}
2957
2958\f
2959/*
2960 * Given the pointer to a symbol we calculate how big the data at the
2961 * symbol is. We do this by looking for the next symbol (local or
2962 * global) which will indicate the start of another datum.
2963 */
2964int VMS_Initialized_Data_Size(sp, End_Of_Data)
8b228fe9
RP
2965 register struct symbol *sp;
2966 int End_Of_Data;
0e39a8bb 2967{
8b228fe9
RP
2968 register struct symbol *sp1,*Next_Symbol;
2969
2970 /*
2971 * Find the next symbol
2972 * it delimits this datum
2973 */
2974 Next_Symbol = 0;
2975 for (sp1 = symbol_rootP; sp1; sp1 = symbol_next(sp1)) {
0e39a8bb 2976 /*
8b228fe9 2977 * The data type must match
0e39a8bb 2978 */
8b228fe9
RP
2979 if ((sp1->sy_nlist.n_type & ~N_EXT) != N_DATA) continue;
2980 /*
2981 * The symbol must be AFTER this symbol
2982 */
2983 if (sp1->sy_nlist.n_value <= sp->sy_nlist.n_value) continue;
2984 /*
2985 * We ignore THIS symbol
2986 */
2987 if (sp1 == sp) continue;
0e39a8bb 2988 /*
8b228fe9
RP
2989 * If there is already a candidate selected for the
2990 * next symbol, see if we are a better candidate
0e39a8bb 2991 */
8b228fe9
RP
2992 if (Next_Symbol) {
2993 /*
2994 * We are a better candidate if we are "closer"
2995 * to the symbol
2996 */
2997 if (sp1->sy_nlist.n_value >
2998 Next_Symbol->sy_nlist.n_value)
2999 continue;
3000 /*
3001 * Win: Make this the candidate
3002 */
3003 Next_Symbol = sp1;
3004 } else {
3005 /*
3006 * This is the 1st candidate
3007 */
3008 Next_Symbol = sp1;
3009 }
3010 }
3011 /*
3012 * Calculate its size
3013 */
3014 return(Next_Symbol ?
3015 (Next_Symbol->sy_nlist.n_value -
3016 sp->sy_nlist.n_value) :
3017 (End_Of_Data - sp->sy_nlist.n_value));
0e39a8bb
RP
3018}
3019
3020\f
3021
3022/* this routine locates a file in the list of files. If an entry does not
3023 * exist, one is created. For include files, a new entry is always created
3024 * such that inline functions can be properly debugged */
3025struct input_file *
8b228fe9 3026 find_file(sp)
0e39a8bb
RP
3027symbolS * sp;
3028{
8b228fe9
RP
3029 struct input_file * same_file;
3030 struct input_file * fpnt;
3031 same_file = (struct input_file*) NULL;
3032 for(fpnt = file_root; fpnt; fpnt = fpnt->next){
3033 if(fpnt == (struct input_file*) NULL) break;
3034 if(fpnt->spnt == sp) return fpnt;
3035 };
3036 for(fpnt = file_root; fpnt; fpnt = fpnt->next){
3037 if(fpnt == (struct input_file*) NULL) break;
3038 if (strcmp(sp->sy_nlist.n_un.n_name,fpnt->name) == 0){
3039 if(fpnt->flag == 1)return fpnt;
3040 same_file = fpnt;
3041 break;
0e39a8bb 3042 };
8b228fe9
RP
3043 };
3044 fpnt = (struct input_file*) malloc(sizeof(struct input_file));
3045 if(file_root == (struct input_file*) NULL) file_root = fpnt;
3046 else {
3047 struct input_file * fpnt1;
3048 for(fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next);
3049 fpnt1->next = fpnt;
3050 };
3051 fpnt->next = (struct input_file*) NULL;
3052 fpnt->name = sp->sy_nlist.n_un.n_name;
3053 fpnt->min_line = 0x7fffffff;
3054 fpnt->max_line = 0;
3055 fpnt->offset = 0;
3056 fpnt->flag = 0;
3057 fpnt->file_number = 0;
3058 fpnt->spnt = sp;
3059 fpnt->same_file_fpnt = same_file;
3060 return fpnt;
0e39a8bb
RP
3061}
3062
3063\f
3064/*
3065 * This is a hacked _doprnt() for VAX-11 "C". It understands that
3066 * it is ONLY called by as_fatal(Format, Args) with a pointer to the
3067 * "Args" argument. From this we can make it all work right!
3068 */
3069#ifndef eunice
3070_doprnt(Format, a, f)
8b228fe9
RP
3071 char *Format;
3072 FILE *f;
3073 char **a;
0e39a8bb 3074{
8b228fe9
RP
3075 int Nargs = ((int *)a)[-2]; /* This understands as_fatal() */
3076
3077 switch(Nargs) {
3078 default: fprintf(f,"_doprnt error on \"%s\"!!",Format); break;
3079 case 1: fprintf(f,Format); break;
3080 case 2: fprintf(f,Format,a[0]); break;
3081 case 3: fprintf(f,Format,a[0],a[1]); break;
3082 case 4: fprintf(f,Format,a[0],a[1],a[2]); break;
3083 case 5: fprintf(f,Format,a[0],a[1],a[2],a[3]); break;
3084 case 6: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4]); break;
3085 case 7: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5]); break;
3086 case 8: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;
3087 case 9: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); break;
3088 case 10: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]); break;
3089 }
0e39a8bb
RP
3090}
3091
3092#endif /* eunice */
3093
3094#endif /* VMS */
3095
3096char const_flag = 0;
3097void s_const();
3098
3099void
8b228fe9 3100 s_const()
0e39a8bb 3101{
8b228fe9
RP
3102 register int temp;
3103
3104 temp = get_absolute_expression ();
3105 subseg_new (SEG_DATA, (subsegT)temp);
3106 const_flag = 1;
3107 demand_empty_rest_of_line();
0e39a8bb
RP
3108}
3109
3110obj_crawl_symbol_chain() {
8b228fe9
RP
3111 /* JF deal with forward references first. . . */
3112 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
0e39a8bb 3113 if (symbolP->sy_forward) {
8b228fe9 3114 symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
0e39a8bb 3115#ifdef OBJ_COFF
8b228fe9
RP
3116 if(SF_GET_GET_SEGMENT(symbolP) &&
3117 S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
3118 S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
0e39a8bb 3119#endif /* OBJ_COFF */
8b228fe9 3120 symbolP->sy_forward=0;
0e39a8bb 3121 } /* if it has a forward reference */
8b228fe9
RP
3122 } /* walk the symbol chain */
3123
3124{ /* crawl symbol table */
3125 register int symbol_number = 0;
3126
0e39a8bb 3127#if defined(OBJ_COFF)
8b228fe9
RP
3128{ /* OBJ_COFF version */
3129 lineno* lineP;
3130 symbolS* symbol_externP = (symbolS*)0;
3131 symbolS* symbol_extern_lastP = (symbolS*)0;
3132
3133 /* The symbol list should be ordered according to the following sequence
3134 * order :
3135 * . .file symbol
3136 * . debug entries for functions
3137 * . fake symbols for .text .data and .bss
3138 * . defined symbols
3139 * . undefined symbols
3140 * But this is not mandatory. The only important point is to put the
3141 * undefined symbols at the end of the list.
3142 */
3143
3144 if (symbol_rootP == NULL
3145 || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
3146 c_dot_file_symbol("fake");
3147 } /* Is there a .file symbol ? If not insert one at the beginning. */
3148
3149 /*
3150 * Build up static symbols for .text, .data and .bss
3151 */
3152 dot_text_symbol = (symbolS*)
3153 c_section_symbol(".text",
3154 0,
3155 H_GET_TEXT_SIZE(&headers),
3156 0/*text_relocation_number*/,
3157 0/*text_lineno_number*/);
3158
3159 dot_data_symbol = (symbolS*)
3160 c_section_symbol(".data",
3161 H_GET_TEXT_SIZE(&headers),
3162 H_GET_DATA_SIZE(&headers),
3163 0/*data_relocation_number*/,
3164 0); /* There are no data lineno
3165 entries */
3166
3167 dot_bss_symbol = (symbolS*)
3168 c_section_symbol(".bss",
3169 H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
3170 H_GET_BSS_SIZE(&headers),
3171 0, /* No relocation for a bss section. */
3172 0); /* There are no bss lineno entries */
3173
3174 /* FIXME late night before delivery, I don't know why the chain is
3175 broken, but I can guess. So! Let's force them to be knit properly
3176 at this point. */
3177
3178 /* as john pointed out, this wasn't right. Instead, we'll check here to
3179 make sure that the list is doubly linked. */
3180
0e39a8bb 3181#if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
8b228fe9
RP
3182 for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
3183 know(symbolP->sy_next->sy_previous == symbolP);
3184 } /* walk the symbol chain */
0e39a8bb 3185#endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
8b228fe9
RP
3186 symbolP = symbol_rootP;
3187
3188 if (symbolP) {
3189 while(symbolP) {
3190 /* If the symbol has a tagndx entry, resolve it */
3191 if(SF_GET_TAGGED(symbolP)) {
3192 SA_SET_SYM_TAGNDX(symbolP,
3193 ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
3194 }
3195 /* Debug symbol do not need all this rubbish */
3196 if(!SF_GET_DEBUG(symbolP)) {
3197 symbolS* real_symbolP;
3198 /* L* and C_EFCN symbols never merge. */
3199 if(!SF_GET_LOCAL(symbolP) &&
3200 (real_symbolP =
3201 symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
3202 real_symbolP != symbolP) {
3203 /* FIXME where do dups come from? xoxorich. */
3204 /* Move the debug data from the debug symbol to the
3205 real symbol. Do NOT do the oposite (i.e. move from
3206 real symbol to symbol and remove real symbol from the
3207 list.) Because some pointers refer to the real symbol
3208 whereas no pointers refer to the symbol. */
3209 c_symbol_merge(symbolP, real_symbolP);
3210 /* Replace the current symbol by the real one */
3211 /* The symbols will never be the last or the first
3212 because : 1st symbol is .file and 3 last symbols are
3213 .text, .data, .bss */
3214 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
3215 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
3216 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
3217 symbolP = real_symbolP;
3218 }
3219 if(flagseen['R'] && S_IS_DATA(symbolP))
3220 S_SET_TEXT(symbolP);
3221
3222 symbolP->sy_value += symbolP->sy_frag->fr_address;
3223
3224 if(!S_IS_DEFINED(symbolP))
3225 S_SET_EXTERNAL(symbolP);
3226 else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
3227 S_SET_STORAGE_CLASS(symbolP, C_STAT);
3228
3229 /* Mainly to speed up if not -g */
3230 if(SF_GET_PROCESS(symbolP)) {
3231 /* Handle the nested blocks auxiliary info. */
3232 if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
3233 if(!strcmp(S_GET_NAME(symbolP), ".bb"))
3234 stack_push(block_stack, (char *) &symbolP);
3235 else { /* .eb */
3236 register symbolS* begin_symbolP;
3237 begin_symbolP = *(symbolS**)stack_pop(block_stack);
3238 if(begin_symbolP == (symbolS*)0)
3239 as_warn("mismatched .eb");
3240 else
3241 SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
3242 }
3243 }
3244 /* If we are able to identify the type of a function, and we
3245 are out of a function (last_functionP == 0) then, the
3246 function symbol will be associated with an auxiliary
3247 entry. */
3248 if(last_functionP == (symbolS*)0 &&
3249 SF_GET_FUNCTION(symbolP)) {
3250 last_functionP = symbolP;
3251 S_SET_NUMBER_AUXILIARY(symbolP, 1);
3252 /* Clobber possible stale .dim information. */
3253 memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
3254 }
3255 /* The C_FCN doesn't need any additional information.
3256 I don't even know if this is needed for sdb. But the
3257 standard assembler generates it, so...
3258 */
3259 if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
3260 if(last_functionP == (symbolS*)0)
3261 as_fatal("C_EFCN symbol out of scope");
3262 SA_SET_SYM_FSIZE(last_functionP,
3263 (long)(symbolP->sy_value -
3264 last_functionP->sy_value));
3265 SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
3266 last_functionP = (symbolS*)0;
3267 }
3268 }
3269 } else {
3270 /* First descriptor of a structure must point to the next
3271 slot outside the structure description. */
3272 if(SF_GET_TAG(symbolP))
3273 last_tagP = symbolP;
3274 else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
3275 /* +2 take in account the current symbol */
3276 SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
3277 }
3278
3279 /* We must put the external symbols apart. The loader
3280 does not bomb if we do not. But the references in
3281 the endndx field for a .bb symbol are not corrected
3282 if an external symbol is removed between .bb and .be.
3283 I.e in the following case :
3284 [20] .bb endndx = 22
3285 [21] foo external
3286 [22] .be
3287 ld will move the symbol 21 to the end of the list but
3288 endndx will still be 22 instead of 21. */
3289 {
3290 register symbolS* thisP = symbolP;
3291
3292 symbolP = symbol_next(thisP);
3293 /* remove C_EFCN and LOCAL (L...) symbols */
3294 if (SF_GET_LOCAL(thisP)) {
3295 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3296 } else {
3297 if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
3298 !SF_GET_FUNCTION(thisP)) {
3299 /* Remove from the list */
3300 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3301 symbol_clear_list_pointers(thisP);
3302 /* Move at the end of the list */
3303 if (symbol_extern_lastP == (symbolS*)0)
3304 symbol_externP = thisP;
3305 else
3306 symbol_append(thisP, symbol_extern_lastP);
3307 symbol_extern_lastP = thisP;
3308 } else {
3309 if(SF_GET_STRING(thisP)) {
3310 thisP->sy_name_offset = string_byte_count;
3311 string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
3312 } else
3313 thisP->sy_name_offset = 0;
3314 thisP->sy_number = symbol_number;
3315 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
3316 }
3317 }
3318 }
3319 }
3320
3321 /* this actually appends the entire extern chain */
3322 symbol_append(symbol_externP, symbol_lastP);
3323 symbolP = symbol_externP;
3324 while(symbolP) {
3325 if(SF_GET_STRING(symbolP)) {
3326 symbolP->sy_name_offset = string_byte_count;
3327 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3328 } else
3329 symbolP->sy_name_offset = 0;
3330 symbolP->sy_number = symbol_number;
3331 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
3332 symbolP = symbol_next(symbolP);
3333 }
3334 }
3335
3336 /* FIXME I'm counting line no's here so we know what to put in the section
3337 headers, and I'm resolving the addresses since I'm not sure how to
3338 do it later. I am NOT resolving the linno's representing functions.
3339 Their symbols need a fileptr pointing to this linno when emitted.
3340 Thus, I resolve them on emit. xoxorich. */
3341
3342 for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
3343 if (lineP->line.l_lnno) {
3344 lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
3345 } else {
3346 ;
3347 }
3348 text_lineno_number++;
3349 } /* for each line number */
3350} /* OBJ_COFF version */
0e39a8bb 3351#elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
8b228fe9
RP
3352{ /* OBJ_AOUT version */
3353 symbolPP = & symbol_rootP; /* -> last symbol chain link. */
3354 while ((symbolP = *symbolPP) != NULL)
3355 {
3356 if (flagseen['R'] && S_IS_DATA(symbolP)) {
3357 S_SET_TEXT(symbolP);
3358 } /* if pusing data into text */
3359
3360 symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
3361
3362 /* OK, here is how we decide which symbols go out into the
3363 brave new symtab. Symbols that do are:
3364
3365 * symbols with no name (stabd's?)
3366 * symbols with debug info in their N_TYPE
3367
3368 Symbols that don't are:
3369 * symbols that are registers
3370 * symbols with \1 as their 3rd character (numeric labels)
3371 * "local labels" as defined by S_LOCAL_NAME(name)
3372 if the -L switch was passed to gas.
3373
3374 All other symbols are output. We complain if a deleted
3375 symbol was marked external. */
3376
3377
3378 if (1
3379 && !S_IS_REGISTER(symbolP)
0e39a8bb 3380#ifndef VMS /* Under VMS we need to keep local symbols */
8b228fe9
RP
3381 && ( !S_GET_NAME(symbolP)
3382 || S_IS_DEBUG(symbolP)
0e39a8bb 3383#ifdef TC_I960
8b228fe9
RP
3384 /* FIXME this ifdef seems highly dubious to me. xoxorich. */
3385 || !S_IS_DEFINED(symbolP)
3386 || S_IS_EXTERNAL(symbolP)
0e39a8bb 3387#endif /* TC_I960 */
8b228fe9 3388 || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
0e39a8bb 3389#endif /* not VMS */
8b228fe9
RP
3390 )
3391 {
0e39a8bb 3392#ifndef VMS
8b228fe9
RP
3393 symbolP->sy_number = symbol_number++;
3394
3395 /* The + 1 after strlen account for the \0 at the
3396 end of each string */
3397 if (!S_IS_STABD(symbolP)) {
3398 /* Ordinary case. */
3399 symbolP->sy_name_offset = string_byte_count;
3400 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3401 }
3402 else /* .Stabd case. */
0e39a8bb 3403#endif /* not VMS */
8b228fe9
RP
3404 symbolP->sy_name_offset = 0;
3405 symbolPP = &(symbol_next(symbolP));
3406 } else {
3407 if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
3408 as_bad ("Local symbol %s never defined", name);
3409 } /* oops. */
3410
0e39a8bb 3411#ifndef VMS
8b228fe9
RP
3412 /* Unhook it from the chain */
3413 *symbolPP = symbol_next(symbolP);
0e39a8bb 3414#endif /* VMS */
8b228fe9
RP
3415 } /* if this symbol should be in the output */
3416 } /* for each symbol */
3417} /* OBJ_AOUT version */
0e39a8bb 3418#else
8b228fe9 3419cant_crawl_symbol_table();
0e39a8bb 3420#endif
8b228fe9
RP
3421H_SET_STRING_SIZE(&headers,string_byte_count);
3422H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
3423} /* crawl symbol table */
0e39a8bb 3424
8b228fe9
RP
3425/* JF deal with forward references first. . . */
3426for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
0e39a8bb 3427 if (symbolP->sy_forward) {
8b228fe9 3428 symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
0e39a8bb 3429#ifdef OBJ_COFF
8b228fe9
RP
3430 if(SF_GET_GET_SEGMENT(symbolP) &&
3431 S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
3432 S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
0e39a8bb 3433#endif /* OBJ_COFF */
8b228fe9 3434 symbolP->sy_forward=0;
0e39a8bb 3435 } /* if it has a forward reference */
8b228fe9 3436} /* walk the symbol chain */
0e39a8bb 3437
8b228fe9
RP
3438{ /* crawl symbol table */
3439 register int symbol_number = 0;
3440
0e39a8bb 3441#if defined(OBJ_COFF)
8b228fe9
RP
3442{ /* OBJ_COFF version */
3443 lineno* lineP;
3444 symbolS* symbol_externP = (symbolS*)0;
3445 symbolS* symbol_extern_lastP = (symbolS*)0;
3446
3447 /* The symbol list should be ordered according to the following sequence
3448 * order :
3449 * . .file symbol
3450 * . debug entries for functions
3451 * . fake symbols for .text .data and .bss
3452 * . defined symbols
3453 * . undefined symbols
3454 * But this is not mandatory. The only important point is to put the
3455 * undefined symbols at the end of the list.
3456 */
3457
3458 if (symbol_rootP == NULL
3459 || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
3460 c_dot_file_symbol("fake");
3461 } /* Is there a .file symbol ? If not insert one at the beginning. */
3462
3463 /*
3464 * Build up static symbols for .text, .data and .bss
3465 */
3466 dot_text_symbol = (symbolS*)
3467 c_section_symbol(".text",
3468 0,
3469 H_GET_TEXT_SIZE(&headers),
3470 0/*text_relocation_number*/,
3471 0/*text_lineno_number*/);
3472
3473 dot_data_symbol = (symbolS*)
3474 c_section_symbol(".data",
3475 H_GET_TEXT_SIZE(&headers),
3476 H_GET_DATA_SIZE(&headers),
3477 0/*data_relocation_number*/,
3478 0); /* There are no data lineno
3479 entries */
3480
3481 dot_bss_symbol = (symbolS*)
3482 c_section_symbol(".bss",
3483 H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
3484 H_GET_BSS_SIZE(&headers),
3485 0, /* No relocation for a bss section. */
3486 0); /* There are no bss lineno entries */
3487
3488 /* FIXME late night before delivery, I don't know why the chain is
3489 broken, but I can guess. So! Let's force them to be knit properly
3490 at this point. */
3491
3492 /* as john pointed out, this wasn't right. Instead, we'll check here to
3493 make sure that the list is doubly linked. */
3494
0e39a8bb 3495#if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
8b228fe9
RP
3496 for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
3497 know(symbolP->sy_next->sy_previous == symbolP);
3498 } /* walk the symbol chain */
0e39a8bb 3499#endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
8b228fe9
RP
3500 symbolP = symbol_rootP;
3501
3502 if (symbolP) {
3503 while(symbolP) {
3504 /* If the symbol has a tagndx entry, resolve it */
3505 if(SF_GET_TAGGED(symbolP)) {
3506 SA_SET_SYM_TAGNDX(symbolP,
3507 ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
3508 }
3509 /* Debug symbol do not need all this rubbish */
3510 if(!SF_GET_DEBUG(symbolP)) {
3511 symbolS* real_symbolP;
3512 /* L* and C_EFCN symbols never merge. */
3513 if(!SF_GET_LOCAL(symbolP) &&
3514 (real_symbolP =
3515 symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
3516 real_symbolP != symbolP) {
3517 /* FIXME where do dups come from? xoxorich. */
3518 /* Move the debug data from the debug symbol to the
3519 real symbol. Do NOT do the oposite (i.e. move from
3520 real symbol to symbol and remove real symbol from the
3521 list.) Because some pointers refer to the real symbol
3522 whereas no pointers refer to the symbol. */
3523 c_symbol_merge(symbolP, real_symbolP);
3524 /* Replace the current symbol by the real one */
3525 /* The symbols will never be the last or the first
3526 because : 1st symbol is .file and 3 last symbols are
3527 .text, .data, .bss */
3528 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
3529 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
3530 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
3531 symbolP = real_symbolP;
3532 }
3533 if(flagseen['R'] && S_IS_DATA(symbolP))
3534 S_SET_TEXT(symbolP);
3535
3536 symbolP->sy_value += symbolP->sy_frag->fr_address;
3537
3538 if(!S_IS_DEFINED(symbolP))
3539 S_SET_EXTERNAL(symbolP);
3540 else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
3541 S_SET_STORAGE_CLASS(symbolP, C_STAT);
3542
3543 /* Mainly to speed up if not -g */
3544 if(SF_GET_PROCESS(symbolP)) {
3545 /* Handle the nested blocks auxiliary info. */
3546 if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
3547 if(!strcmp(S_GET_NAME(symbolP), ".bb"))
3548 stack_push(block_stack, (char *) &symbolP);
3549 else { /* .eb */
3550 register symbolS* begin_symbolP;
3551 begin_symbolP = *(symbolS**)stack_pop(block_stack);
3552 if(begin_symbolP == (symbolS*)0)
3553 as_warn("mismatched .eb");
3554 else
3555 SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
3556 }
3557 }
3558 /* If we are able to identify the type of a function, and we
3559 are out of a function (last_functionP == 0) then, the
3560 function symbol will be associated with an auxiliary
3561 entry. */
3562 if(last_functionP == (symbolS*)0 &&
3563 SF_GET_FUNCTION(symbolP)) {
3564 last_functionP = symbolP;
3565 S_SET_NUMBER_AUXILIARY(symbolP, 1);
3566 /* Clobber possible stale .dim information. */
3567 memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
3568 }
3569 /* The C_FCN doesn't need any additional information.
3570 I don't even know if this is needed for sdb. But the
3571 standard assembler generates it, so...
3572 */
3573 if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
3574 if(last_functionP == (symbolS*)0)
3575 as_fatal("C_EFCN symbol out of scope");
3576 SA_SET_SYM_FSIZE(last_functionP,
3577 (long)(symbolP->sy_value -
3578 last_functionP->sy_value));
3579 SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
3580 last_functionP = (symbolS*)0;
3581 }
3582 }
3583 } else {
3584 /* First descriptor of a structure must point to the next
3585 slot outside the structure description. */
3586 if(SF_GET_TAG(symbolP))
3587 last_tagP = symbolP;
3588 else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
3589 /* +2 take in account the current symbol */
3590 SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
3591 }
3592
3593 /* We must put the external symbols apart. The loader
3594 does not bomb if we do not. But the references in
3595 the endndx field for a .bb symbol are not corrected
3596 if an external symbol is removed between .bb and .be.
3597 I.e in the following case :
3598 [20] .bb endndx = 22
3599 [21] foo external
3600 [22] .be
3601 ld will move the symbol 21 to the end of the list but
3602 endndx will still be 22 instead of 21. */
3603 {
3604 register symbolS* thisP = symbolP;
3605
3606 symbolP = symbol_next(thisP);
3607 /* remove C_EFCN and LOCAL (L...) symbols */
3608 if (SF_GET_LOCAL(thisP)) {
3609 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3610 } else {
3611 if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
3612 !SF_GET_FUNCTION(thisP)) {
3613 /* Remove from the list */
3614 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
3615 symbol_clear_list_pointers(thisP);
3616 /* Move at the end of the list */
3617 if (symbol_extern_lastP == (symbolS*)0)
3618 symbol_externP = thisP;
3619 else
3620 symbol_append(thisP, symbol_extern_lastP);
3621 symbol_extern_lastP = thisP;
3622 } else {
3623 if(SF_GET_STRING(thisP)) {
3624 thisP->sy_name_offset = string_byte_count;
3625 string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
3626 } else
3627 thisP->sy_name_offset = 0;
3628 thisP->sy_number = symbol_number;
3629 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
3630 }
3631 }
3632 }
3633 }
3634
3635 /* this actually appends the entire extern chain */
3636 symbol_append(symbol_externP, symbol_lastP);
3637 symbolP = symbol_externP;
3638 while(symbolP) {
3639 if(SF_GET_STRING(symbolP)) {
3640 symbolP->sy_name_offset = string_byte_count;
3641 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3642 } else
3643 symbolP->sy_name_offset = 0;
3644 symbolP->sy_number = symbol_number;
3645 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
3646 symbolP = symbol_next(symbolP);
3647 }
3648 }
3649
3650 /* FIXME I'm counting line no's here so we know what to put in the section
3651 headers, and I'm resolving the addresses since I'm not sure how to
3652 do it later. I am NOT resolving the linno's representing functions.
3653 Their symbols need a fileptr pointing to this linno when emitted.
3654 Thus, I resolve them on emit. xoxorich. */
3655
3656 for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
3657 if (lineP->line.l_lnno) {
3658 lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
3659 } else {
3660 ;
3661 }
3662 text_lineno_number++;
3663 } /* for each line number */
3664} /* OBJ_COFF version */
0e39a8bb 3665#elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
8b228fe9
RP
3666{ /* OBJ_AOUT version */
3667 symbolPP = & symbol_rootP; /* -> last symbol chain link. */
3668 while ((symbolP = *symbolPP) != NULL)
3669 {
3670 if (flagseen['R'] && S_IS_DATA(symbolP)) {
3671 S_SET_TEXT(symbolP);
3672 } /* if pusing data into text */
3673
3674 symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
3675
3676 /* OK, here is how we decide which symbols go out into the
3677 brave new symtab. Symbols that do are:
3678
3679 * symbols with no name (stabd's?)
3680 * symbols with debug info in their N_TYPE
3681
3682 Symbols that don't are:
3683 * symbols that are registers
3684 * symbols with \1 as their 3rd character (numeric labels)
3685 * "local labels" as defined by S_LOCAL_NAME(name)
3686 if the -L switch was passed to gas.
3687
3688 All other symbols are output. We complain if a deleted
3689 symbol was marked external. */
3690
3691
3692 if (1
3693 && !S_IS_REGISTER(symbolP)
0e39a8bb 3694#ifndef VMS /* Under VMS we need to keep local symbols */
8b228fe9
RP
3695 && ( !S_GET_NAME(symbolP)
3696 || S_IS_DEBUG(symbolP)
0e39a8bb 3697#ifdef TC_I960
8b228fe9
RP
3698 /* FIXME this ifdef seems highly dubious to me. xoxorich. */
3699 || !S_IS_DEFINED(symbolP)
3700 || S_IS_EXTERNAL(symbolP)
0e39a8bb 3701#endif /* TC_I960 */
8b228fe9 3702 || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
0e39a8bb 3703#endif /* not VMS */
8b228fe9
RP
3704 )
3705 {
0e39a8bb 3706#ifndef VMS
8b228fe9
RP
3707 symbolP->sy_number = symbol_number++;
3708
3709 /* The + 1 after strlen account for the \0 at the
3710 end of each string */
3711 if (!S_IS_STABD(symbolP)) {
3712 /* Ordinary case. */
3713 symbolP->sy_name_offset = string_byte_count;
3714 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
3715 }
3716 else /* .Stabd case. */
0e39a8bb 3717#endif /* not VMS */
8b228fe9
RP
3718 symbolP->sy_name_offset = 0;
3719 symbolPP = &(symbol_next(symbolP));
3720 } else {
3721 if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
3722 as_bad ("Local symbol %s never defined", name);
3723 } /* oops. */
3724
0e39a8bb 3725#ifndef VMS
8b228fe9
RP
3726 /* Unhook it from the chain */
3727 *symbolPP = symbol_next(symbolP);
0e39a8bb 3728#endif /* VMS */
8b228fe9
RP
3729 } /* if this symbol should be in the output */
3730 } /* for each symbol */
3731} /* OBJ_AOUT version */
0e39a8bb 3732#else
8b228fe9 3733cant_crawl_symbol_table();
0e39a8bb 3734#endif
8b228fe9
RP
3735H_SET_STRING_SIZE(&headers,string_byte_count);
3736H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
3737} /* crawl symbol table */
0e39a8bb
RP
3738
3739} /* obj_crawl_symbol_chain() */
3740
8b228fe9 3741/* end of vms.c */
This page took 0.193577 seconds and 4 git commands to generate.