📄 vms.c
字号:
/* 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 + -