コード例 #1
0
ファイル: PPCELFObjectWriter.cpp プロジェクト: 8l/SPIRV-LLVM
unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel) const {
  MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);

  // determine the type of the relocation
  unsigned Type;
  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    default:
      llvm_unreachable("Unimplemented");
    case PPC::fixup_ppc_br24:
    case PPC::fixup_ppc_br24abs:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_REL24;
        break;
      case MCSymbolRefExpr::VK_PLT:
        Type = ELF::R_PPC_PLTREL24;
        break;
      case MCSymbolRefExpr::VK_PPC_LOCAL:
        Type = ELF::R_PPC_LOCAL24PC;
        break;
      }
      break;
    case PPC::fixup_ppc_brcond14:
    case PPC::fixup_ppc_brcond14abs:
      Type = ELF::R_PPC_REL14;
      break;
    case PPC::fixup_ppc_half16:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_REL16;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = ELF::R_PPC_REL16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_HI:
        Type = ELF::R_PPC_REL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_HA:
        Type = ELF::R_PPC_REL16_HA;
        break;
      }
      break;
    case FK_Data_4:
    case FK_PCRel_4:
      Type = ELF::R_PPC_REL32;
      break;
    case FK_Data_8:
    case FK_PCRel_8:
      Type = ELF::R_PPC64_REL64;
      break;
    }
  } else {
    switch ((unsigned)Fixup.getKind()) {
      default: llvm_unreachable("invalid fixup kind!");
    case PPC::fixup_ppc_br24abs:
      Type = ELF::R_PPC_ADDR24;
      break;
    case PPC::fixup_ppc_brcond14abs:
      Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
      break;
    case PPC::fixup_ppc_half16:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_ADDR16;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = ELF::R_PPC_ADDR16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_HI:
        Type = ELF::R_PPC_ADDR16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_HA:
        Type = ELF::R_PPC_ADDR16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHER:
        Type = ELF::R_PPC64_ADDR16_HIGHER;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHERA:
        Type = ELF::R_PPC64_ADDR16_HIGHERA;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHEST:
        Type = ELF::R_PPC64_ADDR16_HIGHEST;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHESTA:
        Type = ELF::R_PPC64_ADDR16_HIGHESTA;
        break;
      case MCSymbolRefExpr::VK_GOT:
        Type = ELF::R_PPC_GOT16;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_LO:
        Type = ELF::R_PPC_GOT16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_HI:
        Type = ELF::R_PPC_GOT16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_HA:
        Type = ELF::R_PPC_GOT16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC:
        Type = ELF::R_PPC64_TOC16;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_LO:
        Type = ELF::R_PPC64_TOC16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_HI:
        Type = ELF::R_PPC64_TOC16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_HA:
        Type = ELF::R_PPC64_TOC16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL:
        Type = ELF::R_PPC_TPREL16;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
        Type = ELF::R_PPC_TPREL16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HI:
        Type = ELF::R_PPC_TPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HA:
        Type = ELF::R_PPC_TPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
        Type = ELF::R_PPC64_TPREL16_HIGHER;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
        Type = ELF::R_PPC64_TPREL16_HIGHERA;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
        Type = ELF::R_PPC64_TPREL16_HIGHEST;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
        Type = ELF::R_PPC64_TPREL16_HIGHESTA;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL:
        Type = ELF::R_PPC64_DTPREL16;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
        Type = ELF::R_PPC64_DTPREL16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
        Type = ELF::R_PPC64_DTPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
        Type = ELF::R_PPC64_DTPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
        Type = ELF::R_PPC64_DTPREL16_HIGHER;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
        Type = ELF::R_PPC64_DTPREL16_HIGHERA;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
        Type = ELF::R_PPC64_DTPREL16_HIGHEST;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
        Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
        if (is64Bit())
          Type = ELF::R_PPC64_GOT_TLSGD16;
        else
          Type = ELF::R_PPC_GOT_TLSGD16;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
        Type = ELF::R_PPC64_GOT_TLSGD16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
        Type = ELF::R_PPC64_GOT_TLSGD16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
        Type = ELF::R_PPC64_GOT_TLSGD16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
        if (is64Bit())
          Type = ELF::R_PPC64_GOT_TLSLD16;
        else
          Type = ELF::R_PPC_GOT_TLSLD16;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
        Type = ELF::R_PPC64_GOT_TLSLD16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
        Type = ELF::R_PPC64_GOT_TLSLD16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
        Type = ELF::R_PPC64_GOT_TLSLD16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
        /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
        Type = ELF::R_PPC64_GOT_TPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
        /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
        Type = ELF::R_PPC64_GOT_TPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
        /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
        /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
        Type = ELF::R_PPC64_GOT_TPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
        Type = ELF::R_PPC64_GOT_DTPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
        Type = ELF::R_PPC64_GOT_DTPREL16_HA;
        break;
      }
      break;
    case PPC::fixup_ppc_half16ds:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC64_ADDR16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = ELF::R_PPC64_ADDR16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_GOT:
        Type = ELF::R_PPC64_GOT16_DS;
	break;
      case MCSymbolRefExpr::VK_PPC_GOT_LO:
        Type = ELF::R_PPC64_GOT16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC:
        Type = ELF::R_PPC64_TOC16_DS;
	break;
      case MCSymbolRefExpr::VK_PPC_TOC_LO:
        Type = ELF::R_PPC64_TOC16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL:
        Type = ELF::R_PPC64_TPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
        Type = ELF::R_PPC64_TPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL:
        Type = ELF::R_PPC64_DTPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
        Type = ELF::R_PPC64_DTPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
        Type = ELF::R_PPC64_GOT_TPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
        break;
      }
      break;
    case PPC::fixup_ppc_nofixup:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TLSGD:
        if (is64Bit())
          Type = ELF::R_PPC64_TLSGD;
        else
          Type = ELF::R_PPC_TLSGD;
        break;
      case MCSymbolRefExpr::VK_PPC_TLSLD:
        if (is64Bit())
          Type = ELF::R_PPC64_TLSLD;
        else
          Type = ELF::R_PPC_TLSLD;
        break;
      case MCSymbolRefExpr::VK_PPC_TLS:
        if (is64Bit())
          Type = ELF::R_PPC64_TLS;
        else
          Type = ELF::R_PPC_TLS;
        break;
      }
      break;
    case FK_Data_8:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TOCBASE:
        Type = ELF::R_PPC64_TOC;
        break;
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC64_ADDR64;
	break;
      case MCSymbolRefExpr::VK_PPC_DTPMOD:
        Type = ELF::R_PPC64_DTPMOD64;
	break;
      case MCSymbolRefExpr::VK_PPC_TPREL:
        Type = ELF::R_PPC64_TPREL64;
	break;
      case MCSymbolRefExpr::VK_PPC_DTPREL:
        Type = ELF::R_PPC64_DTPREL64;
	break;
      }
      break;
    case FK_Data_4:
      Type = ELF::R_PPC_ADDR32;
      break;
    case FK_Data_2:
      Type = ELF::R_PPC_ADDR16;
      break;
    }
  }
  return Type;
}
コード例 #2
0
ファイル: ARMAsmBackend.cpp プロジェクト: eaglexmw/llvm
static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
                                 MCContext *Ctx = NULL) {
  unsigned Kind = Fixup.getKind();
  switch (Kind) {
  default:
    llvm_unreachable("Unknown fixup kind!");
  case FK_Data_1:
  case FK_Data_2:
  case FK_Data_4:
    return Value;
  case ARM::fixup_arm_movt_hi16:
    Value >>= 16;
    // Fallthrough
  case ARM::fixup_arm_movw_lo16:
  case ARM::fixup_arm_movt_hi16_pcrel:
  case ARM::fixup_arm_movw_lo16_pcrel: {
    unsigned Hi4 = (Value & 0xF000) >> 12;
    unsigned Lo12 = Value & 0x0FFF;
    // inst{19-16} = Hi4;
    // inst{11-0} = Lo12;
    Value = (Hi4 << 16) | (Lo12);
    return Value;
  }
  case ARM::fixup_t2_movt_hi16:
    Value >>= 16;
    // Fallthrough
  case ARM::fixup_t2_movw_lo16:
  case ARM::fixup_t2_movt_hi16_pcrel:  //FIXME: Shouldn't this be shifted like
                                       // the other hi16 fixup?
  case ARM::fixup_t2_movw_lo16_pcrel: {
    unsigned Hi4 = (Value & 0xF000) >> 12;
    unsigned i = (Value & 0x800) >> 11;
    unsigned Mid3 = (Value & 0x700) >> 8;
    unsigned Lo8 = Value & 0x0FF;
    // inst{19-16} = Hi4;
    // inst{26} = i;
    // inst{14-12} = Mid3;
    // inst{7-0} = Lo8;
    Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
    uint64_t swapped = (Value & 0xFFFF0000) >> 16;
    swapped |= (Value & 0x0000FFFF) << 16;
    return swapped;
  }
  case ARM::fixup_arm_ldst_pcrel_12:
    // ARM PC-relative values are offset by 8.
    Value -= 4;
    // FALLTHROUGH
  case ARM::fixup_t2_ldst_pcrel_12: {
    // Offset by 4, adjusted by two due to the half-word ordering of thumb.
    Value -= 4;
    bool isAdd = true;
    if ((int64_t)Value < 0) {
      Value = -Value;
      isAdd = false;
    }
    if (Ctx && Value >= 4096)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    Value |= isAdd << 23;

    // Same addressing mode as fixup_arm_pcrel_10,
    // but with 16-bit halfwords swapped.
    if (Kind == ARM::fixup_t2_ldst_pcrel_12) {
      uint64_t swapped = (Value & 0xFFFF0000) >> 16;
      swapped |= (Value & 0x0000FFFF) << 16;
      return swapped;
    }

    return Value;
  }
  case ARM::fixup_thumb_adr_pcrel_10:
    return ((Value - 4) >> 2) & 0xff;
  case ARM::fixup_arm_adr_pcrel_12: {
    // ARM PC-relative values are offset by 8.
    Value -= 8;
    unsigned opc = 4; // bits {24-21}. Default to add: 0b0100
    if ((int64_t)Value < 0) {
      Value = -Value;
      opc = 2; // 0b0010
    }
    if (Ctx && ARM_AM::getSOImmVal(Value) == -1)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    // Encode the immediate and shift the opcode into place.
    return ARM_AM::getSOImmVal(Value) | (opc << 21);
  }

  case ARM::fixup_t2_adr_pcrel_12: {
    Value -= 4;
    unsigned opc = 0;
    if ((int64_t)Value < 0) {
      Value = -Value;
      opc = 5;
    }

    uint32_t out = (opc << 21);
    out |= (Value & 0x800) << 15;
    out |= (Value & 0x700) << 4;
    out |= (Value & 0x0FF);

    uint64_t swapped = (out & 0xFFFF0000) >> 16;
    swapped |= (out & 0x0000FFFF) << 16;
    return swapped;
  }

  case ARM::fixup_arm_condbranch:
  case ARM::fixup_arm_uncondbranch:
  case ARM::fixup_arm_uncondbl:
  case ARM::fixup_arm_condbl:
  case ARM::fixup_arm_blx:
    // These values don't encode the low two bits since they're always zero.
    // Offset by 8 just as above.
    return 0xffffff & ((Value - 8) >> 2);
  case ARM::fixup_t2_uncondbranch: {
    Value = Value - 4;
    Value >>= 1; // Low bit is not encoded.

    uint32_t out = 0;
    bool I =  Value & 0x800000;
    bool J1 = Value & 0x400000;
    bool J2 = Value & 0x200000;
    J1 ^= I;
    J2 ^= I;

    out |= I  << 26; // S bit
    out |= !J1 << 13; // J1 bit
    out |= !J2 << 11; // J2 bit
    out |= (Value & 0x1FF800)  << 5; // imm6 field
    out |= (Value & 0x0007FF);        // imm11 field

    uint64_t swapped = (out & 0xFFFF0000) >> 16;
    swapped |= (out & 0x0000FFFF) << 16;
    return swapped;
  }
  case ARM::fixup_t2_condbranch: {
    Value = Value - 4;
    Value >>= 1; // Low bit is not encoded.

    uint64_t out = 0;
    out |= (Value & 0x80000) << 7; // S bit
    out |= (Value & 0x40000) >> 7; // J2 bit
    out |= (Value & 0x20000) >> 4; // J1 bit
    out |= (Value & 0x1F800) << 5; // imm6 field
    out |= (Value & 0x007FF);      // imm11 field

    uint32_t swapped = (out & 0xFFFF0000) >> 16;
    swapped |= (out & 0x0000FFFF) << 16;
    return swapped;
  }
  case ARM::fixup_arm_thumb_bl: {
     // The value doesn't encode the low bit (always zero) and is offset by
     // four. The 32-bit immediate value is encoded as
     //   imm32 = SignExtend(S:I1:I2:imm10:imm11:0)
     // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
     // The value is encoded into disjoint bit positions in the destination
     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
     // J = either J1 or J2 bit
     //
     //   BL:  xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII
     //
     // Note that the halfwords are stored high first, low second; so we need
     // to transpose the fixup value here to map properly.
     uint32_t offset = (Value - 4) >> 1;
     uint32_t signBit = (offset & 0x800000) >> 23;
     uint32_t I1Bit = (offset & 0x400000) >> 22;
     uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
     uint32_t I2Bit = (offset & 0x200000) >> 21;
     uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
     uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
     uint32_t imm11Bits = (offset & 0x000007FF);

     uint32_t Binary = 0;
     uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits);
     uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
                           (uint16_t)imm11Bits);
     Binary |= secondHalf << 16;
     Binary |= firstHalf;
     return Binary;

  }
  case ARM::fixup_arm_thumb_blx: {
     // The value doesn't encode the low two bits (always zero) and is offset by
     // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as
     //   imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)
     // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
     // The value is encoded into disjoint bit positions in the destination
     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
     // J = either J1 or J2 bit, 0 = zero.
     //
     //   BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0
     //
     // Note that the halfwords are stored high first, low second; so we need
     // to transpose the fixup value here to map properly.
     uint32_t offset = (Value - 2) >> 2;
     uint32_t signBit = (offset & 0x400000) >> 22;
     uint32_t I1Bit = (offset & 0x200000) >> 21;
     uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
     uint32_t I2Bit = (offset & 0x100000) >> 20;
     uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
     uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
     uint32_t imm10LBits = (offset & 0x3FF);

     uint32_t Binary = 0;
     uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);
     uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
                           ((uint16_t)imm10LBits) << 1);
     Binary |= secondHalf << 16;
     Binary |= firstHalf;
     return Binary;
  }
  case ARM::fixup_arm_thumb_cp:
    // Offset by 4, and don't encode the low two bits. Two bytes of that
    // 'off by 4' is implicitly handled by the half-word ordering of the
    // Thumb encoding, so we only need to adjust by 2 here.
    return ((Value - 2) >> 2) & 0xff;
  case ARM::fixup_arm_thumb_cb: {
    // Offset by 4 and don't encode the lower bit, which is always 0.
    uint32_t Binary = (Value - 4) >> 1;
    return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
  }
  case ARM::fixup_arm_thumb_br:
    // Offset by 4 and don't encode the lower bit, which is always 0.
    return ((Value - 4) >> 1) & 0x7ff;
  case ARM::fixup_arm_thumb_bcc:
    // Offset by 4 and don't encode the lower bit, which is always 0.
    return ((Value - 4) >> 1) & 0xff;
  case ARM::fixup_arm_pcrel_10_unscaled: {
    Value = Value - 8; // ARM fixups offset by an additional word and don't
                       // need to adjust for the half-word ordering.
    bool isAdd = true;
    if ((int64_t)Value < 0) {
      Value = -Value;
      isAdd = false;
    }
    // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8].
    if (Ctx && Value >= 256)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    Value = (Value & 0xf) | ((Value & 0xf0) << 4);
    return Value | (isAdd << 23);
  }
  case ARM::fixup_arm_pcrel_10:
    Value = Value - 4; // ARM fixups offset by an additional word and don't
                       // need to adjust for the half-word ordering.
    // Fall through.
  case ARM::fixup_t2_pcrel_10: {
    // Offset by 4, adjusted by two due to the half-word ordering of thumb.
    Value = Value - 4;
    bool isAdd = true;
    if ((int64_t)Value < 0) {
      Value = -Value;
      isAdd = false;
    }
    // These values don't encode the low two bits since they're always zero.
    Value >>= 2;
    if (Ctx && Value >= 256)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    Value |= isAdd << 23;

    // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords
    // swapped.
    if (Kind == ARM::fixup_t2_pcrel_10) {
      uint32_t swapped = (Value & 0xFFFF0000) >> 16;
      swapped |= (Value & 0x0000FFFF) << 16;
      return swapped;
    }

    return Value;
  }
コード例 #3
0
ファイル: X86MachObjectWriter.cpp プロジェクト: Dagrol/llvm
void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
                                              const MCAssembler &Asm,
                                              const MCAsmLayout &Layout,
                                              const MCFragment *Fragment,
                                              const MCFixup &Fixup,
                                              MCValue Target,
                                              uint64_t &FixedValue) {
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());

  // If this is a 32-bit TLVP reloc it's handled a bit differently.
  if (Target.getSymA() &&
      Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
    RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
                         FixedValue);
    return;
  }

  // If this is a difference or a defined symbol plus an offset, then we need a
  // scattered relocation entry. Differences always require scattered
  // relocations.
  if (Target.getSymB()) {
    RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
                              Target, Log2Size, FixedValue);
    return;
  }

  // Get the symbol data, if any.
  const MCSymbolData *SD = nullptr;
  if (Target.getSymA())
    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());

  // If this is an internal relocation with an offset, it also needs a scattered
  // relocation entry.
  uint32_t Offset = Target.getConstant();
  if (IsPCRel)
    Offset += 1 << Log2Size;
  // Try to record the scattered relocation if needed. Fall back to non
  // scattered if necessary (see comments in RecordScatteredRelocation()
  // for details).
  if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) &&
      RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
                                Target, Log2Size, FixedValue))
    return;

  // See <reloc.h>.
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
  unsigned Index = 0;
  unsigned Type = 0;
  const MCSymbol *RelSymbol = nullptr;

  if (Target.isAbsolute()) { // constant
    // SymbolNum of 0 indicates the absolute section.
    //
    // FIXME: Currently, these are never generated (see code below). I cannot
    // find a case where they are actually emitted.
    Type = MachO::GENERIC_RELOC_VANILLA;
  } else {
    // Resolve constant variables.
    if (SD->getSymbol().isVariable()) {
      int64_t Res;
      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
            Res, Layout, Writer->getSectionAddressMap())) {
        FixedValue = Res;
        return;
      }
    }

    // Check whether we need an external or internal relocation.
    if (Writer->doesSymbolRequireExternRelocation(SD)) {
      RelSymbol = &SD->getSymbol();
      // For external relocations, make sure to offset the fixup value to
      // compensate for the addend of the symbol address, if it was
      // undefined. This occurs with weak definitions, for example.
      if (!SD->getSymbol().isUndefined())
        FixedValue -= Layout.getSymbolOffset(SD->getSymbol());
    } else {
      // The index is the section ordinal (1-based).
      const MCSectionData &SymSD = Asm.getSectionData(
        SD->getSymbol().getSection());
      Index = SymSD.getOrdinal() + 1;
      FixedValue += Writer->getSectionAddress(&SymSD);
    }
    if (IsPCRel)
      FixedValue -= Writer->getSectionAddress(Fragment->getParent());

    Type = MachO::GENERIC_RELOC_VANILLA;
  }

  // struct relocation_info (8 bytes)
  MachO::any_relocation_info MRE;
  MRE.r_word0 = FixupOffset;
  MRE.r_word1 =
      (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
  Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
コード例 #4
0
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
                                 MCContext *Ctx) {
  unsigned Kind = Fixup.getKind();
  int64_t SignedValue = static_cast<int64_t>(Value);
  switch (Kind) {
  default:
    llvm_unreachable("Unknown fixup kind!");
  case AArch64::fixup_aarch64_pcrel_adr_imm21:
    if (Ctx && (SignedValue > 2097151 || SignedValue < -2097152))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    return AdrImmBits(Value & 0x1fffffULL);
  case AArch64::fixup_aarch64_pcrel_adrp_imm21:
    return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
  case AArch64::fixup_aarch64_ldr_pcrel_imm19:
  case AArch64::fixup_aarch64_pcrel_branch19:
    // Signed 21-bit immediate
    if (SignedValue > 2097151 || SignedValue < -2097152)
      if (Ctx) Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
    // Low two bits are not encoded.
    return (Value >> 2) & 0x7ffff;
  case AArch64::fixup_aarch64_add_imm12:
  case AArch64::fixup_aarch64_ldst_imm12_scale1:
    // Unsigned 12-bit immediate
    if (Ctx && Value >= 0x1000)
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    return Value;
  case AArch64::fixup_aarch64_ldst_imm12_scale2:
    // Unsigned 12-bit immediate which gets multiplied by 2
    if (Ctx && (Value >= 0x2000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x1))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
    return Value >> 1;
  case AArch64::fixup_aarch64_ldst_imm12_scale4:
    // Unsigned 12-bit immediate which gets multiplied by 4
    if (Ctx && (Value >= 0x4000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
    return Value >> 2;
  case AArch64::fixup_aarch64_ldst_imm12_scale8:
    // Unsigned 12-bit immediate which gets multiplied by 8
    if (Ctx && (Value >= 0x8000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x7))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
    return Value >> 3;
  case AArch64::fixup_aarch64_ldst_imm12_scale16:
    // Unsigned 12-bit immediate which gets multiplied by 16
    if (Ctx && (Value >= 0x10000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0xf))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
    return Value >> 4;
  case AArch64::fixup_aarch64_movw:
    if (Ctx)
      Ctx->reportError(Fixup.getLoc(),
                       "no resolvable MOVZ/MOVK fixups supported yet");
    return Value;
  case AArch64::fixup_aarch64_pcrel_branch14:
    // Signed 16-bit immediate
    if (Ctx && (SignedValue > 32767 || SignedValue < -32768))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    // Low two bits are not encoded (4-byte alignment assumed).
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
    return (Value >> 2) & 0x3fff;
  case AArch64::fixup_aarch64_pcrel_branch26:
  case AArch64::fixup_aarch64_pcrel_call26:
    // Signed 28-bit immediate
    if (Ctx && (SignedValue > 134217727 || SignedValue < -134217728))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    // Low two bits are not encoded (4-byte alignment assumed).
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
    return (Value >> 2) & 0x3ffffff;
  case FK_Data_1:
  case FK_Data_2:
  case FK_Data_4:
  case FK_Data_8:
    return Value;
  }
}
コード例 #5
0
unsigned AArch64ELFObjectWriter::GetRelocType(const MCValue &Target,
                                            const MCFixup &Fixup,
                                            bool IsPCRel) const {
  AArch64MCExpr::VariantKind RefKind =
      static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
  AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
  bool IsNC = AArch64MCExpr::isNotChecked(RefKind);

  assert((!Target.getSymA() ||
          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
         "Should only be expression-level modifiers here");

  assert((!Target.getSymB() ||
          Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
         "Should only be expression-level modifiers here");

  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    case FK_Data_2:
      return ELF::R_AARCH64_PREL16;
    case FK_Data_4:
      return ELF::R_AARCH64_PREL32;
    case FK_Data_8:
      return ELF::R_AARCH64_PREL64;
    case AArch64::fixup_aarch64_pcrel_adr_imm21:
      assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
      return ELF::R_AARCH64_ADR_PREL_LO21;
    case AArch64::fixup_aarch64_pcrel_adrp_imm21:
      if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
        return ELF::R_AARCH64_ADR_PREL_PG_HI21;
      if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
        return ELF::R_AARCH64_ADR_GOT_PAGE;
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
        return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
      if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
        return ELF::R_AARCH64_TLSDESC_ADR_PAGE;
      llvm_unreachable("invalid symbol kind for ADRP relocation");
    case AArch64::fixup_aarch64_pcrel_branch26:
      return ELF::R_AARCH64_JUMP26;
    case AArch64::fixup_aarch64_pcrel_call26:
      return ELF::R_AARCH64_CALL26;
    case AArch64::fixup_aarch64_ldr_pcrel_imm19:
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
        return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
      return ELF::R_AARCH64_LD_PREL_LO19;
    case AArch64::fixup_aarch64_pcrel_branch14:
      return ELF::R_AARCH64_TSTBR14;
    case AArch64::fixup_aarch64_pcrel_branch19:
      return ELF::R_AARCH64_CONDBR19;
    default:
      llvm_unreachable("Unsupported pc-relative fixup kind");
    }
  } else {
    switch ((unsigned)Fixup.getKind()) {
    case FK_Data_2:
      return ELF::R_AARCH64_ABS16;
    case FK_Data_4:
      return ELF::R_AARCH64_ABS32;
    case FK_Data_8:
      return ELF::R_AARCH64_ABS64;
    case AArch64::fixup_aarch64_add_imm12:
      if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
        return ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12;
      if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
        return ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12;
      if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
        return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC;
      if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
        return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12;
      if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
        return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC;
      if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
        return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12;
      if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
        return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return ELF::R_AARCH64_ADD_ABS_LO12_NC;

      report_fatal_error("invalid fixup for add (uimm12) instruction");
      return 0;
    case AArch64::fixup_aarch64_ldst_imm12_scale1:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return ELF::R_AARCH64_LDST8_ABS_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC;

      report_fatal_error("invalid fixup for 8-bit load/store instruction");
      return 0;
    case AArch64::fixup_aarch64_ldst_imm12_scale2:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return ELF::R_AARCH64_LDST16_ABS_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC;

      report_fatal_error("invalid fixup for 16-bit load/store instruction");
      return 0;
    case AArch64::fixup_aarch64_ldst_imm12_scale4:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return ELF::R_AARCH64_LDST32_ABS_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC;

      report_fatal_error("invalid fixup for 32-bit load/store instruction");
      return 0;
    case AArch64::fixup_aarch64_ldst_imm12_scale8:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return ELF::R_AARCH64_LDST64_ABS_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_GOT && IsNC)
        return ELF::R_AARCH64_LD64_GOT_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12;
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC)
        return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
      if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC)
        return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;

      report_fatal_error("invalid fixup for 64-bit load/store instruction");
      return 0;
    case AArch64::fixup_aarch64_ldst_imm12_scale16:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return ELF::R_AARCH64_LDST128_ABS_LO12_NC;

      report_fatal_error("invalid fixup for 128-bit load/store instruction");
      return 0;
    case AArch64::fixup_aarch64_movw:
      if (RefKind == AArch64MCExpr::VK_ABS_G3)
        return ELF::R_AARCH64_MOVW_UABS_G3;
      if (RefKind == AArch64MCExpr::VK_ABS_G2)
        return ELF::R_AARCH64_MOVW_UABS_G2;
      if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
        return ELF::R_AARCH64_MOVW_SABS_G2;
      if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
        return ELF::R_AARCH64_MOVW_UABS_G2_NC;
      if (RefKind == AArch64MCExpr::VK_ABS_G1)
        return ELF::R_AARCH64_MOVW_UABS_G1;
      if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
        return ELF::R_AARCH64_MOVW_SABS_G1;
      if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
        return ELF::R_AARCH64_MOVW_UABS_G1_NC;
      if (RefKind == AArch64MCExpr::VK_ABS_G0)
        return ELF::R_AARCH64_MOVW_UABS_G0;
      if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
        return ELF::R_AARCH64_MOVW_SABS_G0;
      if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
        return ELF::R_AARCH64_MOVW_UABS_G0_NC;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC;
      if (RefKind == AArch64MCExpr::VK_TPREL_G2)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
      if (RefKind == AArch64MCExpr::VK_TPREL_G1)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1;
      if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
      if (RefKind == AArch64MCExpr::VK_TPREL_G0)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0;
      if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC;
      if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
        return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
      if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
        return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
      report_fatal_error("invalid fixup for movz/movk instruction");
      return 0;
    case AArch64::fixup_aarch64_tlsdesc_call:
      return ELF::R_AARCH64_TLSDESC_CALL;
    default:
      llvm_unreachable("Unknown ELF relocation type");
    }
  }

  llvm_unreachable("Unimplemented fixup -> relocation");
}
コード例 #6
0
unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
                                               const MCFixup &Fixup,
                                               bool IsPCRel) const
{
  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();

  // determine the type of the relocation
  unsigned Type;
  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    default:
      llvm_unreachable("Unimplemented");
    case PPC::fixup_ppc_br24:
      Type = ELF::R_PPC_REL24;
      break;
    case FK_Data_4:
    case FK_PCRel_4:
      Type = ELF::R_PPC_REL32;
      break;
    case FK_Data_8:
    case FK_PCRel_8:
      Type = ELF::R_PPC64_REL64;
      break;
    }
  } else {
    switch ((unsigned)Fixup.getKind()) {
      default: llvm_unreachable("invalid fixup kind!");
    case PPC::fixup_ppc_br24:
      Type = ELF::R_PPC_ADDR24;
      break;
    case PPC::fixup_ppc_brcond14:
      Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
      break;
    case PPC::fixup_ppc_ha16:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TPREL16_HA:
        Type = ELF::R_PPC_TPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL16_HA:
        Type = ELF::R_PPC64_DTPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_ADDR16_HA;
	break;
      case MCSymbolRefExpr::VK_PPC_TOC16_HA:
        Type = ELF::R_PPC64_TOC16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_HA:
        Type = ELF::R_PPC64_GOT_TPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA:
        Type = ELF::R_PPC64_GOT_TLSGD16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA:
        Type = ELF::R_PPC64_GOT_TLSLD16_HA;
        break;
      }
      break;
    case PPC::fixup_ppc_lo16:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TPREL16_LO:
        Type = ELF::R_PPC_TPREL16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL16_LO:
        Type = ELF::R_PPC64_DTPREL16_LO;
        break;
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_ADDR16_LO;
	break;
      case MCSymbolRefExpr::VK_PPC_TOC_ENTRY:
        Type = ELF::R_PPC64_TOC16;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC16_LO:
        Type = ELF::R_PPC64_TOC16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO:
        Type = ELF::R_PPC64_GOT_TLSGD16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO:
        Type = ELF::R_PPC64_GOT_TLSLD16_LO;
        break;
      }
      break;
    case PPC::fixup_ppc_lo16_ds:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC64_ADDR16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_ENTRY:
        Type = ELF::R_PPC64_TOC16_DS;
	break;
      case MCSymbolRefExpr::VK_PPC_TOC16_LO:
        Type = ELF::R_PPC64_TOC16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_LO:
        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
        break;
      }
      break;
    case PPC::fixup_ppc_tlsreg:
      Type = ELF::R_PPC64_TLS;
      break;
    case PPC::fixup_ppc_nofixup:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TLSGD:
        Type = ELF::R_PPC64_TLSGD;
        break;
      case MCSymbolRefExpr::VK_PPC_TLSLD:
        Type = ELF::R_PPC64_TLSLD;
        break;
      }
      break;
    case FK_Data_8:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TOC:
        Type = ELF::R_PPC64_TOC;
        break;
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC64_ADDR64;
	break;
      }
      break;
    case FK_Data_4:
      Type = ELF::R_PPC_ADDR32;
      break;
    case FK_Data_2:
      Type = ELF::R_PPC_ADDR16;
      break;
    }
  }
  return Type;
}
コード例 #7
0
bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
                                const MCFixup &Fixup, const MCFragment *DF,
                                MCValue &Target, uint64_t &Value) const {
  ++stats::evaluateFixup;

  // FIXME: This code has some duplication with recordRelocation. We should
  // probably merge the two into a single callback that tries to evaluate a
  // fixup and records a relocation if one is needed.
  const MCExpr *Expr = Fixup.getValue();
  if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup))
    getContext().reportFatalError(Fixup.getLoc(), "expected relocatable expression");

  bool IsPCRel = Backend.getFixupKindInfo(
    Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;

  bool IsResolved;
  if (IsPCRel) {
    if (Target.getSymB()) {
      IsResolved = false;
    } else if (!Target.getSymA()) {
      IsResolved = false;
    } else {
      const MCSymbolRefExpr *A = Target.getSymA();
      const MCSymbol &SA = A->getSymbol();
      if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) {
        IsResolved = false;
      } else {
        IsResolved = getWriter().isSymbolRefDifferenceFullyResolvedImpl(
            *this, SA, *DF, false, true);
      }
    }
  } else {
    IsResolved = Target.isAbsolute();
  }

  Value = Target.getConstant();

  if (const MCSymbolRefExpr *A = Target.getSymA()) {
    const MCSymbol &Sym = A->getSymbol();
    if (Sym.isDefined())
      Value += Layout.getSymbolOffset(Sym);
  }
  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    const MCSymbol &Sym = B->getSymbol();
    if (Sym.isDefined())
      Value -= Layout.getSymbolOffset(Sym);
  }


  bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
                         MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
  assert((ShouldAlignPC ? IsPCRel : true) &&
    "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!");

  if (IsPCRel) {
    uint32_t Offset = Layout.getFragmentOffset(DF) + Fixup.getOffset();

    // A number of ARM fixups in Thumb mode require that the effective PC
    // address be determined as the 32-bit aligned version of the actual offset.
    if (ShouldAlignPC) Offset &= ~0x3;
    Value -= Offset;
  }

  // Let the backend adjust the fixup value if necessary, including whether
  // we need a relocation.
  Backend.processFixupValue(*this, Layout, Fixup, DF, Target, Value,
                            IsResolved);

  return IsResolved;
}
コード例 #8
0
void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
                                           const MCAsmLayout &Layout,
                                           const MCFragment *Fragment,
                                           const MCFixup &Fixup,
                                           MCValue Target,
                                           bool &IsPCRel,
                                           uint64_t &FixedValue) {
  assert(Target.getSymA() && "Relocation must reference a symbol!");

  const MCSymbol &Symbol = Target.getSymA()->getSymbol();
  const MCSymbol &A = Symbol.AliasedSymbol();
  if (!Asm.hasSymbolData(A))
    Asm.getContext().FatalError(
        Fixup.getLoc(),
        Twine("symbol '") + A.getName() + "' can not be undefined");

  const MCSymbolData &A_SD = Asm.getSymbolData(A);

  MCSectionData const *SectionData = Fragment->getParent();

  // Mark this symbol as requiring an entry in the symbol table.
  assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
         "Section must already have been defined in ExecutePostLayoutBinding!");
  assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
         "Symbol must already have been defined in ExecutePostLayoutBinding!");

  COFFSection *coff_section = SectionMap[&SectionData->getSection()];
  COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];
  const MCSymbolRefExpr *SymB = Target.getSymB();
  bool CrossSection = false;

  if (SymB) {
    const MCSymbol *B = &SymB->getSymbol();
    const MCSymbolData &B_SD = Asm.getSymbolData(*B);
    if (!B_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + B->getName() +
              "' can not be undefined in a subtraction expression");

    if (!A_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + Symbol.getName() +
              "' can not be undefined in a subtraction expression");

    CrossSection = &Symbol.getSection() != &B->getSection();

    // Offset of the symbol in the section
    int64_t a = Layout.getSymbolOffset(&B_SD);

    // Ofeset of the relocation in the section
    int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();

    FixedValue = b - a;
    // In the case where we have SymbA and SymB, we just need to store the delta
    // between the two symbols.  Update FixedValue to account for the delta, and
    // skip recording the relocation.
    if (!CrossSection)
      return;
  } else {
    FixedValue = Target.getConstant();
  }

  COFFRelocation Reloc;

  Reloc.Data.SymbolTableIndex = 0;
  Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);

  // Turn relocations for temporary symbols into section relocations.
  if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) {
    Reloc.Symb = coff_symbol->Section->Symbol;
    FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment)
                + coff_symbol->MCData->getOffset();
  } else
    Reloc.Symb = coff_symbol;

  ++Reloc.Symb->Relocations;

  Reloc.Data.VirtualAddress += Fixup.getOffset();
  Reloc.Data.Type = TargetObjectWriter->getRelocType(Target, Fixup,
                                                     CrossSection);

  // FIXME: Can anyone explain what this does other than adjust for the size
  // of the offset?
  if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 &&
       Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) ||
      (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 &&
       Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32))
    FixedValue += 4;

  if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) {
    switch (Reloc.Data.Type) {
    case COFF::IMAGE_REL_ARM_ABSOLUTE:
    case COFF::IMAGE_REL_ARM_ADDR32:
    case COFF::IMAGE_REL_ARM_ADDR32NB:
    case COFF::IMAGE_REL_ARM_TOKEN:
    case COFF::IMAGE_REL_ARM_SECTION:
    case COFF::IMAGE_REL_ARM_SECREL:
      break;
    case COFF::IMAGE_REL_ARM_BRANCH11:
    case COFF::IMAGE_REL_ARM_BLX11:
      // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for
      // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid
      // for Windows CE).
    case COFF::IMAGE_REL_ARM_BRANCH24:
    case COFF::IMAGE_REL_ARM_BLX24:
    case COFF::IMAGE_REL_ARM_MOV32A:
      // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are
      // only used for ARM mode code, which is documented as being unsupported
      // by Windows on ARM.  Emperical proof indicates that masm is able to
      // generate the relocations however the rest of the MSVC toolchain is
      // unable to handle it.
      llvm_unreachable("unsupported relocation");
      break;
    case COFF::IMAGE_REL_ARM_MOV32T:
      break;
    case COFF::IMAGE_REL_ARM_BRANCH20T:
    case COFF::IMAGE_REL_ARM_BRANCH24T:
    case COFF::IMAGE_REL_ARM_BLX23T:
      // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all
      // perform a 4 byte adjustment to the relocation.  Relative branches are
      // offset by 4 on ARM, however, because there is no RELA relocations, all
      // branches are offset by 4.
      FixedValue = FixedValue + 4;
      break;
    }
  }

  coff_section->Relocations.push_back(Reloc);
}
コード例 #9
0
void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
                                           const MCAsmLayout &Layout,
                                           const MCFragment *Fragment,
                                           const MCFixup &Fixup,
                                           MCValue Target,
                                           uint64_t &FixedValue) {
  assert(Target.getSymA() != NULL && "Relocation must reference a symbol!");

  const MCSymbol &Symbol = Target.getSymA()->getSymbol();
  const MCSymbol &A = Symbol.AliasedSymbol();
  if (!Asm.hasSymbolData(A))
    Asm.getContext().FatalError(
        Fixup.getLoc(),
        Twine("symbol '") + A.getName() + "' can not be undefined");

  MCSymbolData &A_SD = Asm.getSymbolData(A);

  MCSectionData const *SectionData = Fragment->getParent();

  // Mark this symbol as requiring an entry in the symbol table.
  assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
         "Section must already have been defined in ExecutePostLayoutBinding!");
  assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
         "Symbol must already have been defined in ExecutePostLayoutBinding!");

  COFFSection *coff_section = SectionMap[&SectionData->getSection()];
  COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];
  const MCSymbolRefExpr *SymB = Target.getSymB();
  bool CrossSection = false;

  if (SymB) {
    const MCSymbol *B = &SymB->getSymbol();
    MCSymbolData &B_SD = Asm.getSymbolData(*B);
    if (!B_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + B->getName() +
              "' can not be undefined in a subtraction expression");

    if (!A_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + Symbol.getName() +
              "' can not be undefined in a subtraction expression");

    CrossSection = &Symbol.getSection() != &B->getSection();

    // Offset of the symbol in the section
    int64_t a = Layout.getSymbolOffset(&B_SD);

    // Ofeset of the relocation in the section
    int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();

    FixedValue = b - a;
    // In the case where we have SymbA and SymB, we just need to store the delta
    // between the two symbols.  Update FixedValue to account for the delta, and
    // skip recording the relocation.
    if (!CrossSection)
      return;
  } else {
    FixedValue = Target.getConstant();
  }

  COFFRelocation Reloc;

  Reloc.Data.SymbolTableIndex = 0;
  Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);

  // Turn relocations for temporary symbols into section relocations.
  if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) {
    Reloc.Symb = coff_symbol->Section->Symbol;
    FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment)
                + coff_symbol->MCData->getOffset();
  } else
    Reloc.Symb = coff_symbol;

  ++Reloc.Symb->Relocations;

  Reloc.Data.VirtualAddress += Fixup.getOffset();
  Reloc.Data.Type = TargetObjectWriter->getRelocType(Target, Fixup,
                                                     CrossSection);

  // FIXME: Can anyone explain what this does other than adjust for the size
  // of the offset?
  if (Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32 ||
      Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32)
    FixedValue += 4;

  coff_section->Relocations.push_back(Reloc);
}
コード例 #10
0
ファイル: AArch64ELFObjectWriter.cpp プロジェクト: ralic/llvm
unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
                                              const MCValue &Target,
                                              const MCFixup &Fixup,
                                              bool IsPCRel) const {
  AArch64MCExpr::VariantKind RefKind =
      static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
  AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
  bool IsNC = AArch64MCExpr::isNotChecked(RefKind);

  assert((!Target.getSymA() ||
          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
         "Should only be expression-level modifiers here");

  assert((!Target.getSymB() ||
          Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
         "Should only be expression-level modifiers here");

  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    case FK_Data_1:
      Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
      return ELF::R_AARCH64_NONE;
    case FK_Data_2:
      return R_CLS(PREL16);
    case FK_Data_4:
      return R_CLS(PREL32);
    case FK_Data_8:
      if (IsILP32) {
        Ctx.reportError(Fixup.getLoc(), "ILP32 8 byte PC relative data "
                        "relocation not supported (LP64 eqv: PREL64)");
        return ELF::R_AARCH64_NONE;
      } else
        return ELF::R_AARCH64_PREL64;
    case AArch64::fixup_aarch64_pcrel_adr_imm21:
      assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
      return R_CLS(ADR_PREL_LO21);
    case AArch64::fixup_aarch64_pcrel_adrp_imm21:
      if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
        return R_CLS(ADR_PREL_PG_HI21);
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) {
        if (IsILP32) {
          Ctx.reportError(Fixup.getLoc(),
                          "invalid fixup for 32-bit pcrel ADRP instruction "
                          "VK_ABS VK_NC");
          return ELF::R_AARCH64_NONE;
        } else {
          return ELF::R_AARCH64_ADR_PREL_PG_HI21_NC;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
        return R_CLS(ADR_GOT_PAGE);
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
        return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21);
      if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
        return R_CLS(TLSDESC_ADR_PAGE21);
      Ctx.reportError(Fixup.getLoc(),
                      "invalid symbol kind for ADRP relocation");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_pcrel_branch26:
      return R_CLS(JUMP26);
    case AArch64::fixup_aarch64_pcrel_call26:
      return R_CLS(CALL26);
    case AArch64::fixup_aarch64_ldr_pcrel_imm19:
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
        return R_CLS(TLSIE_LD_GOTTPREL_PREL19);
      return R_CLS(LD_PREL_LO19);
    case AArch64::fixup_aarch64_pcrel_branch14:
      return R_CLS(TSTBR14);
    case AArch64::fixup_aarch64_pcrel_branch19:
      return R_CLS(CONDBR19);
    default:
      Ctx.reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind");
      return ELF::R_AARCH64_NONE;
    }
  } else {
    if (IsILP32 && isNonILP32reloc(Fixup, RefKind, Ctx))
        return ELF::R_AARCH64_NONE;
    switch ((unsigned)Fixup.getKind()) {
    case FK_Data_1:
      Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
      return ELF::R_AARCH64_NONE;
    case FK_Data_2:
      return R_CLS(ABS16);
    case FK_Data_4:
      return R_CLS(ABS32);
    case FK_Data_8:
      if (IsILP32) {
        Ctx.reportError(Fixup.getLoc(), "ILP32 8 byte absolute data "
			"relocation not supported (LP64 eqv: ABS64)");
        return ELF::R_AARCH64_NONE;
      } else
        return ELF::R_AARCH64_ABS64;
    case AArch64::fixup_aarch64_add_imm12:
      if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
        return R_CLS(TLSLD_ADD_DTPREL_HI12);
      if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
        return R_CLS(TLSLE_ADD_TPREL_HI12);
      if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
        return R_CLS(TLSLD_ADD_DTPREL_LO12_NC);
      if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
        return R_CLS(TLSLD_ADD_DTPREL_LO12);
      if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
        return R_CLS(TLSLE_ADD_TPREL_LO12_NC);
      if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
        return R_CLS(TLSLE_ADD_TPREL_LO12);
      if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
        return R_CLS(TLSDESC_ADD_LO12);
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(ADD_ABS_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for add (uimm12) instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale1:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST8_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST8_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST8_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST8_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST8_TPREL_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 8-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale2:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST16_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST16_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST16_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST16_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST16_TPREL_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 16-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale4:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST32_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST32_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST32_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST32_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST32_TPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
        if (IsILP32) {
          return ELF::R_AARCH64_P32_LD32_GOT_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(),
                          "LP64 4 byte unchecked GOT load/store relocation "
			  "not supported (ILP32 eqv: LD32_GOT_LO12_NC");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) {
        if (IsILP32) {
          Ctx.reportError(Fixup.getLoc(),
                          "ILP32 4 byte checked GOT load/store relocation "
			  "not supported (unchecked eqv: LD32_GOT_LO12_NC)");
        } else {
          Ctx.reportError(Fixup.getLoc(),
                          "LP64 4 byte checked GOT load/store relocation "
			  "not supported (unchecked/ILP32 eqv: "
			  "LD32_GOT_LO12_NC)");
        }
        return ELF::R_AARCH64_NONE;
      }
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) {
        if (IsILP32) {
          return ELF::R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(), "LP64 32-bit load/store "
                          "relocation not supported (ILP32 eqv: "
                          "TLSIE_LD32_GOTTPREL_LO12_NC)");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) {
        if (IsILP32) {
          return ELF::R_AARCH64_P32_TLSDESC_LD32_LO12;
        } else {
          Ctx.reportError(Fixup.getLoc(),
                          "LP64 4 byte TLSDESC load/store relocation "
			  "not supported (ILP32 eqv: TLSDESC_LD64_LO12)");
          return ELF::R_AARCH64_NONE;
        }
      }

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 32-bit load/store instruction "
		      "fixup_aarch64_ldst_imm12_scale4");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale8:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST64_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
        if (!IsILP32) {
          return ELF::R_AARCH64_LD64_GOT_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
                          "relocation not supported (LP64 eqv: "
                          "LD64_GOT_LO12_NC)");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST64_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST64_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST64_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST64_TPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) {
        if (!IsILP32) {
          return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
                          "relocation not supported (LP64 eqv: "
                          "TLSIE_LD64_GOTTPREL_LO12_NC)");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_TLSDESC) {
        if (!IsILP32) {
          return ELF::R_AARCH64_TLSDESC_LD64_LO12;
        } else {
          Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
                          "relocation not supported (LP64 eqv: "
                          "TLSDESC_LD64_LO12)");
          return ELF::R_AARCH64_NONE;
        }
      }
      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 64-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale16:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST128_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST128_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST128_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST128_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST128_TPREL_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 128-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    // ILP32 case not reached here, tested with isNonILP32reloc
    case AArch64::fixup_aarch64_movw:
      if (RefKind == AArch64MCExpr::VK_ABS_G3)
        return ELF::R_AARCH64_MOVW_UABS_G3;
      if (RefKind == AArch64MCExpr::VK_ABS_G2)
        return ELF::R_AARCH64_MOVW_UABS_G2;
      if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
        return ELF::R_AARCH64_MOVW_SABS_G2;
      if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
        return ELF::R_AARCH64_MOVW_UABS_G2_NC;
      if (RefKind == AArch64MCExpr::VK_ABS_G1)
        return R_CLS(MOVW_UABS_G1);
      if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
        return ELF::R_AARCH64_MOVW_SABS_G1;
      if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
        return ELF::R_AARCH64_MOVW_UABS_G1_NC;
      if (RefKind == AArch64MCExpr::VK_ABS_G0)
        return R_CLS(MOVW_UABS_G0);
      if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
        return R_CLS(MOVW_SABS_G0);
      if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
        return R_CLS(MOVW_UABS_G0_NC);
      if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
        return R_CLS(TLSLD_MOVW_DTPREL_G1);
      if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
        return R_CLS(TLSLD_MOVW_DTPREL_G0);
      if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
        return R_CLS(TLSLD_MOVW_DTPREL_G0_NC);
      if (RefKind == AArch64MCExpr::VK_TPREL_G2)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
      if (RefKind == AArch64MCExpr::VK_TPREL_G1)
        return R_CLS(TLSLE_MOVW_TPREL_G1);
      if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
      if (RefKind == AArch64MCExpr::VK_TPREL_G0)
        return R_CLS(TLSLE_MOVW_TPREL_G0);
      if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
        return R_CLS(TLSLE_MOVW_TPREL_G0_NC);
      if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
        return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
      if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
        return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for movz/movk instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_tlsdesc_call:
      return R_CLS(TLSDESC_CALL);
    default:
      Ctx.reportError(Fixup.getLoc(), "Unknown ELF relocation type");
      return ELF::R_AARCH64_NONE;
    }
  }

  llvm_unreachable("Unimplemented fixup -> relocation");
}
コード例 #11
0
ファイル: AArch64ELFObjectWriter.cpp プロジェクト: ralic/llvm
// assumes IsILP32 is true
static bool isNonILP32reloc(const MCFixup &Fixup,
                            AArch64MCExpr::VariantKind RefKind,
                            MCContext &Ctx) {
  if ((unsigned)Fixup.getKind() != AArch64::fixup_aarch64_movw)
    return false;
  switch(RefKind) {
    case AArch64MCExpr::VK_ABS_G3:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G3));
      return true;
    case AArch64MCExpr::VK_ABS_G2:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2));
      return true;
    case AArch64MCExpr::VK_ABS_G2_S:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G2));
      return true;
    case AArch64MCExpr::VK_ABS_G2_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2_NC));
      return true;
    case AArch64MCExpr::VK_ABS_G1_S:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G1));
      return true;
    case AArch64MCExpr::VK_ABS_G1_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G1_NC));
      return true;
    case AArch64MCExpr::VK_DTPREL_G2:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G2));
      return true;
    case AArch64MCExpr::VK_DTPREL_G1_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G1_NC));
      return true;
    case AArch64MCExpr::VK_TPREL_G2:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G2));
      return true;
    case AArch64MCExpr::VK_TPREL_G1_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G1_NC));
      return true;
    case AArch64MCExpr::VK_GOTTPREL_G1:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G1));
      return true;
    case AArch64MCExpr::VK_GOTTPREL_G0_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G0_NC));
      return true;
    default: return false;
  }
  return false;
}
コード例 #12
0
//@GetRelocType {
unsigned Cpu0ELFObjectWriter::GetRelocType(const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel) const {
  // determine the type of the relocation
  unsigned Type = (unsigned)ELF::R_CPU0_NONE;
  unsigned Kind = (unsigned)Fixup.getKind();

  switch (Kind) {
  default:
    llvm_unreachable("invalid fixup kind!");
  case FK_Data_4:
    Type = ELF::R_CPU0_32;
    break;
#if CH >= CH8_1 //1
  case FK_GPRel_4:
    Type = ELF::R_CPU0_GPREL32;
    break;
#endif
  case Cpu0::fixup_Cpu0_32:
    Type = ELF::R_CPU0_32;
    break;
  case Cpu0::fixup_Cpu0_GPREL16:
    Type = ELF::R_CPU0_GPREL16;
    break;
#if CH >= CH9_1
  case Cpu0::fixup_Cpu0_CALL16:
    Type = ELF::R_CPU0_CALL16;
    break;
#endif
  case Cpu0::fixup_Cpu0_GOT_Global:
  case Cpu0::fixup_Cpu0_GOT_Local:
    Type = ELF::R_CPU0_GOT16;
    break;
  case Cpu0::fixup_Cpu0_HI16:
    Type = ELF::R_CPU0_HI16;
    break;
  case Cpu0::fixup_Cpu0_LO16:
    Type = ELF::R_CPU0_LO16;
    break;
#if CH >= CH12_1
  case Cpu0::fixup_Cpu0_TLSGD:
    Type = ELF::R_CPU0_TLS_GD;
    break;
  case Cpu0::fixup_Cpu0_GOTTPREL:
    Type = ELF::R_CPU0_TLS_GOTTPREL;
    break;
#endif
#if CH >= CH8_1 //2
  case Cpu0::fixup_Cpu0_PC16:
    Type = ELF::R_CPU0_PC16;
    break;
  case Cpu0::fixup_Cpu0_PC24:
    Type = ELF::R_CPU0_PC24;
    break;
#endif
#if CH >= CH12_1
  case Cpu0::fixup_Cpu0_TP_HI:
    Type = ELF::R_CPU0_TLS_TP_HI16;
    break;
  case Cpu0::fixup_Cpu0_TP_LO:
    Type = ELF::R_CPU0_TLS_TP_LO16;
    break;
  case Cpu0::fixup_Cpu0_TLSLDM:
    Type = ELF::R_CPU0_TLS_LDM;
    break;
  case Cpu0::fixup_Cpu0_DTP_HI:
    Type = ELF::R_CPU0_TLS_DTP_HI16;
    break;
  case Cpu0::fixup_Cpu0_DTP_LO:
    Type = ELF::R_CPU0_TLS_DTP_LO16;
    break;
#endif
  case Cpu0::fixup_Cpu0_GOT_HI16:
    Type = ELF::R_CPU0_GOT_HI16;
    break;
  case Cpu0::fixup_Cpu0_GOT_LO16:
    Type = ELF::R_CPU0_GOT_LO16;
    break;
  }

  return Type;
}
コード例 #13
0
bool ARMWinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const {
  return static_cast<unsigned>(Fixup.getKind()) != ARM::fixup_t2_movt_hi16;
}
コード例 #14
0
void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
                                           const MCAsmLayout &Layout,
                                           const MCFragment *Fragment,
                                           const MCFixup &Fixup,
                                           MCValue Target,
                                           uint64_t &FixedValue) {
  assert(Target.getSymA() != NULL && "Relocation must reference a symbol!");

  const MCSymbol *A = &Target.getSymA()->getSymbol();
  MCSymbolData &A_SD = Asm.getSymbolData(*A);

  MCSectionData const *SectionData = Fragment->getParent();

  // Mark this symbol as requiring an entry in the symbol table.
  assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
         "Section must already have been defined in ExecutePostLayoutBinding!");
  assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
         "Symbol must already have been defined in ExecutePostLayoutBinding!");

  COFFSection *coff_section = SectionMap[&SectionData->getSection()];
  COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];

  if (Target.getSymB()) {
    if (&Target.getSymA()->getSymbol().getSection()
     != &Target.getSymB()->getSymbol().getSection()) {
      llvm_unreachable("Symbol relative relocations are only allowed between "
                       "symbols in the same section");
    }
    const MCSymbol *B = &Target.getSymB()->getSymbol();
    MCSymbolData &B_SD = Asm.getSymbolData(*B);

    FixedValue = Layout.getSymbolOffset(&A_SD) - Layout.getSymbolOffset(&B_SD);

    // In the case where we have SymbA and SymB, we just need to store the delta
    // between the two symbols.  Update FixedValue to account for the delta, and
    // skip recording the relocation.
    return;
  } else {
    FixedValue = Target.getConstant();
  }

  COFFRelocation Reloc;

  Reloc.Data.SymbolTableIndex = 0;
  Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);

  // Turn relocations for temporary symbols into section relocations.
  if (coff_symbol->MCData->getSymbol().isTemporary()) {
    Reloc.Symb = coff_symbol->Section->Symbol;
    FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment)
                + coff_symbol->MCData->getOffset();
  } else
    Reloc.Symb = coff_symbol;

  ++Reloc.Symb->Relocations;

  Reloc.Data.VirtualAddress += Fixup.getOffset();

  switch ((unsigned)Fixup.getKind()) {
  case FK_PCRel_4:
  case X86::reloc_riprel_4byte:
  case X86::reloc_riprel_4byte_movq_load:
    Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_REL32
                              : COFF::IMAGE_REL_I386_REL32;
    // FIXME: Can anyone explain what this does other than adjust for the size
    // of the offset?
    FixedValue += 4;
    break;
  case FK_Data_4:
  case X86::reloc_signed_4byte:
    Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32
                              : COFF::IMAGE_REL_I386_DIR32;
    break;
  case FK_Data_8:
    if (Is64Bit)
      Reloc.Data.Type = COFF::IMAGE_REL_AMD64_ADDR64;
    else
      llvm_unreachable("unsupported relocation type");
    break;
  default:
    llvm_unreachable("unsupported relocation type");
  }

  coff_section->Relocations.push_back(Reloc);
}
コード例 #15
0
bool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
    const MCFixup &Fixup, unsigned &RelocType, const MCSymbolRefExpr *Sym,
    unsigned &Log2Size, const MCAssembler &Asm) {
  RelocType = unsigned(MachO::ARM64_RELOC_UNSIGNED);
  Log2Size = ~0U;

  switch ((unsigned)Fixup.getKind()) {
  default:
    return false;

  case FK_Data_1:
    Log2Size = llvm::Log2_32(1);
    return true;
  case FK_Data_2:
    Log2Size = llvm::Log2_32(2);
    return true;
  case FK_Data_4:
    Log2Size = llvm::Log2_32(4);
    if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
      RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
    return true;
  case FK_Data_8:
    Log2Size = llvm::Log2_32(8);
    if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
      RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
    return true;
  case AArch64::fixup_aarch64_add_imm12:
  case AArch64::fixup_aarch64_ldst_imm12_scale1:
  case AArch64::fixup_aarch64_ldst_imm12_scale2:
  case AArch64::fixup_aarch64_ldst_imm12_scale4:
  case AArch64::fixup_aarch64_ldst_imm12_scale8:
  case AArch64::fixup_aarch64_ldst_imm12_scale16:
    Log2Size = llvm::Log2_32(4);
    switch (Sym->getKind()) {
    default:
      llvm_unreachable("Unexpected symbol reference variant kind!");
    case MCSymbolRefExpr::VK_PAGEOFF:
      RelocType = unsigned(MachO::ARM64_RELOC_PAGEOFF12);
      return true;
    case MCSymbolRefExpr::VK_GOTPAGEOFF:
      RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
      return true;
    case MCSymbolRefExpr::VK_TLVPPAGEOFF:
      RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
      return true;
    }
  case AArch64::fixup_aarch64_pcrel_adrp_imm21:
    Log2Size = llvm::Log2_32(4);
    // This encompasses the relocation for the whole 21-bit value.
    switch (Sym->getKind()) {
    default:
      Asm.getContext().FatalError(Fixup.getLoc(),
                                  "ADR/ADRP relocations must be GOT relative");
    case MCSymbolRefExpr::VK_PAGE:
      RelocType = unsigned(MachO::ARM64_RELOC_PAGE21);
      return true;
    case MCSymbolRefExpr::VK_GOTPAGE:
      RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
      return true;
    case MCSymbolRefExpr::VK_TLVPPAGE:
      RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
      return true;
    }
    return true;
  case AArch64::fixup_aarch64_pcrel_branch26:
  case AArch64::fixup_aarch64_pcrel_call26:
    Log2Size = llvm::Log2_32(4);
    RelocType = unsigned(MachO::ARM64_RELOC_BRANCH26);
    return true;
  }
}
コード例 #16
0
ファイル: MipsELFObjectWriter.cpp プロジェクト: emaste/llvm
unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel) const {
  // Determine the type of the relocation.
  unsigned Kind = (unsigned)Fixup.getKind();

  switch (Kind) {
  case Mips::fixup_Mips_NONE:
    return ELF::R_MIPS_NONE;
  case Mips::fixup_Mips_16:
  case FK_Data_2:
    return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16;
  case Mips::fixup_Mips_32:
  case FK_Data_4:
    return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32;
  }

  if (IsPCRel) {
    switch (Kind) {
    case Mips::fixup_Mips_Branch_PCRel:
    case Mips::fixup_Mips_PC16:
      return ELF::R_MIPS_PC16;
    case Mips::fixup_MICROMIPS_PC7_S1:
      return ELF::R_MICROMIPS_PC7_S1;
    case Mips::fixup_MICROMIPS_PC10_S1:
      return ELF::R_MICROMIPS_PC10_S1;
    case Mips::fixup_MICROMIPS_PC16_S1:
      return ELF::R_MICROMIPS_PC16_S1;
    case Mips::fixup_MIPS_PC19_S2:
      return ELF::R_MIPS_PC19_S2;
    case Mips::fixup_MIPS_PC18_S3:
      return ELF::R_MIPS_PC18_S3;
    case Mips::fixup_MIPS_PC21_S2:
      return ELF::R_MIPS_PC21_S2;
    case Mips::fixup_MIPS_PC26_S2:
      return ELF::R_MIPS_PC26_S2;
    case Mips::fixup_MIPS_PCHI16:
      return ELF::R_MIPS_PCHI16;
    case Mips::fixup_MIPS_PCLO16:
      return ELF::R_MIPS_PCLO16;
    }

    llvm_unreachable("invalid PC-relative fixup kind!");
  }

  switch (Kind) {
  case Mips::fixup_Mips_64:
  case FK_Data_8:
    return ELF::R_MIPS_64;
  case FK_GPRel_4:
    if (isN64()) {
      unsigned Type = (unsigned)ELF::R_MIPS_NONE;
      Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type);
      Type = setRType2((unsigned)ELF::R_MIPS_64, Type);
      Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type);
      return Type;
    }
    return ELF::R_MIPS_GPREL32;
  case Mips::fixup_Mips_GPREL16:
    return ELF::R_MIPS_GPREL16;
  case Mips::fixup_Mips_26:
    return ELF::R_MIPS_26;
  case Mips::fixup_Mips_CALL16:
    return ELF::R_MIPS_CALL16;
  case Mips::fixup_Mips_GOT_Global:
  case Mips::fixup_Mips_GOT_Local:
    return ELF::R_MIPS_GOT16;
  case Mips::fixup_Mips_HI16:
    return ELF::R_MIPS_HI16;
  case Mips::fixup_Mips_LO16:
    return ELF::R_MIPS_LO16;
  case Mips::fixup_Mips_TLSGD:
    return ELF::R_MIPS_TLS_GD;
  case Mips::fixup_Mips_GOTTPREL:
    return ELF::R_MIPS_TLS_GOTTPREL;
  case Mips::fixup_Mips_TPREL_HI:
    return ELF::R_MIPS_TLS_TPREL_HI16;
  case Mips::fixup_Mips_TPREL_LO:
    return ELF::R_MIPS_TLS_TPREL_LO16;
  case Mips::fixup_Mips_TLSLDM:
    return ELF::R_MIPS_TLS_LDM;
  case Mips::fixup_Mips_DTPREL_HI:
    return ELF::R_MIPS_TLS_DTPREL_HI16;
  case Mips::fixup_Mips_DTPREL_LO:
    return ELF::R_MIPS_TLS_DTPREL_LO16;
  case Mips::fixup_Mips_GOT_PAGE:
    return ELF::R_MIPS_GOT_PAGE;
  case Mips::fixup_Mips_GOT_OFST:
    return ELF::R_MIPS_GOT_OFST;
  case Mips::fixup_Mips_GOT_DISP:
    return ELF::R_MIPS_GOT_DISP;
  case Mips::fixup_Mips_GPOFF_HI: {
    unsigned Type = (unsigned)ELF::R_MIPS_NONE;
    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
    Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type);
    return Type;
  }
  case Mips::fixup_Mips_GPOFF_LO: {
    unsigned Type = (unsigned)ELF::R_MIPS_NONE;
    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
    Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
    return Type;
  }
  case Mips::fixup_Mips_HIGHER:
    return ELF::R_MIPS_HIGHER;
  case Mips::fixup_Mips_HIGHEST:
    return ELF::R_MIPS_HIGHEST;
  case Mips::fixup_Mips_GOT_HI16:
    return ELF::R_MIPS_GOT_HI16;
  case Mips::fixup_Mips_GOT_LO16:
    return ELF::R_MIPS_GOT_LO16;
  case Mips::fixup_Mips_CALL_HI16:
    return ELF::R_MIPS_CALL_HI16;
  case Mips::fixup_Mips_CALL_LO16:
    return ELF::R_MIPS_CALL_LO16;
  case Mips::fixup_MICROMIPS_26_S1:
    return ELF::R_MICROMIPS_26_S1;
  case Mips::fixup_MICROMIPS_HI16:
    return ELF::R_MICROMIPS_HI16;
  case Mips::fixup_MICROMIPS_LO16:
    return ELF::R_MICROMIPS_LO16;
  case Mips::fixup_MICROMIPS_GOT16:
    return ELF::R_MICROMIPS_GOT16;
  case Mips::fixup_MICROMIPS_CALL16:
    return ELF::R_MICROMIPS_CALL16;
  case Mips::fixup_MICROMIPS_GOT_DISP:
    return ELF::R_MICROMIPS_GOT_DISP;
  case Mips::fixup_MICROMIPS_GOT_PAGE:
    return ELF::R_MICROMIPS_GOT_PAGE;
  case Mips::fixup_MICROMIPS_GOT_OFST:
    return ELF::R_MICROMIPS_GOT_OFST;
  case Mips::fixup_MICROMIPS_TLS_GD:
    return ELF::R_MICROMIPS_TLS_GD;
  case Mips::fixup_MICROMIPS_TLS_LDM:
    return ELF::R_MICROMIPS_TLS_LDM;
  case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
    return ELF::R_MICROMIPS_TLS_DTPREL_HI16;
  case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
    return ELF::R_MICROMIPS_TLS_DTPREL_LO16;
  case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
    return ELF::R_MICROMIPS_TLS_TPREL_HI16;
  case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
    return ELF::R_MICROMIPS_TLS_TPREL_LO16;
  }

  llvm_unreachable("invalid fixup kind!");
}
コード例 #17
0
unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel,
                                           bool IsRelocWithSymbol,
                                           int64_t Addend) const {
  // determine the type of the relocation
  unsigned Type = (unsigned)ELF::R_MIPS_NONE;
  unsigned Kind = (unsigned)Fixup.getKind();

  switch (Kind) {
  default:
    llvm_unreachable("invalid fixup kind!");
  case FK_Data_4:
    Type = ELF::R_MIPS_32;
    break;
  case FK_Data_8:
    Type = ELF::R_MIPS_64;
    break;
  case FK_GPRel_4:
    Type = ELF::R_MIPS_GPREL32;
    break;
  case Mips::fixup_Mips_GPREL16:
    Type = ELF::R_MIPS_GPREL16;
    break;
  case Mips::fixup_Mips_26:
    Type = ELF::R_MIPS_26;
    break;
  case Mips::fixup_Mips_CALL16:
    Type = ELF::R_MIPS_CALL16;
    break;
  case Mips::fixup_Mips_GOT_Global:
  case Mips::fixup_Mips_GOT_Local:
    Type = ELF::R_MIPS_GOT16;
    break;
  case Mips::fixup_Mips_HI16:
    Type = ELF::R_MIPS_HI16;
    break;
  case Mips::fixup_Mips_LO16:
    Type = ELF::R_MIPS_LO16;
    break;
  case Mips::fixup_Mips_TLSGD:
    Type = ELF::R_MIPS_TLS_GD;
    break;
  case Mips::fixup_Mips_GOTTPREL:
    Type = ELF::R_MIPS_TLS_GOTTPREL;
    break;
  case Mips::fixup_Mips_TPREL_HI:
    Type = ELF::R_MIPS_TLS_TPREL_HI16;
    break;
  case Mips::fixup_Mips_TPREL_LO:
    Type = ELF::R_MIPS_TLS_TPREL_LO16;
    break;
  case Mips::fixup_Mips_TLSLDM:
    Type = ELF::R_MIPS_TLS_LDM;
    break;
  case Mips::fixup_Mips_DTPREL_HI:
    Type = ELF::R_MIPS_TLS_DTPREL_HI16;
    break;
  case Mips::fixup_Mips_DTPREL_LO:
    Type = ELF::R_MIPS_TLS_DTPREL_LO16;
    break;
  case Mips::fixup_Mips_Branch_PCRel:
  case Mips::fixup_Mips_PC16:
    Type = ELF::R_MIPS_PC16;
    break;
  case Mips::fixup_Mips_GOT_PAGE:
    Type = ELF::R_MIPS_GOT_PAGE;
    break;
  case Mips::fixup_Mips_GOT_OFST:
    Type = ELF::R_MIPS_GOT_OFST;
    break;
  case Mips::fixup_Mips_GOT_DISP:
    Type = ELF::R_MIPS_GOT_DISP;
    break;
  case Mips::fixup_Mips_GPOFF_HI:
    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
    Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type);
    break;
  case Mips::fixup_Mips_GPOFF_LO:
    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
    Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
    break;
  case Mips::fixup_Mips_HIGHER:
    Type = ELF::R_MIPS_HIGHER;
    break;
  case Mips::fixup_Mips_HIGHEST:
    Type = ELF::R_MIPS_HIGHEST;
    break;
  }
  return Type;
}
コード例 #18
0
ファイル: ARMELFObjectWriter.cpp プロジェクト: freak97/llvm
unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
                                               const MCFixup &Fixup,
                                               bool IsPCRel) const  {
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();

  unsigned Type = 0;
  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    default:
      report_fatal_error("unsupported relocation on symbol");
      return ELF::R_ARM_NONE;
    case FK_Data_4:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_REL32;
        break;
      case MCSymbolRefExpr::VK_TLSGD:
        llvm_unreachable("unimplemented");
      case MCSymbolRefExpr::VK_GOTTPOFF:
        Type = ELF::R_ARM_TLS_IE32;
        break;
      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
        Type = ELF::R_ARM_GOT_PREL;
        break;
      case MCSymbolRefExpr::VK_ARM_PREL31:
        Type = ELF::R_ARM_PREL31;
        break;
      }
      break;
    case ARM::fixup_arm_blx:
    case ARM::fixup_arm_uncondbl:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_PLT:
        Type = ELF::R_ARM_CALL;
        break;
      case MCSymbolRefExpr::VK_TLSCALL:
        Type = ELF::R_ARM_TLS_CALL;
        break;
      default:
        Type = ELF::R_ARM_CALL;
        break;
      }
      break;
    case ARM::fixup_arm_condbl:
    case ARM::fixup_arm_condbranch:
    case ARM::fixup_arm_uncondbranch:
      Type = ELF::R_ARM_JUMP24;
      break;
    case ARM::fixup_t2_condbranch:
    case ARM::fixup_t2_uncondbranch:
      Type = ELF::R_ARM_THM_JUMP24;
      break;
    case ARM::fixup_arm_movt_hi16:
      Type = ELF::R_ARM_MOVT_PREL;
      break;
    case ARM::fixup_arm_movw_lo16:
      Type = ELF::R_ARM_MOVW_PREL_NC;
      break;
    case ARM::fixup_t2_movt_hi16:
      Type = ELF::R_ARM_THM_MOVT_PREL;
      break;
    case ARM::fixup_t2_movw_lo16:
      Type = ELF::R_ARM_THM_MOVW_PREL_NC;
      break;
    case ARM::fixup_arm_thumb_bl:
    case ARM::fixup_arm_thumb_blx:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_TLSCALL:
        Type = ELF::R_ARM_THM_TLS_CALL;
        break;
      default:
        Type = ELF::R_ARM_THM_CALL;
        break;
      }
      break;
    }
  } else {
    switch ((unsigned)Fixup.getKind()) {
    default:
      report_fatal_error("unsupported relocation on symbol");
      return ELF::R_ARM_NONE;
    case FK_Data_1:
      switch (Modifier) {
      default: llvm_unreachable("unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_ABS8;
        break;
      }
      break;
    case FK_Data_2:
      switch (Modifier) {
      default: llvm_unreachable("unsupported modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_ABS16;
        break;
      }
      break;
    case FK_Data_4:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_ARM_NONE:
        Type = ELF::R_ARM_NONE;
        break;
      case MCSymbolRefExpr::VK_GOT:
        Type = ELF::R_ARM_GOT_BREL;
        break;
      case MCSymbolRefExpr::VK_TLSGD:
        Type = ELF::R_ARM_TLS_GD32;
        break;
      case MCSymbolRefExpr::VK_TPOFF:
        Type = ELF::R_ARM_TLS_LE32;
        break;
      case MCSymbolRefExpr::VK_GOTTPOFF:
        Type = ELF::R_ARM_TLS_IE32;
        break;
      case MCSymbolRefExpr::VK_ARM_GOTPREL:
        Type = ELF::R_ARM_GOT_PREL;
        break;
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_ABS32;
        break;
      case MCSymbolRefExpr::VK_GOTOFF:
        Type = ELF::R_ARM_GOTOFF32;
        break;
      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
        Type = ELF::R_ARM_GOT_PREL;
        break;
      case MCSymbolRefExpr::VK_ARM_TARGET1:
        Type = ELF::R_ARM_TARGET1;
        break;
      case MCSymbolRefExpr::VK_ARM_TARGET2:
        Type = ELF::R_ARM_TARGET2;
        break;
      case MCSymbolRefExpr::VK_ARM_PREL31:
        Type = ELF::R_ARM_PREL31;
        break;
      case MCSymbolRefExpr::VK_ARM_SBREL:
        Type = ELF::R_ARM_SBREL32;
        break;
      case MCSymbolRefExpr::VK_ARM_TLSLDO:
        Type = ELF::R_ARM_TLS_LDO32;
        break;
      case MCSymbolRefExpr::VK_TLSCALL:
        Type = ELF::R_ARM_TLS_CALL;
        break;
      case MCSymbolRefExpr::VK_TLSDESC:
        Type = ELF::R_ARM_TLS_GOTDESC;
        break;
      case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
        Type = ELF::R_ARM_TLS_DESCSEQ;
        break;
      }
      break;
    case ARM::fixup_arm_ldst_pcrel_12:
    case ARM::fixup_arm_pcrel_10:
    case ARM::fixup_arm_adr_pcrel_12:
    case ARM::fixup_arm_thumb_bl:
    case ARM::fixup_arm_thumb_cb:
    case ARM::fixup_arm_thumb_cp:
    case ARM::fixup_arm_thumb_br:
      llvm_unreachable("Unimplemented");
    case ARM::fixup_arm_condbranch:
    case ARM::fixup_arm_uncondbranch:
      Type = ELF::R_ARM_JUMP24;
      break;
    case ARM::fixup_arm_movt_hi16:
      Type = ELF::R_ARM_MOVT_ABS;
      break;
    case ARM::fixup_arm_movw_lo16:
      Type = ELF::R_ARM_MOVW_ABS_NC;
      break;
    case ARM::fixup_t2_movt_hi16:
      Type = ELF::R_ARM_THM_MOVT_ABS;
      break;
    case ARM::fixup_t2_movw_lo16:
      Type = ELF::R_ARM_THM_MOVW_ABS_NC;
      break;
    }
  }

  return Type;
}
コード例 #19
0
ファイル: ARMELFObjectWriter.cpp プロジェクト: Lucretia/llvm
unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
                                               const MCFixup &Fixup,
                                               bool IsPCRel,
                                               MCContext &Ctx) const {
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();

  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    default:
      Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
      return ELF::R_ARM_NONE;
    case FK_Data_4:
      switch (Modifier) {
      default:
        llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        return ELF::R_ARM_REL32;
      case MCSymbolRefExpr::VK_GOTTPOFF:
        return ELF::R_ARM_TLS_IE32;
      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
        return ELF::R_ARM_GOT_PREL;
      case MCSymbolRefExpr::VK_ARM_PREL31:
        return ELF::R_ARM_PREL31;
      }
    case ARM::fixup_arm_blx:
    case ARM::fixup_arm_uncondbl:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_PLT:
        return ELF::R_ARM_CALL;
      case MCSymbolRefExpr::VK_TLSCALL:
        return ELF::R_ARM_TLS_CALL;
      default:
        return ELF::R_ARM_CALL;
      }
    case ARM::fixup_arm_condbl:
    case ARM::fixup_arm_condbranch:
    case ARM::fixup_arm_uncondbranch:
      return ELF::R_ARM_JUMP24;
    case ARM::fixup_t2_condbranch:
      return ELF::R_ARM_THM_JUMP19;
    case ARM::fixup_t2_uncondbranch:
      return ELF::R_ARM_THM_JUMP24;
    case ARM::fixup_arm_movt_hi16:
      return ELF::R_ARM_MOVT_PREL;
    case ARM::fixup_arm_movw_lo16:
      return ELF::R_ARM_MOVW_PREL_NC;
    case ARM::fixup_t2_movt_hi16:
      return ELF::R_ARM_THM_MOVT_PREL;
    case ARM::fixup_t2_movw_lo16:
      return ELF::R_ARM_THM_MOVW_PREL_NC;
    case ARM::fixup_arm_thumb_br:
      return ELF::R_ARM_THM_JUMP11;
    case ARM::fixup_arm_thumb_bcc:
      return ELF::R_ARM_THM_JUMP8;
    case ARM::fixup_arm_thumb_bl:
    case ARM::fixup_arm_thumb_blx:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_TLSCALL:
        return ELF::R_ARM_THM_TLS_CALL;
      default:
        return ELF::R_ARM_THM_CALL;
      }
    }
  }
  switch ((unsigned)Fixup.getKind()) {
  default:
    Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
    return ELF::R_ARM_NONE;
  case FK_Data_1:
    switch (Modifier) {
    default:
      llvm_unreachable("unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_ABS8;
    }
  case FK_Data_2:
    switch (Modifier) {
    default:
      llvm_unreachable("unsupported modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_ABS16;
    }
  case FK_Data_4:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_ARM_NONE:
      return ELF::R_ARM_NONE;
    case MCSymbolRefExpr::VK_GOT:
      return ELF::R_ARM_GOT_BREL;
    case MCSymbolRefExpr::VK_TLSGD:
      return ELF::R_ARM_TLS_GD32;
    case MCSymbolRefExpr::VK_TPOFF:
      return ELF::R_ARM_TLS_LE32;
    case MCSymbolRefExpr::VK_GOTTPOFF:
      return ELF::R_ARM_TLS_IE32;
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_ABS32;
    case MCSymbolRefExpr::VK_GOTOFF:
      return ELF::R_ARM_GOTOFF32;
    case MCSymbolRefExpr::VK_ARM_GOT_PREL:
      return ELF::R_ARM_GOT_PREL;
    case MCSymbolRefExpr::VK_ARM_TARGET1:
      return ELF::R_ARM_TARGET1;
    case MCSymbolRefExpr::VK_ARM_TARGET2:
      return ELF::R_ARM_TARGET2;
    case MCSymbolRefExpr::VK_ARM_PREL31:
      return ELF::R_ARM_PREL31;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_SBREL32;
    case MCSymbolRefExpr::VK_ARM_TLSLDO:
      return ELF::R_ARM_TLS_LDO32;
    case MCSymbolRefExpr::VK_TLSCALL:
      return ELF::R_ARM_TLS_CALL;
    case MCSymbolRefExpr::VK_TLSDESC:
      return ELF::R_ARM_TLS_GOTDESC;
    case MCSymbolRefExpr::VK_TLSLDM:
      return ELF::R_ARM_TLS_LDM32;
    case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
      return ELF::R_ARM_TLS_DESCSEQ;
    }
  case ARM::fixup_arm_condbranch:
  case ARM::fixup_arm_uncondbranch:
    return ELF::R_ARM_JUMP24;
  case ARM::fixup_arm_movt_hi16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_MOVT_ABS;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_MOVT_BREL;
    }
  case ARM::fixup_arm_movw_lo16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_MOVW_ABS_NC;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_MOVW_BREL_NC;
    }
  case ARM::fixup_t2_movt_hi16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_THM_MOVT_ABS;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_THM_MOVT_BREL;
    }
  case ARM::fixup_t2_movw_lo16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_THM_MOVW_ABS_NC;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_THM_MOVW_BREL_NC;
    }
  }
}
コード例 #20
0
ファイル: X86ELFObjectWriter.cpp プロジェクト: Hohahiu/llvm
unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel,
                                          bool IsRelocWithSymbol,
                                          int64_t Addend) const {
  // determine the type of the relocation

  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
  unsigned Type;
  if (getEMachine() == ELF::EM_X86_64) {
    if (IsPCRel) {
      switch ((unsigned)Fixup.getKind()) {
      default: llvm_unreachable("invalid fixup kind!");

      case FK_Data_8: Type = ELF::R_X86_64_PC64; break;
      case FK_Data_4: Type = ELF::R_X86_64_PC32; break;
      case FK_Data_2: Type = ELF::R_X86_64_PC16; break;

      case FK_PCRel_8:
        assert(Modifier == MCSymbolRefExpr::VK_None);
        Type = ELF::R_X86_64_PC64;
        break;
      case X86::reloc_signed_4byte:
      case X86::reloc_riprel_4byte_movq_load:
      case X86::reloc_riprel_4byte:
      case FK_PCRel_4:
        switch (Modifier) {
        default:
          llvm_unreachable("Unimplemented");
        case MCSymbolRefExpr::VK_None:
          Type = ELF::R_X86_64_PC32;
          break;
        case MCSymbolRefExpr::VK_PLT:
          Type = ELF::R_X86_64_PLT32;
          break;
        case MCSymbolRefExpr::VK_GOTPCREL:
          Type = ELF::R_X86_64_GOTPCREL;
          break;
        case MCSymbolRefExpr::VK_GOTTPOFF:
          Type = ELF::R_X86_64_GOTTPOFF;
        break;
        case MCSymbolRefExpr::VK_TLSGD:
          Type = ELF::R_X86_64_TLSGD;
          break;
        case MCSymbolRefExpr::VK_TLSLD:
          Type = ELF::R_X86_64_TLSLD;
          break;
        }
        break;
      case FK_PCRel_2:
        assert(Modifier == MCSymbolRefExpr::VK_None);
        Type = ELF::R_X86_64_PC16;
        break;
      case FK_PCRel_1:
        assert(Modifier == MCSymbolRefExpr::VK_None);
        Type = ELF::R_X86_64_PC8;
        break;
      }
    } else {
      switch ((unsigned)Fixup.getKind()) {
      default: llvm_unreachable("invalid fixup kind!");
      case FK_Data_8:
        switch (Modifier) {
        default:
          llvm_unreachable("Unimplemented");
        case MCSymbolRefExpr::VK_None:
          Type = ELF::R_X86_64_64;
          break;
        case MCSymbolRefExpr::VK_TPOFF:
          Type = ELF::R_X86_64_TPOFF64;
          break;
        case MCSymbolRefExpr::VK_DTPOFF:
          Type = ELF::R_X86_64_DTPOFF64;
          break;
        }
        break;
      case X86::reloc_signed_4byte:
        switch (Modifier) {
        default:
          llvm_unreachable("Unimplemented");
        case MCSymbolRefExpr::VK_None:
          Type = ELF::R_X86_64_32S;
          break;
        case MCSymbolRefExpr::VK_GOT:
          Type = ELF::R_X86_64_GOT32;
          break;
        case MCSymbolRefExpr::VK_GOTPCREL:
          Type = ELF::R_X86_64_GOTPCREL;
          break;
        case MCSymbolRefExpr::VK_TPOFF:
          Type = ELF::R_X86_64_TPOFF32;
          break;
        case MCSymbolRefExpr::VK_DTPOFF:
          Type = ELF::R_X86_64_DTPOFF32;
          break;
        }
        break;
      case FK_Data_4:
        Type = ELF::R_X86_64_32;
        break;
      case FK_Data_2: Type = ELF::R_X86_64_16; break;
      case FK_PCRel_1:
      case FK_Data_1: Type = ELF::R_X86_64_8; break;
      }
    }
  } else if (getEMachine() == ELF::EM_386) {
    if (IsPCRel) {
      switch ((unsigned)Fixup.getKind()) {
      default: llvm_unreachable("invalid fixup kind!");

      case X86::reloc_global_offset_table:
        Type = ELF::R_386_GOTPC;
        break;

      case X86::reloc_signed_4byte:
      case FK_PCRel_4:
      case FK_Data_4:
        switch (Modifier) {
        default:
          llvm_unreachable("Unimplemented");
        case MCSymbolRefExpr::VK_None:
          Type = ELF::R_386_PC32;
          break;
        case MCSymbolRefExpr::VK_PLT:
          Type = ELF::R_386_PLT32;
          break;
        }
        break;
      }
    } else {
      switch ((unsigned)Fixup.getKind()) {
      default: llvm_unreachable("invalid fixup kind!");

      case X86::reloc_global_offset_table:
        Type = ELF::R_386_GOTPC;
        break;

      // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
      // instead?
      case X86::reloc_signed_4byte:
      case FK_PCRel_4:
      case FK_Data_4:
        switch (Modifier) {
        default:
          llvm_unreachable("Unimplemented");
        case MCSymbolRefExpr::VK_None:
          Type = ELF::R_386_32;
          break;
        case MCSymbolRefExpr::VK_GOT:
          Type = ELF::R_386_GOT32;
          break;
        case MCSymbolRefExpr::VK_GOTOFF:
          Type = ELF::R_386_GOTOFF;
          break;
        case MCSymbolRefExpr::VK_TLSGD:
          Type = ELF::R_386_TLS_GD;
          break;
        case MCSymbolRefExpr::VK_TPOFF:
          Type = ELF::R_386_TLS_LE_32;
          break;
        case MCSymbolRefExpr::VK_INDNTPOFF:
          Type = ELF::R_386_TLS_IE;
          break;
        case MCSymbolRefExpr::VK_NTPOFF:
          Type = ELF::R_386_TLS_LE;
          break;
        case MCSymbolRefExpr::VK_GOTNTPOFF:
          Type = ELF::R_386_TLS_GOTIE;
          break;
        case MCSymbolRefExpr::VK_TLSLDM:
          Type = ELF::R_386_TLS_LDM;
          break;
        case MCSymbolRefExpr::VK_DTPOFF:
          Type = ELF::R_386_TLS_LDO_32;
          break;
        case MCSymbolRefExpr::VK_GOTTPOFF:
          Type = ELF::R_386_TLS_IE_32;
          break;
        }
        break;
      case FK_Data_2: Type = ELF::R_386_16; break;
      case FK_PCRel_1:
      case FK_Data_1: Type = ELF::R_386_8; break;
      }
    }
  } else
    llvm_unreachable("Unsupported ELF machine type.");

  return Type;
}
コード例 #21
0
unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
                                              const MCValue &Target,
                                              const MCFixup &Fixup,
                                              bool IsCrossSection,
                                              const MCAsmBackend &MAB) const {
  unsigned FixupKind = Fixup.getKind();
  if (IsCrossSection) {
    if (FixupKind != FK_Data_4 && FixupKind != llvm::X86::reloc_signed_4byte) {
      Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression");
      return COFF::IMAGE_REL_AMD64_ADDR32;
    }
    FixupKind = FK_PCRel_4;
  }

  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();

  if (getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64) {
    switch (FixupKind) {
    case FK_PCRel_4:
    case X86::reloc_riprel_4byte:
    case X86::reloc_riprel_4byte_movq_load:
    case X86::reloc_riprel_4byte_relax:
    case X86::reloc_riprel_4byte_relax_rex:
    case X86::reloc_branch_4byte_pcrel:
      return COFF::IMAGE_REL_AMD64_REL32;
    case FK_Data_4:
    case X86::reloc_signed_4byte:
    case X86::reloc_signed_4byte_relax:
      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
        return COFF::IMAGE_REL_AMD64_ADDR32NB;
      if (Modifier == MCSymbolRefExpr::VK_SECREL)
        return COFF::IMAGE_REL_AMD64_SECREL;
      return COFF::IMAGE_REL_AMD64_ADDR32;
    case FK_Data_8:
      return COFF::IMAGE_REL_AMD64_ADDR64;
    case FK_SecRel_2:
      return COFF::IMAGE_REL_AMD64_SECTION;
    case FK_SecRel_4:
      return COFF::IMAGE_REL_AMD64_SECREL;
    default:
      Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
      return COFF::IMAGE_REL_AMD64_ADDR32;
    }
  } else if (getMachine() == COFF::IMAGE_FILE_MACHINE_I386) {
    switch (FixupKind) {
    case FK_PCRel_4:
    case X86::reloc_riprel_4byte:
    case X86::reloc_riprel_4byte_movq_load:
      return COFF::IMAGE_REL_I386_REL32;
    case FK_Data_4:
    case X86::reloc_signed_4byte:
    case X86::reloc_signed_4byte_relax:
      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
        return COFF::IMAGE_REL_I386_DIR32NB;
      if (Modifier == MCSymbolRefExpr::VK_SECREL)
        return COFF::IMAGE_REL_AMD64_SECREL;
      return COFF::IMAGE_REL_I386_DIR32;
    case FK_SecRel_2:
      return COFF::IMAGE_REL_I386_SECTION;
    case FK_SecRel_4:
      return COFF::IMAGE_REL_I386_SECREL;
    default:
      Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
      return COFF::IMAGE_REL_I386_DIR32;
    }
  } else
    llvm_unreachable("Unsupported COFF machine type.");
}
コード例 #22
0
unsigned HexagonELFObjectWriter::getRelocType(MCContext &Ctx,
                                              MCValue const &Target,
                                              MCFixup const &Fixup,
                                              bool IsPCRel) const {
  MCSymbolRefExpr::VariantKind Variant = Target.getAccessVariant();
  switch ((unsigned)Fixup.getKind()) {
  default:
    report_fatal_error("Unrecognized relocation type");
    break;
  case FK_Data_4:
    switch(Variant) {
    case MCSymbolRefExpr::VariantKind::VK_PPC_DTPREL:
      return ELF::R_HEX_DTPREL_32;
    case MCSymbolRefExpr::VariantKind::VK_GOT:
      return ELF::R_HEX_GOT_32;
    case MCSymbolRefExpr::VariantKind::VK_GOTREL:
      return ELF::R_HEX_GOTREL_32;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_GD_GOT:
      return ELF::R_HEX_GD_GOT_32;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_IE:
      return ELF::R_HEX_IE_32;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_IE_GOT:
      return ELF::R_HEX_IE_GOT_32;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_LD_GOT:
      return ELF::R_HEX_LD_GOT_32;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_PCREL:
      return ELF::R_HEX_32_PCREL;
    case MCSymbolRefExpr::VariantKind::VK_PPC_TPREL:
      return ELF::R_HEX_TPREL_32;
    case MCSymbolRefExpr::VariantKind::VK_None:
      return IsPCRel ? ELF::R_HEX_32_PCREL : ELF::R_HEX_32;
    default:
      report_fatal_error("Unrecognized variant type");
    };
  case FK_PCRel_4:
    return ELF::R_HEX_32_PCREL;
  case FK_Data_2:
    switch(Variant) {
    case MCSymbolRefExpr::VariantKind::VK_PPC_DTPREL:
      return ELF::R_HEX_DTPREL_16;
    case MCSymbolRefExpr::VariantKind::VK_GOT:
      return ELF::R_HEX_GOT_16;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_GD_GOT:
      return ELF::R_HEX_GD_GOT_16;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_IE_GOT:
      return ELF::R_HEX_IE_GOT_16;
    case MCSymbolRefExpr::VariantKind::VK_Hexagon_LD_GOT:
      return ELF::R_HEX_LD_GOT_16;
    case MCSymbolRefExpr::VariantKind::VK_PPC_TPREL:
      return ELF::R_HEX_TPREL_16;
    case MCSymbolRefExpr::VariantKind::VK_None:
      return ELF::R_HEX_16;
    default:
      report_fatal_error("Unrecognized variant type");
    };
  case FK_Data_1:
    return ELF::R_HEX_8;
  case fixup_Hexagon_B22_PCREL:
    return ELF::R_HEX_B22_PCREL;
  case fixup_Hexagon_B15_PCREL:
    return ELF::R_HEX_B15_PCREL;
  case fixup_Hexagon_B7_PCREL:
    return ELF::R_HEX_B7_PCREL;
  case fixup_Hexagon_LO16:
    return ELF::R_HEX_LO16;
  case fixup_Hexagon_HI16:
    return ELF::R_HEX_HI16;
  case fixup_Hexagon_32:
    return ELF::R_HEX_32;
  case fixup_Hexagon_16:
    return ELF::R_HEX_16;
  case fixup_Hexagon_8:
    return ELF::R_HEX_8;
  case fixup_Hexagon_GPREL16_0:
    return ELF::R_HEX_GPREL16_0;
  case fixup_Hexagon_GPREL16_1:
    return ELF::R_HEX_GPREL16_1;
  case fixup_Hexagon_GPREL16_2:
    return ELF::R_HEX_GPREL16_2;
  case fixup_Hexagon_GPREL16_3:
    return ELF::R_HEX_GPREL16_3;
  case fixup_Hexagon_HL16:
    return ELF::R_HEX_HL16;
  case fixup_Hexagon_B13_PCREL:
    return ELF::R_HEX_B13_PCREL;
  case fixup_Hexagon_B9_PCREL:
    return ELF::R_HEX_B9_PCREL;
  case fixup_Hexagon_B32_PCREL_X:
    return ELF::R_HEX_B32_PCREL_X;
  case fixup_Hexagon_32_6_X:
    return ELF::R_HEX_32_6_X;
  case fixup_Hexagon_B22_PCREL_X:
    return ELF::R_HEX_B22_PCREL_X;
  case fixup_Hexagon_B15_PCREL_X:
    return ELF::R_HEX_B15_PCREL_X;
  case fixup_Hexagon_B13_PCREL_X:
    return ELF::R_HEX_B13_PCREL_X;
  case fixup_Hexagon_B9_PCREL_X:
    return ELF::R_HEX_B9_PCREL_X;
  case fixup_Hexagon_B7_PCREL_X:
    return ELF::R_HEX_B7_PCREL_X;
  case fixup_Hexagon_16_X:
    return ELF::R_HEX_16_X;
  case fixup_Hexagon_12_X:
    return ELF::R_HEX_12_X;
  case fixup_Hexagon_11_X:
    return ELF::R_HEX_11_X;
  case fixup_Hexagon_10_X:
    return ELF::R_HEX_10_X;
  case fixup_Hexagon_9_X:
    return ELF::R_HEX_9_X;
  case fixup_Hexagon_8_X:
    return ELF::R_HEX_8_X;
  case fixup_Hexagon_7_X:
    return ELF::R_HEX_7_X;
  case fixup_Hexagon_6_X:
    return ELF::R_HEX_6_X;
  case fixup_Hexagon_32_PCREL:
    return ELF::R_HEX_32_PCREL;
  case fixup_Hexagon_COPY:
    return ELF::R_HEX_COPY;
  case fixup_Hexagon_GLOB_DAT:
    return ELF::R_HEX_GLOB_DAT;
  case fixup_Hexagon_JMP_SLOT:
    return ELF::R_HEX_JMP_SLOT;
  case fixup_Hexagon_RELATIVE:
    return ELF::R_HEX_RELATIVE;
  case fixup_Hexagon_PLT_B22_PCREL:
    return ELF::R_HEX_PLT_B22_PCREL;
  case fixup_Hexagon_GOTREL_LO16:
    return ELF::R_HEX_GOTREL_LO16;
  case fixup_Hexagon_GOTREL_HI16:
    return ELF::R_HEX_GOTREL_HI16;
  case fixup_Hexagon_GOTREL_32:
    return ELF::R_HEX_GOTREL_32;
  case fixup_Hexagon_GOT_LO16:
    return ELF::R_HEX_GOT_LO16;
  case fixup_Hexagon_GOT_HI16:
    return ELF::R_HEX_GOT_HI16;
  case fixup_Hexagon_GOT_32:
    return ELF::R_HEX_GOT_32;
  case fixup_Hexagon_GOT_16:
    return ELF::R_HEX_GOT_16;
  case fixup_Hexagon_DTPMOD_32:
    return ELF::R_HEX_DTPMOD_32;
  case fixup_Hexagon_DTPREL_LO16:
    return ELF::R_HEX_DTPREL_LO16;
  case fixup_Hexagon_DTPREL_HI16:
    return ELF::R_HEX_DTPREL_HI16;
  case fixup_Hexagon_DTPREL_32:
    return ELF::R_HEX_DTPREL_32;
  case fixup_Hexagon_DTPREL_16:
    return ELF::R_HEX_DTPREL_16;
  case fixup_Hexagon_GD_PLT_B22_PCREL:
    return ELF::R_HEX_GD_PLT_B22_PCREL;
  case fixup_Hexagon_LD_PLT_B22_PCREL:
    return ELF::R_HEX_LD_PLT_B22_PCREL;
  case fixup_Hexagon_GD_GOT_LO16:
    return ELF::R_HEX_GD_GOT_LO16;
  case fixup_Hexagon_GD_GOT_HI16:
    return ELF::R_HEX_GD_GOT_HI16;
  case fixup_Hexagon_GD_GOT_32:
    return ELF::R_HEX_GD_GOT_32;
  case fixup_Hexagon_GD_GOT_16:
    return ELF::R_HEX_GD_GOT_16;
  case fixup_Hexagon_LD_GOT_LO16:
    return ELF::R_HEX_LD_GOT_LO16;
  case fixup_Hexagon_LD_GOT_HI16:
    return ELF::R_HEX_LD_GOT_HI16;
  case fixup_Hexagon_LD_GOT_32:
    return ELF::R_HEX_LD_GOT_32;
  case fixup_Hexagon_LD_GOT_16:
    return ELF::R_HEX_LD_GOT_16;
  case fixup_Hexagon_IE_LO16:
    return ELF::R_HEX_IE_LO16;
  case fixup_Hexagon_IE_HI16:
    return ELF::R_HEX_IE_HI16;
  case fixup_Hexagon_IE_32:
    return ELF::R_HEX_IE_32;
  case fixup_Hexagon_IE_GOT_LO16:
    return ELF::R_HEX_IE_GOT_LO16;
  case fixup_Hexagon_IE_GOT_HI16:
    return ELF::R_HEX_IE_GOT_HI16;
  case fixup_Hexagon_IE_GOT_32:
    return ELF::R_HEX_IE_GOT_32;
  case fixup_Hexagon_IE_GOT_16:
    return ELF::R_HEX_IE_GOT_16;
  case fixup_Hexagon_TPREL_LO16:
    return ELF::R_HEX_TPREL_LO16;
  case fixup_Hexagon_TPREL_HI16:
    return ELF::R_HEX_TPREL_HI16;
  case fixup_Hexagon_TPREL_32:
    return ELF::R_HEX_TPREL_32;
  case fixup_Hexagon_TPREL_16:
    return ELF::R_HEX_TPREL_16;
  case fixup_Hexagon_6_PCREL_X:
    return ELF::R_HEX_6_PCREL_X;
  case fixup_Hexagon_GOTREL_32_6_X:
    return ELF::R_HEX_GOTREL_32_6_X;
  case fixup_Hexagon_GOTREL_16_X:
    return ELF::R_HEX_GOTREL_16_X;
  case fixup_Hexagon_GOTREL_11_X:
    return ELF::R_HEX_GOTREL_11_X;
  case fixup_Hexagon_GOT_32_6_X:
    return ELF::R_HEX_GOT_32_6_X;
  case fixup_Hexagon_GOT_16_X:
    return ELF::R_HEX_GOT_16_X;
  case fixup_Hexagon_GOT_11_X:
    return ELF::R_HEX_GOT_11_X;
  case fixup_Hexagon_DTPREL_32_6_X:
    return ELF::R_HEX_DTPREL_32_6_X;
  case fixup_Hexagon_DTPREL_16_X:
    return ELF::R_HEX_DTPREL_16_X;
  case fixup_Hexagon_DTPREL_11_X:
    return ELF::R_HEX_DTPREL_11_X;
  case fixup_Hexagon_GD_GOT_32_6_X:
    return ELF::R_HEX_GD_GOT_32_6_X;
  case fixup_Hexagon_GD_GOT_16_X:
    return ELF::R_HEX_GD_GOT_16_X;
  case fixup_Hexagon_GD_GOT_11_X:
    return ELF::R_HEX_GD_GOT_11_X;
  case fixup_Hexagon_LD_GOT_32_6_X:
    return ELF::R_HEX_LD_GOT_32_6_X;
  case fixup_Hexagon_LD_GOT_16_X:
    return ELF::R_HEX_LD_GOT_16_X;
  case fixup_Hexagon_LD_GOT_11_X:
    return ELF::R_HEX_LD_GOT_11_X;
  case fixup_Hexagon_IE_32_6_X:
    return ELF::R_HEX_IE_32_6_X;
  case fixup_Hexagon_IE_16_X:
    return ELF::R_HEX_IE_16_X;
  case fixup_Hexagon_IE_GOT_32_6_X:
    return ELF::R_HEX_IE_GOT_32_6_X;
  case fixup_Hexagon_IE_GOT_16_X:
    return ELF::R_HEX_IE_GOT_16_X;
  case fixup_Hexagon_IE_GOT_11_X:
    return ELF::R_HEX_IE_GOT_11_X;
  case fixup_Hexagon_TPREL_32_6_X:
    return ELF::R_HEX_TPREL_32_6_X;
  case fixup_Hexagon_TPREL_16_X:
    return ELF::R_HEX_TPREL_16_X;
  case fixup_Hexagon_TPREL_11_X:
    return ELF::R_HEX_TPREL_11_X;
  }
}
コード例 #23
0
ファイル: AVRELFObjectWriter.cpp プロジェクト: jamboree/llvm
unsigned AVRELFObjectWriter::getRelocType(MCContext &Ctx,
                                          const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel) const {
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
  switch ((unsigned) Fixup.getKind()) {
  case FK_Data_1:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_AVR_8;
    case MCSymbolRefExpr::VK_AVR_DIFF8:
      return ELF::R_AVR_DIFF8;
    case MCSymbolRefExpr::VK_AVR_LO8:
      return ELF::R_AVR_8_LO8;
    case MCSymbolRefExpr::VK_AVR_HI8:
      return ELF::R_AVR_8_HI8;
    case MCSymbolRefExpr::VK_AVR_HLO8:
      return ELF::R_AVR_8_HLO8;
    }
  case FK_Data_4:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_AVR_32;
    case MCSymbolRefExpr::VK_AVR_DIFF32:
      return ELF::R_AVR_DIFF32;
    }
  case FK_Data_2:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_AVR_16;
    case MCSymbolRefExpr::VK_AVR_NONE:
      return ELF::R_AVR_16_PM;
    case MCSymbolRefExpr::VK_AVR_DIFF16:
      return ELF::R_AVR_DIFF16;
    }
  case AVR::fixup_32:
    return ELF::R_AVR_32;
  case AVR::fixup_7_pcrel:
    return ELF::R_AVR_7_PCREL;
  case AVR::fixup_13_pcrel:
    return ELF::R_AVR_13_PCREL;
  case AVR::fixup_16:
    return ELF::R_AVR_16;
  case AVR::fixup_16_pm:
    return ELF::R_AVR_16_PM;
  case AVR::fixup_lo8_ldi:
    return ELF::R_AVR_LO8_LDI;
  case AVR::fixup_hi8_ldi:
    return ELF::R_AVR_HI8_LDI;
  case AVR::fixup_hh8_ldi:
    return ELF::R_AVR_HH8_LDI;
  case AVR::fixup_lo8_ldi_neg:
    return ELF::R_AVR_LO8_LDI_NEG;
  case AVR::fixup_hi8_ldi_neg:
    return ELF::R_AVR_HI8_LDI_NEG;
  case AVR::fixup_hh8_ldi_neg:
    return ELF::R_AVR_HH8_LDI_NEG;
  case AVR::fixup_lo8_ldi_pm:
    return ELF::R_AVR_LO8_LDI_PM;
  case AVR::fixup_hi8_ldi_pm:
    return ELF::R_AVR_HI8_LDI_PM;
  case AVR::fixup_hh8_ldi_pm:
    return ELF::R_AVR_HH8_LDI_PM;
  case AVR::fixup_lo8_ldi_pm_neg:
    return ELF::R_AVR_LO8_LDI_PM_NEG;
  case AVR::fixup_hi8_ldi_pm_neg:
    return ELF::R_AVR_HI8_LDI_PM_NEG;
  case AVR::fixup_hh8_ldi_pm_neg:
    return ELF::R_AVR_HH8_LDI_PM_NEG;
  case AVR::fixup_call:
    return ELF::R_AVR_CALL;
  case AVR::fixup_ldi:
    return ELF::R_AVR_LDI;
  case AVR::fixup_6:
    return ELF::R_AVR_6;
  case AVR::fixup_6_adiw:
    return ELF::R_AVR_6_ADIW;
  case AVR::fixup_ms8_ldi:
    return ELF::R_AVR_MS8_LDI;
  case AVR::fixup_ms8_ldi_neg:
    return ELF::R_AVR_MS8_LDI_NEG;
  case AVR::fixup_lo8_ldi_gs:
    return ELF::R_AVR_LO8_LDI_GS;
  case AVR::fixup_hi8_ldi_gs:
    return ELF::R_AVR_HI8_LDI_GS;
  case AVR::fixup_8:
    return ELF::R_AVR_8;
  case AVR::fixup_8_lo8:
    return ELF::R_AVR_8_LO8;
  case AVR::fixup_8_hi8:
    return ELF::R_AVR_8_HI8;
  case AVR::fixup_8_hlo8:
    return ELF::R_AVR_8_HLO8;
  case AVR::fixup_diff8:
    return ELF::R_AVR_DIFF8;
  case AVR::fixup_diff16:
    return ELF::R_AVR_DIFF16;
  case AVR::fixup_diff32:
    return ELF::R_AVR_DIFF32;
  case AVR::fixup_lds_sts_16:
    return ELF::R_AVR_LDS_STS_16;
  case AVR::fixup_port6:
    return ELF::R_AVR_PORT6;
  case AVR::fixup_port5:
    return ELF::R_AVR_PORT5;
  default:
    llvm_unreachable("invalid fixup kind!");
  }
}
コード例 #24
0
ファイル: Cpu0ELFObjectWriter.cpp プロジェクト: Kobe771/lbd
// Cpu0ELFObjectWriter::GetRelocType()
unsigned Cpu0ELFObjectWriter::GetRelocType(const MCValue &Target,
        const MCFixup &Fixup,
        bool IsPCRel,
        bool IsRelocWithSymbol,
        int64_t Addend) const {
    // determine the type of the relocation
    unsigned Type = (unsigned)ELF::R_CPU0_NONE;
    unsigned Kind = (unsigned)Fixup.getKind();

    switch (Kind) {
    default:
        llvm_unreachable("invalid fixup kind!");
    case FK_Data_4:
        Type = ELF::R_CPU0_32;
        break;
    case FK_GPRel_4:
        Type = ELF::R_CPU0_GPREL32;
        break;
    case Cpu0::fixup_Cpu0_GPREL16:
        Type = ELF::R_CPU0_GPREL16;
        break;
    case Cpu0::fixup_Cpu0_24:
        Type = ELF::R_CPU0_24;
        break;
    case Cpu0::fixup_Cpu0_CALL24:
        Type = ELF::R_CPU0_CALL24;
        break;
    case Cpu0::fixup_Cpu0_GOT_Global:
    case Cpu0::fixup_Cpu0_GOT_Local:
        Type = ELF::R_CPU0_GOT16;
        break;
    case Cpu0::fixup_Cpu0_HI16:
        Type = ELF::R_CPU0_HI16;
        break;
    case Cpu0::fixup_Cpu0_LO16:
        Type = ELF::R_CPU0_LO16;
        break;
    case Cpu0::fixup_Cpu0_TLSGD:
        Type = ELF::R_CPU0_TLS_GD;
        break;
    case Cpu0::fixup_Cpu0_GOTTPREL:
        Type = ELF::R_CPU0_TLS_GOTTPREL;
        break;
    case Cpu0::fixup_Cpu0_TPREL_HI:
        Type = ELF::R_CPU0_TLS_TPREL_HI16;
        break;
    case Cpu0::fixup_Cpu0_TPREL_LO:
        Type = ELF::R_CPU0_TLS_TPREL_LO16;
        break;
    case Cpu0::fixup_Cpu0_TLSLDM:
        Type = ELF::R_CPU0_TLS_LDM;
        break;
    case Cpu0::fixup_Cpu0_DTPREL_HI:
        Type = ELF::R_CPU0_TLS_DTPREL_HI16;
        break;
    case Cpu0::fixup_Cpu0_DTPREL_LO:
        Type = ELF::R_CPU0_TLS_DTPREL_LO16;
        break;
    case Cpu0::fixup_Cpu0_Branch_PCRel:
    case Cpu0::fixup_Cpu0_PC24:
        Type = ELF::R_CPU0_PC24;
        break;
    case Cpu0::fixup_Cpu0_GOT_HI16:
        Type = ELF::R_CPU0_GOT_HI16;
        break;
    case Cpu0::fixup_Cpu0_GOT_LO16:
        Type = ELF::R_CPU0_GOT_LO16;
        break;
    }

    return Type;
}
コード例 #25
0
void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
                                       const MCAsmLayout &Layout,
                                       const MCFragment *Fragment,
                                       const MCFixup &Fixup, MCValue Target,
                                       uint64_t &FixedValue) {
  MCAsmBackend &Backend = Asm.getBackend();
  bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
                 MCFixupKindInfo::FKF_IsPCRel;
  const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
  uint64_t C = Target.getConstant();
  uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  MCContext &Ctx = Asm.getContext();

  if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
    // Let A, B and C being the components of Target and R be the location of
    // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
    // If it is pcrel, we want to compute (A - B + C - R).

    // In general, ELF has no relocations for -B. It can only represent (A + C)
    // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
    // replace B to implement it: (A - R - K + C)
    if (IsPCRel) {
      Ctx.reportError(
          Fixup.getLoc(),
          "No relocation available to represent this relative expression");
      return;
    }

    const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());

    if (SymB.isUndefined()) {
      Ctx.reportError(Fixup.getLoc(),
                      Twine("symbol '") + SymB.getName() +
                          "' can not be undefined in a subtraction expression");
      return;
    }

    assert(!SymB.isAbsolute() && "Should have been folded");
    const MCSection &SecB = SymB.getSection();
    if (&SecB != &FixupSection) {
      Ctx.reportError(Fixup.getLoc(),
                      "Cannot represent a difference across sections");
      return;
    }

    uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
    uint64_t K = SymBOffset - FixupOffset;
    IsPCRel = true;
    C -= K;
  }

  // We either rejected the fixup or folded B into C at this point.
  const MCSymbolRefExpr *RefA = Target.getSymA();
  const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;

  bool ViaWeakRef = false;
  if (SymA && SymA->isVariable()) {
    const MCExpr *Expr = SymA->getVariableValue();
    if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
      if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
        SymA = cast<MCSymbolELF>(&Inner->getSymbol());
        ViaWeakRef = true;
      }
    }
  }

  unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel);
  uint64_t OriginalC = C;
  bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type);
  if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
    C += Layout.getSymbolOffset(*SymA);

  uint64_t Addend = 0;
  if (hasRelocationAddend()) {
    Addend = C;
    C = 0;
  }

  FixedValue = C;

  if (!RelocateWithSymbol) {
    const MCSection *SecA =
        (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
    auto *ELFSec = cast_or_null<MCSectionELF>(SecA);
    const auto *SectionSymbol =
        ELFSec ? cast<MCSymbolELF>(ELFSec->getBeginSymbol()) : nullptr;
    if (SectionSymbol)
      SectionSymbol->setUsedInReloc();
    ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA,
                           OriginalC);
    Relocations[&FixupSection].push_back(Rec);
    return;
  }

  const auto *RenamedSymA = SymA;
  if (SymA) {
    if (const MCSymbolELF *R = Renames.lookup(SymA))
      RenamedSymA = R;

    if (ViaWeakRef)
      RenamedSymA->setIsWeakrefUsedInReloc();
    else
      RenamedSymA->setUsedInReloc();
  }
  ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA,
                         OriginalC);
  Relocations[&FixupSection].push_back(Rec);
}
コード例 #26
0
void ARMMachObjectWriter::
RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
                                 const MCAssembler &Asm,
                                 const MCAsmLayout &Layout,
                                 const MCFragment *Fragment,
                                 const MCFixup &Fixup,
                                 MCValue Target,
                                 uint64_t &FixedValue) {
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();

  if (FixupOffset & 0xff000000) {
    Asm.getContext().reportError(Fixup.getLoc(),
                                 "can not encode offset '0x" +
                                     to_hexString(FixupOffset) +
                                     "' in resulting scattered relocation.");
    return;
  }

  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned Type = MachO::ARM_RELOC_HALF;

  // See <reloc.h>.
  const MCSymbol *A = &Target.getSymA()->getSymbol();

  if (!A->getFragment()) {
    Asm.getContext().reportError(Fixup.getLoc(),
                       "symbol '" + A->getName() +
                       "' can not be undefined in a subtraction expression");
    return;
  }

  uint32_t Value = Writer->getSymbolAddress(*A, Layout);
  uint32_t Value2 = 0;
  uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
  FixedValue += SecAddr;

  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    const MCSymbol *SB = &B->getSymbol();

    if (!SB->getFragment()) {
      Asm.getContext().reportError(Fixup.getLoc(),
                         "symbol '" + B->getSymbol().getName() +
                         "' can not be undefined in a subtraction expression");
      return;
    }

    // Select the appropriate difference relocation type.
    Type = MachO::ARM_RELOC_HALF_SECTDIFF;
    Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout);
    FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
  }

  // Relocations are written out in reverse order, so the PAIR comes first.
  // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
  //
  // For these two r_type relocations they always have a pair following them and
  // the r_length bits are used differently.  The encoding of the r_length is as
  // follows:
  //   low bit of r_length:
  //      0 - :lower16: for movw instructions
  //      1 - :upper16: for movt instructions
  //   high bit of r_length:
  //      0 - arm instructions
  //      1 - thumb instructions
  // the other half of the relocated expression is in the following pair
  // relocation entry in the low 16 bits of r_address field.
  unsigned ThumbBit = 0;
  unsigned MovtBit = 0;
  switch ((unsigned)Fixup.getKind()) {
  default: break;
  case ARM::fixup_arm_movt_hi16:
    MovtBit = 1;
    // The thumb bit shouldn't be set in the 'other-half' bit of the
    // relocation, but it will be set in FixedValue if the base symbol
    // is a thumb function. Clear it out here.
    if (Asm.isThumbFunc(A))
      FixedValue &= 0xfffffffe;
    break;
  case ARM::fixup_t2_movt_hi16:
    if (Asm.isThumbFunc(A))
      FixedValue &= 0xfffffffe;
    MovtBit = 1;
    LLVM_FALLTHROUGH;
  case ARM::fixup_t2_movw_lo16:
    ThumbBit = 1;
    break;
  }

  if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
    uint32_t OtherHalf = MovtBit
      ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);

    MachO::any_relocation_info MRE;
    MRE.r_word0 = ((OtherHalf             <<  0) |
                   (MachO::ARM_RELOC_PAIR << 24) |
                   (MovtBit               << 28) |
                   (ThumbBit              << 29) |
                   (IsPCRel               << 30) |
                   MachO::R_SCATTERED);
    MRE.r_word1 = Value2;
    Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
  }
コード例 #27
0
ファイル: X86MachObjectWriter.cpp プロジェクト: Dagrol/llvm
bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
                                                    const MCAssembler &Asm,
                                                    const MCAsmLayout &Layout,
                                                    const MCFragment *Fragment,
                                                    const MCFixup &Fixup,
                                                    MCValue Target,
                                                    unsigned Log2Size,
                                                    uint64_t &FixedValue) {
  uint64_t OriginalFixedValue = FixedValue;
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned Type = MachO::GENERIC_RELOC_VANILLA;

  // See <reloc.h>.
  const MCSymbol *A = &Target.getSymA()->getSymbol();
  const MCSymbolData *A_SD = &Asm.getSymbolData(*A);

  if (!A_SD->getFragment())
    report_fatal_error("symbol '" + A->getName() +
                       "' can not be undefined in a subtraction expression",
                       false);

  uint32_t Value = Writer->getSymbolAddress(*A, Layout);
  uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
  FixedValue += SecAddr;
  uint32_t Value2 = 0;

  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());

    if (!B_SD->getFragment())
      report_fatal_error("symbol '" + B->getSymbol().getName() +
                         "' can not be undefined in a subtraction expression",
                         false);

    // Select the appropriate difference relocation type.
    //
    // Note that there is no longer any semantic difference between these two
    // relocation types from the linkers point of view, this is done solely for
    // pedantic compatibility with 'as'.
    Type = A_SD->isExternal() ? (unsigned)MachO::GENERIC_RELOC_SECTDIFF :
      (unsigned)MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
    Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout);
    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
  }

  // Relocations are written out in reverse order, so the PAIR comes first.
  if (Type == MachO::GENERIC_RELOC_SECTDIFF ||
      Type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
    // If the offset is too large to fit in a scattered relocation,
    // we're hosed. It's an unfortunate limitation of the MachO format.
    if (FixupOffset > 0xffffff) {
      char Buffer[32];
      format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
      Asm.getContext().reportFatalError(Fixup.getLoc(),
                         Twine("Section too large, can't encode "
                                "r_address (") + Buffer +
                         ") into 24 bits of scattered "
                         "relocation entry.");
      llvm_unreachable("fatal error returned?!");
    }

    MachO::any_relocation_info MRE;
    MRE.r_word0 = ((0                         <<  0) | // r_address
                   (MachO::GENERIC_RELOC_PAIR << 24) | // r_type
                   (Log2Size                  << 28) |
                   (IsPCRel                   << 30) |
                   MachO::R_SCATTERED);
    MRE.r_word1 = Value2;
    Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
  } else {
    // If the offset is more than 24-bits, it won't fit in a scattered
    // relocation offset field, so we fall back to using a non-scattered
    // relocation. This is a bit risky, as if the offset reaches out of
    // the block and the linker is doing scattered loading on this
    // symbol, things can go badly.
    //
    // Required for 'as' compatibility.
    if (FixupOffset > 0xffffff) {
      FixedValue = OriginalFixedValue;
      return false;
    }
  }

  MachO::any_relocation_info MRE;
  MRE.r_word0 = ((FixupOffset <<  0) |
                 (Type        << 24) |
                 (Log2Size    << 28) |
                 (IsPCRel     << 30) |
                 MachO::R_SCATTERED);
  MRE.r_word1 = Value;
  Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
  return true;
}
コード例 #28
0
void AArch64MachObjectWriter::RecordRelocation(
    MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
    uint64_t &FixedValue) {
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());

  // See <reloc.h>.
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment);
  unsigned Log2Size = 0;
  int64_t Value = 0;
  unsigned Index = 0;
  unsigned IsExtern = 0;
  unsigned Type = 0;
  unsigned Kind = Fixup.getKind();

  FixupOffset += Fixup.getOffset();

  // AArch64 pcrel relocation addends do not include the section offset.
  if (IsPCRel)
    FixedValue += FixupOffset;

  // ADRP fixups use relocations for the whole symbol value and only
  // put the addend in the instruction itself. Clear out any value the
  // generic code figured out from the sybmol definition.
  if (Kind == AArch64::fixup_aarch64_pcrel_adrp_imm21)
    FixedValue = 0;

  // imm19 relocations are for conditional branches, which require
  // assembler local symbols. If we got here, that's not what we have,
  // so complain loudly.
  if (Kind == AArch64::fixup_aarch64_pcrel_branch19) {
    Asm.getContext().FatalError(Fixup.getLoc(),
                                "conditional branch requires assembler-local"
                                " label. '" +
                                    Target.getSymA()->getSymbol().getName() +
                                    "' is external.");
    return;
  }

  // 14-bit branch relocations should only target internal labels, and so
  // should never get here.
  if (Kind == AArch64::fixup_aarch64_pcrel_branch14) {
    Asm.getContext().FatalError(Fixup.getLoc(),
                                "Invalid relocation on conditional branch!");
    return;
  }

  if (!getAArch64FixupKindMachOInfo(Fixup, Type, Target.getSymA(), Log2Size,
                                  Asm)) {
    Asm.getContext().FatalError(Fixup.getLoc(), "unknown AArch64 fixup kind!");
    return;
  }

  Value = Target.getConstant();

  if (Target.isAbsolute()) { // constant
    // FIXME: Should this always be extern?
    // SymbolNum of 0 indicates the absolute section.
    Type = MachO::ARM64_RELOC_UNSIGNED;
    Index = 0;

    if (IsPCRel) {
      IsExtern = 1;
      Asm.getContext().FatalError(Fixup.getLoc(),
                                  "PC relative absolute relocation!");

      // FIXME: x86_64 sets the type to a branch reloc here. Should we do
      // something similar?
    }
  } else if (Target.getSymB()) { // A - B + constant
    const MCSymbol *A = &Target.getSymA()->getSymbol();
    const MCSymbolData &A_SD = Asm.getSymbolData(*A);
    const MCSymbolData *A_Base = Asm.getAtom(&A_SD);

    const MCSymbol *B = &Target.getSymB()->getSymbol();
    const MCSymbolData &B_SD = Asm.getSymbolData(*B);
    const MCSymbolData *B_Base = Asm.getAtom(&B_SD);

    // Check for "_foo@got - .", which comes through here as:
    // Ltmp0:
    //    ... _foo@got - Ltmp0
    if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOT &&
        Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None &&
        Layout.getSymbolOffset(&B_SD) ==
            Layout.getFragmentOffset(Fragment) + Fixup.getOffset()) {
      // SymB is the PC, so use a PC-rel pointer-to-GOT relocation.
      Index = A_Base->getIndex();
      IsExtern = 1;
      Type = MachO::ARM64_RELOC_POINTER_TO_GOT;
      IsPCRel = 1;
      MachO::any_relocation_info MRE;
      MRE.r_word0 = FixupOffset;
      MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
                     (IsExtern << 27) | (Type << 28));
      Writer->addRelocation(Fragment->getParent(), MRE);
      return;
    } else if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
               Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
      // Otherwise, neither symbol can be modified.
      Asm.getContext().FatalError(Fixup.getLoc(),
                                  "unsupported relocation of modified symbol");

    // We don't support PCrel relocations of differences.
    if (IsPCRel)
      Asm.getContext().FatalError(Fixup.getLoc(),
                                  "unsupported pc-relative relocation of "
                                  "difference");

    // AArch64 always uses external relocations. If there is no symbol to use as
    // a base address (a local symbol with no preceding non-local symbol),
    // error out.
    //
    // FIXME: We should probably just synthesize an external symbol and use
    // that.
    if (!A_Base)
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          "unsupported relocation of local symbol '" + A->getName() +
              "'. Must have non-local symbol earlier in section.");
    if (!B_Base)
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          "unsupported relocation of local symbol '" + B->getName() +
              "'. Must have non-local symbol earlier in section.");

    if (A_Base == B_Base && A_Base)
      Asm.getContext().FatalError(Fixup.getLoc(),
                                  "unsupported relocation with identical base");

    Value += (!A_SD.getFragment() ? 0
                                  : Writer->getSymbolAddress(&A_SD, Layout)) -
             (!A_Base || !A_Base->getFragment()
                  ? 0
                  : Writer->getSymbolAddress(A_Base, Layout));
    Value -= (!B_SD.getFragment() ? 0
                                  : Writer->getSymbolAddress(&B_SD, Layout)) -
             (!B_Base || !B_Base->getFragment()
                  ? 0
                  : Writer->getSymbolAddress(B_Base, Layout));

    Index = A_Base->getIndex();
    IsExtern = 1;
    Type = MachO::ARM64_RELOC_UNSIGNED;

    MachO::any_relocation_info MRE;
    MRE.r_word0 = FixupOffset;
    MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
                   (IsExtern << 27) | (Type << 28));
    Writer->addRelocation(Fragment->getParent(), MRE);

    Index = B_Base->getIndex();
    IsExtern = 1;
    Type = MachO::ARM64_RELOC_SUBTRACTOR;
  } else { // A + constant
    const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
    const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
    const MCSymbolData *Base = Asm.getAtom(&SD);
    const MCSectionMachO &Section = static_cast<const MCSectionMachO &>(
        Fragment->getParent()->getSection());

    // If the symbol is a variable and we weren't able to get a Base for it
    // (i.e., it's not in the symbol table associated with a section) resolve
    // the relocation based its expansion instead.
    if (Symbol->isVariable() && !Base) {
      // If the evaluation is an absolute value, just use that directly
      // to keep things easy.
      int64_t Res;
      if (SD.getSymbol().getVariableValue()->EvaluateAsAbsolute(
              Res, Layout, Writer->getSectionAddressMap())) {
        FixedValue = Res;
        return;
      }

      // FIXME: Will the Target we already have ever have any data in it
      // we need to preserve and merge with the new Target? How about
      // the FixedValue?
      if (!Symbol->getVariableValue()->EvaluateAsRelocatable(Target, &Layout,
                                                             &Fixup))
        Asm.getContext().FatalError(Fixup.getLoc(),
                                    "unable to resolve variable '" +
                                        Symbol->getName() + "'");
      return RecordRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
                              FixedValue);
    }

    // Relocations inside debug sections always use local relocations when
    // possible. This seems to be done because the debugger doesn't fully
    // understand relocation entries and expects to find values that
    // have already been fixed up.
    if (Symbol->isInSection()) {
      if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
        Base = nullptr;
    }

    // AArch64 uses external relocations as much as possible. For debug
    // sections, and for pointer-sized relocations (.quad), we allow section
    // relocations.  It's code sections that run into trouble.
    if (Base) {
      Index = Base->getIndex();
      IsExtern = 1;

      // Add the local offset, if needed.
      if (Base != &SD)
        Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
    } else if (Symbol->isInSection()) {
      // Pointer-sized relocations can use a local relocation. Otherwise,
      // we have to be in a debug info section.
      if (!Section.hasAttribute(MachO::S_ATTR_DEBUG) && Log2Size != 3)
        Asm.getContext().FatalError(
            Fixup.getLoc(),
            "unsupported relocation of local symbol '" + Symbol->getName() +
                "'. Must have non-local symbol earlier in section.");
      // Adjust the relocation to be section-relative.
      // The index is the section ordinal (1-based).
      const MCSectionData &SymSD =
          Asm.getSectionData(SD.getSymbol().getSection());
      Index = SymSD.getOrdinal() + 1;
      IsExtern = 0;
      Value += Writer->getSymbolAddress(&SD, Layout);

      if (IsPCRel)
        Value -= Writer->getFragmentAddress(Fragment, Layout) +
                 Fixup.getOffset() + (1ULL << Log2Size);
    } else {
      // Resolve constant variables.
      if (SD.getSymbol().isVariable()) {
        int64_t Res;
        if (SD.getSymbol().getVariableValue()->EvaluateAsAbsolute(
                Res, Layout, Writer->getSectionAddressMap())) {
          FixedValue = Res;
          return;
        }
      }
      Asm.getContext().FatalError(Fixup.getLoc(),
                                  "unsupported relocation of variable '" +
                                      Symbol->getName() + "'");
    }
  }

  // If the relocation kind is Branch26, Page21, or Pageoff12, any addend
  // is represented via an Addend relocation, not encoded directly into
  // the instruction.
  if ((Type == MachO::ARM64_RELOC_BRANCH26 ||
       Type == MachO::ARM64_RELOC_PAGE21 ||
       Type == MachO::ARM64_RELOC_PAGEOFF12) &&
      Value) {
    assert((Value & 0xff000000) == 0 && "Added relocation out of range!");

    MachO::any_relocation_info MRE;
    MRE.r_word0 = FixupOffset;
    MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
                   (IsExtern << 27) | (Type << 28));
    Writer->addRelocation(Fragment->getParent(), MRE);

    // Now set up the Addend relocation.
    Type = MachO::ARM64_RELOC_ADDEND;
    Index = Value;
    IsPCRel = 0;
    Log2Size = 2;
    IsExtern = 0;

    // Put zero into the instruction itself. The addend is in the relocation.
    Value = 0;
  }

  // If there's any addend left to handle, encode it in the instruction.
  FixedValue = Value;

  // struct relocation_info (8 bytes)
  MachO::any_relocation_info MRE;
  MRE.r_word0 = FixupOffset;
  MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
                 (IsExtern << 27) | (Type << 28));
  Writer->addRelocation(Fragment->getParent(), MRE);
}
コード例 #29
0
ファイル: X86MachObjectWriter.cpp プロジェクト: Dagrol/llvm
void X86MachObjectWriter::RecordX86_64Relocation(
    MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout,
    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
    uint64_t &FixedValue) {
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());

  // See <reloc.h>.
  uint32_t FixupOffset =
    Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  uint32_t FixupAddress =
    Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
  int64_t Value = 0;
  unsigned Index = 0;
  unsigned IsExtern = 0;
  unsigned Type = 0;
  const MCSymbol *RelSymbol = nullptr;

  Value = Target.getConstant();

  if (IsPCRel) {
    // Compensate for the relocation offset, Darwin x86_64 relocations only have
    // the addend and appear to have attempted to define it to be the actual
    // expression addend without the PCrel bias. However, instructions with data
    // following the relocation are not accommodated for (see comment below
    // regarding SIGNED{1,2,4}), so it isn't exactly that either.
    Value += 1LL << Log2Size;
  }

  if (Target.isAbsolute()) { // constant
    // SymbolNum of 0 indicates the absolute section.
    Type = MachO::X86_64_RELOC_UNSIGNED;

    // FIXME: I believe this is broken, I don't think the linker can understand
    // it. I think it would require a local relocation, but I'm not sure if that
    // would work either. The official way to get an absolute PCrel relocation
    // is to use an absolute symbol (which we don't support yet).
    if (IsPCRel) {
      IsExtern = 1;
      Type = MachO::X86_64_RELOC_BRANCH;
    }
  } else if (Target.getSymB()) { // A - B + constant
    const MCSymbol *A = &Target.getSymA()->getSymbol();
    if (A->isTemporary())
      A = &Writer->findAliasedSymbol(*A);
    const MCSymbolData &A_SD = Asm.getSymbolData(*A);
    const MCSymbol *A_Base = Asm.getAtom(&A_SD);

    const MCSymbol *B = &Target.getSymB()->getSymbol();
    if (B->isTemporary())
      B = &Writer->findAliasedSymbol(*B);
    const MCSymbolData &B_SD = Asm.getSymbolData(*B);
    const MCSymbol *B_Base = Asm.getAtom(&B_SD);

    // Neither symbol can be modified.
    if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
        Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
      report_fatal_error("unsupported relocation of modified symbol", false);

    // We don't support PCrel relocations of differences. Darwin 'as' doesn't
    // implement most of these correctly.
    if (IsPCRel)
      report_fatal_error("unsupported pc-relative relocation of difference",
                         false);

    // The support for the situation where one or both of the symbols would
    // require a local relocation is handled just like if the symbols were
    // external.  This is certainly used in the case of debug sections where the
    // section has only temporary symbols and thus the symbols don't have base
    // symbols.  This is encoded using the section ordinal and non-extern
    // relocation entries.

    // Darwin 'as' doesn't emit correct relocations for this (it ends up with a
    // single SIGNED relocation); reject it for now.  Except the case where both
    // symbols don't have a base, equal but both NULL.
    if (A_Base == B_Base && A_Base)
      report_fatal_error("unsupported relocation with identical base", false);

    // A subtraction expression where either symbol is undefined is a
    // non-relocatable expression.
    if (A->isUndefined() || B->isUndefined()) {
      StringRef Name = A->isUndefined() ? A->getName() : B->getName();
      Asm.getContext().reportFatalError(Fixup.getLoc(),
        "unsupported relocation with subtraction expression, symbol '" +
        Name + "' can not be undefined in a subtraction expression");
    }

    Value += Writer->getSymbolAddress(*A, Layout) -
             (!A_Base ? 0 : Writer->getSymbolAddress(*A_Base, Layout));
    Value -= Writer->getSymbolAddress(*B, Layout) -
             (!B_Base ? 0 : Writer->getSymbolAddress(*B_Base, Layout));

    if (!A_Base)
      Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
    Type = MachO::X86_64_RELOC_UNSIGNED;

    MachO::any_relocation_info MRE;
    MRE.r_word0 = FixupOffset;
    MRE.r_word1 =
        (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
    Writer->addRelocation(A_Base, Fragment->getParent(), MRE);

    if (B_Base)
      RelSymbol = B_Base;
    else
      Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
    Type = MachO::X86_64_RELOC_SUBTRACTOR;
  } else {
    const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
    if (Symbol->isTemporary() && Value) {
      const MCSection &Sec = Symbol->getSection();
      if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec))
        Asm.addLocalUsedInReloc(*Symbol);
    }
    const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
    RelSymbol = Asm.getAtom(&SD);

    // Relocations inside debug sections always use local relocations when
    // possible. This seems to be done because the debugger doesn't fully
    // understand x86_64 relocation entries, and expects to find values that
    // have already been fixed up.
    if (Symbol->isInSection()) {
      const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
        Fragment->getParent()->getSection());
      if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
        RelSymbol = nullptr;
    }

    // x86_64 almost always uses external relocations, except when there is no
    // symbol to use as a base address (a local symbol with no preceding
    // non-local symbol).
    if (RelSymbol) {
      // Add the local offset, if needed.
      if (RelSymbol != Symbol)
        Value += Layout.getSymbolOffset(*Symbol) -
                 Layout.getSymbolOffset(*RelSymbol);
    } else if (Symbol->isInSection() && !Symbol->isVariable()) {
      // The index is the section ordinal (1-based).
      Index = SD.getFragment()->getParent()->getOrdinal() + 1;
      Value += Writer->getSymbolAddress(*Symbol, Layout);

      if (IsPCRel)
        Value -= FixupAddress + (1 << Log2Size);
    } else if (Symbol->isVariable()) {
      const MCExpr *Value = Symbol->getVariableValue();
      int64_t Res;
      bool isAbs = Value->EvaluateAsAbsolute(Res, Layout,
                                             Writer->getSectionAddressMap());
      if (isAbs) {
        FixedValue = Res;
        return;
      } else {
        report_fatal_error("unsupported relocation of variable '" +
                           Symbol->getName() + "'", false);
      }
    } else {
      report_fatal_error("unsupported relocation of undefined symbol '" +
                         Symbol->getName() + "'", false);
    }

    MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
    if (IsPCRel) {
      if (IsRIPRel) {
        if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
          // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
          // rewrite the movq to an leaq at link time if the symbol ends up in
          // the same linkage unit.
          if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
            Type = MachO::X86_64_RELOC_GOT_LOAD;
          else
            Type = MachO::X86_64_RELOC_GOT;
        }  else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
          Type = MachO::X86_64_RELOC_TLV;
        }  else if (Modifier != MCSymbolRefExpr::VK_None) {
          report_fatal_error("unsupported symbol modifier in relocation",
                             false);
        } else {
          Type = MachO::X86_64_RELOC_SIGNED;

          // The Darwin x86_64 relocation format has a problem where it cannot
          // encode an address (L<foo> + <constant>) which is outside the atom
          // containing L<foo>. Generally, this shouldn't occur but it does
          // happen when we have a RIPrel instruction with data following the
          // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
          // adjustment Darwin x86_64 uses, the offset is still negative and the
          // linker has no way to recognize this.
          //
          // To work around this, Darwin uses several special relocation types
          // to indicate the offsets. However, the specification or
          // implementation of these seems to also be incomplete; they should
          // adjust the addend as well based on the actual encoded instruction
          // (the additional bias), but instead appear to just look at the final
          // offset.
          switch (-(Target.getConstant() + (1LL << Log2Size))) {
          case 1: Type = MachO::X86_64_RELOC_SIGNED_1; break;
          case 2: Type = MachO::X86_64_RELOC_SIGNED_2; break;
          case 4: Type = MachO::X86_64_RELOC_SIGNED_4; break;
          }
        }
      } else {
        if (Modifier != MCSymbolRefExpr::VK_None)
          report_fatal_error("unsupported symbol modifier in branch "
                             "relocation", false);

        Type = MachO::X86_64_RELOC_BRANCH;
      }
    } else {
      if (Modifier == MCSymbolRefExpr::VK_GOT) {
        Type = MachO::X86_64_RELOC_GOT;
      } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
        // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which
        // case all we do is set the PCrel bit in the relocation entry; this is
        // used with exception handling, for example. The source is required to
        // include any necessary offset directly.
        Type = MachO::X86_64_RELOC_GOT;
        IsPCRel = 1;
      } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
        report_fatal_error("TLVP symbol modifier should have been rip-rel",
                           false);
      } else if (Modifier != MCSymbolRefExpr::VK_None)
        report_fatal_error("unsupported symbol modifier in relocation", false);
      else {
        Type = MachO::X86_64_RELOC_UNSIGNED;
        unsigned Kind = Fixup.getKind();
        if (Kind == X86::reloc_signed_4byte)
          report_fatal_error("32-bit absolute addressing is not supported in "
                             "64-bit mode", false);
      }
    }
  }

  // x86_64 always writes custom values into the fixups.
  FixedValue = Value;

  // struct relocation_info (8 bytes)
  MachO::any_relocation_info MRE;
  MRE.r_word0 = FixupOffset;
  MRE.r_word1 = (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
                (IsExtern << 27) | (Type << 28);
  Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
コード例 #30
0
ファイル: MCAssembler.cpp プロジェクト: CPFL/guc
bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout,
                                const MCFixup &Fixup, const MCFragment *DF,
                                MCValue &Target, uint64_t &Value) const {
  ++stats::EvaluateFixup;

  if (!Fixup.getValue()->EvaluateAsRelocatable(Target, &Layout))
    report_fatal_error("expected relocatable expression");

  // FIXME: How do non-scattered symbols work in ELF? I presume the linker
  // doesn't support small relocations, but then under what criteria does the
  // assembler allow symbol differences?

  Value = Target.getConstant();

  bool IsPCRel = Emitter.getFixupKindInfo(
    Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
  bool IsResolved = true;
  if (const MCSymbolRefExpr *A = Target.getSymA()) {
    if (A->getSymbol().isDefined())
      Value += Layout.getSymbolAddress(&getSymbolData(A->getSymbol()));
    else
      IsResolved = false;
  }
  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    if (B->getSymbol().isDefined())
      Value -= Layout.getSymbolAddress(&getSymbolData(B->getSymbol()));
    else
      IsResolved = false;
  }

  // If we are using scattered symbols, determine whether this value is actually
  // resolved; scattering may cause atoms to move.
  if (IsResolved && getBackend().hasScatteredSymbols()) {
    if (getBackend().hasReliableSymbolDifference()) {
      // If this is a PCrel relocation, find the base atom (identified by its
      // symbol) that the fixup value is relative to.
      const MCSymbolData *BaseSymbol = 0;
      if (IsPCRel) {
        BaseSymbol = DF->getAtom();
        if (!BaseSymbol)
          IsResolved = false;
      }

      if (IsResolved)
        IsResolved = isScatteredFixupFullyResolved(*this, Layout, Fixup, Target,
                                                   BaseSymbol);
    } else {
      const MCSection *BaseSection = 0;
      if (IsPCRel)
        BaseSection = &DF->getParent()->getSection();

      IsResolved = isScatteredFixupFullyResolvedSimple(*this, Fixup, Target,
                                                       BaseSection);
    }
  }

  if (IsPCRel)
    Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset();

  return IsResolved;
}