FreeBSD/contrib/binutils/bfd/elflink.c
/* Generate a reloc when linking an ELF file.  This is a reloc
   requested by the linker, and does not come from any input file.  This
   is used to build constructor and destructor tables when linking
   with -Ur.  */
Generate a reloc when linking an ELF file.  This is a reloc
requested by the linker, and does not come from any input file.  This
is used to build constructor and destructor tables when linking
with -Ur.
Generate a reloc when linking an ELF file . This is a reloc requested by the linker and does not come from any input file . This is used to build constructor and destructor tables when linking with - Ur .
static bfd_boolean
elf_reloc_link_order (bfd *output_bfd,
		      struct bfd_link_info *info,
		      asection *output_section,
		      struct bfd_link_order *link_order)
{
  reloc_howto_type *howto;
  long indx;
  bfd_vma offset;
  bfd_vma addend;
  struct elf_link_hash_entry **rel_hash_ptr;
  Elf_Internal_Shdr *rel_hdr;
  const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
  Elf_Internal_Rela irel[MAX_INT_RELS_PER_EXT_REL];
  bfd_byte *erel;
  unsigned int i;
  howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
  if (howto == NULL)
    {
      bfd_set_error (bfd_error_bad_value);
      return FALSE;
    }
  addend = link_order->u.reloc.p->addend;
  rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
		  + elf_section_data (output_section)->rel_count
		  + elf_section_data (output_section)->rel_count2);
  if (link_order->type == bfd_section_reloc_link_order)
    {
      indx = link_order->u.reloc.p->u.section->target_index;
      BFD_ASSERT (indx != 0);
      *rel_hash_ptr = NULL;
    }
  else
    {
      struct elf_link_hash_entry *h;
      h = ((struct elf_link_hash_entry *)
	   bfd_wrapped_link_hash_lookup (output_bfd, info,
					 link_order->u.reloc.p->u.name,
					 FALSE, FALSE, TRUE));
      if (h != NULL
	  && (h->root.type == bfd_link_hash_defined
	      || h->root.type == bfd_link_hash_defweak))
	{
	  asection *section;
	  section = h->root.u.def.section;
	  indx = section->output_section->target_index;
	  *rel_hash_ptr = NULL;
	  addend += section->output_section->vma + section->output_offset;
	}
      else if (h != NULL)
	{
	  h->indx = -2;
	  *rel_hash_ptr = h;
	  indx = 0;
	}
      else
	{
	  if (! ((*info->callbacks->unattached_reloc)
		 (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
	    return FALSE;
	  indx = 0;
	}
    }
  if (howto->partial_inplace && addend != 0)
    {
      bfd_size_type size;
      bfd_reloc_status_type rstat;
      bfd_byte *buf;
      bfd_boolean ok;
      const char *sym_name;
      size = bfd_get_reloc_size (howto);
      buf = bfd_zmalloc (size);
      if (buf == NULL)
	return FALSE;
      rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
      switch (rstat)
	{
	case bfd_reloc_ok:
	  break;
	default:
	case bfd_reloc_outofrange:
	  abort ();
	case bfd_reloc_overflow:
	  if (link_order->type == bfd_section_reloc_link_order)
	    sym_name = bfd_section_name (output_bfd,
					 link_order->u.reloc.p->u.section);
	  else
	    sym_name = link_order->u.reloc.p->u.name;
	  if (! ((*info->callbacks->reloc_overflow)
		 (info, NULL, sym_name, howto->name, addend, NULL,
		  NULL, (bfd_vma) 0)))
	    {
	      free (buf);
	      return FALSE;
	    }
	  break;
	}
      ok = bfd_set_section_contents (output_bfd, output_section, buf,
				     link_order->offset, size);
      free (buf);
      if (! ok)
	return FALSE;
    }
  offset = link_order->offset;
  if (! info->relocatable)
    offset += output_section->vma;
  for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
    {
      irel[i].r_offset = offset;
      irel[i].r_info = 0;
      irel[i].r_addend = 0;
    }
  if (bed->s->arch_size == 32)
    irel[0].r_info = ELF32_R_INFO (indx, howto->type);
  else
    irel[0].r_info = ELF64_R_INFO (indx, howto->type);
  rel_hdr = &elf_section_data (output_section)->rel_hdr;
  erel = rel_hdr->contents;
  if (rel_hdr->sh_type == SHT_REL)
    {
      erel += (elf_section_data (output_section)->rel_count
	       * bed->s->sizeof_rel);
      (*bed->s->swap_reloc_out) (output_bfd, irel, erel);
    }
  else
    {
      irel[0].r_addend = addend;
      erel += (elf_section_data (output_section)->rel_count
	       * bed->s->sizeof_rela);
      (*bed->s->swap_reloca_out) (output_bfd, irel, erel);
    }
  ++elf_section_data (output_section)->rel_count;
  return TRUE;
}
static bfd_boolean elf_reloc_link_order ( bfd * output_bfd , struct bfd_link_info * info , asection * output_section , struct bfd_link_order * link_order ) { reloc_howto_type * howto ; long indx ; bfd_vma offset ; bfd_vma addend ; struct elf_link_hash_entry * * rel_hash_ptr ; Elf_Internal_Shdr * rel_hdr ; const struct elf_backend_data * bed = get_elf_backend_data ( output_bfd ) ; Elf_Internal_Rela irel [ MAX_INT_RELS_PER_EXT_REL ] ; bfd_byte * erel ; unsigned int i ; howto = bfd_reloc_type_lookup ( output_bfd , link_order -> u . reloc . p -> reloc ) ; if ( howto == NULL ) { bfd_set_error ( bfd_error_bad_value ) ; return FALSE ; } addend = link_order -> u . reloc . p -> addend ; rel_hash_ptr = ( elf_section_data ( output_section ) -> rel_hashes + elf_section_data ( output_section ) -> rel_count + elf_section_data ( output_section ) -> rel_count2 ) ; if ( link_order -> type == bfd_section_reloc_link_order ) { indx = link_order -> u . reloc . p -> u . section -> target_index ; BFD_ASSERT ( indx != 0 ) ; * rel_hash_ptr = NULL ; } else { struct elf_link_hash_entry * h ; h = ( ( struct elf_link_hash_entry * ) bfd_wrapped_link_hash_lookup ( output_bfd , info , link_order -> u . reloc . p -> u . name , FALSE , FALSE , TRUE ) ) ; if ( h != NULL && ( h -> root . type == bfd_link_hash_defined || h -> root . type == bfd_link_hash_defweak ) ) { asection * section ; section = h -> root . u . def . section ; indx = section -> output_section -> target_index ; * rel_hash_ptr = NULL ; addend += section -> output_section -> vma + section -> output_offset ; } else if ( h != NULL ) { h -> indx = -2 ; * rel_hash_ptr = h ; indx = 0 ; } else { if ( ! ( ( * info -> callbacks -> unattached_reloc ) ( info , link_order -> u . reloc . p -> u . name , NULL , NULL , 0 ) ) ) return FALSE ; indx = 0 ; } } if ( howto -> partial_inplace && addend != 0 ) { bfd_size_type size ; bfd_reloc_status_type rstat ; bfd_byte * buf ; bfd_boolean ok ; const char * sym_name ; size = bfd_get_reloc_size ( howto ) ; buf = bfd_zmalloc ( size ) ; if ( buf == NULL ) return FALSE ; rstat = _bfd_relocate_contents ( howto , output_bfd , addend , buf ) ; switch ( rstat ) { case bfd_reloc_ok : break ; default : case bfd_reloc_outofrange : abort ( ) ; case bfd_reloc_overflow : if ( link_order -> type == bfd_section_reloc_link_order ) sym_name = bfd_section_name ( output_bfd , link_order -> u . reloc . p -> u . section ) ; else sym_name = link_order -> u . reloc . p -> u . name ; if ( ! ( ( * info -> callbacks -> reloc_overflow ) ( info , NULL , sym_name , howto -> name , addend , NULL , NULL , ( bfd_vma ) 0 ) ) ) { free ( buf ) ; return FALSE ; } break ; } ok = bfd_set_section_contents ( output_bfd , output_section , buf , link_order -> offset , size ) ; free ( buf ) ; if ( ! ok ) return FALSE ; } offset = link_order -> offset ; if ( ! info -> relocatable ) offset += output_section -> vma ; for ( i = 0 ; i < bed -> s -> int_rels_per_ext_rel ; i ++ ) { irel [ i ] . r_offset = offset ; irel [ i ] . r_info = 0 ; irel [ i ] . r_addend = 0 ; } if ( bed -> s -> arch_size == 32 ) irel [ 0 ] . r_info = ELF32_R_INFO ( indx , howto -> type ) ; else irel [ 0 ] . r_info = ELF64_R_INFO ( indx , howto -> type ) ; rel_hdr = & elf_section_data ( output_section ) -> rel_hdr ; erel = rel_hdr -> contents ; if ( rel_hdr -> sh_type == SHT_REL ) { erel += ( elf_section_data ( output_section ) -> rel_count * bed -> s -> sizeof_rel ) ; ( * bed -> s -> swap_reloc_out ) ( output_bfd , irel , erel ) ; } else { irel [ 0 ] . r_addend = addend ; erel += ( elf_section_data ( output_section ) -> rel_count * bed -> s -> sizeof_rela ) ; ( * bed -> s -> swap_reloca_out ) ( output_bfd , irel , erel ) ; } ++ elf_section_data ( output_section ) -> rel_count ; return TRUE ; }
Generate a reloc when linking an ELF file.
Generate a reloc when linking an ELF file .
/* Figure out the symbol index.  */ /* Treat a reloc against a defined symbol as though it were
	 actually against the section.  */ /* It seems that we ought to add the symbol value to the
	     addend here, but in practice it has already been added
	     because it was passed to constructor_callback.  */ /* Setting the index to -2 tells elf_link_output_extsym that
	     this symbol is used by a reloc.  */ /* If this is an inplace reloc, we must write the addend into the
     object file.  */ /* The address of a reloc is relative to the section in a
     relocatable file, and is a virtual address in an executable
     file.  */