FreeBSD/contrib/binutils/bfd/elflink.c
/* Entry point to evaluator, called from elf_link_input_bfd.  */
Entry point to evaluator, called from elf_link_input_bfd.
Entry point to evaluator called from elf_link_input_bfd .
static bfd_boolean
evaluate_complex_relocation_symbols (bfd * input_bfd,
				     struct elf_final_link_info * finfo,
				     size_t locsymcount)
{
  const struct elf_backend_data * bed;
  Elf_Internal_Shdr *             symtab_hdr;
  struct elf_link_hash_entry **   sym_hashes;
  asection *                      reloc_sec;
  bfd_boolean                     result = TRUE;
  if (finfo->info->relocatable)
    return TRUE;
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (input_bfd);
  bed = get_elf_backend_data (input_bfd);
  for (reloc_sec = input_bfd->sections; reloc_sec; reloc_sec = reloc_sec->next)
    {
      Elf_Internal_Rela * internal_relocs;
      unsigned long i;
      if (! reloc_sec->linker_mark)
	continue;
      if ((reloc_sec->flags & SEC_RELOC) == 0)
	continue;
      if (reloc_sec->reloc_count == 0)
	continue;
      internal_relocs
	= _bfd_elf_link_read_relocs (input_bfd, reloc_sec, NULL,
				     (Elf_Internal_Rela *) NULL,
				     FALSE);
      if (internal_relocs == NULL)
	continue;
      for (i = reloc_sec->reloc_count; i--;)
	{
	  Elf_Internal_Rela * rel;
	  char * sym_name;
	  bfd_vma index;
	  Elf_Internal_Sym * sym;
	  bfd_vma result;
	  bfd_vma section_offset;
	  bfd_vma addr;
	  int signed_p = 0;
	  rel = internal_relocs + i;
	  section_offset = reloc_sec->output_section->vma
	    + reloc_sec->output_offset;
	  addr = rel->r_offset;
	  index = ELF32_R_SYM (rel->r_info);
	  if (bed->s->arch_size == 64)
	    index >>= 24;
	  if (index == STN_UNDEF)
	    continue;
	  if (index < locsymcount)
	    {
	      sym = finfo->internal_syms + index;
	      if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) &&
		  (ELF_ST_TYPE (sym->st_info) != STT_SRELC))
		continue;
	      sym_name = bfd_elf_string_from_elf_section
		(input_bfd, symtab_hdr->sh_link, sym->st_name);
	      signed_p = (ELF_ST_TYPE (sym->st_info) == STT_SRELC);
	    }
	  else
	    {
	      struct elf_link_hash_entry * h;
	      if (elf_bad_symtab (input_bfd))
		continue;
	      h = sym_hashes [index - locsymcount];
	      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;
	      if (h->type != STT_RELC && h->type != STT_SRELC)
		continue;
	      signed_p = (h->type == STT_SRELC);
	      sym_name = (char *) h->root.root.string;
	    }
#ifdef DEBUG
	  printf ("Encountered a complex symbol!");
	  printf (" (input_bfd %s, section %s, reloc %ld\n",
		  input_bfd->filename, reloc_sec->name, i);
	  printf (" symbol: idx  %8.8lx, name %s\n",
		  index, sym_name);
	  printf (" reloc : info %8.8lx, addr %8.8lx\n",
		  rel->r_info, addr);
	  printf (" Evaluating '%s' ...\n ", sym_name);
#endif
	  if (eval_symbol (& result, sym_name, & sym_name, input_bfd, 
			   finfo, addr, section_offset, locsymcount,
			   signed_p))
	    set_symbol_value (input_bfd, finfo, index, result);
	  else
	    result = FALSE;
	}
      if (internal_relocs != elf_section_data (reloc_sec)->relocs)
	free (internal_relocs);
    }
  return result;
}
static bfd_boolean evaluate_complex_relocation_symbols ( bfd * input_bfd , struct elf_final_link_info * finfo , size_t locsymcount ) { const struct elf_backend_data * bed ; Elf_Internal_Shdr * symtab_hdr ; struct elf_link_hash_entry * * sym_hashes ; asection * reloc_sec ; bfd_boolean result = TRUE ; if ( finfo -> info -> relocatable ) return TRUE ; symtab_hdr = & elf_tdata ( input_bfd ) -> symtab_hdr ; sym_hashes = elf_sym_hashes ( input_bfd ) ; bed = get_elf_backend_data ( input_bfd ) ; for ( reloc_sec = input_bfd -> sections ; reloc_sec ; reloc_sec = reloc_sec -> next ) { Elf_Internal_Rela * internal_relocs ; unsigned long i ; if ( ! reloc_sec -> linker_mark ) continue ; if ( ( reloc_sec -> flags & SEC_RELOC ) == 0 ) continue ; if ( reloc_sec -> reloc_count == 0 ) continue ; internal_relocs = _bfd_elf_link_read_relocs ( input_bfd , reloc_sec , NULL , ( Elf_Internal_Rela * ) NULL , FALSE ) ; if ( internal_relocs == NULL ) continue ; for ( i = reloc_sec -> reloc_count ; i -- ; ) { Elf_Internal_Rela * rel ; char * sym_name ; bfd_vma index ; Elf_Internal_Sym * sym ; bfd_vma result ; bfd_vma section_offset ; bfd_vma addr ; int signed_p = 0 ; rel = internal_relocs + i ; section_offset = reloc_sec -> output_section -> vma + reloc_sec -> output_offset ; addr = rel -> r_offset ; index = ELF32_R_SYM ( rel -> r_info ) ; if ( bed -> s -> arch_size == 64 ) index >>= 24 ; if ( index == STN_UNDEF ) continue ; if ( index < locsymcount ) { sym = finfo -> internal_syms + index ; if ( ( ELF_ST_TYPE ( sym -> st_info ) != STT_RELC ) && ( ELF_ST_TYPE ( sym -> st_info ) != STT_SRELC ) ) continue ; sym_name = bfd_elf_string_from_elf_section ( input_bfd , symtab_hdr -> sh_link , sym -> st_name ) ; signed_p = ( ELF_ST_TYPE ( sym -> st_info ) == STT_SRELC ) ; } else { struct elf_link_hash_entry * h ; if ( elf_bad_symtab ( input_bfd ) ) continue ; h = sym_hashes [ index - locsymcount ] ; 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 ; if ( h -> type != STT_RELC && h -> type != STT_SRELC ) continue ; signed_p = ( h -> type == STT_SRELC ) ; sym_name = ( char * ) h -> root . root . string ; } #ifdef DEBUG printf ( " " ) ; printf ( " \n " , input_bfd -> filename , reloc_sec -> name , i ) ; printf ( " \n " , index , sym_name ) ; printf ( " \n " , rel -> r_info , addr ) ; printf ( " \n " , sym_name ) ; #endif if ( eval_symbol ( & result , sym_name , & sym_name , input_bfd , finfo , addr , section_offset , locsymcount , signed_p ) ) set_symbol_value ( input_bfd , finfo , index , result ) ; else result = FALSE ; } if ( internal_relocs != elf_section_data ( reloc_sec ) -> relocs ) free ( internal_relocs ) ; } return result ; }
Entry point to evaluator, called from elf_link_input_bfd.
Entry point to evaluator called from elf_link_input_bfd .
/* For each section, we're going to check and see if it has any
     complex relocations, and we're going to evaluate any of them
     we can.  */ /* This section was omitted from the link.  */ /* Only process sections containing relocs.  */ /* Read in the relocs for this section.  */ /* The symbol is local.  */ /* We're only processing STT_RELC or STT_SRELC type symbols.  */ /* The symbol is global.  */ /* Symbol evaluated OK.  Update to absolute value.  */ /* If nothing went wrong, then we adjusted 
     everything we wanted to adjust.  */