mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[MC][ARM] Make .reloc support arbitrary relocation types
Generalizes D61992. In GNU as, the .reloc directive supports arbitrary relocation types. A MCFixupKind value `V` larger than or equal to FirstLiteralRelocationKind is used to represent the relocation type whose number is V-FirstLiteralRelocationKind. This is useful for linker tests. Without the feature the assembler cannot produce certain relocation records (e.g. R_ARM_ALU_PC_G0/R_ARM_LDR_PC_G0) This helps move forward D75349 and D76575. Differential Revision: https://reviews.llvm.org/D76746
This commit is contained in:
parent
2723dcfb82
commit
eaa3fc5b64
@ -55,9 +55,14 @@ enum MCFixupKind {
|
||||
|
||||
FirstTargetFixupKind = 128,
|
||||
|
||||
// Limit range of target fixups, in case we want to pack more efficiently
|
||||
// later.
|
||||
MaxTargetFixupKind = (1 << 8)
|
||||
/// The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for
|
||||
/// relocations coming from .reloc directive. Fixup kind
|
||||
/// FirstLiteralRelocationKind+V represents the relocation type with number V.
|
||||
FirstLiteralRelocationKind = 256,
|
||||
|
||||
/// Set limit to accommodate the highest reloc type in use for all Targets,
|
||||
/// currently R_AARCH64_IRELATIVE at 1032, including room for expansion.
|
||||
MaxFixupKind = FirstLiteralRelocationKind + 1032 + 32,
|
||||
};
|
||||
|
||||
/// Encode information on a single operation to perform on a byte
|
||||
@ -92,7 +97,7 @@ class MCFixup {
|
||||
public:
|
||||
static MCFixup create(uint32_t Offset, const MCExpr *Value,
|
||||
MCFixupKind Kind, SMLoc Loc = SMLoc()) {
|
||||
assert(Kind < MaxTargetFixupKind && "Kind out of range!");
|
||||
assert(Kind <= MaxFixupKind && "Kind out of range!");
|
||||
MCFixup FI;
|
||||
FI.Value = Value;
|
||||
FI.Offset = Offset;
|
||||
|
@ -48,10 +48,17 @@ public:
|
||||
} // end anonymous namespace
|
||||
|
||||
Optional<MCFixupKind> ARMAsmBackend::getFixupKind(StringRef Name) const {
|
||||
if (STI.getTargetTriple().isOSBinFormatELF() && Name == "R_ARM_NONE")
|
||||
return FK_NONE;
|
||||
if (!STI.getTargetTriple().isOSBinFormatELF())
|
||||
return None;
|
||||
|
||||
return MCAsmBackend::getFixupKind(Name);
|
||||
unsigned Type = llvm::StringSwitch<unsigned>(Name)
|
||||
#define ELF_RELOC(X, Y) .Case(#X, Y)
|
||||
#include "llvm/BinaryFormat/ELFRelocs/ARM.def"
|
||||
#undef ELF_RELOC
|
||||
.Default(-1u);
|
||||
if (Type == -1u)
|
||||
return None;
|
||||
return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
|
||||
}
|
||||
|
||||
const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
||||
@ -172,6 +179,11 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
||||
{"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}
|
||||
};
|
||||
|
||||
// Fixup kinds from .reloc directive are like R_ARM_NONE. They do not require
|
||||
// any extra processing.
|
||||
if (Kind >= FirstLiteralRelocationKind)
|
||||
return MCAsmBackend::getFixupKindInfo(FK_NONE);
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
@ -438,7 +450,6 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
|
||||
default:
|
||||
Ctx.reportError(Fixup.getLoc(), "bad relocation fixup type");
|
||||
return 0;
|
||||
case FK_NONE:
|
||||
case FK_Data_1:
|
||||
case FK_Data_2:
|
||||
case FK_Data_4:
|
||||
@ -871,7 +882,7 @@ bool ARMAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
|
||||
const MCSymbolRefExpr *A = Target.getSymA();
|
||||
const MCSymbol *Sym = A ? &A->getSymbol() : nullptr;
|
||||
const unsigned FixupKind = Fixup.getKind();
|
||||
if (FixupKind == FK_NONE)
|
||||
if (FixupKind >= FirstLiteralRelocationKind)
|
||||
return true;
|
||||
if (FixupKind == ARM::fixup_arm_thumb_bl) {
|
||||
assert(Sym && "How did we resolve this?");
|
||||
@ -915,9 +926,6 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
|
||||
case FK_NONE:
|
||||
return 0;
|
||||
|
||||
case FK_Data_1:
|
||||
case ARM::fixup_arm_thumb_bcc:
|
||||
case ARM::fixup_arm_thumb_cp:
|
||||
@ -979,9 +987,6 @@ static unsigned getFixupKindContainerSizeBytes(unsigned Kind) {
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
|
||||
case FK_NONE:
|
||||
return 0;
|
||||
|
||||
case FK_Data_1:
|
||||
return 1;
|
||||
case FK_Data_2:
|
||||
@ -1037,7 +1042,10 @@ void ARMAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
MutableArrayRef<char> Data, uint64_t Value,
|
||||
bool IsResolved,
|
||||
const MCSubtargetInfo* STI) const {
|
||||
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
|
||||
unsigned Kind = Fixup.getKind();
|
||||
if (Kind >= FirstLiteralRelocationKind)
|
||||
return;
|
||||
unsigned NumBytes = getFixupKindNumBytes(Kind);
|
||||
MCContext &Ctx = Asm.getContext();
|
||||
Value = adjustFixupValue(Asm, Fixup, Target, Value, IsResolved, Ctx, STI);
|
||||
if (!Value)
|
||||
@ -1049,7 +1057,7 @@ void ARMAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
// Used to point to big endian bytes.
|
||||
unsigned FullSizeBytes;
|
||||
if (Endian == support::big) {
|
||||
FullSizeBytes = getFixupKindContainerSizeBytes(Fixup.getKind());
|
||||
FullSizeBytes = getFixupKindContainerSizeBytes(Kind);
|
||||
assert((Offset + FullSizeBytes) <= Data.size() && "Invalid fixup size!");
|
||||
assert(NumBytes <= FullSizeBytes && "Invalid fixup size!");
|
||||
}
|
||||
|
@ -79,6 +79,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel,
|
||||
MCContext &Ctx) const {
|
||||
unsigned Kind = Fixup.getTargetKind();
|
||||
if (Kind >= FirstLiteralRelocationKind)
|
||||
return Kind - FirstLiteralRelocationKind;
|
||||
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
|
||||
|
||||
if (IsPCRel) {
|
||||
@ -152,12 +155,10 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
|
||||
return ELF::R_ARM_THM_BF18;
|
||||
}
|
||||
}
|
||||
switch (Fixup.getTargetKind()) {
|
||||
switch (Kind) {
|
||||
default:
|
||||
Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
|
||||
return ELF::R_ARM_NONE;
|
||||
case FK_NONE:
|
||||
return ELF::R_ARM_NONE;
|
||||
case FK_Data_1:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
|
6
test/MC/ARM/reloc-directive-err.s
Normal file
6
test/MC/ARM/reloc-directive-err.s
Normal file
@ -0,0 +1,6 @@
|
||||
# RUN: llvm-mc -triple=armv7 %s 2>&1 | FileCheck --check-prefix=PRINT %s
|
||||
# RUN: not llvm-mc -filetype=obj -triple=armv7 %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
# PRINT: .reloc 0, R_INVALID, 0
|
||||
# CHECK: {{.*}}.s:[[# @LINE+1]]:11: error: unknown relocation name
|
||||
.reloc 0, R_INVALID, 0
|
@ -17,6 +17,10 @@
|
||||
.reloc 4, R_ARM_NONE, foo+4
|
||||
.reloc 0, R_ARM_NONE, 8
|
||||
|
||||
.reloc 0, R_ARM_ALU_PC_G0, .data+2
|
||||
.reloc 0, R_ARM_LDR_PC_G0, foo+3
|
||||
.reloc 0, R_ARM_THM_ALU_PREL_11_0, 5
|
||||
|
||||
.data
|
||||
.globl foo
|
||||
foo:
|
||||
@ -27,11 +31,17 @@ foo:
|
||||
# PRINT: .reloc 8, R_ARM_NONE, .data
|
||||
# PRINT: .reloc 4, R_ARM_NONE, foo+4
|
||||
# PRINT: .reloc 0, R_ARM_NONE, 8
|
||||
# PRINT: .reloc 0, R_ARM_ALU_PC_G0, .data+2
|
||||
# PRINT: .reloc 0, R_ARM_LDR_PC_G0, foo+3
|
||||
# PRINT: .reloc 0, R_ARM_THM_ALU_PREL_11_0, 5
|
||||
|
||||
# ARM relocations use the Elf32_Rel format. Addends are neither stored in the
|
||||
# relocation entries nor applied in the referenced locations.
|
||||
# CHECK: 0x8 R_ARM_NONE .data 0x0
|
||||
# CHECK-NEXT: 0x4 R_ARM_NONE foo 0x0
|
||||
# CHECK-NEXT: 0x0 R_ARM_NONE - 0x0
|
||||
# CHECK-NEXT: 0x0 R_ARM_ALU_PC_G0 .data 0x0
|
||||
# CHECK-NEXT: 0x0 R_ARM_LDR_PC_G0 foo 0x0
|
||||
# CHECK-NEXT: 0x0 R_ARM_THM_ALU_PREL_11_0 - 0x0
|
||||
|
||||
# HEX: 0x00000000 00000000 00000000
|
||||
|
Loading…
Reference in New Issue
Block a user