usr.bin/ld/ld.c
/* Write the symbol table and string table of the output file.  */
Write the symbol table and string table of the output file.
Write the symbol table and string table of the output file .
void
write_syms ()
{
  int syms_written = 0;
  register int i;
  register symbol *sp;
  struct nlist *buf
    = (struct nlist *) alloca ((defined_global_sym_count
				+ undefined_global_sym_count
				+ global_indirect_count)
			       * sizeof (struct nlist));
  register struct nlist *bufp = buf;
  strtab_size = sizeof strtab_size;
  symbol_table_offset = N_SYMOFF (outheader);
  symbol_table_len = 0;
  string_table_offset = N_STROFF (outheader);
  string_table_len = strtab_size;
  if (strip_symbols == STRIP_ALL)
    return;
  each_file (write_file_syms, &syms_written);
  file_close ();
  strtab_vector = (char **) alloca ((num_hash_tab_syms
				     + global_indirect_count) * sizeof (char *));
  strtab_lens = (int *) alloca ((num_hash_tab_syms
				 + global_indirect_count) * sizeof (int));
  strtab_index = 0;
  for (i = 0; i < TABSIZE; i++)
    for (sp = symtab[i]; sp; sp = sp->link)
      {
	struct nlist nl;
	nl.n_other = 0;
	nl.n_desc = 0;
	if (sp->defined || sp->referenced)
	  {
	    if (sp->defined > 1) 
	      {
		if (!relocatable_output
		    && ((sp->defined & N_TYPE) == N_INDR)
		    && (((symbol *) sp->value)->defined > 1))
		  {
		    symbol *newsp = (symbol *) sp->value;
		    nl.n_type = newsp->defined;
		    nl.n_value = newsp->value;
		  }
		else
		  {
		    nl.n_type = sp->defined;
		    if (sp->defined != (N_INDR | N_EXT))
		      nl.n_value = sp->value;
		    else
		      nl.n_value = 0;
		  }
	      }
	    else if (sp->max_common_size) 
	      {
		nl.n_type = N_UNDF | N_EXT;
		nl.n_value = sp->max_common_size;
	      }
	    else if (!sp->defined)	      
	      {
		nl.n_type = N_UNDF | N_EXT;
		nl.n_value = 0;
	      }
	    else
	      fatal ("internal error: %s defined in mysterious way", sp->name);
	    nl.n_un.n_strx = assign_string_table_index (sp->name);
	    *bufp++ = nl;
	    syms_written++;
	    if (nl.n_type == (N_INDR | N_EXT))
	      {
		struct nlist xtra_ref;
		xtra_ref.n_type = N_EXT | N_UNDF;
		xtra_ref.n_un.n_strx
		  = assign_string_table_index (((symbol *) sp->value)->name);
		xtra_ref.n_other = 0;
		xtra_ref.n_desc = 0;
		xtra_ref.n_value = 0;
		*bufp++ = xtra_ref;
		syms_written++;
	      }
	  }
      }
  lseek (outdesc, symbol_table_offset + symbol_table_len, 0);
  mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
  symbol_table_len += sizeof (struct nlist) * (bufp - buf);
  if (syms_written != nsyms)
    fatal ("internal error: wrong number of symbols written into output file", 0);
  if (symbol_table_offset + symbol_table_len != string_table_offset)
    fatal ("internal error: inconsistent symbol table length", 0);
  mywrite (&strtab_size, sizeof (int), 1, outdesc);  
  write_string_table ();
}
void write_syms ( ) { int syms_written = 0 ; register int i ; register symbol * sp ; struct nlist * buf = ( struct nlist * ) alloca ( ( defined_global_sym_count + undefined_global_sym_count + global_indirect_count ) * sizeof ( struct nlist ) ) ; register struct nlist * bufp = buf ; strtab_size = sizeof strtab_size ; symbol_table_offset = N_SYMOFF ( outheader ) ; symbol_table_len = 0 ; string_table_offset = N_STROFF ( outheader ) ; string_table_len = strtab_size ; if ( strip_symbols == STRIP_ALL ) return ; each_file ( write_file_syms , & syms_written ) ; file_close ( ) ; strtab_vector = ( char * * ) alloca ( ( num_hash_tab_syms + global_indirect_count ) * sizeof ( char * ) ) ; strtab_lens = ( int * ) alloca ( ( num_hash_tab_syms + global_indirect_count ) * sizeof ( int ) ) ; strtab_index = 0 ; for ( i = 0 ; i < TABSIZE ; i ++ ) for ( sp = symtab [ i ] ; sp ; sp = sp -> link ) { struct nlist nl ; nl . n_other = 0 ; nl . n_desc = 0 ; if ( sp -> defined || sp -> referenced ) { if ( sp -> defined > 1 ) { if ( ! relocatable_output && ( ( sp -> defined & N_TYPE ) == N_INDR ) && ( ( ( symbol * ) sp -> value ) -> defined > 1 ) ) { symbol * newsp = ( symbol * ) sp -> value ; nl . n_type = newsp -> defined ; nl . n_value = newsp -> value ; } else { nl . n_type = sp -> defined ; if ( sp -> defined != ( N_INDR | N_EXT ) ) nl . n_value = sp -> value ; else nl . n_value = 0 ; } } else if ( sp -> max_common_size ) { nl . n_type = N_UNDF | N_EXT ; nl . n_value = sp -> max_common_size ; } else if ( ! sp -> defined ) { nl . n_type = N_UNDF | N_EXT ; nl . n_value = 0 ; } else fatal ( " " , sp -> name ) ; nl . n_un . n_strx = assign_string_table_index ( sp -> name ) ; * bufp ++ = nl ; syms_written ++ ; if ( nl . n_type == ( N_INDR | N_EXT ) ) { struct nlist xtra_ref ; xtra_ref . n_type = N_EXT | N_UNDF ; xtra_ref . n_un . n_strx = assign_string_table_index ( ( ( symbol * ) sp -> value ) -> name ) ; xtra_ref . n_other = 0 ; xtra_ref . n_desc = 0 ; xtra_ref . n_value = 0 ; * bufp ++ = xtra_ref ; syms_written ++ ; } } } lseek ( outdesc , symbol_table_offset + symbol_table_len , 0 ) ; mywrite ( buf , sizeof ( struct nlist ) , bufp - buf , outdesc ) ; symbol_table_len += sizeof ( struct nlist ) * ( bufp - buf ) ; if ( syms_written != nsyms ) fatal ( " " , 0 ) ; if ( symbol_table_offset + symbol_table_len != string_table_offset ) fatal ( " " , 0 ) ; mywrite ( & strtab_size , sizeof ( int ) , 1 , outdesc ) ; write_string_table ( ) ; }
Write the symbol table and string table of the output file.
Write the symbol table and string table of the output file .
/* Number of symbols written so far.  */ /* Buffer big enough for all the global symbols.  One
     extra struct for each indirect symbol to hold the extra reference
     following. */ /* Pointer for storing into BUF.  */ /* Size of string table includes the bytes that store the size.  */ /* Write the local symbols defined by the various files.  */ /* Now write out the global symbols.  */ /* Allocate two vectors that record the data to generate the string
     table from the global symbols written so far.  This must include
     extra space for the references following indirect outputs. */ /* Scan the symbol hash table, bucket by bucket.  */ /* Compute a `struct nlist' for the symbol.  */ /* common condition needs to be before undefined condition */ /* because unallocated commons are set undefined in */ /* digest_symbols */ /* defined with known type */ /* If the target of an indirect symbol has been
		   defined and we are outputting an executable,
		   resolve the indirection; it's no longer needed */ /* defined as common but not allocated. */ /* happens only with -r and not -d */ /* write out a common definition */ /* undefined -- legit only if -r */ /* Allocate string table space for the symbol name.  */ /* Output to the buffer and count it.  */ /* Output the buffer full of `struct nlist's.  */ /* Now the total string table size is known, so write it.
     We are already positioned at the right place in the file.  */ /* we're at right place */ /* Write the strings for the global symbols.  */