1 /* vms.c -- Write out a VAX/VMS object file
3 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
21 /* Written by David L. Kashtan */
28 #include "struc-symbol.h"
32 #ifdef VMS /* THIS MODULE IS FOR VMS ONLY */
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 */
42 const pseudo_typeS obj_pseudo_table
[] = {
43 { "const", s_const
, 0 },
45 }; /* obj_pseudo_table */
48 * Version string of the compiler that produced the code we are
49 * assembling. (And this assembler, if we do not have compiler info.)
51 extern char version_string
[];
52 char *compiler_version_string
;
55 static symbolS
*Entry_Point_Symbol
= 0; /* Pointer to "_main" */
58 * We augment the "gas" symbol structure with this
61 struct VMS_Symbol
*Next
;
62 struct symbol
*Symbol
;
67 struct VMS_Symbol
*VMS_Symbols
= 0;
69 /* we need this to keep track of the various input files, so that we can
70 * give the debugger the correct source line
74 struct input_file
* next
;
75 struct input_file
* same_file_fpnt
;
85 static struct input_file
* file_root
= (struct input_file
*)NULL
;
87 struct input_file
* find_file(symbolS
*);
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".
96 register symbolS
*symbolP
;
97 #ifdef HACK_DEC_C_STARTUP /* JF */
98 register struct frchain
*frchainP
;
99 register fragS
*fragP
;
100 register fragS
**prev_fragPP
;
101 register struct fix
*fixP
;
102 register fragS
*New_Frag
;
104 #endif HACK_DEC_C_STARTUP
106 symbolP
= (struct symbol
*)symbol_find("_main");
107 if (symbolP
&& (symbolP
->sy_nlist
.n_type
== (N_TEXT
| N_EXT
))) {
108 #ifdef HACK_DEC_C_STARTUP
109 if( !flagseen
['+']) {
112 * Remember the entry point symbol
114 Entry_Point_Symbol
= symbolP
;
115 #ifdef HACK_DEC_C_STARTUP
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)
122 frchainP
= frchain_root
;
125 * Scan all the fragments in this chain, remembering
126 * the "previous fragment"
128 prev_fragPP
= &frchainP
->frch_root
;
129 fragP
= frchainP
->frch_root
;
130 while(fragP
&& (fragP
!= frchainP
->frch_last
)) {
132 * Is this the fragment?
134 if (fragP
== symbolP
->sy_frag
) {
136 * Yes: Modify the fragment by replacing
137 * it with a new fragment.
140 xmalloc(sizeof(*New_Frag
) +
145 * The fragments are the same except
146 * that the "fixed" area is larger
149 New_Frag
->fr_fix
+= 6;
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.
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
];
168 * Now replace the old fragment with the
169 * newly generated one.
171 *prev_fragPP
= New_Frag
;
173 * Remember the entry point symbol
175 Entry_Point_Symbol
= symbolP
;
177 * Scan the text area fixup structures
178 * as offsets in the fragment may have
181 for(fixP
= text_fix_root
; fixP
; fixP
= fixP
->fx_next
) {
183 * Look for references to this
186 if (fixP
->fx_frag
== fragP
) {
188 * Change the fragment
191 fixP
->fx_frag
= New_Frag
;
193 * If the offset is after
194 * the entry mask we need
195 * to account for the JSB
196 * instruction we just
199 if (fixP
->fx_where
>= 2)
204 * Scan the symbols as offsets in the
205 * fragment may have changed
207 for(symbolP
= symbol_rootP
;
209 symbolP
= symbol_next(symbolP
)) {
211 * Look for references to this
214 if (symbolP
->sy_frag
== fragP
) {
216 * Change the fragment
219 symbolP
->sy_frag
= New_Frag
;
221 * If the offset is after
222 * the entry mask we need
223 * to account for the JSB
224 * instruction we just
227 if (symbolP
->sy_nlist
.n_value
>= 2)
228 symbolP
->sy_nlist
.n_value
+= 6;
232 * Make a symbol reference to
233 * "_c$main_args" so we can get
234 * its address inserted into the
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
);
250 symbol_rootP
= symbolP
;
252 * Generate a text fixup structure
253 * to get "_c$main_args" stored into the
256 fixP
= (struct fix
*)xmalloc(sizeof(*fixP
));
257 fixP
->fx_frag
= New_Frag
;
259 fixP
->fx_addsy
= symbolP
;
262 fixP
->fx_size
= sizeof(long);
264 fixP
->fx_next
= text_fix_root
;
265 text_fix_root
= fixP
;
267 * Now make sure we exit from the loop
273 * Try the next fragment
275 prev_fragPP
= &fragP
->fr_next
;
276 fragP
= fragP
->fr_next
;
279 * Try the next fragment chain
281 if (frchainP
) frchainP
=frchainP
->frch_next
;
284 #endif /* HACK_DEC_C_STARTUP */
289 * Write a VAX/VMS object file (everything else has been done!)
291 VMS_write_object_file(text_siz
, data_siz
, text_frag_root
, data_frag_root
)
294 struct frag
*text_frag_root
;
295 struct frag
*data_frag_root
;
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 */
309 * Create the VMS object file
311 Create_VMS_Object_File();
313 * Write the module header records
315 Write_VMS_MHD_Records();
318 * Generate the VMS object file records
319 * 1st GSD then TIR records
322 /******* Global Symbol Dictionary *******/
324 * Define the Text Psect
327 Text_Psect
= Psect_Number
++;
328 VMS_Psect_Spec("$code",text_siz
,"TEXT");
331 * Define the BSS Psect
333 if (local_bss_counter
> 0) {
334 Bss_Psect
= Psect_Number
++;
335 VMS_Psect_Spec("$uninitialized_data",local_bss_counter
,"DATA");
338 * Now scan the symbols and emit the appropriate GSD records
340 for (sp
= symbol_rootP
; sp
; sp
= symbol_next(sp
)) {
342 * Dispatch on symbol type
344 switch(sp
->sy_type
) {
346 * Global uninitialized data
350 * Make a VMS data symbol entry
352 vsp
= (struct VMS_Symbol
*)
353 xmalloc(sizeof(*vsp
));
355 vsp
->Size
= sp
->sy_nlist
.n_value
;
356 vsp
->Psect_Index
= Psect_Number
++;
357 vsp
->Psect_Offset
= 0;
358 vsp
->Next
= VMS_Symbols
;
360 sp
->sy_number
= (int)vsp
;
362 * Make the psect for this data
364 if(sp
->sy_nlist
.n_other
)
365 VMS_Psect_Spec(sp
->sy_nlist
.n_un
.n_name
,
369 VMS_Psect_Spec(sp
->sy_nlist
.n_un
.n_name
,
372 #ifdef NOT_VAX_11_C_COMPATIBLE
374 * Place a global symbol at the
375 * beginning of the Psect
377 VMS_Global_Symbol_Spec(sp
->sy_nlist
.n_un
.n_name
,
381 #endif NOT_VAX_11_C_COMPATIBLE
384 * Local uninitialized data
388 * Make a VMS data symbol entry
390 vsp
= (struct VMS_Symbol
*)
391 xmalloc(sizeof(*vsp
));
394 vsp
->Psect_Index
= Bss_Psect
;
396 sp
->sy_nlist
.n_value
-
397 bss_address_frag
. fr_address
;
398 vsp
->Next
= VMS_Symbols
;
400 sp
->sy_number
= (int)vsp
;
403 * Global initialized data
407 * Make a VMS data symbol entry
409 vsp
= (struct VMS_Symbol
*)
410 xmalloc(sizeof(*vsp
));
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
;
418 sp
->sy_number
= (int)vsp
;
422 if(sp
->sy_nlist
.n_other
)
423 VMS_Psect_Spec(sp
->sy_nlist
.n_un
.n_name
,
427 VMS_Psect_Spec(sp
->sy_nlist
.n_un
.n_name
,
430 #ifdef NOT_VAX_11_C_COMPATIBLE
432 * Place a global symbol at the
433 * beginning of the Psect
435 VMS_Global_Symbol_Spec(sp
->sy_nlist
.n_un
.n_name
,
439 #endif NOT_VAX_11_C_COMPATIBLE
442 * Local initialized data
446 * Make a VMS data symbol entry
448 vsp
= (struct VMS_Symbol
*)
449 xmalloc(sizeof(*vsp
));
452 VMS_Initialized_Data_Size(sp
,
453 text_siz
+ data_siz
);
454 vsp
->Psect_Index
= Data_Psect
;
456 Local_Initialized_Data_Size
;
457 Local_Initialized_Data_Size
+= vsp
->Size
;
458 vsp
->Next
= VMS_Symbols
;
460 sp
->sy_number
= (int)vsp
;
463 * Global Text definition
465 case N_TEXT
| N_EXT
: {
466 unsigned short Entry_Mask
;
472 Entry_Mask
= (fragP
->fr_literal
[0] & 0xff) +
473 ((fragP
->fr_literal
[1] & 0xff)
476 * Define the Procedure entry pt.
478 VMS_Procedure_Entry_Pt(sp
->sy_nlist
.n_un
.n_name
,
480 sp
->sy_nlist
.n_value
,
485 * Local Text definition
489 * Make a VMS data symbol entry
491 if(Text_Psect
!= -1) {
492 vsp
= (struct VMS_Symbol
*)
493 xmalloc(sizeof(*vsp
));
496 vsp
->Psect_Index
= Text_Psect
;
497 vsp
->Psect_Offset
= sp
->sy_nlist
.n_value
;
498 vsp
->Next
= VMS_Symbols
;
500 sp
->sy_number
= (int)vsp
;
508 * Make a GSD global symbol reference
511 VMS_Global_Symbol_Spec(sp
->sy_nlist
.n_un
.n_name
,
521 * Ignore STAB symbols
522 * Including .stabs emitted by g++
524 if ((sp
->sy_type
& N_STAB
) != 0 || sp
->sy_nlist
.n_type
==22)
529 if(sp
->sy_nlist
.n_type
!=22)
530 printf(" ERROR, unknown type (%d)\n",
531 sp
->sy_nlist
.n_type
);
536 * Define the Data Psect
538 if ((data_siz
> 0) && (Local_Initialized_Data_Size
> 0)) {
542 Data_Psect
= Psect_Number
++;
543 VMS_Psect_Spec("$data",
544 Local_Initialized_Data_Size
,
547 * Scan the VMS symbols and fill in the data psect
549 for (vsp
= VMS_Symbols
; vsp
; vsp
= vsp
->Next
) {
551 * Only look for undefined psects
553 if (vsp
->Psect_Index
< 0) {
555 * And only initialized data
557 if (vsp
->Symbol
->sy_nlist
.n_type
== N_DATA
)
558 vsp
->Psect_Index
= Data_Psect
;
563 /******* Text Information and Relocation Records *******/
565 * Write the text segment data
569 * Scan the text fragments
571 for(fragP
= text_frag_root
; fragP
; fragP
= fragP
->fr_next
) {
573 * Stop if we get to the data fragments
575 if (fragP
== data_frag_root
) break;
577 * Ignore fragments with no data
579 if ((fragP
->fr_fix
== 0) && (fragP
->fr_var
== 0))
582 * Go the the appropriate offset in the
585 VMS_Set_Psect(Text_Psect
,fragP
->fr_address
,OBJ$C_TIR
);
587 * Store the "fixed" part
590 VMS_Store_Immediate_Data(fragP
->fr_literal
,
594 * Store the "variable" part
596 if (fragP
->fr_var
&& fragP
->fr_offset
)
597 VMS_Store_Repeated_Data(fragP
->fr_offset
,
604 * Now we go through the text segment fixups and
605 * generate TIR records to fix up addresses within
608 for(fixP
= text_fix_root
; fixP
; fixP
= fixP
->fx_next
) {
610 * We DO handle the case of "Symbol - Symbol" as
611 * long as it is in the same segment.
613 if (fixP
->fx_subsy
&& fixP
->fx_addsy
) {
617 * They need to be in the same segment
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");
623 * And they need to be in one that we
624 * can check the psect on
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");
630 * This had better not be PC relative!
633 error("Fixup data was erroneously \"pcrel\"");
635 * Subtract their values to get the
638 i
= fixP
->fx_addsy
->sy_value
-
639 fixP
->fx_subsy
->sy_value
;
641 * Now generate the fixup object records
642 * Set the psect and store the data
644 VMS_Set_Psect(Text_Psect
,
646 fixP
->fx_frag
->fr_address
,
648 VMS_Store_Immediate_Data(&i
,
657 * Size will HAVE to be "long"
659 if (fixP
->fx_size
!= sizeof(long))
660 error("Fixup datum was not a longword");
662 * Symbol must be "added" (if it is ever
664 * fix this assumption)
666 if (fixP
->fx_addsy
== 0)
667 error("Fixup datum was not \"fixP->fx_addsy\"");
669 * Store the symbol value in a PIC fashion
671 VMS_Store_PIC_Symbol_Reference(fixP
->fx_addsy
,
676 fixP
->fx_frag
->fr_address
,
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).
684 VMS_Fix_Indirect_Reference(Text_Psect
,
686 fixP
->fx_frag
->fr_address
,
692 * Store the Data segment:
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.
702 * Allocate the data segment
704 Data_Segment
= (char *)xmalloc(data_siz
);
706 * Run through the data fragments, filling in the segment
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
;
714 i
= fragP
->fr_address
- text_siz
;
716 bcopy(fragP
->fr_literal
,
721 fill_literal
= fragP
-> fr_literal
+ fragP
-> fr_fix
;
722 fill_size
= fragP
-> fr_var
;
723 for (count
= fragP
-> fr_offset
; count
; count
--) {
732 * Now we can run through all the data symbols
735 for(vsp
= VMS_Symbols
; vsp
; vsp
= vsp
->Next
) {
737 * Ignore anything other than data symbols
739 if ((vsp
->Symbol
->sy_nlist
.n_type
& ~N_EXT
) != N_DATA
)
742 * Set the Psect + Offset
744 VMS_Set_Psect(vsp
->Psect_Index
,
750 VMS_Store_Immediate_Data(Data_Segment
+
751 vsp
->Symbol
->sy_nlist
.n_value
-
757 * Now we go through the data segment fixups and
758 * generate TIR records to fix up addresses within
761 for(fixP
= data_fix_root
; fixP
; fixP
= fixP
->fx_next
) {
763 * Find the symbol for the containing datum
765 for(vsp
= VMS_Symbols
; vsp
; vsp
= vsp
->Next
) {
767 * Only bother with Data symbols
770 if ((sp
->sy_nlist
.n_type
& ~N_EXT
) != N_DATA
)
773 * Ignore symbol if After fixup
775 if (sp
->sy_nlist
.n_value
>
777 fixP
->fx_frag
->fr_address
))
780 * See if the datum is here
782 if ((sp
->sy_nlist
.n_value
+ vsp
->Size
) <=
784 fixP
->fx_frag
->fr_address
))
787 * We DO handle the case of "Symbol - Symbol" as
788 * long as it is in the same segment.
790 if (fixP
->fx_subsy
&& fixP
->fx_addsy
) {
794 * They need to be in the same segment
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");
800 * And they need to be in one that we
801 * can check the psect on
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");
807 * This had better not be PC relative!
810 error("Fixup data was erroneously \"pcrel\"");
812 * Subtract their values to get the
815 i
= fixP
->fx_addsy
->sy_value
-
816 fixP
->fx_subsy
->sy_value
;
818 * Now generate the fixup object records
819 * Set the psect and store the data
821 VMS_Set_Psect(vsp
->Psect_Index
,
822 fixP
->fx_frag
->fr_address
+
824 vsp
->Symbol
->sy_value
+
827 VMS_Store_Immediate_Data(&i
,
836 * Size will HAVE to be "long"
838 if (fixP
->fx_size
!= sizeof(long))
839 error("Fixup datum was not a longword");
841 * Symbol must be "added" (if it is ever
843 * fix this assumption)
845 if (fixP
->fx_addsy
== 0)
846 error("Fixup datum was not \"fixP->fx_addsy\"");
848 * Store the symbol value in a PIC fashion
850 VMS_Store_PIC_Symbol_Reference(
855 fixP
->fx_frag
->fr_address
+
857 vsp
->Symbol
->sy_value
+
870 * Write the Traceback Begin Module record
872 VMS_TBT_Module_Begin();
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)
879 struct symbol
*Current_Routine
= 0;
880 int Current_Line_Number
= 0;
881 int Current_Offset
= -1;
882 struct input_file
* Current_File
;
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.
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.
898 for(symbolP
= symbol_rootP
; symbolP
; symbolP
= symbol_next(symbolP
)) {
900 * Deal with STAB symbols
902 if ((symbolP
->sy_nlist
.n_type
& N_STAB
) != 0) {
904 * Dispatch on STAB type
906 switch((unsigned char)symbolP
->sy_nlist
.n_type
) {
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
;
914 Current_File
=find_file(symbolP
);
915 Current_File
->flag
= 1;
916 Current_File
->min_line
= 1;
919 Current_File
= find_file(symbolP
);
922 VMS_GSYM_Parse(symbolP
,Text_Psect
);
925 VMS_LCSYM_Parse(symbolP
,Text_Psect
);
927 case N_FUN
: /* For static constant symbols */
929 VMS_STSYM_Parse(symbolP
,Text_Psect
);
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
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 */
941 int Debugger_Offset
= 0;
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
;
958 Current_File
->file_number
= ++File_Number
;
959 file_available
= VMS_TBT_Source_File(Current_File
->name
,
960 Current_File
->file_number
);
961 if(!file_available
) {Current_File
->file_number
= 0;
965 VMS_TBT_Source_Lines(Current_File
->file_number
,
966 Current_File
->min_line
,
967 Current_File
->max_line
-Current_File
->min_line
+1);
970 Current_File
= (struct input_file
*) NULL
;
972 for(symbolP
= symbol_rootP
; symbolP
; symbolP
= symbol_next(symbolP
)) {
974 * Deal with text symbols
976 if ((symbolP
->sy_nlist
.n_type
& ~N_EXT
) == N_TEXT
) {
978 * Ignore symbols starting with "L",
979 * as they are local symbols
981 if (symbolP
->sy_nlist
.n_un
.n_name
[0] == 'L') continue;
983 * If there is a routine start defined,
986 if (Current_Routine
) {
990 VMS_TBT_Routine_End(text_siz
,Current_Routine
);
993 * Store the routine begin traceback info
995 if(Text_Psect
!= -1) {
996 VMS_TBT_Routine_Begin(symbolP
,Text_Psect
);
997 Current_Routine
= symbolP
;
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
1003 { symbolS
* symbolP1
;
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;
1015 if(symbolP1
!= (symbolS
*) NULL
)
1016 VMS_DBG_Define_Routine(symbolP1
,Current_Routine
,Text_Psect
);
1017 } /* local symbol block */
1024 * Deal with STAB symbols
1026 if ((symbolP
->sy_nlist
.n_type
& N_STAB
) != 0) {
1028 * Dispatch on STAB type
1030 switch((unsigned char)symbolP
->sy_nlist
.n_type
) {
1035 /* Offset the line into the correct portion
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
;
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
1058 if (Current_Offset
== -1) {
1059 VMS_TBT_Line_PC_Correlation(
1060 symbolP
->sy_nlist
.n_desc
,
1061 symbolP
->sy_nlist
.n_value
,
1065 if ((symbolP
->sy_nlist
.n_desc
-
1066 Current_Line_Number
) <= 0) {
1068 * Line delta is not +ve, we
1069 * need to close the line and
1070 * start a new PC/Line
1073 VMS_TBT_Line_PC_Correlation(0,
1074 symbolP
->sy_nlist
.n_value
-
1078 VMS_TBT_Line_PC_Correlation(
1079 symbolP
->sy_nlist
.n_desc
,
1080 symbolP
->sy_nlist
.n_value
,
1085 * Line delta is +ve, all is well
1087 VMS_TBT_Line_PC_Correlation(
1088 symbolP
->sy_nlist
.n_desc
-
1089 Current_Line_Number
,
1090 symbolP
->sy_nlist
.n_value
-
1097 * Update the current line/PC
1099 Current_Line_Number
= symbolP
->sy_nlist
.n_desc
;
1100 Current_Offset
= symbolP
->sy_nlist
.n_value
;
1110 * Remember that we had a source file
1111 * and emit the source file debugger
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
1128 * If there is a routine start defined,
1129 * terminate it (and the line numbers)
1131 if (Current_Routine
) {
1133 * Terminate the line numbers
1135 VMS_TBT_Line_PC_Correlation(0,
1136 text_siz
- Current_Routine
->sy_nlist
.n_value
,
1140 * Terminate the routine
1142 VMS_TBT_Routine_End(text_siz
,Current_Routine
);
1146 * Write the Traceback End Module TBT record
1148 VMS_TBT_Module_End();
1151 * Write the End Of Module record
1153 if (Entry_Point_Symbol
== 0)
1154 Write_VMS_EOM_Record(-1,0);
1156 Write_VMS_EOM_Record(Text_Psect
,
1157 Entry_Point_Symbol
->sy_nlist
.n_value
);
1160 * All done, close the object file
1162 Close_VMS_Object_File();
1166 /****** VMS OBJECT FILE HACKING ROUTINES *******/
1170 * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
1172 static int VMS_Object_File_FD
; /* File Descriptor for object file */
1173 static char Object_Record_Buffer
[512]; /* Buffer for object file records */
1174 static int Object_Record_Offset
; /* Offset to end of data */
1175 static int Current_Object_Record_Type
; /* Type of record in above */
1178 * Macros for placing data into the object record buffer
1180 #define PUT_LONG(val) *((long *)(Object_Record_Buffer + \
1181 Object_Record_Offset)) = val; \
1182 Object_Record_Offset += sizeof(long)
1184 #define PUT_SHORT(val) *((short *)(Object_Record_Buffer + \
1185 Object_Record_Offset)) = val; \
1186 Object_Record_Offset += sizeof(short)
1188 #define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val
1190 #define PUT_COUNTED_STRING(cp) {\
1191 register char *p = cp; \
1192 PUT_CHAR(strlen(p)); \
1193 while(*p) PUT_CHAR(*p++);}
1196 * Macro for determining if a Name has psect attributes attached
1199 #define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
1200 #define PSECT_ATTRIBUTES_STRING_LENGTH 18
1202 #define HAS_PSECT_ATTRIBUTES(Name) \
1203 (strncmp((Name[0] == '_' ? Name + 1 : Name), \
1204 PSECT_ATTRIBUTES_STRING, \
1205 PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
1209 * Create the VMS object file
1211 Create_VMS_Object_File()
1214 VMS_Object_File_FD
= creat(out_file_name
, 0777, "var");
1216 VMS_Object_File_FD
= creat(out_file_name
, 0, "rfm=var");
1221 if (VMS_Object_File_FD
< 0) {
1222 char Error_Line
[256];
1224 sprintf(Error_Line
,"Couldn't create VMS object file \"%s\"",
1229 * Initialize object file hacking variables
1231 Object_Record_Offset
= 0;
1232 Current_Object_Record_Type
= -1;
1237 * Declare a particular type of object file record
1239 Set_VMS_Object_File_Record(Type
)
1243 * If the type matches, we are done
1245 if (Type
== Current_Object_Record_Type
) return;
1247 * Otherwise: flush the buffer
1249 Flush_VMS_Object_Record_Buffer();
1253 Current_Object_Record_Type
= Type
;
1258 * Flush the object record buffer to the object file
1260 Flush_VMS_Object_Record_Buffer()
1265 * If the buffer is empty, we are done
1267 if (Object_Record_Offset
== 0) return;
1269 * Write the data to the file
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");
1277 * The buffer is now empty
1279 Object_Record_Offset
= 0;
1284 * Close the VMS Object file
1286 Close_VMS_Object_File()
1288 close(VMS_Object_File_FD
);
1293 * Write the MHD (Module Header) records
1295 Write_VMS_MHD_Records()
1297 register char *cp
,*cp1
;
1299 struct {int Size
; char *Ptr
;} Descriptor
;
1300 char Module_Name
[256];
1304 * We are writing a module header record
1306 Set_VMS_Object_File_Record(OBJ$C_HDR
);
1308 * ***************************
1309 * *MAIN MODULE HEADER RECORD*
1310 * ***************************
1312 * Store record type and header type
1314 PUT_CHAR(OBJ$C_HDR
);
1315 PUT_CHAR(MHD$C_MHD
);
1317 * Structure level is 0
1319 PUT_CHAR(OBJ$C_STRLVL
);
1321 * Maximum record size is size of the object record buffer
1323 PUT_SHORT(sizeof(Object_Record_Buffer
));
1325 * Get module name (the FILENAME part of the object file)
1330 if ((*cp
== ']') || (*cp
== '>') ||
1331 (*cp
== ':') || (*cp
== '/')) {
1336 *cp1
++ = islower(*cp
) ? toupper(*cp
++) : *cp
++;
1340 * Limit it to 31 characters and store in the object record
1342 while(--cp1
>= Module_Name
)
1343 if (*cp1
== '.') *cp1
= 0;
1344 if (strlen(Module_Name
) > 31) {
1346 printf("%s: Module name truncated: %s\n", myname
, Module_Name
);
1347 Module_Name
[31] = 0;
1349 PUT_COUNTED_STRING(Module_Name
);
1351 * Module Version is "V1.0"
1353 PUT_COUNTED_STRING("V1.0");
1355 * Creation time is "now" (17 chars of time string)
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
]);
1362 * Patch time is "never" (17 zeros)
1364 for(i
= 0; i
< 17; i
++) PUT_CHAR(0);
1368 Flush_VMS_Object_Record_Buffer();
1370 * *************************
1371 * *LANGUAGE PROCESSOR NAME*
1372 * *************************
1374 * Store record type and header type
1376 PUT_CHAR(OBJ$C_HDR
);
1377 PUT_CHAR(MHD$C_LNM
);
1379 * Store language processor name and version
1380 * (not a counted string!)
1382 cp
= compiler_version_string
;
1385 while(*cp
) PUT_CHAR(*cp
++);
1386 cp
= strchr(&version_string
,'.');
1387 while(*cp
!= ' ') cp
--; cp
++;
1389 while(*cp
>= 32) PUT_CHAR(*cp
++);
1393 Flush_VMS_Object_Record_Buffer();
1398 * Write the EOM (End Of Module) record
1400 Write_VMS_EOM_Record(Psect
, Offset
)
1405 * We are writing an end-of-module record
1407 Set_VMS_Object_File_Record(OBJ$C_EOM
);
1411 PUT_CHAR(OBJ$C_EOM
);
1413 * Store the error severity (0)
1417 * Store the entry point, if it exists
1421 * Store the entry point Psect
1425 * Store the entry point Psect offset
1432 Flush_VMS_Object_Record_Buffer();
1436 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
1442 register unsigned char *p
= ptr
;
1443 register unsigned char *end
= p
+ strlen(ptr
);
1444 register unsigned char c
;
1445 register int hash
= 0;
1450 hash
= ((hash
<<3) + (hash
<<15) + (hash
>>28) + c
);
1456 * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
1458 VMS_Case_Hack_Symbol(In
,Out
)
1468 int destructor
= 0; /*hack to allow for case sens in a destructor*/
1470 int Case_Hack_Bits
= 0;
1472 static char Hex_Table
[16] =
1473 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1476 * Kill any leading "_"
1478 if (*In
== '_') In
++;
1480 new_name
=Out
; /* save this for later*/
1482 if((In
[0]=='_')&&(In
[1]=='$')&&(In
[2]=='_'))
1485 /* We may need to truncate the symbol, save the hash for later*/
1486 if(strlen(In
)>23) result
= hash_string(In
);
1488 * Is there a Psect Attribute to skip??
1490 if (HAS_PSECT_ATTRIBUTES(In
)) {
1494 In
+= PSECT_ATTRIBUTES_STRING_LENGTH
;
1496 if ((In
[0] == '$') && (In
[1] == '$')) {
1505 /* if(strlen(In) > 31 && flagseen['+'])
1506 printf("%s: Symbol name truncated: %s\n",myname,In);*/
1508 * Do the case conversion
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;
1517 Case_Hack_Bits
|= 1;
1519 *Out
++ = islower(*In
) ? toupper(*In
++) : *In
++;
1523 * If we saw a dollar sign, we don't do case hacking
1525 if(flagseen
['h'] || Saw_Dollar
)
1529 * If we have more than 23 characters and everything is lowercase
1530 * we can insert the full 31 characters
1534 * We have more than 23 characters
1535 * If we must add the case hack, then we have truncated the str
1539 if (Case_Hack_Bits
== 0) {
1541 * And so far they are all lower case:
1542 * Check up to 8 more characters
1543 * and ensure that they are lowercase
1548 for(i
= 0; (In
[i
] != 0) && (i
< 8); i
++)
1549 if (isupper(In
[i
]) && !Saw_Dollar
)
1554 if ((i
>= 8) || (In
[i
] == 0)) {
1556 * They are: Copy up to 31 characters
1557 * to the output string
1560 while((--i
>= 0) && (*In
))
1561 *Out
++ = islower(*In
) ?
1568 * If there were any uppercase characters in the name we
1569 * take on the case hacking string
1572 /* Old behavior for regular GNU-C compiler */
1575 if ((Case_Hack_Bits
!= 0)||(truncate
==1)) {
1578 for(i
= 0; i
< 6; i
++) {
1579 *Out
++ = Hex_Table
[Case_Hack_Bits
& 0xf];
1580 Case_Hack_Bits
>>= 4;
1584 Out
=pnt
; /*Cut back to 23 characters maximum */
1586 for( i
=0; i
< 7; i
++) {
1587 init
= result
& 0x01f;
1591 *Out
++ = 'A'+init
-10;
1592 result
= result
>> 5;
1600 if( truncate
==1 && flagseen
['+'] && flagseen
['H'])
1601 printf("%s: Symbol %s replaced by %s\n",myname
,old_name
,new_name
);
1606 * Scan a symbol name for a psect attribute specification
1608 VMS_Modify_Psect_Attributes(Name
, Attribute_Pointer
)
1610 int *Attribute_Pointer
;
1634 if (*Name
== '_') Name
++;
1636 * Check for a PSECT attribute list
1638 if (!HAS_PSECT_ATTRIBUTES(Name
)) return; /* If not, return */
1640 * Skip the attribute list indicator
1642 Name
+= PSECT_ATTRIBUTES_STRING_LENGTH
;
1644 * Process the attributes ("_" separated, "$" terminated)
1646 while(*Name
!= '$') {
1648 * Assume not negating
1654 if ((Name
[0] == 'N') && (Name
[1] == 'O')) {
1656 * We are negating (and skip the NO)
1662 * Find the token delimiter
1665 while(*cp
&& (*cp
!= '_') && (*cp
!= '$')) cp
++;
1667 * Look for the token in the attribute list
1669 for(i
= 0; Attributes
[i
].Name
; i
++) {
1671 * If the strings match, set/clear the attr.
1673 if (strncmp(Name
, Attributes
[i
].Name
, cp
- Name
) == 0) {
1678 *Attribute_Pointer
&=
1679 ~Attributes
[i
].Value
;
1681 *Attribute_Pointer
|=
1682 Attributes
[i
].Value
;
1690 * Now skip the attribute
1693 if (*Name
== '_') Name
++;
1705 VMS_Psect_Spec(Name
, Size
, Type
)
1711 int Psect_Attributes
;
1714 * We are writing a GSD record
1716 Set_VMS_Object_File_Record(OBJ$C_GSD
);
1718 * If the buffer is empty we must insert the GSD record type
1720 if (Object_Record_Offset
== 0) PUT_CHAR(OBJ$C_GSD
);
1722 * We are writing a PSECT definition subrecord
1724 PUT_CHAR(GSD$C_PSC
);
1726 * Psects are always LONGWORD aligned
1730 * Generate the appropriate PSECT flags given the PSECT type
1732 if (strcmp(Type
,"COMMON") == 0) {
1734 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
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) {
1740 * Common block psects are: PIC,OVR,REL,GBL,SHR,RD
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) {
1746 * The Data psects are PIC,REL,RD,WRT
1749 (GPS$M_PIC
|GPS$M_REL
|GPS$M_RD
|GPS$M_WRT
);
1750 } else if (strcmp(Type
,"TEXT") == 0) {
1752 * The Text psects are PIC,REL,SHR,EXE,RD
1755 (GPS$M_PIC
|GPS$M_REL
|GPS$M_SHR
|
1756 GPS$M_EXE
|GPS$M_RD
);
1759 * Error: Unknown psect type
1761 error("Unknown VMS psect type");
1764 * Modify the psect attributes according to any attribute string
1766 if (HAS_PSECT_ATTRIBUTES(Name
))
1767 VMS_Modify_Psect_Attributes(Name
,&Psect_Attributes
);
1769 * Specify the psect attributes
1771 PUT_SHORT(Psect_Attributes
);
1773 * Specify the allocation
1777 * Finally, the psect name
1779 VMS_Case_Hack_Symbol(Name
,Local
);
1780 PUT_COUNTED_STRING(Local
);
1782 * Flush the buffer if it is more than 75% full
1784 if (Object_Record_Offset
>
1785 (sizeof(Object_Record_Buffer
)*3/4))
1786 Flush_VMS_Object_Record_Buffer();
1791 * Define a global symbol
1793 VMS_Global_Symbol_Spec(Name
, Psect_Number
, Psect_Offset
, Defined
)
1801 * We are writing a GSD record
1803 Set_VMS_Object_File_Record(OBJ$C_GSD
);
1805 * If the buffer is empty we must insert the GSD record type
1807 if (Object_Record_Offset
== 0) PUT_CHAR(OBJ$C_GSD
);
1809 * We are writing a Global symbol definition subrecord
1811 if (Psect_Number
<= 255) {
1812 PUT_CHAR(GSD$C_SYM
);
1814 PUT_CHAR(GSD$C_SYMW
);
1817 * Data type is undefined
1821 * Switch on Definition/Reference
1826 * Flags = "RELOCATABLE" and "DEFINED"
1828 PUT_SHORT(GSY$M_DEF
|GSY$M_REL
);
1832 if (Psect_Number
<= 255) {
1833 PUT_CHAR(Psect_Number
);
1835 PUT_SHORT(Psect_Number
);
1840 PUT_LONG(Psect_Offset
);
1844 * Flags = "RELOCATABLE"
1846 PUT_SHORT(GSY$M_REL
);
1849 * Finally, the global symbol name
1851 VMS_Case_Hack_Symbol(Name
,Local
);
1852 PUT_COUNTED_STRING(Local
);
1854 * Flush the buffer if it is more than 75% full
1856 if (Object_Record_Offset
>
1857 (sizeof(Object_Record_Buffer
)*3/4))
1858 Flush_VMS_Object_Record_Buffer();
1863 * Define a procedure entry pt/mask
1865 VMS_Procedure_Entry_Pt(Name
, Psect_Number
, Psect_Offset
, Entry_Mask
)
1874 * We are writing a GSD record
1876 Set_VMS_Object_File_Record(OBJ$C_GSD
);
1878 * If the buffer is empty we must insert the GSD record type
1880 if (Object_Record_Offset
== 0) PUT_CHAR(OBJ$C_GSD
);
1882 * We are writing a Procedure Entry Pt/Mask subrecord
1884 if (Psect_Number
<= 255) {
1885 PUT_CHAR(GSD$C_EPM
);
1887 PUT_CHAR(GSD$C_EPMW
);
1890 * Data type is undefined
1894 * Flags = "RELOCATABLE" and "DEFINED"
1896 PUT_SHORT(GSY$M_DEF
|GSY$M_REL
);
1900 if (Psect_Number
<= 255) {
1901 PUT_CHAR(Psect_Number
);
1903 PUT_SHORT(Psect_Number
);
1908 PUT_LONG(Psect_Offset
);
1912 PUT_SHORT(Entry_Mask
);
1914 * Finally, the global symbol name
1916 VMS_Case_Hack_Symbol(Name
,Local
);
1917 PUT_COUNTED_STRING(Local
);
1919 * Flush the buffer if it is more than 75% full
1921 if (Object_Record_Offset
>
1922 (sizeof(Object_Record_Buffer
)*3/4))
1923 Flush_VMS_Object_Record_Buffer();
1928 * Set the current location counter to a particular Psect and Offset
1930 VMS_Set_Psect(Psect_Index
, Offset
, Record_Type
)
1936 * We are writing a "Record_Type" record
1938 Set_VMS_Object_File_Record(Record_Type
);
1940 * If the buffer is empty we must insert the record type
1942 if (Object_Record_Offset
== 0) PUT_CHAR(Record_Type
);
1944 * Stack the Psect base + Longword Offset
1946 if (Psect_Index
< 255) {
1947 PUT_CHAR(TIR$C_STA_PL
);
1948 PUT_CHAR(Psect_Index
);
1950 PUT_CHAR(TIR$C_STA_WPL
);
1951 PUT_SHORT(Psect_Index
);
1955 * Set relocation base
1957 PUT_CHAR(TIR$C_CTL_SETRB
);
1959 * Flush the buffer if it is more than 75% full
1961 if (Object_Record_Offset
>
1962 (sizeof(Object_Record_Buffer
)*3/4))
1963 Flush_VMS_Object_Record_Buffer();
1967 * Make a data reference
1969 VMS_Set_Data(Psect_Index
, Offset
, Record_Type
,Force
)
1976 * We are writing a "Record_Type" record
1978 Set_VMS_Object_File_Record(Record_Type
);
1980 * If the buffer is empty we must insert the record type
1982 if (Object_Record_Offset
== 0) PUT_CHAR(Record_Type
);
1984 * Stack the Psect base + Longword Offset
1987 if(Psect_Index
>127){
1988 PUT_CHAR(TIR$C_STA_WPL
);
1989 PUT_SHORT(Psect_Index
);
1992 PUT_CHAR(TIR$C_STA_PL
);
1993 PUT_CHAR(Psect_Index
);
1995 } else {if(Offset
>32767){
1996 PUT_CHAR(TIR$C_STA_WPL
);
1997 PUT_SHORT(Psect_Index
);
1999 else if(Offset
>127){
2000 PUT_CHAR(TIR$C_STA_WPW
);
2001 PUT_SHORT(Psect_Index
);
2004 PUT_CHAR(TIR$C_STA_WPB
);
2005 PUT_SHORT(Psect_Index
);
2006 PUT_CHAR(Offset
);};};
2008 * Set relocation base
2010 PUT_CHAR(TIR$C_STO_PIDR
);
2012 * Flush the buffer if it is more than 75% full
2014 if (Object_Record_Offset
>
2015 (sizeof(Object_Record_Buffer
)*3/4))
2016 Flush_VMS_Object_Record_Buffer();
2020 * Make a debugger reference to a struct, union or enum.
2022 VMS_Store_Struct(int Struct_Index
)
2025 * We are writing a "OBJ$C_DBG" record
2027 Set_VMS_Object_File_Record(OBJ$C_DBG
);
2029 * If the buffer is empty we must insert the record type
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
);
2037 * Flush the buffer if it is more than 75% full
2039 if (Object_Record_Offset
>
2040 (sizeof(Object_Record_Buffer
)*3/4))
2041 Flush_VMS_Object_Record_Buffer();
2045 * Make a debugger reference to partially define a struct, union or enum.
2047 VMS_Def_Struct(int Struct_Index
)
2050 * We are writing a "OBJ$C_DBG" record
2052 Set_VMS_Object_File_Record(OBJ$C_DBG
);
2054 * If the buffer is empty we must insert the record type
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
);
2061 * Flush the buffer if it is more than 75% full
2063 if (Object_Record_Offset
>
2064 (sizeof(Object_Record_Buffer
)*3/4))
2065 Flush_VMS_Object_Record_Buffer();
2068 VMS_Set_Struct(int Struct_Index
)
2069 {/* see previous functions for comments */
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();
2081 * Store immediate data in current Psect
2083 VMS_Store_Immediate_Data(Pointer
, Size
, Record_Type
)
2084 register char *Pointer
;
2091 * We are writing a "Record_Type" record
2093 Set_VMS_Object_File_Record(Record_Type
);
2095 * We can only store 128 bytes at a time
2099 * Store a maximum of 128 bytes
2101 i
= (Size
> 128) ? 128 : Size
;
2104 * If we cannot accommodate this record, flush the
2107 if ((Object_Record_Offset
+ i
+ 1) >=
2108 sizeof(Object_Record_Buffer
))
2109 Flush_VMS_Object_Record_Buffer();
2111 * If the buffer is empty we must insert record type
2113 if (Object_Record_Offset
== 0) PUT_CHAR(Record_Type
);
2117 PUT_CHAR(-i
& 0xff);
2121 while(--i
>= 0) PUT_CHAR(*Pointer
++);
2123 * Flush the buffer if it is more than 75% full
2125 if (Object_Record_Offset
>
2126 (sizeof(Object_Record_Buffer
)*3/4))
2127 Flush_VMS_Object_Record_Buffer();
2133 * Store repeated immediate data in current Psect
2135 VMS_Store_Repeated_Data(Repeat_Count
,Pointer
, Size
, Record_Type
)
2137 register char *Pointer
;
2143 * Ignore zero bytes/words/longwords
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;
2149 * If the data is too big for a TIR$C_STO_RIVB sub-record
2150 * then we do it manually
2153 while(--Repeat_Count
>= 0)
2154 VMS_Store_Immediate_Data(Pointer
,Size
,Record_Type
);
2158 * We are writing a "Record_Type" record
2160 Set_VMS_Object_File_Record(Record_Type
);
2162 * If the buffer is empty we must insert record type
2164 if (Object_Record_Offset
== 0) PUT_CHAR(Record_Type
);
2166 * Stack the repeat count
2168 PUT_CHAR(TIR$C_STA_LW
);
2169 PUT_LONG(Repeat_Count
);
2171 * And now the command and its data
2173 PUT_CHAR(TIR$C_STO_RIVB
);
2175 while(--Size
>= 0) PUT_CHAR(*Pointer
++);
2177 * Flush the buffer if it is more than 75% full
2179 if (Object_Record_Offset
>
2180 (sizeof(Object_Record_Buffer
)*3/4))
2181 Flush_VMS_Object_Record_Buffer();
2186 * Store a Position Independent Reference
2188 VMS_Store_PIC_Symbol_Reference(Symbol
, Offset
, PC_Relative
,
2189 Psect
, Psect_Offset
, Record_Type
)
2190 struct symbol
*Symbol
;
2197 register struct VMS_Symbol
*vsp
=
2198 (struct VMS_Symbol
*)(Symbol
->sy_number
);
2202 * We are writing a "Record_Type" record
2204 Set_VMS_Object_File_Record(Record_Type
);
2206 * If the buffer is empty we must insert record type
2208 if (Object_Record_Offset
== 0) PUT_CHAR(Record_Type
);
2210 * Set to the appropriate offset in the Psect
2214 * For a Code reference we need to fix the operand
2215 * specifier as well (so back up 1 byte)
2217 VMS_Set_Psect(Psect
, Psect_Offset
- 1, Record_Type
);
2220 * For a Data reference we just store HERE
2222 VMS_Set_Psect(Psect
, Psect_Offset
, Record_Type
);
2225 * Make sure we are still generating a "Record Type" record
2227 if (Object_Record_Offset
== 0) PUT_CHAR(Record_Type
);
2229 * Dispatch on symbol type (so we can stack its value)
2231 switch(Symbol
->sy_nlist
.n_type
) {
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
2240 case N_TEXT
| N_EXT
:
2242 * Get the symbol name (case hacked)
2244 VMS_Case_Hack_Symbol(Symbol
->sy_nlist
.n_un
.n_name
,Local
);
2246 * Stack the global symbol value
2248 PUT_CHAR(TIR$C_STA_GBL
);
2249 PUT_COUNTED_STRING(Local
);
2252 * Stack the longword offset
2254 PUT_CHAR(TIR$C_STA_LW
);
2257 * Add the two, leaving the result on the stack
2259 PUT_CHAR(TIR$C_OPR_ADD
);
2263 * Uninitialized local data
2267 * Stack the Psect (+offset)
2269 if (vsp
->Psect_Index
< 255) {
2270 PUT_CHAR(TIR$C_STA_PL
);
2271 PUT_CHAR(vsp
->Psect_Index
);
2273 PUT_CHAR(TIR$C_STA_WPL
);
2274 PUT_SHORT(vsp
->Psect_Index
);
2276 PUT_LONG(vsp
->Psect_Offset
+ Offset
);
2283 * Stack the Psect (+offset)
2285 if (vsp
->Psect_Index
< 255) {
2286 PUT_CHAR(TIR$C_STA_PL
);
2287 PUT_CHAR(vsp
->Psect_Index
);
2289 PUT_CHAR(TIR$C_STA_WPL
);
2290 PUT_SHORT(vsp
->Psect_Index
);
2292 PUT_LONG(Symbol
->sy_nlist
.n_value
);
2295 * Initialized local or global data
2298 #ifndef NOT_VAX_11_C_COMPATIBLE
2299 case N_UNDF
| N_EXT
:
2300 case N_DATA
| N_EXT
:
2301 #endif NOT_VAX_11_C_COMPATIBLE
2303 * Stack the Psect (+offset)
2305 if (vsp
->Psect_Index
< 255) {
2306 PUT_CHAR(TIR$C_STA_PL
);
2307 PUT_CHAR(vsp
->Psect_Index
);
2309 PUT_CHAR(TIR$C_STA_WPL
);
2310 PUT_SHORT(vsp
->Psect_Index
);
2312 PUT_LONG(vsp
->Psect_Offset
+ Offset
);
2316 * Store either a code or data reference
2318 PUT_CHAR(PC_Relative
? TIR$C_STO_PICR
: TIR$C_STO_PIDR
);
2320 * Flush the buffer if it is more than 75% full
2322 if (Object_Record_Offset
>
2323 (sizeof(Object_Record_Buffer
)*3/4))
2324 Flush_VMS_Object_Record_Buffer();
2329 * Check in the text area for an indirect pc-relative reference
2330 * and fix it up with addressing mode 0xff [PC indirect]
2332 * THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
2333 * PIC CODE GENERATING FIXUP ROUTINE.
2335 VMS_Fix_Indirect_Reference(Text_Psect
, Offset
, fragP
, text_frag_root
)
2338 register fragS
*fragP
;
2339 struct frag
*text_frag_root
;
2342 * The addressing mode byte is 1 byte before the address
2346 * Is it in THIS frag??
2348 if ((Offset
< fragP
->fr_address
) ||
2349 (Offset
>= (fragP
->fr_address
+ fragP
->fr_fix
))) {
2351 * We need to search for the fragment containing this
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
)))
2360 * If we couldn't find the frag, things are BAD!!
2363 error("Couldn't find fixup fragment when checking for indirect reference");
2366 * Check for indirect PC relative addressing mode
2368 if (fragP
->fr_literal
[Offset
- fragP
->fr_address
] == (char)0xff) {
2369 static char Address_Mode
= 0xff;
2372 * Yes: Store the indirect mode back into the image
2373 * to fix up the damage done by STO_PICR
2375 VMS_Set_Psect(Text_Psect
,Offset
,OBJ$C_TIR
);
2376 VMS_Store_Immediate_Data(&Address_Mode
,1,OBJ$C_TIR
);
2382 * Write the Traceback Module Begin record
2384 VMS_TBT_Module_Begin()
2386 register char *cp
,*cp1
;
2388 char Module_Name
[256];
2392 * Get module name (the FILENAME part of the object file)
2397 if ((*cp
== ']') || (*cp
== '>') ||
2398 (*cp
== ':') || (*cp
== '/')) {
2403 *cp1
++ = islower(*cp
) ? toupper(*cp
++) : *cp
++;
2407 * Limit it to 31 characters
2409 while(--cp1
>= Module_Name
)
2410 if (*cp1
== '.') *cp1
= 0;
2411 if (strlen(Module_Name
) > 31) {
2413 printf("%s: Module name truncated: %s\n",myname
, Module_Name
);
2414 Module_Name
[31] = 0;
2417 * Arrange to store the data locally (leave room for size byte)
2423 *cp
++ = DST$C_MODBEG
;
2429 * Language type == "C"
2431 *(long *)cp
= DST$C_C
;
2434 * Store the module name
2436 *cp
++ = strlen(Module_Name
);
2438 while(*cp1
) *cp
++ = *cp1
++;
2440 * Now we can store the record size
2442 Size
= (cp
- Local
);
2445 * Put it into the object record
2447 VMS_Store_Immediate_Data(Local
, Size
, OBJ$C_TBT
);
2452 * Write the Traceback Module End record
2454 VMS_TBT_Module_End()
2462 Local
[1] = DST$C_MODEND
;
2464 * Put it into the object record
2466 VMS_Store_Immediate_Data(Local
, 2, OBJ$C_TBT
);
2471 * Write the Traceback Routine Begin record
2473 VMS_TBT_Routine_Begin(symbolP
, Psect
)
2474 struct symbol
*symbolP
;
2477 register char *cp
,*cp1
;
2484 * Strip the leading "_" from the name
2486 Name
= symbolP
->sy_nlist
.n_un
.n_name
;
2487 if (*Name
== '_') Name
++;
2489 * Get the text psect offset
2491 Offset
= symbolP
->sy_nlist
.n_value
;
2493 * Calculate the record size
2495 Size
= 1+1+4+1+strlen(Name
);
2503 Local
[1] = DST$C_RTNBEG
;
2509 * Store the data so far
2511 VMS_Store_Immediate_Data(Local
, 3, OBJ$C_TBT
);
2513 * Make sure we are still generating a OBJ$C_TBT record
2515 if (Object_Record_Offset
== 0) PUT_CHAR(OBJ$C_TBT
);
2517 * Now get the symbol address
2519 PUT_CHAR(TIR$C_STA_WPL
);
2523 * Store the data reference
2525 PUT_CHAR(TIR$C_STO_PIDR
);
2527 * Store the counted string as data
2531 Size
= strlen(cp1
) + 1;
2533 while(*cp1
) *cp
++ = *cp1
++;
2534 VMS_Store_Immediate_Data(Local
, Size
, OBJ$C_TBT
);
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.
2546 VMS_TBT_Routine_End(Max_Size
,sp
)
2551 int Size
= 0x7fffffff;
2555 for(symbolP
= symbol_rootP
; symbolP
; symbolP
= symbol_next(symbolP
)) {
2556 if ((symbolP
->sy_nlist
.n_type
& ~N_EXT
) == N_TEXT
) {
2557 if (symbolP
->sy_nlist
.n_un
.n_name
[0] == 'L') continue;
2558 if((symbolP
->sy_nlist
.n_value
> sp
->sy_nlist
.n_value
) &&
2559 (symbolP
->sy_nlist
.n_value
< Size
))
2560 Size
= symbolP
->sy_nlist
.n_value
;
2561 /* check if gcc_compiled. has size of zero */
2562 if((symbolP
->sy_nlist
.n_value
== sp
->sy_nlist
.n_value
) &&
2564 !strcmp(sp
->sy_nlist
.n_un
.n_name
,"gcc_compiled."))
2565 Size
= symbolP
->sy_nlist
.n_value
;
2569 if(Size
== 0x7fffffff) Size
= Max_Size
;
2570 Size
-= sp
->sy_nlist
.n_value
; /* and get the size of the routine */
2578 Local
[1] = DST$C_RTNEND
;
2586 *((long *)(Local
+3)) = Size
;
2590 VMS_Store_Immediate_Data(Local
,7, OBJ$C_TBT
);
2593 * Write the Traceback Block End record
2595 VMS_TBT_Block_Begin(symbolP
, Psect
, Name
)
2596 struct symbol
*symbolP
;
2600 register char *cp
,*cp1
;
2607 Size
= 1+1+4+1+strlen(Name
);
2613 * Begin Block - We simulate with a phony routine
2615 Local
[1] = DST$C_BLKBEG
;
2621 * Store the data so far
2623 VMS_Store_Immediate_Data(Local
, 3, OBJ$C_DBG
);
2625 * Make sure we are still generating a OBJ$C_DBG record
2627 if (Object_Record_Offset
== 0) PUT_CHAR(OBJ$C_DBG
);
2629 * Now get the symbol address
2631 PUT_CHAR(TIR$C_STA_WPL
);
2634 * Get the text psect offset
2636 Offset
= symbolP
->sy_nlist
.n_value
;
2639 * Store the data reference
2641 PUT_CHAR(TIR$C_STO_PIDR
);
2643 * Store the counted string as data
2647 Size
= strlen(cp1
) + 1;
2649 while(*cp1
) *cp
++ = *cp1
++;
2650 VMS_Store_Immediate_Data(Local
, Size
, OBJ$C_DBG
);
2655 * Write the Traceback Block End record
2657 VMS_TBT_Block_End(int Size
)
2662 * End block - simulate with a phony end routine
2665 Local
[1] = DST$C_BLKEND
;
2666 *((long *)(Local
+3)) = Size
;
2671 VMS_Store_Immediate_Data(Local
,7, OBJ$C_DBG
);
2677 * Write a Line number / PC correlation record
2679 VMS_TBT_Line_PC_Correlation(Line_Number
, Offset
, Psect
, Do_Delta
)
2689 * If not delta, set our PC/Line number correlation
2691 if (Do_Delta
== 0) {
2695 Local
[0] = 1+1+2+1+4;
2697 * Line Number/PC correlation
2699 Local
[1] = DST$C_LINE_NUM
;
2703 Local
[2] = DST$C_SET_LINE_NUM
;
2704 *((unsigned short *)(Local
+3)) = Line_Number
-1;
2708 Local
[5] = DST$C_SET_ABS_PC
;
2709 VMS_Store_Immediate_Data(Local
, 6, OBJ$C_TBT
);
2711 * Make sure we are still generating a OBJ$C_TBT record
2713 if (Object_Record_Offset
== 0) PUT_CHAR(OBJ$C_TBT
);
2715 PUT_CHAR(TIR$C_STA_PL
);
2718 PUT_CHAR(TIR$C_STA_WPL
);
2722 PUT_CHAR(TIR$C_STO_PIDR
);
2724 * Do a PC offset of 0 to register the line number
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
);
2732 * If Delta is negative, terminate the line numbers
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
);
2746 * Do a PC/Line delta
2749 *cp
++ = DST$C_LINE_NUM
;
2750 if (Line_Number
> 1) {
2752 * We need to increment the line number
2754 if (Line_Number
-1 <= 255) {
2755 *cp
++ = DST$C_INCR_LINUM
;
2756 *cp
++ = Line_Number
-1;
2758 *cp
++ = DST$C_INCR_LINUM_W
;
2759 *(short *)cp
= Line_Number
-1;
2760 cp
+= sizeof(short);
2766 if (Offset
<= 128) {
2769 if (Offset
< 0x10000) {
2770 *cp
++ = DST$C_DELTA_PC_W
;
2771 *(short *)cp
= Offset
;
2772 cp
+= sizeof(short);
2774 *cp
++ = DST$C_DELTA_PC_L
;
2775 *(long *)cp
= Offset
;
2779 Local
[0] = cp
- (Local
+1);
2780 VMS_Store_Immediate_Data(Local
,cp
- Local
, OBJ$C_TBT
);
2786 * Describe a source file to the debugger
2788 VMS_TBT_Source_File(Filename
, ID_Number
)
2792 register char *cp
,*cp1
;
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];
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
;
2809 * Setup the Nam block so we can find out the FULL name
2810 * of the source file.
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
);
2819 * Setup the Date and File Header Xabs
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); */
2832 * Get the file information
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",
2844 * Calculate the size of the resultant string
2850 Local
[0] = 1+1+1+1+1+2+8+4+2+1+1+i
+1;
2852 * Source declaration
2854 Local
[1] = DST$C_SOURCE
;
2856 * Make formfeeds count as source records
2858 Local
[2] = DST$C_SRC_FORMFEED
;
2860 * Declare source file
2862 Local
[3] = DST$C_SRC_DECLFILE
;
2863 Local
[4] = 1+2+8+4+2+1+1+i
+1;
2872 *(short *)cp
= ID_Number
;
2873 cp
+= sizeof(short);
2877 *(long *)cp
= ((long *) &Date_Xab
.xab$q_cdt
)[0];
2879 *(long *)cp
= ((long *) &Date_Xab
.xab$q_cdt
)[1];
2884 *(long *)cp
= File_Header_Xab
.xab$l_ebk
;
2889 *(short *)cp
= File_Header_Xab
.xab$w_ffb
;
2890 cp
+= sizeof(short);
2894 *cp
++ = File_Header_Xab
.xab$b_rfo
;
2900 while(--i
>= 0) *cp
++ = *cp1
++;
2902 * Library module name (none)
2908 VMS_Store_Immediate_Data(Local
,cp
- Local
, OBJ$C_TBT
);
2913 * Give the number of source lines to the debugger
2915 VMS_TBT_Source_Lines(ID_Number
,Starting_Line_Number
,Number_Of_Lines
)
2917 int Starting_Line_Number
;
2918 int Number_Of_Lines
;
2926 Local
[0] = 1+1+2+1+4+1+2;
2928 * Source declaration
2930 Local
[1] = DST$C_SOURCE
;
2935 *cp
++ = DST$C_SRC_SETFILE
;
2939 *(short *)cp
= ID_Number
;
2940 cp
+= sizeof(short);
2944 *cp
++ = DST$C_SRC_SETREC_L
;
2945 *(long *)cp
= Starting_Line_Number
;
2950 *cp
++ = DST$C_SRC_DEFLINES_W
;
2951 *(short *)cp
= Number_Of_Lines
;
2952 cp
+= sizeof(short);
2956 VMS_Store_Immediate_Data(Local
, cp
-Local
, OBJ$C_TBT
);
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.
2965 int VMS_Initialized_Data_Size(sp
, End_Of_Data
)
2966 register struct symbol
*sp
;
2969 register struct symbol
*sp1
,*Next_Symbol
;
2972 * Find the next symbol
2973 * it delimits this datum
2976 for (sp1
= symbol_rootP
; sp1
; sp1
= symbol_next(sp1
)) {
2978 * The data type must match
2980 if ((sp1
->sy_nlist
.n_type
& ~N_EXT
) != N_DATA
) continue;
2982 * The symbol must be AFTER this symbol
2984 if (sp1
->sy_nlist
.n_value
<= sp
->sy_nlist
.n_value
) continue;
2986 * We ignore THIS symbol
2988 if (sp1
== sp
) continue;
2990 * If there is already a candidate selected for the
2991 * next symbol, see if we are a better candidate
2995 * We are a better candidate if we are "closer"
2998 if (sp1
->sy_nlist
.n_value
>
2999 Next_Symbol
->sy_nlist
.n_value
)
3002 * Win: Make this the candidate
3007 * This is the 1st candidate
3013 * Calculate its size
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
));
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 */
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
;
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
;
3045 fpnt
= (struct input_file
*) malloc(sizeof(struct input_file
));
3046 if(file_root
== (struct input_file
*) NULL
) file_root
= fpnt
;
3048 struct input_file
* fpnt1
;
3049 for(fpnt1
= file_root
; fpnt1
->next
; fpnt1
= fpnt1
->next
);
3052 fpnt
->next
= (struct input_file
*) NULL
;
3053 fpnt
->name
= sp
->sy_nlist
.n_un
.n_name
;
3054 fpnt
->min_line
= 0x7fffffff;
3058 fpnt
->file_number
= 0;
3060 fpnt
->same_file_fpnt
= same_file
;
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!
3071 _doprnt(Format
, a
, f
)
3076 int Nargs
= ((int *)a
)[-2]; /* This understands as_fatal() */
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;
3097 char const_flag
= 0;
3105 temp
= get_absolute_expression ();
3106 subseg_new (SEG_DATA
, (subsegT
)temp
);
3108 demand_empty_rest_of_line();
3111 obj_crawl_symbol_chain() {
3112 /* JF deal with forward references first. . . */
3113 for (symbolP
= symbol_rootP
; symbolP
; symbolP
= symbol_next(symbolP
)) {
3114 if (symbolP
->sy_forward
) {
3115 symbolP
->sy_value
+= symbolP
->sy_forward
->sy_value
+ symbolP
->sy_forward
->sy_frag
->fr_address
;
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
));
3120 #endif /* OBJ_COFF */
3121 symbolP
->sy_forward
=0;
3122 } /* if it has a forward reference */
3123 } /* walk the symbol chain */
3125 { /* crawl symbol table */
3126 register int symbol_number
= 0;
3128 #if defined(OBJ_COFF)
3129 { /* OBJ_COFF version */
3131 symbolS
* symbol_externP
= (symbolS
*)0;
3132 symbolS
* symbol_extern_lastP
= (symbolS
*)0;
3134 /* The symbol list should be ordered according to the following sequence
3137 * . debug entries for functions
3138 * . fake symbols for .text .data and .bss
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.
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. */
3151 * Build up static symbols for .text, .data and .bss
3153 dot_text_symbol
= (symbolS
*)
3154 c_section_symbol(".text",
3156 H_GET_TEXT_SIZE(&headers
),
3157 0/*text_relocation_number*/,
3158 0/*text_lineno_number*/);
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
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 */
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
3179 /* as john pointed out, this wasn't right. Instead, we'll check here to
3180 make sure that the list is doubly linked. */
3182 #if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
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 */
3186 #endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
3187 symbolP
= symbol_rootP
;
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
);
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
) &&
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
;
3220 if(flagseen
['R'] && S_IS_DATA(symbolP
))
3221 S_SET_TEXT(symbolP
);
3223 symbolP
->sy_value
+= symbolP
->sy_frag
->fr_address
;
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
);
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
);
3237 register symbolS
* begin_symbolP
;
3238 begin_symbolP
= *(symbolS
**)stack_pop(block_stack
);
3239 if(begin_symbolP
== (symbolS
*)0)
3240 as_warn("mismatched .eb");
3242 SA_SET_SYM_ENDNDX(begin_symbolP
, symbol_number
);
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
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
));
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...
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;
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);
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
3288 ld will move the symbol 21 to the end of the list but
3289 endndx will still be 22 instead of 21. */
3291 register symbolS
* thisP
= symbolP
;
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
);
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
;
3307 symbol_append(thisP
, symbol_extern_lastP
);
3308 symbol_extern_lastP
= thisP
;
3310 if(SF_GET_STRING(thisP
)) {
3311 thisP
->sy_name_offset
= string_byte_count
;
3312 string_byte_count
+= strlen(S_GET_NAME(thisP
)) + 1;
3314 thisP
->sy_name_offset
= 0;
3315 thisP
->sy_number
= symbol_number
;
3316 symbol_number
+= 1 + S_GET_NUMBER_AUXILIARY(thisP
);
3322 /* this actually appends the entire extern chain */
3323 symbol_append(symbol_externP
, symbol_lastP
);
3324 symbolP
= symbol_externP
;
3326 if(SF_GET_STRING(symbolP
)) {
3327 symbolP
->sy_name_offset
= string_byte_count
;
3328 string_byte_count
+= strlen(S_GET_NAME(symbolP
)) + 1;
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
);
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. */
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
;
3349 text_lineno_number
++;
3350 } /* for each line number */
3351 } /* OBJ_COFF version */
3352 #elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
3353 { /* OBJ_AOUT version */
3354 symbolPP
= & symbol_rootP
; /* -> last symbol chain link. */
3355 while ((symbolP
= *symbolPP
) != NULL
)
3357 if (flagseen
['R'] && S_IS_DATA(symbolP
)) {
3358 S_SET_TEXT(symbolP
);
3359 } /* if pusing data into text */
3361 symbolP
-> sy_value
+= symbolP
-> sy_frag
-> fr_address
;
3363 /* OK, here is how we decide which symbols go out into the
3364 brave new symtab. Symbols that do are:
3366 * symbols with no name (stabd's?)
3367 * symbols with debug info in their N_TYPE
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.
3375 All other symbols are output. We complain if a deleted
3376 symbol was marked external. */
3380 && !S_IS_REGISTER(symbolP
)
3381 #ifndef VMS /* Under VMS we need to keep local symbols */
3382 && ( !S_GET_NAME(symbolP
)
3383 || S_IS_DEBUG(symbolP
)
3385 /* FIXME this ifdef seems highly dubious to me. xoxorich. */
3386 || !S_IS_DEFINED(symbolP
)
3387 || S_IS_EXTERNAL(symbolP
)
3388 #endif /* TC_I960 */
3389 || (S_GET_NAME(symbolP
)[0] != '\001' && (flagseen
['L'] || ! S_LOCAL_NAME(symbolP
))))
3390 #endif /* not VMS */
3394 symbolP
->sy_number
= symbol_number
++;
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;
3403 else /* .Stabd case. */
3404 #endif /* not VMS */
3405 symbolP
->sy_name_offset
= 0;
3406 symbolPP
= &(symbol_next(symbolP
));
3408 if (S_IS_EXTERNAL(symbolP
) || !S_IS_DEFINED(symbolP
)) {
3409 as_bad ("Local symbol %s never defined", name
);
3413 /* Unhook it from the chain */
3414 *symbolPP
= symbol_next(symbolP
);
3416 } /* if this symbol should be in the output */
3417 } /* for each symbol */
3418 } /* OBJ_AOUT version */
3420 cant_crawl_symbol_table();
3422 H_SET_STRING_SIZE(&headers
,string_byte_count
);
3423 H_SET_SYMBOL_TABLE_SIZE(&headers
, symbol_number
);
3424 } /* crawl symbol table */
3426 /* JF deal with forward references first. . . */
3427 for (symbolP
= symbol_rootP
; symbolP
; symbolP
= symbol_next(symbolP
)) {
3428 if (symbolP
->sy_forward
) {
3429 symbolP
->sy_value
+= symbolP
->sy_forward
->sy_value
+ symbolP
->sy_forward
->sy_frag
->fr_address
;
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
));
3434 #endif /* OBJ_COFF */
3435 symbolP
->sy_forward
=0;
3436 } /* if it has a forward reference */
3437 } /* walk the symbol chain */
3439 { /* crawl symbol table */
3440 register int symbol_number
= 0;
3442 #if defined(OBJ_COFF)
3443 { /* OBJ_COFF version */
3445 symbolS
* symbol_externP
= (symbolS
*)0;
3446 symbolS
* symbol_extern_lastP
= (symbolS
*)0;
3448 /* The symbol list should be ordered according to the following sequence
3451 * . debug entries for functions
3452 * . fake symbols for .text .data and .bss
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.
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. */
3465 * Build up static symbols for .text, .data and .bss
3467 dot_text_symbol
= (symbolS
*)
3468 c_section_symbol(".text",
3470 H_GET_TEXT_SIZE(&headers
),
3471 0/*text_relocation_number*/,
3472 0/*text_lineno_number*/);
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
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 */
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
3493 /* as john pointed out, this wasn't right. Instead, we'll check here to
3494 make sure that the list is doubly linked. */
3496 #if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
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 */
3500 #endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
3501 symbolP
= symbol_rootP
;
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
);
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
) &&
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
;
3534 if(flagseen
['R'] && S_IS_DATA(symbolP
))
3535 S_SET_TEXT(symbolP
);
3537 symbolP
->sy_value
+= symbolP
->sy_frag
->fr_address
;
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
);
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
);
3551 register symbolS
* begin_symbolP
;
3552 begin_symbolP
= *(symbolS
**)stack_pop(block_stack
);
3553 if(begin_symbolP
== (symbolS
*)0)
3554 as_warn("mismatched .eb");
3556 SA_SET_SYM_ENDNDX(begin_symbolP
, symbol_number
);
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
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
));
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...
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;
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);
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
3602 ld will move the symbol 21 to the end of the list but
3603 endndx will still be 22 instead of 21. */
3605 register symbolS
* thisP
= symbolP
;
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
);
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
;
3621 symbol_append(thisP
, symbol_extern_lastP
);
3622 symbol_extern_lastP
= thisP
;
3624 if(SF_GET_STRING(thisP
)) {
3625 thisP
->sy_name_offset
= string_byte_count
;
3626 string_byte_count
+= strlen(S_GET_NAME(thisP
)) + 1;
3628 thisP
->sy_name_offset
= 0;
3629 thisP
->sy_number
= symbol_number
;
3630 symbol_number
+= 1 + S_GET_NUMBER_AUXILIARY(thisP
);
3636 /* this actually appends the entire extern chain */
3637 symbol_append(symbol_externP
, symbol_lastP
);
3638 symbolP
= symbol_externP
;
3640 if(SF_GET_STRING(symbolP
)) {
3641 symbolP
->sy_name_offset
= string_byte_count
;
3642 string_byte_count
+= strlen(S_GET_NAME(symbolP
)) + 1;
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
);
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. */
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
;
3663 text_lineno_number
++;
3664 } /* for each line number */
3665 } /* OBJ_COFF version */
3666 #elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
3667 { /* OBJ_AOUT version */
3668 symbolPP
= & symbol_rootP
; /* -> last symbol chain link. */
3669 while ((symbolP
= *symbolPP
) != NULL
)
3671 if (flagseen
['R'] && S_IS_DATA(symbolP
)) {
3672 S_SET_TEXT(symbolP
);
3673 } /* if pusing data into text */
3675 symbolP
-> sy_value
+= symbolP
-> sy_frag
-> fr_address
;
3677 /* OK, here is how we decide which symbols go out into the
3678 brave new symtab. Symbols that do are:
3680 * symbols with no name (stabd's?)
3681 * symbols with debug info in their N_TYPE
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.
3689 All other symbols are output. We complain if a deleted
3690 symbol was marked external. */
3694 && !S_IS_REGISTER(symbolP
)
3695 #ifndef VMS /* Under VMS we need to keep local symbols */
3696 && ( !S_GET_NAME(symbolP
)
3697 || S_IS_DEBUG(symbolP
)
3699 /* FIXME this ifdef seems highly dubious to me. xoxorich. */
3700 || !S_IS_DEFINED(symbolP
)
3701 || S_IS_EXTERNAL(symbolP
)
3702 #endif /* TC_I960 */
3703 || (S_GET_NAME(symbolP
)[0] != '\001' && (flagseen
['L'] || ! S_LOCAL_NAME(symbolP
))))
3704 #endif /* not VMS */
3708 symbolP
->sy_number
= symbol_number
++;
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;
3717 else /* .Stabd case. */
3718 #endif /* not VMS */
3719 symbolP
->sy_name_offset
= 0;
3720 symbolPP
= &(symbol_next(symbolP
));
3722 if (S_IS_EXTERNAL(symbolP
) || !S_IS_DEFINED(symbolP
)) {
3723 as_bad ("Local symbol %s never defined", name
);
3727 /* Unhook it from the chain */
3728 *symbolPP
= symbol_next(symbolP
);
3730 } /* if this symbol should be in the output */
3731 } /* for each symbol */
3732 } /* OBJ_AOUT version */
3734 cant_crawl_symbol_table();
3736 H_SET_STRING_SIZE(&headers
,string_byte_count
);
3737 H_SET_SYMBOL_TABLE_SIZE(&headers
, symbol_number
);
3738 } /* crawl symbol table */
3740 } /* obj_crawl_symbol_chain() */