FreeBSD/contrib/binutils/bfd/elflink.c
/* Do mark and sweep of unused sections.  */
Do mark and sweep of unused sections.
Do mark and sweep of unused sections .
bfd_boolean
bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
{
  bfd_boolean ok = TRUE;
  bfd *sub;
  elf_gc_mark_hook_fn gc_mark_hook;
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  if (!bed->can_gc_sections
      || info->relocatable
      || info->emitrelocations
      || !is_elf_hash_table (info->hash))
    {
      (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
      return TRUE;
    }
  elf_link_hash_traverse (elf_hash_table (info),
			  elf_gc_propagate_vtable_entries_used,
			  &ok);
  if (!ok)
    return FALSE;
  elf_link_hash_traverse (elf_hash_table (info),
			  elf_gc_smash_unused_vtentry_relocs,
			  &ok);
  if (!ok)
    return FALSE;
  if (elf_hash_table (info)->dynamic_sections_created)
    elf_link_hash_traverse (elf_hash_table (info),
			    bed->gc_mark_dynamic_ref,
			    info);
  gc_mark_hook = bed->gc_mark_hook;
  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
    {
      asection *o;
      if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
	continue;
      for (o = sub->sections; o != NULL; o = o->next)
	if ((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP && !o->gc_mark)
	  if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
	    return FALSE;
    }
  if (bed->gc_mark_extra_sections)
    bed->gc_mark_extra_sections(info, gc_mark_hook);
  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
    {
      asection *o;
      if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
	continue;
#define TEXT_PREFIX			".text."
#define TEXT_PREFIX2			".gnu.linkonce.t."
#define GCC_EXCEPT_TABLE_PREFIX		".gcc_except_table."
      for (o = sub->sections; o != NULL; o = o->next)
	if (!o->gc_mark && o->gc_mark_from_eh && (o->flags & SEC_CODE) == 0)
	  {
	    if (CONST_STRNEQ (o->name, GCC_EXCEPT_TABLE_PREFIX))
	      {
		char *fn_name;
		const char *sec_name;
		asection *fn_text;
		unsigned o_name_prefix_len , fn_name_prefix_len, tmp;
		o_name_prefix_len = strlen (GCC_EXCEPT_TABLE_PREFIX);
		sec_name = o->name + o_name_prefix_len;
		fn_name_prefix_len = strlen (TEXT_PREFIX);
		tmp = strlen (TEXT_PREFIX2);
		if (tmp > fn_name_prefix_len)
		  fn_name_prefix_len = tmp;
		fn_name
		  = bfd_malloc (fn_name_prefix_len + strlen (sec_name) + 1);
		if (fn_name == NULL)
		  return FALSE;
		sprintf (fn_name, "%s%s", TEXT_PREFIX, sec_name);
		fn_text = bfd_get_section_by_name (sub, fn_name);
		if (fn_text == NULL)
		  {
		    sprintf (fn_name, "%s%s", TEXT_PREFIX2, sec_name);
		    fn_text = bfd_get_section_by_name (sub, fn_name);
		  }
		free (fn_name);
		if (fn_text == NULL || !fn_text->gc_mark)
		  continue;
	      }
	    if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
	      return FALSE;
	  }
    }
  return elf_gc_sweep (abfd, info);
}
bfd_boolean bfd_elf_gc_sections ( bfd * abfd , struct bfd_link_info * info ) { bfd_boolean ok = TRUE ; bfd * sub ; elf_gc_mark_hook_fn gc_mark_hook ; const struct elf_backend_data * bed = get_elf_backend_data ( abfd ) ; if ( ! bed -> can_gc_sections || info -> relocatable || info -> emitrelocations || ! is_elf_hash_table ( info -> hash ) ) { ( * _bfd_error_handler ) ( _ ( " " ) ) ; return TRUE ; } elf_link_hash_traverse ( elf_hash_table ( info ) , elf_gc_propagate_vtable_entries_used , & ok ) ; if ( ! ok ) return FALSE ; elf_link_hash_traverse ( elf_hash_table ( info ) , elf_gc_smash_unused_vtentry_relocs , & ok ) ; if ( ! ok ) return FALSE ; if ( elf_hash_table ( info ) -> dynamic_sections_created ) elf_link_hash_traverse ( elf_hash_table ( info ) , bed -> gc_mark_dynamic_ref , info ) ; gc_mark_hook = bed -> gc_mark_hook ; for ( sub = info -> input_bfds ; sub != NULL ; sub = sub -> link_next ) { asection * o ; if ( bfd_get_flavour ( sub ) != bfd_target_elf_flavour ) continue ; for ( o = sub -> sections ; o != NULL ; o = o -> next ) if ( ( o -> flags & ( SEC_EXCLUDE | SEC_KEEP ) ) == SEC_KEEP && ! o -> gc_mark ) if ( ! _bfd_elf_gc_mark ( info , o , gc_mark_hook ) ) return FALSE ; } if ( bed -> gc_mark_extra_sections ) bed -> gc_mark_extra_sections ( info , gc_mark_hook ) ; for ( sub = info -> input_bfds ; sub != NULL ; sub = sub -> link_next ) { asection * o ; if ( bfd_get_flavour ( sub ) != bfd_target_elf_flavour ) continue ; #define TEXT_PREFIX 			".text." #define TEXT_PREFIX2 			".gnu.linkonce.t." #define GCC_EXCEPT_TABLE_PREFIX 		".gcc_except_table." for ( o = sub -> sections ; o != NULL ; o = o -> next ) if ( ! o -> gc_mark && o -> gc_mark_from_eh && ( o -> flags & SEC_CODE ) == 0 ) { if ( CONST_STRNEQ ( o -> name , GCC_EXCEPT_TABLE_PREFIX ) ) { char * fn_name ; const char * sec_name ; asection * fn_text ; unsigned o_name_prefix_len , fn_name_prefix_len , tmp ; o_name_prefix_len = strlen ( GCC_EXCEPT_TABLE_PREFIX ) ; sec_name = o -> name + o_name_prefix_len ; fn_name_prefix_len = strlen ( TEXT_PREFIX ) ; tmp = strlen ( TEXT_PREFIX2 ) ; if ( tmp > fn_name_prefix_len ) fn_name_prefix_len = tmp ; fn_name = bfd_malloc ( fn_name_prefix_len + strlen ( sec_name ) + 1 ) ; if ( fn_name == NULL ) return FALSE ; sprintf ( fn_name , " " , TEXT_PREFIX , sec_name ) ; fn_text = bfd_get_section_by_name ( sub , fn_name ) ; if ( fn_text == NULL ) { sprintf ( fn_name , " " , TEXT_PREFIX2 , sec_name ) ; fn_text = bfd_get_section_by_name ( sub , fn_name ) ; } free ( fn_name ) ; if ( fn_text == NULL || ! fn_text -> gc_mark ) continue ; } if ( ! _bfd_elf_gc_mark ( info , o , gc_mark_hook ) ) return FALSE ; } } return elf_gc_sweep ( abfd , info ) ; }
Do mark and sweep of unused sections.
Do mark and sweep of unused sections .
/* Apply transitive closure to the vtable entry usage info.  */ /* Kill the vtable relocations that were not used.  */ /* Mark dynamically referenced symbols.  */ /* Grovel through relocs to find out who stays ...  */ /* Allow the backend to mark additional target specific sections.  */ /* ... again for sections marked from eh_frame.  */ /* Keep .gcc_except_table.* if the associated .text.* (or the
	 associated .gnu.linkonce.t.* if .text.* doesn't exist) is
	 marked.  This isn't very nice, but the proper solution,
	 splitting .eh_frame up and using comdat doesn't pan out
	 easily due to needing special relocs to handle the
	 difference of two symbols in separate sections.
	 Don't keep code sections referenced by .eh_frame.  */ /* Try the first prefix.  */ /* Try the second prefix.  */ /* If not using specially named exception table section,
	       then keep whatever we are using.  */ /* ... and mark SEC_EXCLUDE for those that go.  */