forked from OSchip/llvm-project
[AArch64] Add support for secrel add/load/store relocations for COFF
Differential Revision: https://reviews.llvm.org/D43288 llvm-svn: 326480
This commit is contained in:
parent
36b99e1937
commit
c61ff3bef1
|
@ -182,6 +182,30 @@ which gnu as does not support. For gas compatibility, sections with a name
|
||||||
starting with ".debug" are implicitly discardable.
|
starting with ".debug" are implicitly discardable.
|
||||||
|
|
||||||
|
|
||||||
|
ARM64/COFF-Dependent
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Relocations
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following additional symbol variants are supported:
|
||||||
|
|
||||||
|
**:secrel_lo12:** generates a relocation that corresponds to the COFF relocation
|
||||||
|
types ``IMAGE_REL_ARM64_SECREL_LOW12A`` or ``IMAGE_REL_ARM64_SECREL_LOW12L``.
|
||||||
|
|
||||||
|
**:secrel_hi12:** generates a relocation that corresponds to the COFF relocation
|
||||||
|
type ``IMAGE_REL_ARM64_SECREL_HIGH12A``.
|
||||||
|
|
||||||
|
.. code-block:: gas
|
||||||
|
|
||||||
|
add x0, x0, :secrel_hi12:symbol
|
||||||
|
ldr x0, [x0, :secrel_lo12:symbol]
|
||||||
|
|
||||||
|
add x1, x1, :secrel_hi12:symbol
|
||||||
|
add x1, x1, :secrel_lo12:symbol
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
ELF-Dependent
|
ELF-Dependent
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -518,7 +518,9 @@ public:
|
||||||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
|
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
|
||||||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
|
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
|
||||||
ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
|
ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
|
||||||
ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
|
ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
|
||||||
|
ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
|
||||||
|
ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
|
||||||
// Note that we don't range-check the addend. It's adjusted modulo page
|
// Note that we don't range-check the addend. It's adjusted modulo page
|
||||||
// size when converted, so there is no "out of range" condition when using
|
// size when converted, so there is no "out of range" condition when using
|
||||||
// @pageoff.
|
// @pageoff.
|
||||||
|
@ -607,7 +609,9 @@ public:
|
||||||
|| ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
|
|| ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
|
||||||
|| ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
|
|| ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
|
||||||
|| ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
|
|| ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
|
||||||
|| ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
|
|| ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
|
||||||
|
|| ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
|
||||||
|
|| ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a constant, it should be a real immediate in range:
|
// If it's a constant, it should be a real immediate in range:
|
||||||
|
@ -2854,6 +2858,8 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
|
||||||
.Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
|
.Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
|
||||||
.Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
|
.Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
|
||||||
.Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
|
.Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
|
||||||
|
.Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
|
||||||
|
.Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
|
||||||
.Default(AArch64MCExpr::VK_INVALID);
|
.Default(AArch64MCExpr::VK_INVALID);
|
||||||
|
|
||||||
if (RefKind == AArch64MCExpr::VK_INVALID)
|
if (RefKind == AArch64MCExpr::VK_INVALID)
|
||||||
|
@ -3466,7 +3472,9 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst,
|
||||||
ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
|
ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
|
||||||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
|
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
|
||||||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
|
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
|
||||||
ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
|
ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
|
||||||
|
ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
|
||||||
|
ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
|
||||||
(Inst.getOpcode() == AArch64::ADDXri ||
|
(Inst.getOpcode() == AArch64::ADDXri ||
|
||||||
Inst.getOpcode() == AArch64::ADDWri))
|
Inst.getOpcode() == AArch64::ADDWri))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -276,7 +276,8 @@ AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
|
if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
|
||||||
AArch64MCExpr::VariantKind RefKind = A64E->getKind();
|
AArch64MCExpr::VariantKind RefKind = A64E->getKind();
|
||||||
if (RefKind == AArch64MCExpr::VK_TPREL_HI12 ||
|
if (RefKind == AArch64MCExpr::VK_TPREL_HI12 ||
|
||||||
RefKind == AArch64MCExpr::VK_DTPREL_HI12)
|
RefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
|
||||||
|
RefKind == AArch64MCExpr::VK_SECREL_HI12)
|
||||||
ShiftVal = 12;
|
ShiftVal = 12;
|
||||||
}
|
}
|
||||||
return ShiftVal == 0 ? 0 : (1 << ShiftVal);
|
return ShiftVal == 0 ? 0 : (1 << ShiftVal);
|
||||||
|
|
|
@ -70,6 +70,8 @@ StringRef AArch64MCExpr::getVariantKindName() const {
|
||||||
case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:";
|
case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:";
|
||||||
case VK_TLSDESC: return "";
|
case VK_TLSDESC: return "";
|
||||||
case VK_TLSDESC_PAGE: return ":tlsdesc:";
|
case VK_TLSDESC_PAGE: return ":tlsdesc:";
|
||||||
|
case VK_SECREL_LO12: return ":secrel_lo12:";
|
||||||
|
case VK_SECREL_HI12: return ":secrel_hi12:";
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Invalid ELF symbol kind");
|
llvm_unreachable("Invalid ELF symbol kind");
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
VK_GOTTPREL = 0x005,
|
VK_GOTTPREL = 0x005,
|
||||||
VK_TPREL = 0x006,
|
VK_TPREL = 0x006,
|
||||||
VK_TLSDESC = 0x007,
|
VK_TLSDESC = 0x007,
|
||||||
|
VK_SECREL = 0x008,
|
||||||
VK_SymLocBits = 0x00f,
|
VK_SymLocBits = 0x00f,
|
||||||
|
|
||||||
// Variants specifying which part of the final address calculation is
|
// Variants specifying which part of the final address calculation is
|
||||||
|
@ -98,6 +99,8 @@ public:
|
||||||
VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC,
|
VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC,
|
||||||
VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF,
|
VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF,
|
||||||
VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE,
|
VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE,
|
||||||
|
VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF,
|
||||||
|
VK_SECREL_HI12 = VK_SECREL | VK_HI12,
|
||||||
|
|
||||||
VK_INVALID = 0xfff
|
VK_INVALID = 0xfff
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "MCTargetDesc/AArch64FixupKinds.h"
|
#include "MCTargetDesc/AArch64FixupKinds.h"
|
||||||
|
#include "MCTargetDesc/AArch64MCExpr.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/BinaryFormat/COFF.h"
|
#include "llvm/BinaryFormat/COFF.h"
|
||||||
#include "llvm/MC/MCAsmBackend.h"
|
#include "llvm/MC/MCAsmBackend.h"
|
||||||
|
@ -46,6 +47,7 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType(
|
||||||
bool IsCrossSection, const MCAsmBackend &MAB) const {
|
bool IsCrossSection, const MCAsmBackend &MAB) const {
|
||||||
auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None
|
auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None
|
||||||
: Target.getSymA()->getKind();
|
: Target.getSymA()->getKind();
|
||||||
|
const MCExpr *Expr = Fixup.getValue();
|
||||||
|
|
||||||
switch (static_cast<unsigned>(Fixup.getKind())) {
|
switch (static_cast<unsigned>(Fixup.getKind())) {
|
||||||
default: {
|
default: {
|
||||||
|
@ -73,6 +75,13 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType(
|
||||||
return COFF::IMAGE_REL_ARM64_SECREL;
|
return COFF::IMAGE_REL_ARM64_SECREL;
|
||||||
|
|
||||||
case AArch64::fixup_aarch64_add_imm12:
|
case AArch64::fixup_aarch64_add_imm12:
|
||||||
|
if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
|
||||||
|
AArch64MCExpr::VariantKind RefKind = A64E->getKind();
|
||||||
|
if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
|
||||||
|
return COFF::IMAGE_REL_ARM64_SECREL_LOW12A;
|
||||||
|
if (RefKind == AArch64MCExpr::VK_SECREL_HI12)
|
||||||
|
return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A;
|
||||||
|
}
|
||||||
return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A;
|
return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A;
|
||||||
|
|
||||||
case AArch64::fixup_aarch64_ldst_imm12_scale1:
|
case AArch64::fixup_aarch64_ldst_imm12_scale1:
|
||||||
|
@ -80,6 +89,11 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType(
|
||||||
case AArch64::fixup_aarch64_ldst_imm12_scale4:
|
case AArch64::fixup_aarch64_ldst_imm12_scale4:
|
||||||
case AArch64::fixup_aarch64_ldst_imm12_scale8:
|
case AArch64::fixup_aarch64_ldst_imm12_scale8:
|
||||||
case AArch64::fixup_aarch64_ldst_imm12_scale16:
|
case AArch64::fixup_aarch64_ldst_imm12_scale16:
|
||||||
|
if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
|
||||||
|
AArch64MCExpr::VariantKind RefKind = A64E->getKind();
|
||||||
|
if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
|
||||||
|
return COFF::IMAGE_REL_ARM64_SECREL_LOW12L;
|
||||||
|
}
|
||||||
return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L;
|
return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L;
|
||||||
|
|
||||||
case AArch64::fixup_aarch64_pcrel_adrp_imm21:
|
case AArch64::fixup_aarch64_pcrel_adrp_imm21:
|
||||||
|
|
|
@ -45,6 +45,13 @@ add x0, x0, :lo12:foo + 0x12345
|
||||||
ldrb w0, [x0, :lo12:foo + 0x12345]
|
ldrb w0, [x0, :lo12:foo + 0x12345]
|
||||||
ldr x0, [x0, :lo12:foo + 0x12348]
|
ldr x0, [x0, :lo12:foo + 0x12348]
|
||||||
|
|
||||||
|
; IMAGE_REL_ARM64_SECREL_LOW12A
|
||||||
|
add x0, x0, :secrel_lo12:foo
|
||||||
|
; IMAGE_REL_ARM64_SECREL_HIGH12A
|
||||||
|
add x0, x0, :secrel_hi12:foo
|
||||||
|
; IMAGE_REL_ARM64_SECREL_LOW12L
|
||||||
|
ldr x0, [x0, :secrel_lo12:foo]
|
||||||
|
|
||||||
; CHECK: Format: COFF-ARM64
|
; CHECK: Format: COFF-ARM64
|
||||||
; CHECK: Arch: aarch64
|
; CHECK: Arch: aarch64
|
||||||
; CHECK: AddressSize: 64bit
|
; CHECK: AddressSize: 64bit
|
||||||
|
@ -64,6 +71,9 @@ ldr x0, [x0, :lo12:foo + 0x12348]
|
||||||
; CHECK: 0x34 IMAGE_REL_ARM64_PAGEOFFSET_12A foo
|
; CHECK: 0x34 IMAGE_REL_ARM64_PAGEOFFSET_12A foo
|
||||||
; CHECK: 0x38 IMAGE_REL_ARM64_PAGEOFFSET_12L foo
|
; CHECK: 0x38 IMAGE_REL_ARM64_PAGEOFFSET_12L foo
|
||||||
; CHECK: 0x3C IMAGE_REL_ARM64_PAGEOFFSET_12L foo
|
; CHECK: 0x3C IMAGE_REL_ARM64_PAGEOFFSET_12L foo
|
||||||
|
; CHECK: 0x40 IMAGE_REL_ARM64_SECREL_LOW12A foo
|
||||||
|
; CHECK: 0x44 IMAGE_REL_ARM64_SECREL_HIGH12A foo
|
||||||
|
; CHECK: 0x48 IMAGE_REL_ARM64_SECREL_LOW12L foo
|
||||||
; CHECK: }
|
; CHECK: }
|
||||||
; CHECK: ]
|
; CHECK: ]
|
||||||
|
|
||||||
|
@ -71,3 +81,6 @@ ldr x0, [x0, :lo12:foo + 0x12348]
|
||||||
; DISASM: 34: 00 14 0d 91 add x0, x0, #837
|
; DISASM: 34: 00 14 0d 91 add x0, x0, #837
|
||||||
; DISASM: 38: 00 14 4d 39 ldrb w0, [x0, #837]
|
; DISASM: 38: 00 14 4d 39 ldrb w0, [x0, #837]
|
||||||
; DISASM: 3c: 00 a4 41 f9 ldr x0, [x0, #840]
|
; DISASM: 3c: 00 a4 41 f9 ldr x0, [x0, #840]
|
||||||
|
; DISASM: 40: 00 00 00 91 add x0, x0, #0
|
||||||
|
; DISASM: 44: 00 00 40 91 add x0, x0, #0, lsl #12
|
||||||
|
; DISASM: 48: 00 00 40 f9 ldr x0, [x0]
|
||||||
|
|
Loading…
Reference in New Issue