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

📄 write.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	      case rs_align:		growth = relax_align ((relax_addressT)(address + fragP -> fr_fix), offset)		  - relax_align ((relax_addressT)(was_address +  fragP -> fr_fix), offset);		break;	      case rs_org:		target = offset;		if (symbolP)		  {		    know(   ((symbolP -> sy_type & N_TYPE) == N_ABS) || ((symbolP -> sy_type & N_TYPE) == N_DATA) || ((symbolP -> sy_type & N_TYPE) == N_TEXT));		    know( symbolP -> sy_frag );		    know( (symbolP->sy_type&N_TYPE)!=N_ABS || symbolP->sy_frag==&zero_address_frag );		    target +=		      symbolP -> sy_value			+ symbolP -> sy_frag -> fr_address;		  }		know( fragP -> fr_next );		after = fragP -> fr_next -> fr_address;		growth = ((target - after ) > 0) ? (target - after) : 0;				/* Growth may be -ve, but variable part */				/* of frag cannot have < 0 chars. */				/* That is, we can't .org backwards. */		growth -= stretch;	/* This is an absolute growth factor */		break;	      case rs_machine_dependent:		{		  register const relax_typeS *	this_type;		  register const relax_typeS *	start_type;		  register relax_substateT	next_state;		  register relax_substateT	this_state;		  start_type = this_type		    = md_relax_table + (this_state = fragP -> fr_subtype);		target = offset;		if (symbolP)		  { know(   ((symbolP -> sy_type & N_TYPE) == N_ABS) || ((symbolP -> sy_type & N_TYPE) == N_DATA) || ((symbolP -> sy_type & N_TYPE) == N_TEXT));		    know( symbolP -> sy_frag );		    know( (symbolP->sy_type&N_TYPE)!=N_ABS || symbolP->sy_frag==&zero_address_frag );		    target +=		      symbolP -> sy_value			+ symbolP -> sy_frag -> fr_address;			/* If frag has yet to be reached on this pass,			   assume it will move by STRETCH just as we did.			   If this is not so, it will be because some frag			   between grows, and that will force another pass.  */			   	/* JF was just address */				/* JF also added is_dnrange hack */				/* There's gotta be a better/faster/etc way				   to do this. . . */			/* gnu@cygnus.com:  I changed this from > to >=			   because I ran into a zero-length frag (fr_fix=0)			   which was created when the obstack needed a new			   chunk JUST AFTER the opcode of a branch.  Since			   fr_fix is zero, fr_address of this frag is the same			   as fr_address of the next frag.  This			   zero-length frag was variable and jumped to .+2			   (in the next frag), but since the > comparison			   below failed (the two were =, not >), "stretch"			   was not added to the target.  Stretch was 178, so			   the offset appeared to be .-176 instead, which did			   not fit into a byte branch, so the assembler			   relaxed the branch to a word.  This didn't compare			   with what happened when the same source file was			   assembled on other machines, which is how I found it.			   You might want to think about what other places have			   trouble with zero length frags... */		    if (symbolP->sy_frag->fr_address >= was_address && is_dnrange(fragP,symbolP->sy_frag))		      target += stretch;		  }		  aim = target - address - fragP -> fr_fix;		  /* The displacement is affected by the instruction size		   * for the 32k architecture. I think we ought to be able		   * to add fragP->fr_pcrel_adjust in all cases (it should be		   * zero if not used), but just in case it breaks something		   * else we'll put this inside #ifdef NS32K ... #endif		   */#ifdef NS32K		  aim += fragP->fr_pcrel_adjust;#endif		  if (aim < 0)		    {		      /* Look backwards. */		      for (next_state = this_type -> rlx_more;  next_state;  )			{			  if (aim >= this_type -> rlx_backward)			      next_state = 0;			  else			    {	/* Grow to next state. */			      this_type = md_relax_table + (this_state = next_state);			      next_state = this_type -> rlx_more;			    }			}		    }		  else		    {#ifdef DONTDEF/* JF these next few lines of code are for the mc68020 which can't handle short   offsets of zero in branch instructions.  What a kludge! */ if(aim==0 && this_state==(1<<2+0)) {	/* FOO hard encoded from m.c */	aim=this_type->rlx_forward+1;	/* Force relaxation into word mode */ }#endif/* JF end of 68020 code */		      /* Look forwards. */		      for (next_state = this_type -> rlx_more;  next_state;  )			{			  if (aim <= this_type -> rlx_forward)			      next_state = 0;			  else			    {	/* Grow to next state. */			      this_type = md_relax_table + (this_state = next_state);			      next_state = this_type -> rlx_more;			    }			}		    }		  if (growth = this_type -> rlx_length - start_type -> rlx_length)		      fragP -> fr_subtype = this_state;		}		break;	      default:		BAD_CASE( fragP -> fr_type );		break;	      }	    if(growth) {	      stretch += growth;	      stretched++;	    }	  }			/* For each frag in the segment. */      } while (stretched);	/* Until nothing further to relax. */  }  /*   * We now have valid fr_address'es for each frag.   */  /*   * All fr_address's are correct, relative to their own segment.   * We have made all the fixS we will ever make.   */}				/* relax_segment() *//* * Relax_align. Advance location counter to next address that has 'alignment' * lowest order bits all 0s. */static relax_addressT		/* How many addresses does the .align take? */relax_align (address, alignment)     register relax_addressT	address; /* Address now. */     register long int		alignment; /* Alignment (binary). */{  relax_addressT	mask;  relax_addressT	new_address;  mask = ~ ( (~0) << alignment );  new_address = (address + mask) & (~ mask);  return (new_address - address);}/* *			fixup_segment() */static long intfixup_segment (fixP, this_segment_type)     register fixS *	fixP;     int		this_segment_type; /* N_TYPE bits for segment. */{  register long int		seg_reloc_count;		/* JF these all used to be local to the for loop, but GDB doesn't seem to be able to deal with them there, so I moved them here for a bit. */      register symbolS *	add_symbolP;      register symbolS *	sub_symbolP;      register long int		add_number;      register int		size;      register char *		place;      register long int		where;      register char		pcrel;      register fragS *		fragP;      register int		add_symbol_N_TYPE;  seg_reloc_count = 0;  for ( ;  fixP;  fixP = fixP -> fx_next)    {      fragP       = fixP  -> fx_frag;      know( fragP );      where	  = fixP  -> fx_where;      place       = fragP -> fr_literal + where;      size	  = fixP  -> fx_size;      add_symbolP = fixP  -> fx_addsy;      sub_symbolP = fixP  -> fx_subsy;      add_number  = fixP  -> fx_offset;      pcrel	  = fixP  -> fx_pcrel;      if(add_symbolP)	add_symbol_N_TYPE = add_symbolP -> sy_type & N_TYPE;      if (sub_symbolP)	{	  if(!add_symbolP)	/* Its just -sym */	    {	      if(sub_symbolP->sy_type!=N_ABS)	        as_warn("Negative of non-absolute symbol %s", sub_symbolP->sy_name);	      add_number-=sub_symbolP->sy_value;	    }	  else if (   ((sub_symbolP -> sy_type ^ add_symbol_N_TYPE) & N_TYPE) == 0	      && (   add_symbol_N_TYPE == N_DATA		  || add_symbol_N_TYPE == N_TEXT		  || add_symbol_N_TYPE == N_BSS		  || add_symbol_N_TYPE == N_ABS))	    {	      /* Difference of 2 symbols from same segment. */	      /* Can't make difference of 2 undefineds: 'value' means */	      /* something different for N_UNDF. */	      add_number += add_symbolP -> sy_value - sub_symbolP -> sy_value;	      add_symbolP = NULL;	      fixP -> fx_addsy = NULL;	    }	  else	    {	      /* Different segments in subtraction. */	      know( sub_symbolP -> sy_type != (N_ABS | N_EXT))		if (sub_symbolP -> sy_type == N_ABS)		    add_number -= sub_symbolP -> sy_value;		else		  {			   as_warn("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",				    seg_name[(int)N_TYPE_seg[sub_symbolP->sy_type&N_TYPE]],				    sub_symbolP -> sy_name, fragP -> fr_address + where);		  }	    }	}      if (add_symbolP)	{	  if (add_symbol_N_TYPE == this_segment_type && pcrel)	    {	      /*	       * This fixup was made when the symbol's segment was	       * SEG_UNKNOWN, but it is now in the local segment.	       * So we know how to do the address without relocation.	       */	      add_number += add_symbolP -> sy_value;	      add_number -=#ifndef NS32K		      size +#endif		      where + fragP -> fr_address;#if defined(NS32K) && defined(SEQUENT_COMPATABILITY)	      if (fragP->fr_bsr)	        add_number -= 0x12;	/* FOO Kludge alert! */#endif		/* Kenny thinks this needs *		/* add_number +=size-2; */	      pcrel = 0;	/* Lie. Don't want further pcrel processing. */	      fixP -> fx_addsy = NULL; /* No relocations please. */	      /*	       * It would be nice to check that the address does not overflow.	       * I didn't do this check because:	       * +  It is machine dependent in the general case (eg 32032)	       * +  Compiler output will never need this checking, so why	       *    slow down the usual case?	       */	    }	  else	    {	      switch (add_symbol_N_TYPE)		{		case N_ABS:		  add_number += add_symbolP -> sy_value;		  fixP -> fx_addsy = NULL;		  add_symbolP = NULL;		  break;		  		case N_BSS:		case N_DATA:		case N_TEXT:		  seg_reloc_count ++;		  add_number += add_symbolP -> sy_value;		  break;		  		case N_UNDF:		  seg_reloc_count ++;		  break;		  		default:		  BAD_CASE( add_symbol_N_TYPE );		  break;		}		/* switch on symbol seg */	    }			/* if not in local seg */	}			/* if there was a + symbol */      if (pcrel)	{	  add_number -=#ifndef NS32K		  size + #endif		  where + fragP -> fr_address;	  if (add_symbolP == 0)	    {	      fixP -> fx_addsy = & abs_symbol;	      seg_reloc_count ++;	    }	}      /* OVE added fx_im_disp for ns32k and others */      if (!fixP->fx_bit_fixP) {	/* JF I hope this works . . . */	if((size==1 && (add_number& ~0xFF)   && (add_number&~0xFF!=(-1&~0xFF))) ||	   (size==2 && (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF))))	  as_warn("Fixup of %d too large for field width of %d",add_number, size);	switch (fixP->fx_im_disp) {	case 0:#if defined(SPARC) || defined(I860)	  fixP->fx_addnumber = add_number;	  md_number_to_imm(place, add_number, size, fixP, this_segment_type);#else	  md_number_to_imm (place, add_number, size);	  /* OVE: the immediates, like disps, have lsb at lowest address */#endif	  break;	case 1:	  md_number_to_disp (place,			     fixP->fx_pcrel ? add_number+fixP->fx_pcrel_adjust:add_number,			     size);	  break;	case 2: /* fix requested for .long .word etc */	  md_number_to_chars (place, add_number, size);	  break;	default:	  as_fatal("Internal error in write.c in fixup_segment");	} /* OVE: maybe one ought to put _imm _disp _chars in one md-func */      } else {	md_number_to_field (place, add_number, fixP->fx_bit_fixP);      }    }				/* For each fixS in this segment. */  return (seg_reloc_count);}				/* fixup_segment() *//* The sparc needs its own emit_relocations() */#if !defined(SPARC) && !defined(I860)/* *		emit_relocations() * * Crawl along a fixS chain. Emit the segment's relocations. */static voidemit_relocations (fixP, segment_address_in_file)     register fixS *	fixP;	/* Fixup chain for this segment. */     relax_addressT	segment_address_in_file;{  struct relocation_info	ri;  register symbolS *		symbolP;	/* JF this is for paranoia */  bzero((char *)&ri,sizeof(ri));  for ( ;  fixP;  fixP = fixP -> fx_next)    {      if (symbolP = fixP -> fx_addsy)	{#ifdef NS32K		/* These two 'cuz of NS32K */	  ri . r_bsr		= fixP -> fx_bsr;	  ri . r_disp		= fixP -> fx_im_disp;#endif	  ri . r_length		= nbytes_r_length [fixP -> fx_size];	  ri . r_pcrel		= fixP -> fx_pcrel;	  ri . r_address	= fixP -> fx_frag -> fr_address	    +   fixP -> fx_where	      - segment_address_in_file;	  if ((symbolP -> sy_type & N_TYPE) == N_UNDF)	    {	      ri . r_extern	= 1;	      ri . r_symbolnum	= symbolP -> sy_number;	    }	  else	    {	      ri . r_extern	= 0;	      ri . r_symbolnum	= symbolP -> sy_type & N_TYPE;	    }	  /* 	    The 68k machines assign bit-fields from higher bits to 	    lower bits ("left-to-right") within the int.  VAXen assign 	    bit-fields from lower bits to higher bits ("right-to-left").	    Both handle multi-byte numbers in their usual fashion	    (Big-endian and little-endian stuff).	    Thus we need a machine dependent routine to make	    sure the structure is written out correctly.  FUN!	   */	  md_ri_to_chars((char *) &ri, ri); 	  append (&next_object_file_charP, (char *)& ri, (unsigned long)sizeof(ri));	}    }}#endifintis_dnrange(f1,f2)struct frag *f1,*f2;{	while(f1) {		if(f1->fr_next==f2)			return 1;		f1=f1->fr_next;	}	return 0;}/* End: as-write.c */

⌨️ 快捷键说明

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