FreeBSD/contrib/binutils/gas/config/tc-arm.c
/* Translate internal representation of relocation info to BFD target
   format.  */
Translate internal representation of relocation info to BFD target
format.
Translate internal representation of relocation info to BFD target format .
arelent *
tc_gen_reloc (asection *section, fixS *fixp)
{
  arelent * reloc;
  bfd_reloc_code_real_type code;
  reloc = xmalloc (sizeof (arelent));
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  if (fixp->fx_pcrel)
    {
      if (section->use_rela_p)
	fixp->fx_offset -= md_pcrel_from_section (fixp, section);
      else
	fixp->fx_offset = reloc->address;
    }
  reloc->addend = fixp->fx_offset;
  switch (fixp->fx_r_type)
    {
    case BFD_RELOC_8:
      if (fixp->fx_pcrel)
	{
	  code = BFD_RELOC_8_PCREL;
	  break;
	}
    case BFD_RELOC_16:
      if (fixp->fx_pcrel)
	{
	  code = BFD_RELOC_16_PCREL;
	  break;
	}
    case BFD_RELOC_32:
      if (fixp->fx_pcrel)
	{
	  code = BFD_RELOC_32_PCREL;
	  break;
	}
    case BFD_RELOC_ARM_MOVW:
      if (fixp->fx_pcrel)
	{
	  code = BFD_RELOC_ARM_MOVW_PCREL;
	  break;
	}
    case BFD_RELOC_ARM_MOVT:
      if (fixp->fx_pcrel)
	{
	  code = BFD_RELOC_ARM_MOVT_PCREL;
	  break;
	}
    case BFD_RELOC_ARM_THUMB_MOVW:
      if (fixp->fx_pcrel)
	{
	  code = BFD_RELOC_ARM_THUMB_MOVW_PCREL;
	  break;
	}
    case BFD_RELOC_ARM_THUMB_MOVT:
      if (fixp->fx_pcrel)
	{
	  code = BFD_RELOC_ARM_THUMB_MOVT_PCREL;
	  break;
	}
    case BFD_RELOC_NONE:
    case BFD_RELOC_ARM_PCREL_BRANCH:
    case BFD_RELOC_ARM_PCREL_BLX:
    case BFD_RELOC_RVA:
    case BFD_RELOC_THUMB_PCREL_BRANCH7:
    case BFD_RELOC_THUMB_PCREL_BRANCH9:
    case BFD_RELOC_THUMB_PCREL_BRANCH12:
    case BFD_RELOC_THUMB_PCREL_BRANCH20:
    case BFD_RELOC_THUMB_PCREL_BRANCH23:
    case BFD_RELOC_THUMB_PCREL_BRANCH25:
    case BFD_RELOC_THUMB_PCREL_BLX:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_INHERIT:
#ifdef TE_PE
    case BFD_RELOC_32_SECREL:
#endif
      code = fixp->fx_r_type;
      break;
    case BFD_RELOC_ARM_LITERAL:
    case BFD_RELOC_ARM_HWLITERAL:
      as_bad_where (fixp->fx_file, fixp->fx_line,
		    _("literal referenced across section boundary"));
      return NULL;
#ifdef OBJ_ELF
    case BFD_RELOC_ARM_GOT32:
    case BFD_RELOC_ARM_GOTOFF:
    case BFD_RELOC_ARM_PLT32:
    case BFD_RELOC_ARM_TARGET1:
    case BFD_RELOC_ARM_ROSEGREL32:
    case BFD_RELOC_ARM_SBREL32:
    case BFD_RELOC_ARM_PREL31:
    case BFD_RELOC_ARM_TARGET2:
    case BFD_RELOC_ARM_TLS_LE32:
    case BFD_RELOC_ARM_TLS_LDO32:
    case BFD_RELOC_ARM_PCREL_CALL:
    case BFD_RELOC_ARM_PCREL_JUMP:
    case BFD_RELOC_ARM_ALU_PC_G0_NC:
    case BFD_RELOC_ARM_ALU_PC_G0:
    case BFD_RELOC_ARM_ALU_PC_G1_NC:
    case BFD_RELOC_ARM_ALU_PC_G1:
    case BFD_RELOC_ARM_ALU_PC_G2:
    case BFD_RELOC_ARM_LDR_PC_G0:
    case BFD_RELOC_ARM_LDR_PC_G1:
    case BFD_RELOC_ARM_LDR_PC_G2:
    case BFD_RELOC_ARM_LDRS_PC_G0:
    case BFD_RELOC_ARM_LDRS_PC_G1:
    case BFD_RELOC_ARM_LDRS_PC_G2:
    case BFD_RELOC_ARM_LDC_PC_G0:
    case BFD_RELOC_ARM_LDC_PC_G1:
    case BFD_RELOC_ARM_LDC_PC_G2:
    case BFD_RELOC_ARM_ALU_SB_G0_NC:
    case BFD_RELOC_ARM_ALU_SB_G0:
    case BFD_RELOC_ARM_ALU_SB_G1_NC:
    case BFD_RELOC_ARM_ALU_SB_G1:
    case BFD_RELOC_ARM_ALU_SB_G2:
    case BFD_RELOC_ARM_LDR_SB_G0:
    case BFD_RELOC_ARM_LDR_SB_G1:
    case BFD_RELOC_ARM_LDR_SB_G2:
    case BFD_RELOC_ARM_LDRS_SB_G0:
    case BFD_RELOC_ARM_LDRS_SB_G1:
    case BFD_RELOC_ARM_LDRS_SB_G2:
    case BFD_RELOC_ARM_LDC_SB_G0:
    case BFD_RELOC_ARM_LDC_SB_G1:
    case BFD_RELOC_ARM_LDC_SB_G2:
      code = fixp->fx_r_type;
      break;
    case BFD_RELOC_ARM_TLS_GD32:
    case BFD_RELOC_ARM_TLS_IE32:
    case BFD_RELOC_ARM_TLS_LDM32:
      if (!S_IS_COMMON (fixp->fx_addsy))
	reloc->addend -= (*reloc->sym_ptr_ptr)->value;
      code = fixp->fx_r_type;
      break;
#endif
    case BFD_RELOC_ARM_IMMEDIATE:
      as_bad_where (fixp->fx_file, fixp->fx_line,
		    _("internal relocation (type: IMMEDIATE) not fixed up"));
      return NULL;
    case BFD_RELOC_ARM_ADRL_IMMEDIATE:
      as_bad_where (fixp->fx_file, fixp->fx_line,
		    _("ADRL used for a symbol not defined in the same file"));
      return NULL;
    case BFD_RELOC_ARM_OFFSET_IMM:
      if (section->use_rela_p)
	{
	  code = fixp->fx_r_type;
	  break;
	}
      if (fixp->fx_addsy != NULL
	  && !S_IS_DEFINED (fixp->fx_addsy)
	  && S_IS_LOCAL (fixp->fx_addsy))
	{
	  as_bad_where (fixp->fx_file, fixp->fx_line,
			_("undefined local label `%s'"),
			S_GET_NAME (fixp->fx_addsy));
	  return NULL;
	}
      as_bad_where (fixp->fx_file, fixp->fx_line,
		    _("internal_relocation (type: OFFSET_IMM) not fixed up"));
      return NULL;
    default:
      {
	char * type;
	switch (fixp->fx_r_type)
	  {
	  case BFD_RELOC_NONE:		   type = "NONE";	  break;
	  case BFD_RELOC_ARM_OFFSET_IMM8:  type = "OFFSET_IMM8";  break;
	  case BFD_RELOC_ARM_SHIFT_IMM:	   type = "SHIFT_IMM";	  break;
	  case BFD_RELOC_ARM_SMC:	   type = "SMC";	  break;
	  case BFD_RELOC_ARM_SWI:	   type = "SWI";	  break;
	  case BFD_RELOC_ARM_MULTI:	   type = "MULTI";	  break;
	  case BFD_RELOC_ARM_CP_OFF_IMM:   type = "CP_OFF_IMM";	  break;
	  case BFD_RELOC_ARM_T32_CP_OFF_IMM: type = "T32_CP_OFF_IMM"; break;
	  case BFD_RELOC_ARM_THUMB_ADD:	   type = "THUMB_ADD";	  break;
	  case BFD_RELOC_ARM_THUMB_SHIFT:  type = "THUMB_SHIFT";  break;
	  case BFD_RELOC_ARM_THUMB_IMM:	   type = "THUMB_IMM";	  break;
	  case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
	  default:			   type = _("<unknown>"); break;
	  }
	as_bad_where (fixp->fx_file, fixp->fx_line,
		      _("cannot represent %s relocation in this object file format"),
		      type);
	return NULL;
      }
    }
#ifdef OBJ_ELF
  if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
      && GOT_symbol
      && fixp->fx_addsy == GOT_symbol)
    {
      code = BFD_RELOC_ARM_GOTPC;
      reloc->addend = fixp->fx_offset = reloc->address;
    }
#endif
  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
  if (reloc->howto == NULL)
    {
      as_bad_where (fixp->fx_file, fixp->fx_line,
		    _("cannot represent %s relocation in this object file format"),
		    bfd_get_reloc_code_name (code));
      return NULL;
    }
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    reloc->address = fixp->fx_offset;
  return reloc;
}
arelent * tc_gen_reloc ( asection * section , fixS * fixp ) { arelent * reloc ; bfd_reloc_code_real_type code ; reloc = xmalloc ( sizeof ( arelent ) ) ; reloc -> sym_ptr_ptr = xmalloc ( sizeof ( asymbol * ) ) ; * reloc -> sym_ptr_ptr = symbol_get_bfdsym ( fixp -> fx_addsy ) ; reloc -> address = fixp -> fx_frag -> fr_address + fixp -> fx_where ; if ( fixp -> fx_pcrel ) { if ( section -> use_rela_p ) fixp -> fx_offset -= md_pcrel_from_section ( fixp , section ) ; else fixp -> fx_offset = reloc -> address ; } reloc -> addend = fixp -> fx_offset ; switch ( fixp -> fx_r_type ) { case BFD_RELOC_8 : if ( fixp -> fx_pcrel ) { code = BFD_RELOC_8_PCREL ; break ; } case BFD_RELOC_16 : if ( fixp -> fx_pcrel ) { code = BFD_RELOC_16_PCREL ; break ; } case BFD_RELOC_32 : if ( fixp -> fx_pcrel ) { code = BFD_RELOC_32_PCREL ; break ; } case BFD_RELOC_ARM_MOVW : if ( fixp -> fx_pcrel ) { code = BFD_RELOC_ARM_MOVW_PCREL ; break ; } case BFD_RELOC_ARM_MOVT : if ( fixp -> fx_pcrel ) { code = BFD_RELOC_ARM_MOVT_PCREL ; break ; } case BFD_RELOC_ARM_THUMB_MOVW : if ( fixp -> fx_pcrel ) { code = BFD_RELOC_ARM_THUMB_MOVW_PCREL ; break ; } case BFD_RELOC_ARM_THUMB_MOVT : if ( fixp -> fx_pcrel ) { code = BFD_RELOC_ARM_THUMB_MOVT_PCREL ; break ; } case BFD_RELOC_NONE : case BFD_RELOC_ARM_PCREL_BRANCH : case BFD_RELOC_ARM_PCREL_BLX : case BFD_RELOC_RVA : case BFD_RELOC_THUMB_PCREL_BRANCH7 : case BFD_RELOC_THUMB_PCREL_BRANCH9 : case BFD_RELOC_THUMB_PCREL_BRANCH12 : case BFD_RELOC_THUMB_PCREL_BRANCH20 : case BFD_RELOC_THUMB_PCREL_BRANCH23 : case BFD_RELOC_THUMB_PCREL_BRANCH25 : case BFD_RELOC_THUMB_PCREL_BLX : case BFD_RELOC_VTABLE_ENTRY : case BFD_RELOC_VTABLE_INHERIT : #ifdef TE_PE case BFD_RELOC_32_SECREL : #endif code = fixp -> fx_r_type ; break ; case BFD_RELOC_ARM_LITERAL : case BFD_RELOC_ARM_HWLITERAL : as_bad_where ( fixp -> fx_file , fixp -> fx_line , _ ( " " ) ) ; return NULL ; #ifdef OBJ_ELF case BFD_RELOC_ARM_GOT32 : case BFD_RELOC_ARM_GOTOFF : case BFD_RELOC_ARM_PLT32 : case BFD_RELOC_ARM_TARGET1 : case BFD_RELOC_ARM_ROSEGREL32 : case BFD_RELOC_ARM_SBREL32 : case BFD_RELOC_ARM_PREL31 : case BFD_RELOC_ARM_TARGET2 : case BFD_RELOC_ARM_TLS_LE32 : case BFD_RELOC_ARM_TLS_LDO32 : case BFD_RELOC_ARM_PCREL_CALL : case BFD_RELOC_ARM_PCREL_JUMP : case BFD_RELOC_ARM_ALU_PC_G0_NC : case BFD_RELOC_ARM_ALU_PC_G0 : case BFD_RELOC_ARM_ALU_PC_G1_NC : case BFD_RELOC_ARM_ALU_PC_G1 : case BFD_RELOC_ARM_ALU_PC_G2 : case BFD_RELOC_ARM_LDR_PC_G0 : case BFD_RELOC_ARM_LDR_PC_G1 : case BFD_RELOC_ARM_LDR_PC_G2 : case BFD_RELOC_ARM_LDRS_PC_G0 : case BFD_RELOC_ARM_LDRS_PC_G1 : case BFD_RELOC_ARM_LDRS_PC_G2 : case BFD_RELOC_ARM_LDC_PC_G0 : case BFD_RELOC_ARM_LDC_PC_G1 : case BFD_RELOC_ARM_LDC_PC_G2 : case BFD_RELOC_ARM_ALU_SB_G0_NC : case BFD_RELOC_ARM_ALU_SB_G0 : case BFD_RELOC_ARM_ALU_SB_G1_NC : case BFD_RELOC_ARM_ALU_SB_G1 : case BFD_RELOC_ARM_ALU_SB_G2 : case BFD_RELOC_ARM_LDR_SB_G0 : case BFD_RELOC_ARM_LDR_SB_G1 : case BFD_RELOC_ARM_LDR_SB_G2 : case BFD_RELOC_ARM_LDRS_SB_G0 : case BFD_RELOC_ARM_LDRS_SB_G1 : case BFD_RELOC_ARM_LDRS_SB_G2 : case BFD_RELOC_ARM_LDC_SB_G0 : case BFD_RELOC_ARM_LDC_SB_G1 : case BFD_RELOC_ARM_LDC_SB_G2 : code = fixp -> fx_r_type ; break ; case BFD_RELOC_ARM_TLS_GD32 : case BFD_RELOC_ARM_TLS_IE32 : case BFD_RELOC_ARM_TLS_LDM32 : if ( ! S_IS_COMMON ( fixp -> fx_addsy ) ) reloc -> addend -= ( * reloc -> sym_ptr_ptr ) -> value ; code = fixp -> fx_r_type ; break ; #endif case BFD_RELOC_ARM_IMMEDIATE : as_bad_where ( fixp -> fx_file , fixp -> fx_line , _ ( " " ) ) ; return NULL ; case BFD_RELOC_ARM_ADRL_IMMEDIATE : as_bad_where ( fixp -> fx_file , fixp -> fx_line , _ ( " " ) ) ; return NULL ; case BFD_RELOC_ARM_OFFSET_IMM : if ( section -> use_rela_p ) { code = fixp -> fx_r_type ; break ; } if ( fixp -> fx_addsy != NULL && ! S_IS_DEFINED ( fixp -> fx_addsy ) && S_IS_LOCAL ( fixp -> fx_addsy ) ) { as_bad_where ( fixp -> fx_file , fixp -> fx_line , _ ( " " ) , S_GET_NAME ( fixp -> fx_addsy ) ) ; return NULL ; } as_bad_where ( fixp -> fx_file , fixp -> fx_line , _ ( " " ) ) ; return NULL ; default : { char * type ; switch ( fixp -> fx_r_type ) { case BFD_RELOC_NONE : type = " " ; break ; case BFD_RELOC_ARM_OFFSET_IMM8 : type = " " ; break ; case BFD_RELOC_ARM_SHIFT_IMM : type = " " ; break ; case BFD_RELOC_ARM_SMC : type = " " ; break ; case BFD_RELOC_ARM_SWI : type = " " ; break ; case BFD_RELOC_ARM_MULTI : type = " " ; break ; case BFD_RELOC_ARM_CP_OFF_IMM : type = " " ; break ; case BFD_RELOC_ARM_T32_CP_OFF_IMM : type = " " ; break ; case BFD_RELOC_ARM_THUMB_ADD : type = " " ; break ; case BFD_RELOC_ARM_THUMB_SHIFT : type = " " ; break ; case BFD_RELOC_ARM_THUMB_IMM : type = " " ; break ; case BFD_RELOC_ARM_THUMB_OFFSET : type = " " ; break ; default : type = _ ( " " ) ; break ; } as_bad_where ( fixp -> fx_file , fixp -> fx_line , _ ( " " ) , type ) ; return NULL ; } } #ifdef OBJ_ELF if ( ( code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32 ) && GOT_symbol && fixp -> fx_addsy == GOT_symbol ) { code = BFD_RELOC_ARM_GOTPC ; reloc -> addend = fixp -> fx_offset = reloc -> address ; } #endif reloc -> howto = bfd_reloc_type_lookup ( stdoutput , code ) ; if ( reloc -> howto == NULL ) { as_bad_where ( fixp -> fx_file , fixp -> fx_line , _ ( " " ) , bfd_get_reloc_code_name ( code ) ) ; return NULL ; } if ( fixp -> fx_r_type == BFD_RELOC_VTABLE_ENTRY ) reloc -> address = fixp -> fx_offset ; return reloc ; }
Translate internal representation of relocation info to BFD target
format.
Translate internal representation of relocation info to BFD target format .
/* If this is called then the a literal has
	 been referenced across a section boundary.  */ /* BFD will include the symbol's address in the addend.
	 But we don't want that, so subtract it out again here.  */ /* HACK: Since arm ELF uses Rel instead of Rela, encode the
     vtable entry to be used in the relocation's section offset.  */