FreeBSD/contrib/binutils/bfd/elflink.c
/* The mark phase of garbage collection.  For a given section, mark
   it and any sections in this section's group, and all the sections
   which define symbols to which it refers.  */
The mark phase of garbage collection.  For a given section, mark
it and any sections in this section's group, and all the sections
which define symbols to which it refers.
The mark phase of garbage collection . For a given section mark it and any sections in this section ' s group and all the sections which define symbols to which it refers .
bfd_boolean
_bfd_elf_gc_mark (struct bfd_link_info *info,
		  asection *sec,
		  elf_gc_mark_hook_fn gc_mark_hook)
{
  bfd_boolean ret;
  bfd_boolean is_eh;
  asection *group_sec;
  sec->gc_mark = 1;
  group_sec = elf_section_data (sec)->next_in_group;
  if (group_sec && !group_sec->gc_mark)
    if (!_bfd_elf_gc_mark (info, group_sec, gc_mark_hook))
      return FALSE;
  ret = TRUE;
  is_eh = strcmp (sec->name, ".eh_frame") == 0;
  if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
    {
      Elf_Internal_Rela *relstart, *rel, *relend;
      Elf_Internal_Shdr *symtab_hdr;
      struct elf_link_hash_entry **sym_hashes;
      size_t nlocsyms;
      size_t extsymoff;
      bfd *input_bfd = sec->owner;
      const struct elf_backend_data *bed = get_elf_backend_data (input_bfd);
      Elf_Internal_Sym *isym = NULL;
      int r_sym_shift;
      symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
      sym_hashes = elf_sym_hashes (input_bfd);
      if (elf_bad_symtab (input_bfd))
	{
	  nlocsyms = symtab_hdr->sh_size / bed->s->sizeof_sym;
	  extsymoff = 0;
	}
      else
	extsymoff = nlocsyms = symtab_hdr->sh_info;
      isym = (Elf_Internal_Sym *) symtab_hdr->contents;
      if (isym == NULL && nlocsyms != 0)
	{
	  isym = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, nlocsyms, 0,
				       NULL, NULL, NULL);
	  if (isym == NULL)
	    return FALSE;
	}
      relstart = _bfd_elf_link_read_relocs (input_bfd, sec, NULL, NULL,
					    info->keep_memory);
      if (relstart == NULL)
	{
	  ret = FALSE;
	  goto out1;
	}
      relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
      if (bed->s->arch_size == 32)
	r_sym_shift = 8;
      else
	r_sym_shift = 32;
      for (rel = relstart; rel < relend; rel++)
	{
	  unsigned long r_symndx;
	  asection *rsec;
	  struct elf_link_hash_entry *h;
	  r_symndx = rel->r_info >> r_sym_shift;
	  if (r_symndx == 0)
	    continue;
	  if (r_symndx >= nlocsyms
	      || ELF_ST_BIND (isym[r_symndx].st_info) != STB_LOCAL)
	    {
	      h = sym_hashes[r_symndx - extsymoff];
	      while (h->root.type == bfd_link_hash_indirect
		     || h->root.type == bfd_link_hash_warning)
		h = (struct elf_link_hash_entry *) h->root.u.i.link;
	      rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
	    }
	  else
	    {
	      rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]);
	    }
	  if (rsec && !rsec->gc_mark)
	    {
	      if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
		rsec->gc_mark = 1;
	      else if (is_eh)
		rsec->gc_mark_from_eh = 1;
	      else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
		{
		  ret = FALSE;
		  goto out2;
		}
	    }
	}
    out2:
      if (elf_section_data (sec)->relocs != relstart)
	free (relstart);
    out1:
      if (isym != NULL && symtab_hdr->contents != (unsigned char *) isym)
	{
	  if (! info->keep_memory)
	    free (isym);
	  else
	    symtab_hdr->contents = (unsigned char *) isym;
	}
    }
  return ret;
}
bfd_boolean _bfd_elf_gc_mark ( struct bfd_link_info * info , asection * sec , elf_gc_mark_hook_fn gc_mark_hook ) { bfd_boolean ret ; bfd_boolean is_eh ; asection * group_sec ; sec -> gc_mark = 1 ; group_sec = elf_section_data ( sec ) -> next_in_group ; if ( group_sec && ! group_sec -> gc_mark ) if ( ! _bfd_elf_gc_mark ( info , group_sec , gc_mark_hook ) ) return FALSE ; ret = TRUE ; is_eh = strcmp ( sec -> name , " " ) == 0 ; if ( ( sec -> flags & SEC_RELOC ) != 0 && sec -> reloc_count > 0 ) { Elf_Internal_Rela * relstart , * rel , * relend ; Elf_Internal_Shdr * symtab_hdr ; struct elf_link_hash_entry * * sym_hashes ; size_t nlocsyms ; size_t extsymoff ; bfd * input_bfd = sec -> owner ; const struct elf_backend_data * bed = get_elf_backend_data ( input_bfd ) ; Elf_Internal_Sym * isym = NULL ; int r_sym_shift ; symtab_hdr = & elf_tdata ( input_bfd ) -> symtab_hdr ; sym_hashes = elf_sym_hashes ( input_bfd ) ; if ( elf_bad_symtab ( input_bfd ) ) { nlocsyms = symtab_hdr -> sh_size / bed -> s -> sizeof_sym ; extsymoff = 0 ; } else extsymoff = nlocsyms = symtab_hdr -> sh_info ; isym = ( Elf_Internal_Sym * ) symtab_hdr -> contents ; if ( isym == NULL && nlocsyms != 0 ) { isym = bfd_elf_get_elf_syms ( input_bfd , symtab_hdr , nlocsyms , 0 , NULL , NULL , NULL ) ; if ( isym == NULL ) return FALSE ; } relstart = _bfd_elf_link_read_relocs ( input_bfd , sec , NULL , NULL , info -> keep_memory ) ; if ( relstart == NULL ) { ret = FALSE ; goto out1 ; } relend = relstart + sec -> reloc_count * bed -> s -> int_rels_per_ext_rel ; if ( bed -> s -> arch_size == 32 ) r_sym_shift = 8 ; else r_sym_shift = 32 ; for ( rel = relstart ; rel < relend ; rel ++ ) { unsigned long r_symndx ; asection * rsec ; struct elf_link_hash_entry * h ; r_symndx = rel -> r_info >> r_sym_shift ; if ( r_symndx == 0 ) continue ; if ( r_symndx >= nlocsyms || ELF_ST_BIND ( isym [ r_symndx ] . st_info ) != STB_LOCAL ) { h = sym_hashes [ r_symndx - extsymoff ] ; while ( h -> root . type == bfd_link_hash_indirect || h -> root . type == bfd_link_hash_warning ) h = ( struct elf_link_hash_entry * ) h -> root . u . i . link ; rsec = ( * gc_mark_hook ) ( sec , info , rel , h , NULL ) ; } else { rsec = ( * gc_mark_hook ) ( sec , info , rel , NULL , & isym [ r_symndx ] ) ; } if ( rsec && ! rsec -> gc_mark ) { if ( bfd_get_flavour ( rsec -> owner ) != bfd_target_elf_flavour ) rsec -> gc_mark = 1 ; else if ( is_eh ) rsec -> gc_mark_from_eh = 1 ; else if ( ! _bfd_elf_gc_mark ( info , rsec , gc_mark_hook ) ) { ret = FALSE ; goto out2 ; } } } out2 : if ( elf_section_data ( sec ) -> relocs != relstart ) free ( relstart ) ; out1 : if ( isym != NULL && symtab_hdr -> contents != ( unsigned char * ) isym ) { if ( ! info -> keep_memory ) free ( isym ) ; else symtab_hdr -> contents = ( unsigned char * ) isym ; } } return ret ; }
The mark phase of garbage collection.
The mark phase of garbage collection .
/* Mark all the sections in the group.  */ /* Look through the section relocs.  */ /* Read the local symbols.  */ /* Read the relocations.  */