usr.bin/ld/ld.c
/* Having entered all the global symbols and found the sizes of sections
   of all files to be linked, make all appropriate deductions from this data.

   We propagate global symbol values from definitions to references.
   We compute the layout of the output file and where each input file's
   contents fit into it.  */
Having entered all the global symbols and found the sizes of sections
of all files to be linked, make all appropriate deductions from this data.

We propagate global symbol values from definitions to references.
We compute the layout of the output file and where each input file's
contents fit into it.
Having entered all the global symbols and found the sizes of sections of all files to be linked make all appropriate deductions from this data . We propagate global symbol values from definitions to references . We compute the layout of the output file and where each input file ' s contents fit into it .
void
digest_symbols ()
{
  register int i;
  int setv_fill_count;
  if (trace_files)
    fprintf (stderr, "Digesting symbol information:\n\n");
  each_file (consider_file_section_lengths, 0);
  if (magic == ZMAGIC)
    {
      int text_end = text_size + N_TXTOFF (outheader);
      text_pad = ((text_end + page_size - 1) & (- page_size)) - text_end;
      text_size += text_pad;
    }
  if (padtext)
    {
      int text_end = text_size;
      text_pad = ((text_end + page_size - 1) & (- page_size)) - text_end;
      text_size += text_pad;
    }
#ifdef _N_BASEADDR
  outheader.a_entry = N_PAGSIZ (outheader);
#endif
  outheader.a_text = text_size;
#ifdef sequent
  outheader.a_text += N_ADDRADJ (outheader);
#endif
  if (! Tdata_flag_specified)
    data_start = N_DATADDR (outheader) + text_start - TEXT_START (outheader);
  if (!relocatable_output)
    {
      set_sect_size
	= (2 * set_symbol_count + set_vector_count) * sizeof (unsigned long);
      set_sect_start = data_start + data_size;
      data_size += set_sect_size;
      set_vectors = (unsigned long *) xmalloc (set_sect_size);
      setv_fill_count = 0;
    }
  each_full_file (relocate_file_addresses, 0);
  defined_global_sym_count = 0;
  for (i = 0; i < TABSIZE; i++)
    {
      register symbol *sp;
      for (sp = symtab[i]; sp; sp = sp->link)
	{
	  register struct nlist *p, *next;
	  int defs = 0, com = sp->max_common_size;
	  struct nlist *first_definition;
	  for (p = sp->refs; p; p = next)
	    {
	      register int type = p->n_type;
	      if (SET_ELEMENT_P (type))
		{
		  if (relocatable_output)
		    fatal ("internal: global ref to set element with -r");
		  if (!defs++)
		    {
		      sp->value = set_sect_start
			+ setv_fill_count++ * sizeof (unsigned long);
		      sp->defined = N_SETV | N_EXT;
		      first_definition = p;
		    }
		  else if ((sp->defined & ~N_EXT) != N_SETV)
		    {
		      sp->multiply_defined = 1;
		      multiple_def_count++;
		    }
		  set_vectors[setv_fill_count++] = p->n_value;
		}
	      else if ((type & N_EXT) && type != (N_UNDF | N_EXT))
		{
		  if (defs++ && sp->value != p->n_value)
		    {
		      sp->multiply_defined = 1;
		      multiple_def_count++;
		    }
		  sp->value = p->n_value;
		  sp->defined = type;
		  first_definition = p;
		}
	      next = (struct nlist *) p->n_un.n_name;
	      p->n_un.n_name = (char *) sp;
	    }
	  if (com && !defs)
	    {
	      if (!relocatable_output || force_common_definition)
		{
		  int align = sizeof (int);
		  com = (com + sizeof (int) - 1) & (- sizeof (int));
		  while (!(com & align))
		    align <<= 1;
		  align = align > MAX_ALIGNMENT ? MAX_ALIGNMENT : align;
		  bss_size = ((((bss_size + data_size + data_start)
			      + (align - 1)) & (- align))
			      - data_size - data_start);
		  sp->value = data_start + data_size + bss_size;
		  sp->defined = N_BSS | N_EXT;
		  bss_size += com;
		  if (write_map)
		    printf ("Allocating common %s: %x at %x\n",
			    sp->name, com, sp->value);
		}
	      else
		{
		  sp->defined = 0;
		  undefined_global_sym_count++;
		}
	    }
	  if ((sp->defined & ~N_EXT) == N_SETV)
	    {
	      unsigned long length_word_index
		= (sp->value - set_sect_start) / sizeof (unsigned long);
	      unsigned long i, tmp;
	      set_vectors[length_word_index]
		= setv_fill_count - 1 - length_word_index;
	      for (i = 1;
		   i < (setv_fill_count - length_word_index - 1) / 2 + 1;
		   i++)
		{
		  tmp = set_vectors[length_word_index + i];
		  set_vectors[length_word_index + i]
		    = set_vectors[setv_fill_count - i];
		  set_vectors[setv_fill_count - i] = tmp;
		}
	      set_vectors[setv_fill_count++] = 0;
	    }
	  if (sp->defined)
	    defined_global_sym_count++;
	}
    }
  if (end_symbol)		
    {
      etext_symbol->value = text_size + text_start;
      edata_symbol->value = data_start + data_size;
      end_symbol->value = data_start + data_size + bss_size;
    }
  if (specified_data_size && specified_data_size > data_size)
    data_pad = specified_data_size - data_size;
  if (magic == ZMAGIC)
    data_pad = ((data_pad + data_size + page_size - 1) & (- page_size))
               - data_size;
  bss_size -= data_pad;
  if (bss_size < 0) bss_size = 0;
  data_size += data_pad;
}
void digest_symbols ( ) { register int i ; int setv_fill_count ; if ( trace_files ) fprintf ( stderr , " \n \n " ) ; each_file ( consider_file_section_lengths , 0 ) ; if ( magic == ZMAGIC ) { int text_end = text_size + N_TXTOFF ( outheader ) ; text_pad = ( ( text_end + page_size - 1 ) & ( - page_size ) ) - text_end ; text_size += text_pad ; } if ( padtext ) { int text_end = text_size ; text_pad = ( ( text_end + page_size - 1 ) & ( - page_size ) ) - text_end ; text_size += text_pad ; } #ifdef _N_BASEADDR outheader . a_entry = N_PAGSIZ ( outheader ) ; #endif outheader . a_text = text_size ; #ifdef sequent outheader . a_text += N_ADDRADJ ( outheader ) ; #endif if ( ! Tdata_flag_specified ) data_start = N_DATADDR ( outheader ) + text_start - TEXT_START ( outheader ) ; if ( ! relocatable_output ) { set_sect_size = ( 2 * set_symbol_count + set_vector_count ) * sizeof ( unsigned long ) ; set_sect_start = data_start + data_size ; data_size += set_sect_size ; set_vectors = ( unsigned long * ) xmalloc ( set_sect_size ) ; setv_fill_count = 0 ; } each_full_file ( relocate_file_addresses , 0 ) ; defined_global_sym_count = 0 ; for ( i = 0 ; i < TABSIZE ; i ++ ) { register symbol * sp ; for ( sp = symtab [ i ] ; sp ; sp = sp -> link ) { register struct nlist * p , * next ; int defs = 0 , com = sp -> max_common_size ; struct nlist * first_definition ; for ( p = sp -> refs ; p ; p = next ) { register int type = p -> n_type ; if ( SET_ELEMENT_P ( type ) ) { if ( relocatable_output ) fatal ( " " ) ; if ( ! defs ++ ) { sp -> value = set_sect_start + setv_fill_count ++ * sizeof ( unsigned long ) ; sp -> defined = N_SETV | N_EXT ; first_definition = p ; } else if ( ( sp -> defined & ~ N_EXT ) != N_SETV ) { sp -> multiply_defined = 1 ; multiple_def_count ++ ; } set_vectors [ setv_fill_count ++ ] = p -> n_value ; } else if ( ( type & N_EXT ) && type != ( N_UNDF | N_EXT ) ) { if ( defs ++ && sp -> value != p -> n_value ) { sp -> multiply_defined = 1 ; multiple_def_count ++ ; } sp -> value = p -> n_value ; sp -> defined = type ; first_definition = p ; } next = ( struct nlist * ) p -> n_un . n_name ; p -> n_un . n_name = ( char * ) sp ; } if ( com && ! defs ) { if ( ! relocatable_output || force_common_definition ) { int align = sizeof ( int ) ; com = ( com + sizeof ( int ) - 1 ) & ( - sizeof ( int ) ) ; while ( ! ( com & align ) ) align <<= 1 ; align = align > MAX_ALIGNMENT ? MAX_ALIGNMENT : align ; bss_size = ( ( ( ( bss_size + data_size + data_start ) + ( align - 1 ) ) & ( - align ) ) - data_size - data_start ) ; sp -> value = data_start + data_size + bss_size ; sp -> defined = N_BSS | N_EXT ; bss_size += com ; if ( write_map ) printf ( " \n " , sp -> name , com , sp -> value ) ; } else { sp -> defined = 0 ; undefined_global_sym_count ++ ; } } if ( ( sp -> defined & ~ N_EXT ) == N_SETV ) { unsigned long length_word_index = ( sp -> value - set_sect_start ) / sizeof ( unsigned long ) ; unsigned long i , tmp ; set_vectors [ length_word_index ] = setv_fill_count - 1 - length_word_index ; for ( i = 1 ; i < ( setv_fill_count - length_word_index - 1 ) / 2 + 1 ; i ++ ) { tmp = set_vectors [ length_word_index + i ] ; set_vectors [ length_word_index + i ] = set_vectors [ setv_fill_count - i ] ; set_vectors [ setv_fill_count - i ] = tmp ; } set_vectors [ setv_fill_count ++ ] = 0 ; } if ( sp -> defined ) defined_global_sym_count ++ ; } } if ( end_symbol ) { etext_symbol -> value = text_size + text_start ; edata_symbol -> value = data_start + data_size ; end_symbol -> value = data_start + data_size + bss_size ; } if ( specified_data_size && specified_data_size > data_size ) data_pad = specified_data_size - data_size ; if ( magic == ZMAGIC ) data_pad = ( ( data_pad + data_size + page_size - 1 ) & ( - page_size ) ) - data_size ; bss_size -= data_pad ; if ( bss_size < 0 ) bss_size = 0 ; data_size += data_pad ; }
Having entered all the global symbols and found the sizes of sections
of all files to be linked, make all appropriate deductions from this data.
Having entered all the global symbols and found the sizes of sections of all files to be linked make all appropriate deductions from this data .
/* Compute total size of sections */ /* If necessary, pad text section to full page in the file.
     Include the padding in the text segment size.  */ /* SunOS 4.1 N_TXTADDR depends on the value of outheader.a_entry.  */ /* Make the data segment address start in memory on a suitable boundary.  */ /* Set up the set element vector */ /* The set sector size is the number of set elements + a word
         for each symbol for the length word at the beginning of the
	 vector, plus a word for each symbol for a zero at the end of
	 the vector (for incremental linking).  */ /* Compute start addresses of each file's sections and symbols.  */ /* Now, for each symbol, verify that it is defined globally at most once.
     Put the global value into the symbol entry.
     Common symbols are allocated here, in the BSS section.
     Each defined symbol is given a '->defined' field
      which is the correct N_ code for its definition,
      except in the case of common symbols with -r.
     Then make all the references point at the symbol entry
     instead of being chained together. */ /* For each symbol */ /* non-common definition */ /* Allocate as common if defined as common and not defined for real */ /* Round up to nearest sizeof (int).  I don't know
		     whether this is necessary or not (given that
		     alignment is taken care of later), but it's
		     traditional, so I'll leave it in.  Note that if
		     this size alignment is ever removed, ALIGN above
		     will have to be initialized to 1 instead of
		     sizeof (int).  */ /* Set length word at front of vector and zero byte at end.
	     Reverse the vector itself to put it in file order.  */ /* Reverse the vector.  */ /* These are null if -r.  */ /* Figure the data_pad now, so that it overlaps with the bss addresses.  */