obj-vms.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,166 行 · 第 1/5 页
C
2,166 行
/* Since we don't need `arg', use it as our scratch variable so that we won't get any "not used" warnings about it. */ arg = get_absolute_expression (); subseg_set (SEG_DATA, (subsegT) arg); const_flag = 1; demand_empty_rest_of_line ();}const pseudo_typeS obj_pseudo_table[] ={ {"const", s_const, 0}, {0, 0, 0},}; /* obj_pseudo_table *//* Routine to perform RESOLVE_SYMBOL_REDEFINITION(). */intvms_resolve_symbol_redef (sym) symbolS *sym;{ /* * If the new symbol is .comm AND it has a size of zero, * we ignore it (i.e. the old symbol overrides it) */ if (SEGMENT_TO_SYMBOL_TYPE ((int) now_seg) == (N_UNDF | N_EXT) && frag_now_fix () == 0) { as_warn (_("compiler emitted zero-size common symbol `%s' already defined"), S_GET_NAME (sym)); return 1; } /* * If the old symbol is .comm and it has a size of zero, * we override it with the new symbol value. */ if (S_IS_EXTERNAL (sym) && S_IS_DEFINED (sym) && S_GET_VALUE (sym) == 0) { as_warn (_("compiler redefined zero-size common symbol `%s'"), S_GET_NAME (sym)); sym->sy_frag = frag_now; S_SET_OTHER (sym, const_flag); S_SET_VALUE (sym, frag_now_fix ()); /* Keep N_EXT bit. */ sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE ((int) now_seg); return 1; } return 0;}/* `tc_frob_label' handler for colon(symbols.c), used to examine the dummy label(s) gcc inserts at the beginning of each file it generates. gcc 1.x put "gcc_compiled."; gcc 2.x (as of 2.7) puts "gcc2_compiled." and "__gnu_language_<name>" and possibly "__vax_<type>_doubles". */voidvms_check_for_special_label (symbolP)symbolS *symbolP;{ /* Special labels only occur prior to explicit section directives. */ if ((const_flag & IN_DEFAULT_SECTION) != 0) { char *sym_name = S_GET_NAME (symbolP); if (*sym_name == '_') ++sym_name; if (!strcmp (sym_name, "__vax_g_doubles")) vax_g_doubles = 1;#if 0 /* not necessary */ else if (!strcmp (sym_name, "__vax_d_doubles")) vax_g_doubles = 0;#endif#if 0 /* these are potential alternatives to tc-vax.c's md_parse_options() */ else if (!strcmp (sym_name, "gcc_compiled.")) flag_one = 1; else if (!strcmp (sym_name, "__gnu_language_cplusplus")) flag_hash_long_names = 1;#endif } return;}voidobj_read_begin_hook (){ return;}voidobj_crawl_symbol_chain (headers) object_headers *headers;{ symbolS *symbolP; symbolS **symbolPP; int symbol_number = 0; symbolPP = &symbol_rootP; /* -> last symbol chain link. */ while ((symbolP = *symbolPP) != NULL) { resolve_symbol_value (symbolP, 1); /* OK, here is how we decide which symbols go out into the brave new symtab. Symbols that do are: * symbols with no name (stabd's?) * symbols with debug info in their N_TYPE * symbols with \1 as their 3rd character (numeric labels) * "local labels" needed for PIC fixups Symbols that don't are: * symbols that are registers All other symbols are output. We complain if a deleted symbol was marked external. */ if (!S_IS_REGISTER (symbolP)) { symbolP->sy_number = symbol_number++; symbolP->sy_name_offset = 0; symbolPP = &symbolP->sy_next; } else { if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) { as_bad (_("Local symbol %s never defined"), S_GET_NAME (symbolP)); } /* oops. */ /* Unhook it from the chain. */ *symbolPP = symbol_next (symbolP); } /* if this symbol should be in the output */ } /* for each symbol */ H_SET_STRING_SIZE (headers, string_byte_count); H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);} /* obj_crawl_symbol_chain() */ /****** VMS OBJECT FILE HACKING ROUTINES *******//* Create the VMS object file. */static voidCreate_VMS_Object_File (){#if defined(eunice) || !defined(VMS) VMS_Object_File_FD = creat (out_file_name, 0777, "var");#else /* eunice */ VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var", "ctx=bin", "mbc=16", "deq=64", "fop=tef", "shr=nil");#endif /* eunice */ /* Deal with errors. */ if (VMS_Object_File_FD < 0) as_fatal (_("Couldn't create VMS object file \"%s\""), out_file_name); /* Initialize object file hacking variables. */ Object_Record_Offset = 0; Current_Object_Record_Type = -1;}/* Flush the object record buffer to the object file. */static voidFlush_VMS_Object_Record_Buffer (){ /* If the buffer is empty, there's nothing to do. */ if (Object_Record_Offset == 0) return;#ifndef VMS /* For cross-assembly purposes. */ { char RecLen[2]; /* "Variable-length record" files have a two byte length field prepended to each record. It's normally out-of-band, and native VMS output will insert it automatically for this type of file. When cross-assembling, we must write it explicitly. */ md_number_to_chars (RecLen, Object_Record_Offset, 2); if (write (VMS_Object_File_FD, RecLen, 2) != 2) error (_("I/O error writing VMS object file (length prefix)")); /* We also need to force the actual record to be an even number of bytes. For native output, that's automatic; when cross-assembling, pad with a NUL byte if length is odd. Do so _after_ writing the pre-padded length. Since our buffer is defined with even size, an odd offset implies that it has some room left. */ if ((Object_Record_Offset & 1) != 0) Object_Record_Buffer[Object_Record_Offset++] = '\0'; }#endif /* not VMS */ /* Write the data to the file. */ if (write (VMS_Object_File_FD, Object_Record_Buffer, Object_Record_Offset) != Object_Record_Offset) error (_("I/O error writing VMS object file")); /* The buffer is now empty. */ Object_Record_Offset = 0;}/* Declare a particular type of object file record. */static voidSet_VMS_Object_File_Record (Type) int Type;{ /* If the type matches, we are done. */ if (Type == Current_Object_Record_Type) return; /* Otherwise: flush the buffer. */ Flush_VMS_Object_Record_Buffer (); /* Remember the new type. */ Current_Object_Record_Type = Type;}/* Close the VMS Object file. */static voidClose_VMS_Object_File (){ /* Flush (should never be necessary) and reset saved record-type context. */ Set_VMS_Object_File_Record (-1);#ifndef VMS /* For cross-assembly purposes. */ { char RecLen[2]; int minus_one = -1; /* Write a 2 byte record-length field of -1 into the file, which means end-of-block when read, hence end-of-file when occurring in the file's last block. It is only needed for variable-length record files transferred to VMS as fixed-length record files (typical for binary FTP; NFS shouldn't need it, but it won't hurt). */ md_number_to_chars (RecLen, minus_one, 2); write (VMS_Object_File_FD, RecLen, 2); }#else /* When written on a VMS system, the file header (cf inode) will record the actual end-of-file position and no inline marker is needed. */#endif close (VMS_Object_File_FD);} /****** Text Information and Relocation routines ******//* Stack Psect base followed by signed, varying-sized offset. Common to several object records. */static voidvms_tir_stack_psect (Psect_Index, Offset, Force) int Psect_Index; int Offset; int Force;{ int psect_width, offset_width; psect_width = ((unsigned) Psect_Index > 255) ? 2 : 1; offset_width = (Force || Offset > 32767 || Offset < -32768) ? 4 : (Offset > 127 || Offset < -128) ? 2 : 1;#define Sta_P(p,o) (((o)<<1) | ((p)-1)) /* byte or word psect; byte, word, or longword offset */ switch (Sta_P(psect_width,offset_width)) { case Sta_P(1,1): PUT_CHAR (TIR_S_C_STA_PB); PUT_CHAR ((char) (unsigned char) Psect_Index); PUT_CHAR ((char) Offset); break; case Sta_P(1,2): PUT_CHAR (TIR_S_C_STA_PW); PUT_CHAR ((char) (unsigned char) Psect_Index); PUT_SHORT (Offset); break; case Sta_P(1,4): PUT_CHAR (TIR_S_C_STA_PL); PUT_CHAR ((char) (unsigned char) Psect_Index); PUT_LONG (Offset); break; case Sta_P(2,1): PUT_CHAR (TIR_S_C_STA_WPB); PUT_SHORT (Psect_Index); PUT_CHAR ((char) Offset); break; case Sta_P(2,2): PUT_CHAR (TIR_S_C_STA_WPW); PUT_SHORT (Psect_Index); PUT_SHORT (Offset); break; case Sta_P(2,4): PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (Psect_Index); PUT_LONG (Offset); break; }#undef Sta_P}/* Store immediate data in current Psect. */static voidVMS_Store_Immediate_Data (Pointer, Size, Record_Type) const char *Pointer; int Size; int Record_Type;{ register int i; Set_VMS_Object_File_Record (Record_Type); /* We can only store as most 128 bytes at a time due to the way that TIR commands are encoded. */ while (Size > 0) { i = (Size > 128) ? 128 : Size; Size -= i; /* If we cannot accommodate this record, flush the buffer. */ if ((Object_Record_Offset + i + 1) >= sizeof Object_Record_Buffer) Flush_VMS_Object_Record_Buffer (); /* If the buffer is empty we must insert record type. */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* Store the count. The Store Immediate TIR command is implied by a negative command byte, and the length of the immediate data is abs(command_byte). So, we write the negated length value. */ PUT_CHAR ((char) (-i & 0xff)); /* Now store the data. */ while (--i >= 0) PUT_CHAR (*Pointer++); } /* Flush the buffer if it is more than 75% full. */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer ();}/* Make a data reference. */static voidVMS_Set_Data (Psect_Index, Offset, Record_Type, Force) int Psect_Index; int Offset; int Record_Type; int Force;{ Set_VMS_Object_File_Record (Record_Type); /* If the buffer is empty we must insert the record type. */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* Stack the Psect base with its offset. */ vms_tir_stack_psect (Psect_Index, Offset, Force); /* Set relocation base. */ PUT_CHAR (TIR_S_C_STO_PIDR); /* Flush the buffer if it is more than 75% full. */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer ();}/* Make a debugger reference to a struct, union or enum. */static voidVMS_Store_Struct (Struct_Index) int Struct_Index;{ /* We are writing a debug record. */ Set_VMS_Object_File_Record (OBJ_S_C_DBG); /* If the buffer is empty we must insert the record type. */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_DBG); PUT_CHAR (TIR_S_C_STA_UW); PUT_SHORT (Struct_Index); PUT_CHAR (TIR_S_C_CTL_STKDL); PUT_CHAR (TIR_S_C_STO_L); /* Flush the buffer if it is more than 75% full. */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer ();}/* Make a debugger reference to partially define a struct, union or enum. */static voidVMS_Def_Struct (Struct_Index) int Struct_Index;{ /* We are writing a debug record. */ Set_VMS_Object_File_Record (OBJ_S_C_DBG); /* If the buffer is empty we must insert the record type. */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_DBG); PUT_CHAR (TIR_S_C_STA_UW); PUT_SHORT (Struct_Index); PUT_CHAR (TIR_S_C_CTL_DFLOC); /* Flush the buffer if it is more than 75% full. */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer ();}static voidVMS_Set_Struct (Struct_Index) int Struct_Index;{ /* see previous functions for comments */ Set_VMS_Object_File_Record (OBJ_S_C_DBG); if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_DBG); PUT_CHAR (TIR_S_C_STA_UW); PUT_SHORT (Struct_Index); PUT_CHAR (TIR_S_C_CTL_STLOC); if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer ();} /****** Traceback Information routines ******//* Write the Traceback Module Begin record. */static voidVMS_TBT_Module_Begin (){ register char *cp, *cp1; int Size; char Local[256]; /* Arrange to store the data locally (leave room for size byte). */ cp = &Local[1]; /* Begin module. */ *cp++ = DST_S_C_MODBEG; *cp++ = 0; /* flags; not used */ /* * Language type == "C" * * (FIXME: this should be based on the input...) */ COPY_LONG (cp, DST_S_C_C); cp += 4; /* Store the module name. */ *cp++ = (char) strlen (Module_Name); cp1 = Module_Name; while (*cp1) *cp++ = *cp1++;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?