if (symp->sy_value.X_op == O_symbol && (! S_IS_DEFINED (symp) || S_IS_COMMON (symp))) { symbol_remove (symp, &symbol_rootP, &symbol_lastP); continue; }
write_object_file (){  struct frchain *frchainP;	/* Track along all frchains. */#if ! defined (BFD_ASSEMBLER) || ! defined (WORKING_DOT_WORD)  fragS *fragP;			/* Track along all frags. */#endif  /* Do we really want to write it?  */  {    int n_warns, n_errs;    n_warns = had_warnings ();    n_errs = had_errors ();    /* The -Z flag indicates that an object file should be generated,       regardless of warnings and errors.  */    if (flag_always_generate_output)      {	if (n_warns || n_errs)	  as_warn ("%d error%s, %d warning%s, generating bad object file.\n",		   n_errs, n_errs == 1 ? "" : "s",		   n_warns, n_warns == 1 ? "" : "s");      }    else      {	if (n_errs)	  as_fatal ("%d error%s, %d warning%s, no object file generated.\n",		    n_errs, n_errs == 1 ? "" : "s",		    n_warns, n_warns == 1 ? "" : "s");      }  }#ifdef	OBJ_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 /* OBJ_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.     @@ Is this really necessary??  */#ifndef SUB_SEGMENT_ALIGN#ifdef BFD_ASSEMBLER#define SUB_SEGMENT_ALIGN(SEG) (0)#else#define SUB_SEGMENT_ALIGN(SEG) (2)#endif#endif  for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)    {      subseg_set (frchainP->frch_seg, frchainP->frch_subseg);      frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE);      /* 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);    }  /* From now on, we don't care about sub-segments.  Build one frag chain     for each segment. Linked thru fr_next.  */#ifdef BFD_ASSEMBLER  /* Remove the sections created by gas for its own purposes.  */  {    asection **seclist, *sec;    int i;    seclist = &stdoutput->sections;    while (seclist && *seclist)      {	sec = *seclist;	while (sec == reg_section || sec == expr_section)	  {	    sec = sec->next;	    *seclist = sec;	    stdoutput->section_count--;	    if (!sec)	      break;	  }	if (*seclist)	  seclist = &(*seclist)->next;      }    i = 0;    bfd_map_over_sections (stdoutput, renumber_sections, &i);  }  bfd_map_over_sections (stdoutput, chain_frchains_together, (char *) 0);#else  remove_subsegs (frchain_root, SEG_TEXT, &text_frag_root, &text_last_frag);  remove_subsegs (data0_frchainP, SEG_DATA, &data_frag_root, &data_last_frag);  remove_subsegs (bss0_frchainP, SEG_BSS, &bss_frag_root, &bss_last_frag);#endif  /* 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 !defined (OBJ_AOUT) || defined (BFD_ASSEMBLER)  if (flag_readonly_data_in_text)    {      merge_data_into_text ();    }#endif#ifdef BFD_ASSEMBLER  bfd_map_over_sections (stdoutput, relax_and_size_seg, (char *) 0);#else  relax_and_size_all_segments ();#endif /* BFD_ASSEMBLER */#ifndef BFD_ASSEMBLER  /*   *   * 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.  (They are still pointed to by the fixes.)   *   * Count the remaining symbols.   * Assign a symbol number to each symbol.   * Count the number of string-table chars we will emit.   * Put this info into the headers as appropriate.   *   */  know (zero_address_frag.fr_address == 0);  string_byte_count = sizeof (string_byte_count);  obj_crawl_symbol_chain (&headers);  if (string_byte_count == sizeof (string_byte_count))    string_byte_count = 0;  H_SET_STRING_SIZE (&headers, string_byte_count);  /*   * 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)    {      cvt_frag_to_fill (&headers, SEG_TEXT, fragP);      /* Some assert macros don't work with # directives mixed in.  */#ifndef NDEBUG      if (!(fragP->fr_next == NULL#ifdef OBJ_BOUT	    || fragP->fr_next == data_frag_root#endif	    || ((fragP->fr_next->fr_address - fragP->fr_address)		== (fragP->fr_fix + fragP->fr_offset * fragP->fr_var))))	abort ();#endif    }#endif /* ! BFD_ASSEMBLER */#ifndef WORKING_DOT_WORD  {    struct broken_word *lie;    struct broken_word **prevP;    prevP = &broken_words;    for (lie = broken_words; lie; lie = lie->next_broken_word)      if (!lie->added)	{	  expressionS exp;	  exp.X_op = O_subtract;	  exp.X_add_symbol = lie->add;	  exp.X_op_symbol = lie->sub;	  exp.X_add_number = lie->addnum;#ifdef BFD_ASSEMBLER#ifdef TC_CONS_FIX_NEW	  TC_CONS_FIX_NEW (lie->frag,		       lie->word_goes_here - lie->frag->fr_literal,		       2, &exp);#else	  fix_new_exp (lie->frag,		       lie->word_goes_here - lie->frag->fr_literal,		       2, &exp, 0, BFD_RELOC_NONE);#endif#else#if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE)	  fix_new_exp (lie->frag,		       lie->word_goes_here - lie->frag->fr_literal,		       2, &exp, 0, NO_RELOC);#else#ifdef TC_NS32K	  fix_new_ns32k_exp (lie->frag,			     lie->word_goes_here - lie->frag->fr_literal,			     2, &exp, 0, 0, 2, 0, 0);#else	  fix_new_exp (lie->frag,		       lie->word_goes_here - lie->frag->fr_literal,		       2, &exp, 0, 0);#endif /* TC_NS32K */#endif /* TC_SPARC|TC_A29K|NEED_FX_R_TYPE */#endif /* BFD_ASSEMBLER */	  *prevP = lie->next_broken_word;	}      else	prevP = &(lie->next_broken_word);    for (lie = broken_words; lie;)      {	struct broken_word *untruth;	char *table_ptr;	addressT table_addr;	addressT from_addr, to_addr;	int n, m;	fragP = lie->dispfrag;	/* Find out how many broken_words go here.  */	n = 0;	for (untruth = lie; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)	  if (untruth->added == 1)	    n++;	table_ptr = lie->dispfrag->fr_opcode;	table_addr = lie->dispfrag->fr_address + (table_ptr - lie->dispfrag->fr_literal);	/* Create the jump around the long jumps.  This is a short	   jump from table_ptr+0 to table_ptr+n*long_jump_size.  */	from_addr = table_addr;	to_addr = table_addr + md_short_jump_size + n * md_long_jump_size;	md_create_short_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);	table_ptr += md_short_jump_size;	table_addr += md_short_jump_size;	for (m = 0; lie && lie->dispfrag == fragP; m++, lie = lie->next_broken_word)	  {	    if (lie->added == 2)	      continue;	    /* Patch the jump table */	    /* This is the offset from ??? to table_ptr+0 */	    to_addr = table_addr - S_GET_VALUE (lie->sub);#ifdef BFD_ASSEMBLER	    to_addr -= lie->sub->sy_frag->fr_address;#endif	    md_number_to_chars (lie->word_goes_here, to_addr, 2);	    for (untruth = lie->next_broken_word; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)	      {		if (untruth->use_jump == lie)		  md_number_to_chars (untruth->word_goes_here, to_addr, 2);	      }	    /* Install the long jump */	    /* this is a long jump from table_ptr+0 to the final target */	    from_addr = table_addr;	    to_addr = S_GET_VALUE (lie->add) + lie->addnum;#ifdef BFD_ASSEMBLER	    to_addr += lie->add->sy_frag->fr_address;#endif	    md_create_long_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);	    table_ptr += md_long_jump_size;	    table_addr += md_long_jump_size;	  }      }  }#endif /* not WORKING_DOT_WORD */#ifndef BFD_ASSEMBLER#ifndef	OBJ_VMS  {				/* not vms */    char *the_object_file;    long object_file_size;    /*     * Scan every FixS performing fixups. We had to wait until now to do     * this because md_convert_frag() may have made some fixSs.     */    int trsize, drsize;    subseg_change (SEG_TEXT, 0);    trsize = md_reloc_size * fixup_segment (text_fix_root, SEG_TEXT);    subseg_change (SEG_DATA, 0);    drsize = md_reloc_size * fixup_segment (data_fix_root, SEG_DATA);    H_SET_RELOCATION_SIZE (&headers, trsize, drsize);    /* FIXME move this stuff into the pre-write-hook */    H_SET_MAGIC_NUMBER (&headers, magic_number_for_object_file);    H_SET_ENTRY_POINT (&headers, 0);    obj_pre_write_hook (&headers);	/* extra coff stuff */    object_file_size = H_GET_FILE_SIZE (&headers);    next_object_file_charP = the_object_file = xmalloc (object_file_size);    output_file_create (out_file_name);    obj_header_append (&next_object_file_charP, &headers);    know ((next_object_file_charP - the_object_file) == H_GET_HEADER_SIZE (&headers));    /*     * Emit code.     */    for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)      {	register long count;	register char *fill_literal;	register long fill_size;	PROGRESS (1);	know (fragP->fr_type == rs_fill);	append (&next_object_file_charP, fragP->fr_literal, (unsigned long) fragP->fr_fix);	fill_literal = fragP->fr_literal + fragP->fr_fix;	fill_size = fragP->fr_var;	know (fragP->fr_offset >= 0);	for (count = fragP->fr_offset; count; count--)	  {	    append (&next_object_file_charP, fill_literal, (unsigned long) fill_size);	  }			/* for each  */      }				/* for each code frag. */    know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers)));    /*     * Emit relocations.     */    obj_emit_relocations (&next_object_file_charP, text_fix_root, (relax_addressT) 0);    know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers)));#ifdef TC_I960    /* Make addresses in data relocation directives relative to beginning of     * first data fragment, not end of last text fragment:  alignment of the     * start of the data segment may place a gap between the segments.     */    obj_emit_relocations (&next_object_file_charP, data_fix_root, data0_frchainP->frch_root->fr_address);#else /* TC_I960 */    obj_emit_relocations (&next_object_file_charP, data_fix_root, text_last_frag->fr_address);#endif /* TC_I960 */    know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers)));    /*     * Emit line number entries.     */    OBJ_EMIT_LINENO (&next_object_file_charP, lineno_rootP, the_object_file);    know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers) + H_GET_LINENO_SIZE (&headers)));    /*     * Emit symbols.     */    obj_emit_symbols (&next_object_file_charP, symbol_rootP);    know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers) + H_GET_LINENO_SIZE (&headers) + H_GET_SYMBOL_TABLE_SIZE (&headers)));    /*     * Emit strings.     */    if (string_byte_count > 0)      {	obj_emit_strings (&next_object_file_charP);      }				/* only if we have a string table */#ifdef BFD_HEADERS    bfd_seek (stdoutput, 0, 0);    bfd_write (the_object_file, 1, object_file_size, stdoutput);#else    /* Write the data to the file */    output_file_append (the_object_file, object_file_size, out_file_name);    free (the_object_file);#endif  }				/* non vms output */#else /* OBJ_VMS */  /*   *	Now do the VMS-dependent part of writing the object file   */  vms_write_object_file (H_GET_TEXT_SIZE (&headers),			 H_GET_DATA_SIZE (&headers),			 H_GET_BSS_SIZE (&headers),			 text_frag_root, data_frag_root);#endif /* OBJ_VMS */#else /* BFD_ASSEMBLER */  /* Resolve symbol values.  This needs to be done before processing     the relocations.  */  if (symbol_rootP)    {      symbolS *symp;      for (symp = symbol_rootP; symp; symp = symbol_next (symp))	if (!symp->sy_resolved)	  resolve_symbol_value (symp);    }  PROGRESS (1);  bfd_map_over_sections (stdoutput, adjust_reloc_syms, (char *)0);  /* Set up symbol table, and write it out.  */  if (symbol_rootP)    {      symbolS *symp;      for (symp = symbol_rootP; symp; symp = symbol_next (symp))	{	  int punt = 0;	  const char *name;	  if (symp->sy_mri_common)	    {	      if (S_IS_EXTERNAL (symp))		as_bad ("%s: global symbols not supported in common sections",			S_GET_NAME (symp));	      symbol_remove (symp, &symbol_rootP, &symbol_lastP);	      continue;	    }	  name = S_GET_NAME (symp);	  if (name)	    {	      const char *name2 = decode_local_label_name ((char *)S_GET_NAME (symp));	      /* They only differ if `name' is a fb or dollar local		 label name.  */	      if (name2 != name && ! S_IS_DEFINED (symp))		as_bad ("local label %s is not defined", name2);	    }	  /* Do it again, because adjust_reloc_syms might introduce	     more symbols.  They'll probably only be section symbols,	     but they'll still need to have the values computed.  */	  if (! symp->sy_resolved)	    {	      if (symp->sy_value.X_op == O_constant)		{		  /* This is the normal case; skip the call.  */		  S_SET_VALUE (symp,			       (S_GET_VALUE (symp)				+ symp->sy_frag->fr_address));		  symp->sy_resolved = 1;		}	      else		resolve_symbol_value (symp);	    }	  /* So far, common symbols have been treated like undefined symbols.	     Put them in the common section now.  */	  if (S_IS_DEFINED (symp) == 0	      && S_GET_VALUE (symp) != 0)	    S_SET_SEGMENT (symp, bfd_com_section_ptr);#if 0	  printf ("symbol `%s'\n\t@%x: value=%d flags=%x seg=%s\n",		  S_GET_NAME (symp), symp,		  S_GET_VALUE (symp),		  symp->bsym->flags,		  segment_name (symp->bsym->section));#endif#ifdef obj_frob_symbol	  obj_frob_symbol (symp, punt);#endif#ifdef tc_frob_symbol	  if (! punt || symp->sy_used_in_reloc)	    tc_frob_symbol (symp, punt);#endif	  /* If we don't want to keep this symbol, splice it out of	     the chain now.  If EMIT_SECTION_SYMBOLS is 0, we never	     want section symbols.  Otherwise, we skip local symbols	     and symbols that the frob_symbol macros told us to punt,	     but we keep such symbols if they are used in relocs.  */	  if ((! EMIT_SECTION_SYMBOLS	       && (symp->bsym->flags & BSF_SECTION_SYM) != 0)	      /* Note that S_IS_EXTERN and S_IS_LOCAL are not always		 opposites.  Sometimes the former checks flags and the		 latter examines the name...  */	      || (!S_IS_EXTERN (symp)		  && (S_IS_LOCAL (symp) || punt)		  && ! symp->sy_used_in_reloc))	    {	      symbol_remove (symp, &symbol_rootP, &symbol_lastP);	      /* After symbol_remove, symbol_next(symp) still returns		 the one that came after it in the chain.  So we don't		 need to do any extra cleanup work here.  */	      continue;	    }	  /* Make sure we really got a value for the symbol.  */	  if (! symp->sy_resolved)	    {	      as_bad ("can't resolve value for symbol \"%s\"",		      S_GET_NAME (symp));	      symp->sy_resolved = 1;	    }	  /* Set the value into the BFD symbol.  Up til now the value	     has only been kept in the gas symbolS struct.  */	  symp->bsym->value = S_GET_VALUE (symp);	}    }  PROGRESS (1);  /* Now do any format-specific adjustments to the symbol table, such     as adding file symbols.  */#ifdef tc_adjust_symtab  tc_adjust_symtab ();#endif#ifdef obj_adjust_symtab  obj_adjust_symtab ();#endif  /* Now that all the sizes are known, and contents correct, we can     start writing to the file.  */  set_symtab ();  /* If *_frob_file changes the symbol value at this point, it is     responsible for moving the changed value into symp->bsym->value     as well.  Hopefully all symbol value changing can be done in     *_frob_symbol.  */#ifdef tc_frob_file  tc_frob_file ();#endif#ifdef obj_frob_file  obj_frob_file ();#endif  bfd_map_over_sections (stdoutput, write_relocs, (char *) 0);  bfd_map_over_sections (stdoutput, write_contents, (char *) 0);#endif /* BFD_ASSEMBLER */}