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