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

📄 write.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* write.c - emit .o file - Copyright(C)1986 Free Software Foundation, Inc.   Copyright (C) 1986,1987 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.  *//*    Umm, with real good luck, this thing should be set up to do byteordering   correctly, but I may have managed to miss a place or two.  Treat a.out   very carefully until you're SURE that it works. . .   In order to cross-assemble the target machine must have an a.out header   similar to the one in a.out.h on THIS machine.  Byteorder doesn't matter;   we take special care of it, but the numbers must be the same SIZE (# of   bytes) and in the same PLACE.  If this is not true, you will have some   trouble. */#include "as.h"#include "md.h"#include "subsegs.h"#include "obstack.h"#include "struc-symbol.h"#include "write.h"#include "symbols.h"#ifdef SPARC#include "sparc.h"#endif#ifdef I860#include "i860.h"#endifvoid	append();#ifdef hpux#define EXEC_MACHINE_TYPE HP9000S200_ID#endif#ifdef DOT_LABEL_PREFIX#define LOCAL_LABEL(name) (name[0] =='.' \                         && ( name [1] == 'L' || name [1] == '.' ))#else  /* not defined DOT_LABEL_PREFIX */#define LOCAL_LABEL(name) (name [0] == 'L' )#endif /* not defined DOT_LABEL_PREFIX *//* * In: length of relocation (or of address) in chars: 1, 2 or 4. * Out: GNU LD relocation length code: 0, 1, or 2. */static unsigned charnbytes_r_length [] = {  42, 0, 1, 42, 2  };static struct frag *	text_frag_root;static struct frag *	data_frag_root;static struct frag *	text_last_frag;	/* Last frag in segment. */static struct frag *	data_last_frag;	/* Last frag in segment. */static struct exec	the_exec;static long int string_byte_count;static char *		the_object_file;#if !defined(SPARC) && !defined(I860)static#endifchar *		next_object_file_charP;	/* Tracks object file bytes. */static long int		size_of_the_object_file; /* # bytes in object file. *//* static long int		length; JF unused */	/* String length, including trailing '\0'. */static void	relax_segment();void		emit_segment();static relax_addressT	relax_align();static long int	fixup_segment();#if !defined(SPARC) && !defined(I860)static void		emit_relocations();#endif/* *			fix_new() * * Create a fixS in obstack 'notes'. */void#if defined(SPARC) || defined(I860)fix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type)#elsefix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel)#endif     fragS *	frag;		/* Which frag? */     int	where;		/* Where in that frag? */     short int	size;		/* 1, 2  or 4 usually. */     symbolS *	add_symbol;	/* X_add_symbol. */     symbolS *	sub_symbol;	/* X_subtract_symbol. */     long int	offset;		/* X_add_number. */     int	pcrel;		/* TRUE if PC-relative relocation. */#if defined(SPARC) || defined(I860)    int		r_type;#endif{  register fixS *	fixP;  fixP = (fixS *)obstack_alloc(&notes,sizeof(fixS));  fixP -> fx_frag	= frag;  fixP -> fx_where	= where;  fixP -> fx_size	= size;  fixP -> fx_addsy	= add_symbol;  fixP -> fx_subsy	= sub_symbol;  fixP -> fx_offset	= offset;  fixP -> fx_pcrel	= pcrel;  fixP -> fx_next	= * seg_fix_rootP;  /* JF these 'cuz of the NS32K stuff */  fixP -> fx_im_disp	= 0;  fixP -> fx_pcrel_adjust = 0;  fixP -> fx_bsr	= 0;  fixP ->fx_bit_fixP	= 0;#if defined(SPARC) || defined(I860)  fixP->fx_r_type = r_type;#endif  * seg_fix_rootP = fixP;}voidwrite_object_file(){  register struct frchain *	frchainP; /* Track along all frchains. */  register fragS *		fragP;	/* Track along all frags. */  register struct frchain *	next_frchainP;  register fragS * *		prev_fragPP;  register char *		name;  register symbolS *		symbolP;  register symbolS **		symbolPP;  /* register fixS *		fixP; JF unused */  unsigned  	text_siz,	data_siz,	syms_siz,	tr_siz,	dr_siz;  void output_file_create();  void output_file_append();  void output_file_close();#ifdef DONTDEF  void gdb_emit();  void gdb_end();#endif  extern long omagic;		/* JF magic # to write out.  Is different for				   Suns and Vaxen and other boxes */#ifdef	VMS  /*   *	Under VMS we try to be compatible with VAX-11 "C".  Thus, we   *	call a routine to check for the definition of the procedure   *	"_main", and if so -- fix it up so that it can be program   *	entry point.   */  VMS_Check_For_Main();#endif /* VMS */  /*   * After every sub-segment, we fake an ".align ...". This conforms to BSD4.2   * brane-damage. We then fake ".fill 0" because that is the kind of frag   * that requires least thought. ".align" frags like to have a following   * frag since that makes calculating their intended length trivial.   */#define SUB_SEGMENT_ALIGN (2)  for ( frchainP=frchain_root; frchainP; frchainP=frchainP->frch_next )    {#ifdef	VMS      /*       *	Under VAX/VMS, the linker (and PSECT specifications)       *	take care of correctly aligning the segments.       *	Doing the alignment here (on initialized data) can       *	mess up the calculation of global data PSECT sizes.       */#undef	SUB_SEGMENT_ALIGN#define	SUB_SEGMENT_ALIGN ((frchainP->frch_seg != SEG_DATA) ? 2 : 0)#endif	/* VMS */      subseg_new (frchainP -> frch_seg, frchainP -> frch_subseg);      frag_align (SUB_SEGMENT_ALIGN, 0);				/* frag_align will have left a new frag. */				/* Use this last frag for an empty ".fill". */      /*       * For this segment ...       * Create a last frag. Do not leave a "being filled in frag".       */      frag_wane (frag_now);      frag_now -> fr_fix	= 0;      know( frag_now -> fr_next == NULL );      /* know( frags . obstack_c_base == frags . obstack_c_next_free ); */      /* Above shows we haven't left a half-completed object on obstack. */    }  /*   * From now on, we don't care about sub-segments.   * Build one frag chain for each segment. Linked thru fr_next.   * We know that there is at least 1 text frchain & at least 1 data frchain.   */  prev_fragPP = &text_frag_root;  for ( frchainP=frchain_root; frchainP; frchainP=next_frchainP )    {      know( frchainP -> frch_root );      * prev_fragPP = frchainP -> frch_root;      prev_fragPP = & frchainP -> frch_last -> fr_next;      if (   ((next_frchainP = frchainP->frch_next) == NULL)	  || next_frchainP == data0_frchainP)	{	  prev_fragPP = & data_frag_root;	  if ( next_frchainP )	    {	      text_last_frag = frchainP -> frch_last;	    }	  else	    {	      data_last_frag = frchainP -> frch_last;	    }	}    }				/* for(each struct frchain) */  /*   * We have two segments. If user gave -R flag, then we must put the   * data frags into the text segment. Do this before relaxing so   * we know to take advantage of -R and make shorter addresses.   */  if ( flagseen [ 'R' ] )    {      fixS *tmp;      text_last_frag -> fr_next = data_frag_root;      text_last_frag = data_last_frag;      data_last_frag = NULL;      data_frag_root = NULL;      if(text_fix_root) {	for(tmp=text_fix_root;tmp->fx_next;tmp=tmp->fx_next)	  ;	tmp->fx_next=data_fix_root;      } else        text_fix_root=data_fix_root;      data_fix_root=NULL;    }  relax_segment (text_frag_root, SEG_TEXT);  relax_segment (data_frag_root, SEG_DATA);  /*   * Now the addresses of frags are correct within the segment.   */  know(   text_last_frag -> fr_type   == rs_fill && text_last_frag -> fr_offset == 0 );  text_siz=text_last_frag->fr_address;#ifdef SPARC  text_siz= (text_siz+7)&(~7);  text_last_frag->fr_address=text_siz;#endif  md_number_to_chars((char *)&the_exec.a_text,text_siz, sizeof(the_exec.a_text));  /* the_exec . a_text = text_last_frag -> fr_address; */  /*   * Join the 2 segments into 1 huge segment.   * To do this, re-compute every rn_address in the SEG_DATA frags.   * Then join the data frags after the text frags.   *   * Determine a_data [length of data segment].   */  if (data_frag_root)    {      register relax_addressT	slide;      know(   text_last_frag -> fr_type   == rs_fill && text_last_frag -> fr_offset == 0 );      data_siz=data_last_frag->fr_address;#ifdef SPARC      data_siz += (8 - (data_siz % 8)) % 8;      data_last_frag->fr_address = data_siz;#endif      md_number_to_chars((char *)&the_exec.a_data,data_siz,sizeof(the_exec.a_data));      /* the_exec . a_data = data_last_frag -> fr_address; */      slide = text_siz; /* Address in file of the data segment. */      for (fragP = data_frag_root;	   fragP;	   fragP = fragP -> fr_next)	{	  fragP -> fr_address += slide;	}      know( text_last_frag );      text_last_frag -> fr_next = data_frag_root;    }  else {      md_number_to_chars((char *)&the_exec.a_data,0,sizeof(the_exec.a_data));      data_siz = 0;  }  bss_address_frag . fr_address = text_siz + data_siz;#ifdef SPARC  local_bss_counter=(local_bss_counter+7)&(~7);#endif  md_number_to_chars((char *)&the_exec.a_bss,local_bss_counter,sizeof(the_exec.a_bss));	        /*   *   * Crawl the symbol chain.   *   * For each symbol whose value depends on a frag, take the address of   * that frag and subsume it into the value of the symbol.   * After this, there is just one way to lookup a symbol value.   * Values are left in their final state for object file emission.   * We adjust the values of 'L' local symbols, even if we do   * not intend to emit them to the object file, because their values   * are needed for fix-ups.   *   * Unless we saw a -L flag, remove all symbols that begin with 'L'   * from the symbol chain.   *   * Count the (length of the nlists of the) (remaining) symbols.   * Assign a symbol number to each symbol.   * Count the number of string-table chars we will emit.   *   */  know( zero_address_frag . fr_address == 0 );  string_byte_count = sizeof( string_byte_count );  /* JF deal with forward references first. . . */  for(symbolP=symbol_rootP;symbolP;symbolP=symbolP->sy_next) {  	if(symbolP->sy_forward) {		symbolP->sy_value+=symbolP->sy_forward->sy_value+symbolP->sy_forward->sy_frag->fr_address;		symbolP->sy_forward=0;	}  }  symbolPP = & symbol_rootP;	/* -> last symbol chain link. */  {    register long int		symbol_number;    symbol_number = 0;    while (symbolP  = * symbolPP)      {	name = symbolP -> sy_name;	if(flagseen['R'] && (symbolP->sy_nlist.n_type&N_DATA)) {	  symbolP->sy_nlist.n_type&= ~N_DATA;	  symbolP->sy_nlist.n_type|= N_TEXT;	}	/* if(symbolP->sy_forward) {	  symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;	} */		symbolP -> sy_value += symbolP -> sy_frag -> fr_address;		/* JF the 128 bit is a hack so stabs like		   "LET_STMT:23. . ."  don't go away */	/* CPH: 128 bit hack is moby loser.  N_SO for file "Lower.c"	   fell through the cracks.  I think that N_STAB should be	   used instead of 128. */		/* JF the \001 bit is to make sure that local labels		   ( 1: - 9: don't make it into the symtable either */#ifndef	VMS	/* Under VMS we need to keep local symbols */	if ( !name || (symbolP->sy_nlist.n_type&N_STAB)	    || (name[2]!='\001' && (flagseen ['L'] || ! LOCAL_LABEL(name) )))#endif	/* not VMS */	  {	    symbolP -> sy_number = symbol_number ++;#ifndef	VMS	    if (name)	      {			/* Ordinary case. */		symbolP -> sy_name_offset = string_byte_count;		string_byte_count += strlen (symbolP  -> sy_name) + 1;	      }	    else			/* .Stabd case. */#endif	/* not VMS */		symbolP -> sy_name_offset = 0;	    symbolPP = & (symbolP -> sy_next);	  }#ifndef	VMS	else	    * symbolPP = symbolP -> sy_next;#endif	/* not VMS */      }				/* for each symbol */    syms_siz = sizeof( struct nlist) * symbol_number;    md_number_to_chars((char *)&the_exec.a_syms,syms_siz,sizeof(the_exec.a_syms));    /* the_exec . a_syms = sizeof( struct nlist) * symbol_number; */  }  /*   * Addresses of frags now reflect addresses we use in the object file.   * Symbol values are correct.   * Scan the frags, converting any ".org"s and ".align"s to ".fill"s.   * Also converting any machine-dependent frags using md_convert_frag();   */  subseg_change( SEG_TEXT, 0);  for (fragP = text_frag_root;  fragP;  fragP = fragP -> fr_next)    {      switch (fragP -> fr_type)	{	case rs_align:	case rs_org:	  fragP -> fr_type = rs_fill;	  know( fragP -> fr_var == 1 );

⌨️ 快捷键说明

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