⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vms.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* vms.c -- Write out a VAX/VMS object file   Copyright (C) 1987, 1988 Free Software Foundation, Inc.This file is part of GAS, the GNU Assembler.GAS is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GAS is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GAS; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* Written by David L. Kashtan */#include <ctype.h>#include <stdio.h>#include "as.h"#include "md.h"#include "subsegs.h"#include "obstack.h"#include "struc-symbol.h"#include "write.h"#include "symbols.h"#ifdef	VMS		/* THIS MODULE IS FOR VMS ONLY */#include <stab.h>#include "objrecdef.h"			/* Define VMS Object record lang. */#include <vms/fabdef.h>			/* Define File Access Block	  */#include <vms/namdef.h>			/* Define NAM Block		  */#include <vms/xabdef.h>			/* Define XAB			  */#include <vms/xabdatdef.h>		/* Define Date XAB		  */#include <vms/xabfhcdef.h>		/* Define File Header XAB	  *//* *	Version string of the compiler that produced the code we are *	assembling.  (And this assembler, if we do not have compiler info.) */extern char version_string[];char *compiler_version_string;extern char *myname;static symbolS *Entry_Point_Symbol = 0;	/* Pointer to "_main"	 *//* *	We augment the "gas" symbol structure with this */struct VMS_Symbol {	struct VMS_Symbol *Next;	struct symbol *Symbol;	int Size;	int Psect_Index;	int Psect_Offset;	};struct VMS_Symbol *VMS_Symbols = 0;/* we need this to keep track of the various input files, so that we can * give the debugger the correct source line  */struct input_file{	struct input_file* next;	struct input_file* same_file_fpnt;	int file_number;	int max_line;	int min_line;	int offset;	char flag;	char * name;	symbolS * spnt;	};static struct input_file * file_root = (struct input_file*)NULL;struct input_file * find_file(symbolS *);/* *	If the procedure "main()" exists we have to add the instruction *	"jsb c$main_args" at the beginning to be compatible with VAX-11 "C". */VMS_Check_For_Main(){  register symbolS *symbolP;#ifdef	HACK_DEC_C_STARTUP	/* JF */  register struct frchain *frchainP;  register fragS *fragP;  register fragS **prev_fragPP;  register struct fix *fixP;  register fragS *New_Frag;  int i;#endif	HACK_DEC_C_STARTUP  symbolP = (struct symbol *)symbol_find("_main");  if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {#ifdef	HACK_DEC_C_STARTUP	if( !flagseen['+']) {#endif		/*		 *	Remember the entry point symbol		 */		Entry_Point_Symbol = symbolP;#ifdef HACK_DEC_C_STARTUP	} else {		/*		 *	Scan all the fragment chains for the one with "_main"		 *	(Actually we know the fragment from the symbol, but we need		 *	 the previous fragment so we can change its pointer)		 */		frchainP = frchain_root;		while(frchainP) {			/*			 *	Scan all the fragments in this chain, remembering			 *	the "previous fragment"			 */			prev_fragPP = &frchainP->frch_root;			fragP = frchainP->frch_root;			while(fragP && (fragP != frchainP->frch_last)) {				/*				 *	Is this the fragment?				 */				if (fragP == symbolP->sy_frag) {					/*					 *	Yes: Modify the fragment by replacing					 *	     it with a new fragment.					 */					New_Frag = (fragS *)						xmalloc(sizeof(*New_Frag) +								fragP->fr_fix +								fragP->fr_var +								5);					/*					 *	The fragments are the same except					 *	that the "fixed" area is larger					 */					*New_Frag = *fragP;					New_Frag->fr_fix += 6;					/*					 *	Copy the literal data opening a hole					 *	2 bytes after "_main" (i.e. just after					 *	the entry mask).  Into which we place					 *	the JSB instruction.					 */					New_Frag->fr_literal[0] = fragP->fr_literal[0];					New_Frag->fr_literal[1] = fragP->fr_literal[1];					New_Frag->fr_literal[2] = 0x16; /* Jsb */					New_Frag->fr_literal[3] = 0xef;					New_Frag->fr_literal[4] = 0;					New_Frag->fr_literal[5] = 0;					New_Frag->fr_literal[6] = 0;					New_Frag->fr_literal[7] = 0;					for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)						New_Frag->fr_literal[i+6] =							fragP->fr_literal[i];					/*					 *	Now replace the old fragment with the					 *	newly generated one.					 */					*prev_fragPP = New_Frag;					/*					 *	Remember the entry point symbol					 */					Entry_Point_Symbol = symbolP;					/*					 *	Scan the text area fixup structures					 *	as offsets in the fragment may have					 *	changed					 */					for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {						/*						 *	Look for references to this						 *	fragment.						 */						if (fixP->fx_frag == fragP) {							/*							 *	Change the fragment							 *	pointer							 */							fixP->fx_frag = New_Frag;							/*							 *	If the offset is after							 *	the entry mask we need							 *	to account for the JSB							 *	instruction we just							 *	inserted.							 */							if (fixP->fx_where >= 2)								fixP->fx_where += 6;						}					}					/*					 *	Scan the symbols as offsets in the					 *	fragment may have changed					 */					for(symbolP = symbol_rootP;					    symbolP;					    symbolP = symbolP->sy_next) {						/*						 *	Look for references to this						 *	fragment.						 */						if (symbolP->sy_frag == fragP) {							/*							 *	Change the fragment							 *	pointer							 */							symbolP->sy_frag = New_Frag;							/*							 *	If the offset is after							 *	the entry mask we need							 *	to account for the JSB							 *	instruction we just							 *	inserted.							 */							if (symbolP->sy_nlist.n_value >= 2)								symbolP->sy_nlist.n_value += 6;						}					}					/*					 *	Make a symbol reference to					 *	"_c$main_args" so we can get					 *	its address inserted into the					 *	JSB instruction.					 */					symbolP = (symbolS *)xmalloc(sizeof(*symbolP));					symbolP->sy_nlist.n_un.n_name = "_c$main_args";					symbolP->sy_nlist.n_type = N_UNDF;					symbolP->sy_nlist.n_other = 0;					symbolP->sy_nlist.n_desc = 0;					symbolP->sy_nlist.n_value = 0;					symbolP->sy_name_offset = 0;					symbolP->sy_number = 0;					symbolP->sy_frag = New_Frag;					symbolP->sy_forward = 0;					symbolP->sy_next = symbol_rootP;					symbol_rootP = symbolP;					/*					 *	Generate a text fixup structure					 *	to get "_c$main_args" stored into the					 *	JSB instruction.					 */					fixP = (struct fix *)xmalloc(sizeof(*fixP));					fixP->fx_frag = New_Frag;					fixP->fx_where = 4;					fixP->fx_addsy = symbolP;					fixP->fx_subsy = 0;					fixP->fx_offset = 0;					fixP->fx_size = sizeof(long);					fixP->fx_pcrel = 1;					fixP->fx_next = text_fix_root;					text_fix_root = fixP;					/*					 *	Now make sure we exit from the loop					 */					frchainP = 0;					break;				}				/*				 *	Try the next fragment				 */				prev_fragPP = &fragP->fr_next;				fragP = fragP->fr_next;			}			/*			 *	Try the next fragment chain			 */			if (frchainP) frchainP=frchainP->frch_next;		}	}#endif	/* HACK_DEC_C_STARTUP */  }}/* *	Write a VAX/VMS object file (everything else has been done!) */VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)unsigned text_siz;unsigned data_siz;struct frag *text_frag_root;struct frag *data_frag_root;{   register fragS *		fragP;   register symbolS *		symbolP;   register symbolS *		sp;   register struct fix *	fixP;   register struct VMS_Symbol *	vsp;   int Local_Initialized_Data_Size = 0;   int Psect_Number = 0;		/* Psect Index Number */   int Text_Psect = -1;			/* Text Psect Index   */   int Data_Psect = -2;			/* Data Psect Index   JF: Was -1 */   int Bss_Psect = -3;			/* Bss Psect Index    JF: Was -1 */   /*    *	Create the VMS object file    */   Create_VMS_Object_File();   /*    *	Write the module header records    */   Write_VMS_MHD_Records();    /*     *	Generate the VMS object file records     *	1st GSD then TIR records     */	/*******       Global Symbol Dictionary       *******/	/*	 *	Define the Text Psect	 */	if (text_siz > 0) {		Text_Psect = Psect_Number++;		VMS_Psect_Spec("$code",text_siz,"TEXT");	}	/*	 *	Define the BSS Psect	 */	if (local_bss_counter > 0) {		Bss_Psect = Psect_Number++;		VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA");	}	/*	 *	Now scan the symbols and emit the appropriate GSD records	 */	for (sp = symbol_rootP; sp; sp = sp->sy_next) {		/*		 *	Dispatch on symbol type		 */		switch(sp->sy_type) {			/*			 *	Global uninitialized data			 */			case N_UNDF | N_EXT:				/*				 *	Make a VMS data symbol entry				 */				vsp = (struct VMS_Symbol *)					xmalloc(sizeof(*vsp));				vsp->Symbol = sp;				vsp->Size = sp->sy_nlist.n_value;				vsp->Psect_Index = Psect_Number++;				vsp->Psect_Offset = 0;				vsp->Next = VMS_Symbols;				VMS_Symbols = vsp;				sp->sy_number = (int)vsp;				/*				 *	Make the psect for this data				 */				if(sp->sy_nlist.n_other)					VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,					       vsp->Size,					       "CONST");				else					VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,					       vsp->Size,					       "COMMON");#ifdef	NOT_VAX_11_C_COMPATIBLE				/*				 *	Place a global symbol at the				 *	beginning of the Psect				 */				VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,						       vsp->Psect_Index,						       0,						       1);#endif	NOT_VAX_11_C_COMPATIBLE				break;			/*			 *	Local uninitialized data			 */			case N_BSS:				/*				 *	Make a VMS data symbol entry				 */				vsp = (struct VMS_Symbol *)					xmalloc(sizeof(*vsp));				vsp->Symbol = sp;				vsp->Size = 0;				vsp->Psect_Index = Bss_Psect;				vsp->Psect_Offset =					sp->sy_nlist.n_value -						bss_address_frag . fr_address;				vsp->Next = VMS_Symbols;				VMS_Symbols = vsp;				sp->sy_number = (int)vsp;				break;			/*			 *	Global initialized data			 */			case N_DATA | N_EXT:				/*				 *	Make a VMS data symbol entry				 */				vsp = (struct VMS_Symbol *)					xmalloc(sizeof(*vsp));				vsp->Symbol = sp;				vsp->Size = VMS_Initialized_Data_Size(sp,							text_siz + data_siz);				vsp->Psect_Index = Psect_Number++;				vsp->Psect_Offset = 0;				vsp->Next = VMS_Symbols;				VMS_Symbols = vsp;				sp->sy_number = (int)vsp;				/*				 *	Make its psect				 */				if(sp->sy_nlist.n_other)					VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,					       vsp->Size,					       "CONST");				else					VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,					       vsp->Size,					       "COMMON");#ifdef	NOT_VAX_11_C_COMPATIBLE				/*				 *	Place a global symbol at the				 *	beginning of the Psect				 */				VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,						       vsp->Psect_Index,						       0,						       1);#endif	NOT_VAX_11_C_COMPATIBLE				break;			/*			 *	Local initialized data			 */			case N_DATA:				/*				 *	Make a VMS data symbol entry				 */				vsp = (struct VMS_Symbol *)					xmalloc(sizeof(*vsp));				vsp->Symbol = sp;				vsp->Size = 					VMS_Initialized_Data_Size(sp,							  text_siz + data_siz);				vsp->Psect_Index = Data_Psect;				vsp->Psect_Offset =					Local_Initialized_Data_Size;				Local_Initialized_Data_Size += vsp->Size;				vsp->Next = VMS_Symbols;				VMS_Symbols = vsp;				sp->sy_number = (int)vsp;				break;			/*			 *	Global Text definition			 */			case N_TEXT | N_EXT: {				unsigned short Entry_Mask;				/*				 *	Get the entry mask				 */				fragP = sp->sy_frag;				Entry_Mask = (fragP->fr_literal[0] & 0xff) +						((fragP->fr_literal[1] & 0xff)							<< 8);				/*				 *	Define the Procedure entry pt.				 */				VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,						       Text_Psect,						       sp->sy_nlist.n_value,						       Entry_Mask);				break;			}			/*			 *	Local Text definition			 */			case N_TEXT:				/*				 *	Make a VMS data symbol entry				 */				 if(Text_Psect != -1) {					vsp = (struct VMS_Symbol *)						xmalloc(sizeof(*vsp));					vsp->Symbol = sp;					vsp->Size = 0;					vsp->Psect_Index = Text_Psect;					vsp->Psect_Offset = sp->sy_nlist.n_value;					vsp->Next = VMS_Symbols;					VMS_Symbols = vsp;					sp->sy_number = (int)vsp;				 }				break;			/*			 *	Global Reference			 */			case N_UNDF:				/*				 *	Make a GSD global symbol reference				 *	record.				 */				VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,						       0,						       0,						       0);				break;			/*			 *	Anything else			 */			default:				/*				 *	Ignore STAB symbols				 *	Including .stabs emitted by g++				 */				if ((sp->sy_type & N_STAB) != 0 || sp->sy_nlist.n_type==22)					break;				/*				 *	Error				 */				if(sp->sy_nlist.n_type !=22)					printf(" ERROR, unknown type (%d)\n",						sp->sy_nlist.n_type);				break;		}	}	/*	 *	Define the Data Psect	 */	if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {		/*		 *	Do it		 */		Data_Psect = Psect_Number++;		VMS_Psect_Spec("$data",				Local_Initialized_Data_Size,				"DATA");		/*		 *	Scan the VMS symbols and fill in the data psect		 */		for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {			/*			 *	Only look for undefined psects			 */			if (vsp->Psect_Index < 0)  {				/*				 *	And only initialized data				 */				if (vsp->Symbol->sy_nlist.n_type == N_DATA)					vsp->Psect_Index = Data_Psect;			}		}	}	/*******  Text Information and Relocation Records  *******/	/*	 *	Write the text segment data	 */	if (text_siz > 0) {		/*		 *	Scan the text fragments		 */		for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {			/*			 *	Stop if we get to the data fragments			 */			if (fragP == data_frag_root) break;			/*			 *	Ignore fragments with no data			 */			if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))				continue;			/*			 *	Go the the appropriate offset in the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -