-
Notifications
You must be signed in to change notification settings - Fork 11.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ARM,MC] Support FDPIC relocations #82187
[ARM,MC] Support FDPIC relocations #82187
Conversation
Created using spr 1.3.4
@llvm/pr-subscribers-mc @llvm/pr-subscribers-objectyaml Author: Fangrui Song (MaskRay) ChangesLinux kernel fs/binfmt_elf_fdpic.c supports FDPIC for MMU-less systems. This patch implements FDPIC relocations to the integrated assembler. gas requires Full diff: https://github.com/llvm/llvm-project/pull/82187.diff 18 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 124bba76c1774c..bace3a92677a82 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -362,6 +362,7 @@ enum {
ELFOSABI_AMDGPU_PAL = 65, // AMD PAL runtime
ELFOSABI_AMDGPU_MESA3D = 66, // AMD GCN GPUs (GFX6+) for MESA runtime
ELFOSABI_ARM = 97, // ARM
+ ELFOSABI_ARM_FDPIC = 65, // ARM FDPIC
ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000
ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000
ELFOSABI_STANDALONE = 255, // Standalone (embedded) application
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def
index 47084d1eb0aad5..7e9fe965241f25 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def
@@ -143,3 +143,10 @@ ELF_RELOC(R_ARM_THM_BF16, 0x88)
ELF_RELOC(R_ARM_THM_BF12, 0x89)
ELF_RELOC(R_ARM_THM_BF18, 0x8a)
ELF_RELOC(R_ARM_IRELATIVE, 0xa0)
+ELF_RELOC(R_ARM_GOTFUNCDESC, 0xa1)
+ELF_RELOC(R_ARM_GOTOFFFUNCDESC, 0xa2)
+ELF_RELOC(R_ARM_FUNCDESC, 0xa3)
+ELF_RELOC(R_ARM_FUNCDESC_VALUE, 0xa4)
+ELF_RELOC(R_ARM_TLS_GD32_FDPIC, 0xa5)
+ELF_RELOC(R_ARM_TLS_LDM32_FDPIC, 0xa6)
+ELF_RELOC(R_ARM_TLS_IE32_FDPIC, 0xa7)
diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 67836292874f5f..b3119609372049 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -223,6 +223,12 @@ class MCSymbolRefExpr : public MCExpr {
VK_SECREL,
VK_SIZE, // symbol@SIZE
VK_WEAKREF, // The link between the symbols in .weakref foo, bar
+ VK_FUNCDESC,
+ VK_GOTFUNCDESC,
+ VK_GOTOFFFUNCDESC,
+ VK_TLSGD_FDPIC,
+ VK_TLSLDM_FDPIC,
+ VK_GOTTPOFF_FDPIC,
VK_X86_ABS8,
VK_X86_PLTOFF,
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index fe905f2c3ba5fe..7edd3f8ce4904c 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -525,6 +525,10 @@ class MCTargetAsmParser : public MCAsmParserExtension {
// Return whether this parser accept star as start of statement
virtual bool starIsStartOfStatement() { return false; };
+ virtual MCSymbolRefExpr::VariantKind
+ getVariantKindForName(StringRef Name) const {
+ return MCSymbolRefExpr::getVariantKindForName(Name);
+ }
virtual const MCExpr *applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind,
MCContext &Ctx) {
diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h
index e2dd1e0433dbe4..a7295879e15f0f 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -51,6 +51,7 @@ class MCTargetOptions {
bool MCNoTypeCheck : 1;
bool MCSaveTempLabels : 1;
bool MCIncrementalLinkerCompatible : 1;
+ bool FDPIC : 1;
bool ShowMCEncoding : 1;
bool ShowMCInst : 1;
bool AsmVerbose : 1;
diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
index 7f6ee6c8be224a..ba3784cab5b11d 100644
--- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
+++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
@@ -29,6 +29,8 @@ std::optional<bool> getExplicitRelaxAll();
bool getIncrementalLinkerCompatible();
+bool getFDPIC();
+
int getDwarfVersion();
bool getDwarf64();
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 80def6dfc24b1a..485fd1885ddb52 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -220,6 +220,7 @@ const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind,
StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
switch (Kind) {
+ // clang-format off
case VK_Invalid: return "<<invalid>>";
case VK_None: return "<<none>>";
@@ -232,13 +233,16 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_GOTPCREL: return "GOTPCREL";
case VK_GOTPCREL_NORELAX: return "GOTPCREL_NORELAX";
case VK_GOTTPOFF: return "GOTTPOFF";
+ case VK_GOTTPOFF_FDPIC: return "gottpoff_fdpic";
case VK_INDNTPOFF: return "INDNTPOFF";
case VK_NTPOFF: return "NTPOFF";
case VK_GOTNTPOFF: return "GOTNTPOFF";
case VK_PLT: return "PLT";
case VK_TLSGD: return "TLSGD";
+ case VK_TLSGD_FDPIC: return "tlsgd_fdpic";
case VK_TLSLD: return "TLSLD";
case VK_TLSLDM: return "TLSLDM";
+ case VK_TLSLDM_FDPIC: return "tlsldm_fdpic";
case VK_TPOFF: return "TPOFF";
case VK_TPREL: return "TPREL";
case VK_TLSCALL: return "tlscall";
@@ -253,6 +257,9 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_SECREL: return "SECREL32";
case VK_SIZE: return "SIZE";
case VK_WEAKREF: return "WEAKREF";
+ case VK_FUNCDESC: return "FUNCDESC";
+ case VK_GOTFUNCDESC: return "GOTFUNCDESC";
+ case VK_GOTOFFFUNCDESC: return "GOTOFFFUNCDESC";
case VK_X86_ABS8: return "ABS8";
case VK_X86_PLTOFF: return "PLTOFF";
case VK_ARM_NONE: return "none";
@@ -386,6 +393,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_VE_TLS_GD_LO32: return "tls_gd_lo";
case VK_VE_TPOFF_HI32: return "tpoff_hi";
case VK_VE_TPOFF_LO32: return "tpoff_lo";
+ // clang-format on
}
llvm_unreachable("Invalid variant kind");
}
@@ -493,13 +501,6 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("ie", VK_Hexagon_IE)
.Case("ldgot", VK_Hexagon_LD_GOT)
.Case("ldplt", VK_Hexagon_LD_PLT)
- .Case("none", VK_ARM_NONE)
- .Case("got_prel", VK_ARM_GOT_PREL)
- .Case("target1", VK_ARM_TARGET1)
- .Case("target2", VK_ARM_TARGET2)
- .Case("prel31", VK_ARM_PREL31)
- .Case("sbrel", VK_ARM_SBREL)
- .Case("tlsldo", VK_ARM_TLSLDO)
.Case("lo8", VK_AVR_LO8)
.Case("hi8", VK_AVR_HI8)
.Case("hlo8", VK_AVR_HLO8)
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 8e508dbdb1c69b..a1c32eee328643 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1237,7 +1237,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
// Lookup the symbol variant if used.
if (!Split.second.empty()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ Variant = getTargetParser().getVariantKindForName(Split.second);
if (Variant != MCSymbolRefExpr::VK_Invalid) {
SymbolName = Split.first;
} else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
index 07c6e752cb613d..bff4b8da2fb1b0 100644
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -15,7 +15,7 @@ MCTargetOptions::MCTargetOptions()
: MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false),
MCNoWarn(false), MCNoDeprecatedWarn(false), MCNoTypeCheck(false),
MCSaveTempLabels(false), MCIncrementalLinkerCompatible(false),
- ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
+ FDPIC(false), ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
PreserveAsmComments(true), Dwarf64(false),
EmitDwarfUnwind(EmitDwarfUnwindType::Default),
MCUseDwarfDirectory(DefaultDwarfDirectory),
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 8a4923e4792fb5..fb8334d626cb8b 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -36,6 +36,7 @@ using namespace llvm;
MCOPT_EXP(bool, RelaxAll)
MCOPT(bool, IncrementalLinkerCompatible)
+MCOPT(bool, FDPIC)
MCOPT(int, DwarfVersion)
MCOPT(bool, Dwarf64)
MCOPT(EmitDwarfUnwindType, EmitDwarfUnwind)
@@ -66,6 +67,9 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
"emit an object file which can be used with an incremental linker"));
MCBINDOPT(IncrementalLinkerCompatible);
+ static cl::opt<bool> FDPIC("fdpic", cl::desc("Use the FDPIC ABI"));
+ MCBINDOPT(FDPIC);
+
static cl::opt<int> DwarfVersion("dwarf-version", cl::desc("Dwarf version"),
cl::init(0));
MCBINDOPT(DwarfVersion);
@@ -135,6 +139,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
MCTargetOptions Options;
Options.MCRelaxAll = getRelaxAll();
Options.MCIncrementalLinkerCompatible = getIncrementalLinkerCompatible();
+ Options.FDPIC = getFDPIC();
Options.Dwarf64 = getDwarf64();
Options.DwarfVersion = getDwarfVersion();
Options.ShowMCInst = getShowMCInst();
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index de1ef2458152c8..9c1a28db592a1c 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -406,6 +406,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration(
ECase(ELFOSABI_AMDGPU_PAL);
ECase(ELFOSABI_AMDGPU_MESA3D);
ECase(ELFOSABI_ARM);
+ ECase(ELFOSABI_ARM_FDPIC);
ECase(ELFOSABI_C6000_ELFABI);
ECase(ELFOSABI_C6000_LINUX);
ECase(ELFOSABI_STANDALONE);
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index c82ab57bdf80f1..37bfb76a494dee 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -737,6 +737,9 @@ class ARMAsmParser : public MCTargetAsmParser {
void ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses, SMLoc IDLoc,
OperandVector &Operands);
+ MCSymbolRefExpr::VariantKind
+ getVariantKindForName(StringRef Name) const override;
+
void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override;
void onLabelParsed(MCSymbol *Symbol) override;
@@ -11358,6 +11361,37 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
return false;
}
+MCSymbolRefExpr::VariantKind
+ARMAsmParser::getVariantKindForName(StringRef Name) const {
+ return StringSwitch<MCSymbolRefExpr::VariantKind>(Name.lower())
+ .Case("funcdesc", MCSymbolRefExpr::VK_FUNCDESC)
+ .Case("got", MCSymbolRefExpr::VK_GOT)
+ .Case("got_prel", MCSymbolRefExpr::VK_ARM_GOT_PREL)
+ .Case("gotfuncdesc", MCSymbolRefExpr::VK_GOTFUNCDESC)
+ .Case("gotoff", MCSymbolRefExpr::VK_GOTOFF)
+ .Case("gotofffuncdesc", MCSymbolRefExpr::VK_GOTOFFFUNCDESC)
+ .Case("gottpoff", MCSymbolRefExpr::VK_GOTTPOFF)
+ .Case("gottpoff_fdpic", MCSymbolRefExpr::VK_GOTTPOFF_FDPIC)
+ .Case("imgrel", MCSymbolRefExpr::VK_COFF_IMGREL32)
+ .Case("none", MCSymbolRefExpr::VK_ARM_NONE)
+ .Case("plt", MCSymbolRefExpr::VK_PLT)
+ .Case("prel31", MCSymbolRefExpr::VK_ARM_PREL31)
+ .Case("sbrel", MCSymbolRefExpr::VK_ARM_SBREL)
+ .Case("secrel32", MCSymbolRefExpr::VK_SECREL)
+ .Case("target1", MCSymbolRefExpr::VK_ARM_TARGET1)
+ .Case("target2", MCSymbolRefExpr::VK_ARM_TARGET2)
+ .Case("tlscall", MCSymbolRefExpr::VK_TLSCALL)
+ .Case("tlsdesc", MCSymbolRefExpr::VK_TLSDESC)
+ .Case("tlsgd", MCSymbolRefExpr::VK_TLSGD)
+ .Case("tlsgd_fdpic", MCSymbolRefExpr::VK_TLSGD_FDPIC)
+ .Case("tlsld", MCSymbolRefExpr::VK_TLSLD)
+ .Case("tlsldm", MCSymbolRefExpr::VK_TLSLDM)
+ .Case("tlsldm_fdpic", MCSymbolRefExpr::VK_TLSLDM_FDPIC)
+ .Case("tlsldo", MCSymbolRefExpr::VK_ARM_TLSLDO)
+ .Case("tpoff", MCSymbolRefExpr::VK_TPOFF)
+ .Default(MCSymbolRefExpr::VK_Invalid);
+}
+
void ARMAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {
// We need to flush the current implicit IT block on a label, because it is
// not legal to branch into an IT block.
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 1d17bb349f24ba..6cd4badb7704b7 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -29,6 +29,7 @@
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/EndianStream.h"
@@ -1349,7 +1350,9 @@ static MCAsmBackend *createARMAsmBackend(const Target &T,
return new ARMAsmBackendWinCOFF(T, STI.getTargetTriple().isThumb());
case Triple::ELF:
assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target");
- uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
+ uint8_t OSABI = Options.FDPIC
+ ? ELF::ELFOSABI_ARM_FDPIC
+ : MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
return new ARMAsmBackendELF(T, STI.getTargetTriple().isThumb(), OSABI,
Endian);
}
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
index 44695a86c4e36c..baec4a5cb5215a 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
@@ -84,6 +84,11 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
if (Kind >= FirstLiteralRelocationKind)
return Kind - FirstLiteralRelocationKind;
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
+ auto CheckFDPIC = [&]() {
+ if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC)
+ Ctx.reportError(Fixup.getLoc(),
+ "relocation only supported in FDPIC mode");
+ };
if (IsPCRel) {
switch (Fixup.getTargetKind()) {
@@ -240,6 +245,24 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
return ELF::R_ARM_TLS_LDM32;
case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
return ELF::R_ARM_TLS_DESCSEQ;
+ case MCSymbolRefExpr::VK_FUNCDESC:
+ CheckFDPIC();
+ return ELF::R_ARM_FUNCDESC;
+ case MCSymbolRefExpr::VK_GOTFUNCDESC:
+ CheckFDPIC();
+ return ELF::R_ARM_GOTFUNCDESC;
+ case MCSymbolRefExpr::VK_GOTOFFFUNCDESC:
+ CheckFDPIC();
+ return ELF::R_ARM_GOTOFFFUNCDESC;
+ case MCSymbolRefExpr::VK_TLSGD_FDPIC:
+ CheckFDPIC();
+ return ELF::R_ARM_TLS_GD32_FDPIC;
+ case MCSymbolRefExpr::VK_TLSLDM_FDPIC:
+ CheckFDPIC();
+ return ELF::R_ARM_TLS_LDM32_FDPIC;
+ case MCSymbolRefExpr::VK_GOTTPOFF_FDPIC:
+ CheckFDPIC();
+ return ELF::R_ARM_TLS_IE32_FDPIC;
}
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
diff --git a/llvm/test/MC/ARM/fdpic.s b/llvm/test/MC/ARM/fdpic.s
new file mode 100644
index 00000000000000..4f36393d9110e8
--- /dev/null
+++ b/llvm/test/MC/ARM/fdpic.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc -triple=armv7-linux-gnueabi %s | FileCheck %s --check-prefix=ASM
+# RUN: llvm-mc -filetype=obj -triple=armv7-linux-gnueabi --fdpic %s | llvm-readelf -h -r - | FileCheck %s
+
+# RUN: not llvm-mc -filetype=obj -triple=armv7-linux-gnueabi %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+# ASM: .long f(FUNCDESC)
+# ASM-NEXT: .long f(GOTFUNCDESC)
+# ASM-NEXT: .long f(GOTOFFFUNCDESC)
+
+# CHECK: OS/ABI: ARM FDPIC
+# CHECK: Machine: ARM
+# CHECK: Flags: 0x5000000
+
+# CHECK: R_ARM_FUNCDESC 00000000 f
+# CHECK-NEXT: R_ARM_GOTFUNCDESC 00000000 f
+# CHECK-NEXT: R_ARM_GOTOFFFUNCDESC 00000000 f
+# CHECK-NEXT: R_ARM_TLS_GD32_FDPIC 00000000 tls
+# CHECK-NEXT: R_ARM_TLS_LDM32_FDPIC 00000000 tls
+# CHECK-NEXT: R_ARM_TLS_IE32_FDPIC 00000000 tls
+
+.data
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long f(FUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long f(GOTFUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long f(GOTOFFFUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long tls(tlsgd_fdpic)
+.long tls(tlsldm_fdpic)
+.long tls(gottpoff_fdpic)
diff --git a/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test b/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test
index eb60d2a021af63..a48346d6b9c85e 100644
--- a/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test
+++ b/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test
@@ -192,6 +192,13 @@ FileHeader:
# OSABI-ARM-LLVM: OS/ABI: ARM (0x61)
# OSABI-ARM-GNU: OS/ABI: ARM
+# RUN: yaml2obj %s -DOSABI=ELFOSABI_ARM_FDPIC -DMACHINE=EM_ARM -o %t.osabi.arm_fdpic
+# RUN: llvm-readobj --file-headers %t.osabi.arm_fdpic | FileCheck %s --match-full-lines --check-prefix=OSABI-ARMFDPIC-LLVM
+# RUN: llvm-readelf --file-headers %t.osabi.arm_fdpic | FileCheck %s --match-full-lines --check-prefix=OSABI-ARMFDPIC-GNU
+
+# OSABI-ARMFDPIC-LLVM: OS/ABI: ARM FDPIC (0x41)
+# OSABI-ARMFDPIC-GNU: OS/ABI: ARM FDPIC
+
## Check all EM_TI_C6000 specific values.
# RUN: yaml2obj %s -DOSABI=ELFOSABI_C6000_ELFABI -DMACHINE=EM_TI_C6000 -o %t.osabi.c6000.elfabi
diff --git a/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test b/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test
index 96d6cfed4df3e1..dafe01ba36afb1 100644
--- a/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test
+++ b/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test
@@ -135,6 +135,13 @@
# CHECK: Type: R_ARM_THM_TLS_DESCSEQ16 (129)
# CHECK: Type: R_ARM_THM_TLS_DESCSEQ32 (130)
# CHECK: Type: R_ARM_IRELATIVE (160)
+# CHECK: Type: R_ARM_GOTFUNCDESC (161)
+# CHECK: Type: R_ARM_GOTOFFFUNCDESC (162)
+# CHECK: Type: R_ARM_FUNCDESC (163)
+# CHECK: Type: R_ARM_FUNCDESC_VALUE (164)
+# CHECK: Type: R_ARM_TLS_GD32_FDPIC (165)
+# CHECK: Type: R_ARM_TLS_LDM32_FDPIC (166)
+# CHECK: Type: R_ARM_TLS_IE32_FDPIC (167)
--- !ELF
FileHeader:
@@ -278,3 +285,10 @@ Sections:
- Type: R_ARM_THM_TLS_DESCSEQ16
- Type: R_ARM_THM_TLS_DESCSEQ32
- Type: R_ARM_IRELATIVE
+ - Type: R_ARM_GOTFUNCDESC
+ - Type: R_ARM_GOTOFFFUNCDESC
+ - Type: R_ARM_FUNCDESC
+ - Type: R_ARM_FUNCDESC_VALUE
+ - Type: R_ARM_TLS_GD32_FDPIC
+ - Type: R_ARM_TLS_LDM32_FDPIC
+ - Type: R_ARM_TLS_IE32_FDPIC
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index fa39e04f4ce9c0..8b8c4aa8d842b5 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -1095,7 +1095,8 @@ const EnumEntry<unsigned> AMDGPUElfOSABI[] = {
};
const EnumEntry<unsigned> ARMElfOSABI[] = {
- {"ARM", "ARM", ELF::ELFOSABI_ARM}
+ {"ARM", "ARM", ELF::ELFOSABI_ARM},
+ {"ARM FDPIC", "ARM FDPIC", ELF::ELFOSABI_ARM_FDPIC},
};
const EnumEntry<unsigned> C6000ElfOSABI[] = {
|
@llvm/pr-subscribers-backend-arm Author: Fangrui Song (MaskRay) ChangesLinux kernel fs/binfmt_elf_fdpic.c supports FDPIC for MMU-less systems. This patch implements FDPIC relocations to the integrated assembler. gas requires Full diff: https://github.com/llvm/llvm-project/pull/82187.diff 18 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 124bba76c1774c..bace3a92677a82 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -362,6 +362,7 @@ enum {
ELFOSABI_AMDGPU_PAL = 65, // AMD PAL runtime
ELFOSABI_AMDGPU_MESA3D = 66, // AMD GCN GPUs (GFX6+) for MESA runtime
ELFOSABI_ARM = 97, // ARM
+ ELFOSABI_ARM_FDPIC = 65, // ARM FDPIC
ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000
ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000
ELFOSABI_STANDALONE = 255, // Standalone (embedded) application
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def
index 47084d1eb0aad5..7e9fe965241f25 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def
@@ -143,3 +143,10 @@ ELF_RELOC(R_ARM_THM_BF16, 0x88)
ELF_RELOC(R_ARM_THM_BF12, 0x89)
ELF_RELOC(R_ARM_THM_BF18, 0x8a)
ELF_RELOC(R_ARM_IRELATIVE, 0xa0)
+ELF_RELOC(R_ARM_GOTFUNCDESC, 0xa1)
+ELF_RELOC(R_ARM_GOTOFFFUNCDESC, 0xa2)
+ELF_RELOC(R_ARM_FUNCDESC, 0xa3)
+ELF_RELOC(R_ARM_FUNCDESC_VALUE, 0xa4)
+ELF_RELOC(R_ARM_TLS_GD32_FDPIC, 0xa5)
+ELF_RELOC(R_ARM_TLS_LDM32_FDPIC, 0xa6)
+ELF_RELOC(R_ARM_TLS_IE32_FDPIC, 0xa7)
diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 67836292874f5f..b3119609372049 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -223,6 +223,12 @@ class MCSymbolRefExpr : public MCExpr {
VK_SECREL,
VK_SIZE, // symbol@SIZE
VK_WEAKREF, // The link between the symbols in .weakref foo, bar
+ VK_FUNCDESC,
+ VK_GOTFUNCDESC,
+ VK_GOTOFFFUNCDESC,
+ VK_TLSGD_FDPIC,
+ VK_TLSLDM_FDPIC,
+ VK_GOTTPOFF_FDPIC,
VK_X86_ABS8,
VK_X86_PLTOFF,
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index fe905f2c3ba5fe..7edd3f8ce4904c 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -525,6 +525,10 @@ class MCTargetAsmParser : public MCAsmParserExtension {
// Return whether this parser accept star as start of statement
virtual bool starIsStartOfStatement() { return false; };
+ virtual MCSymbolRefExpr::VariantKind
+ getVariantKindForName(StringRef Name) const {
+ return MCSymbolRefExpr::getVariantKindForName(Name);
+ }
virtual const MCExpr *applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind,
MCContext &Ctx) {
diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h
index e2dd1e0433dbe4..a7295879e15f0f 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -51,6 +51,7 @@ class MCTargetOptions {
bool MCNoTypeCheck : 1;
bool MCSaveTempLabels : 1;
bool MCIncrementalLinkerCompatible : 1;
+ bool FDPIC : 1;
bool ShowMCEncoding : 1;
bool ShowMCInst : 1;
bool AsmVerbose : 1;
diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
index 7f6ee6c8be224a..ba3784cab5b11d 100644
--- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
+++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
@@ -29,6 +29,8 @@ std::optional<bool> getExplicitRelaxAll();
bool getIncrementalLinkerCompatible();
+bool getFDPIC();
+
int getDwarfVersion();
bool getDwarf64();
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 80def6dfc24b1a..485fd1885ddb52 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -220,6 +220,7 @@ const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind,
StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
switch (Kind) {
+ // clang-format off
case VK_Invalid: return "<<invalid>>";
case VK_None: return "<<none>>";
@@ -232,13 +233,16 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_GOTPCREL: return "GOTPCREL";
case VK_GOTPCREL_NORELAX: return "GOTPCREL_NORELAX";
case VK_GOTTPOFF: return "GOTTPOFF";
+ case VK_GOTTPOFF_FDPIC: return "gottpoff_fdpic";
case VK_INDNTPOFF: return "INDNTPOFF";
case VK_NTPOFF: return "NTPOFF";
case VK_GOTNTPOFF: return "GOTNTPOFF";
case VK_PLT: return "PLT";
case VK_TLSGD: return "TLSGD";
+ case VK_TLSGD_FDPIC: return "tlsgd_fdpic";
case VK_TLSLD: return "TLSLD";
case VK_TLSLDM: return "TLSLDM";
+ case VK_TLSLDM_FDPIC: return "tlsldm_fdpic";
case VK_TPOFF: return "TPOFF";
case VK_TPREL: return "TPREL";
case VK_TLSCALL: return "tlscall";
@@ -253,6 +257,9 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_SECREL: return "SECREL32";
case VK_SIZE: return "SIZE";
case VK_WEAKREF: return "WEAKREF";
+ case VK_FUNCDESC: return "FUNCDESC";
+ case VK_GOTFUNCDESC: return "GOTFUNCDESC";
+ case VK_GOTOFFFUNCDESC: return "GOTOFFFUNCDESC";
case VK_X86_ABS8: return "ABS8";
case VK_X86_PLTOFF: return "PLTOFF";
case VK_ARM_NONE: return "none";
@@ -386,6 +393,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_VE_TLS_GD_LO32: return "tls_gd_lo";
case VK_VE_TPOFF_HI32: return "tpoff_hi";
case VK_VE_TPOFF_LO32: return "tpoff_lo";
+ // clang-format on
}
llvm_unreachable("Invalid variant kind");
}
@@ -493,13 +501,6 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("ie", VK_Hexagon_IE)
.Case("ldgot", VK_Hexagon_LD_GOT)
.Case("ldplt", VK_Hexagon_LD_PLT)
- .Case("none", VK_ARM_NONE)
- .Case("got_prel", VK_ARM_GOT_PREL)
- .Case("target1", VK_ARM_TARGET1)
- .Case("target2", VK_ARM_TARGET2)
- .Case("prel31", VK_ARM_PREL31)
- .Case("sbrel", VK_ARM_SBREL)
- .Case("tlsldo", VK_ARM_TLSLDO)
.Case("lo8", VK_AVR_LO8)
.Case("hi8", VK_AVR_HI8)
.Case("hlo8", VK_AVR_HLO8)
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 8e508dbdb1c69b..a1c32eee328643 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1237,7 +1237,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
// Lookup the symbol variant if used.
if (!Split.second.empty()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ Variant = getTargetParser().getVariantKindForName(Split.second);
if (Variant != MCSymbolRefExpr::VK_Invalid) {
SymbolName = Split.first;
} else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
index 07c6e752cb613d..bff4b8da2fb1b0 100644
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -15,7 +15,7 @@ MCTargetOptions::MCTargetOptions()
: MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false),
MCNoWarn(false), MCNoDeprecatedWarn(false), MCNoTypeCheck(false),
MCSaveTempLabels(false), MCIncrementalLinkerCompatible(false),
- ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
+ FDPIC(false), ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
PreserveAsmComments(true), Dwarf64(false),
EmitDwarfUnwind(EmitDwarfUnwindType::Default),
MCUseDwarfDirectory(DefaultDwarfDirectory),
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 8a4923e4792fb5..fb8334d626cb8b 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -36,6 +36,7 @@ using namespace llvm;
MCOPT_EXP(bool, RelaxAll)
MCOPT(bool, IncrementalLinkerCompatible)
+MCOPT(bool, FDPIC)
MCOPT(int, DwarfVersion)
MCOPT(bool, Dwarf64)
MCOPT(EmitDwarfUnwindType, EmitDwarfUnwind)
@@ -66,6 +67,9 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
"emit an object file which can be used with an incremental linker"));
MCBINDOPT(IncrementalLinkerCompatible);
+ static cl::opt<bool> FDPIC("fdpic", cl::desc("Use the FDPIC ABI"));
+ MCBINDOPT(FDPIC);
+
static cl::opt<int> DwarfVersion("dwarf-version", cl::desc("Dwarf version"),
cl::init(0));
MCBINDOPT(DwarfVersion);
@@ -135,6 +139,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
MCTargetOptions Options;
Options.MCRelaxAll = getRelaxAll();
Options.MCIncrementalLinkerCompatible = getIncrementalLinkerCompatible();
+ Options.FDPIC = getFDPIC();
Options.Dwarf64 = getDwarf64();
Options.DwarfVersion = getDwarfVersion();
Options.ShowMCInst = getShowMCInst();
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index de1ef2458152c8..9c1a28db592a1c 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -406,6 +406,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration(
ECase(ELFOSABI_AMDGPU_PAL);
ECase(ELFOSABI_AMDGPU_MESA3D);
ECase(ELFOSABI_ARM);
+ ECase(ELFOSABI_ARM_FDPIC);
ECase(ELFOSABI_C6000_ELFABI);
ECase(ELFOSABI_C6000_LINUX);
ECase(ELFOSABI_STANDALONE);
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index c82ab57bdf80f1..37bfb76a494dee 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -737,6 +737,9 @@ class ARMAsmParser : public MCTargetAsmParser {
void ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses, SMLoc IDLoc,
OperandVector &Operands);
+ MCSymbolRefExpr::VariantKind
+ getVariantKindForName(StringRef Name) const override;
+
void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override;
void onLabelParsed(MCSymbol *Symbol) override;
@@ -11358,6 +11361,37 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
return false;
}
+MCSymbolRefExpr::VariantKind
+ARMAsmParser::getVariantKindForName(StringRef Name) const {
+ return StringSwitch<MCSymbolRefExpr::VariantKind>(Name.lower())
+ .Case("funcdesc", MCSymbolRefExpr::VK_FUNCDESC)
+ .Case("got", MCSymbolRefExpr::VK_GOT)
+ .Case("got_prel", MCSymbolRefExpr::VK_ARM_GOT_PREL)
+ .Case("gotfuncdesc", MCSymbolRefExpr::VK_GOTFUNCDESC)
+ .Case("gotoff", MCSymbolRefExpr::VK_GOTOFF)
+ .Case("gotofffuncdesc", MCSymbolRefExpr::VK_GOTOFFFUNCDESC)
+ .Case("gottpoff", MCSymbolRefExpr::VK_GOTTPOFF)
+ .Case("gottpoff_fdpic", MCSymbolRefExpr::VK_GOTTPOFF_FDPIC)
+ .Case("imgrel", MCSymbolRefExpr::VK_COFF_IMGREL32)
+ .Case("none", MCSymbolRefExpr::VK_ARM_NONE)
+ .Case("plt", MCSymbolRefExpr::VK_PLT)
+ .Case("prel31", MCSymbolRefExpr::VK_ARM_PREL31)
+ .Case("sbrel", MCSymbolRefExpr::VK_ARM_SBREL)
+ .Case("secrel32", MCSymbolRefExpr::VK_SECREL)
+ .Case("target1", MCSymbolRefExpr::VK_ARM_TARGET1)
+ .Case("target2", MCSymbolRefExpr::VK_ARM_TARGET2)
+ .Case("tlscall", MCSymbolRefExpr::VK_TLSCALL)
+ .Case("tlsdesc", MCSymbolRefExpr::VK_TLSDESC)
+ .Case("tlsgd", MCSymbolRefExpr::VK_TLSGD)
+ .Case("tlsgd_fdpic", MCSymbolRefExpr::VK_TLSGD_FDPIC)
+ .Case("tlsld", MCSymbolRefExpr::VK_TLSLD)
+ .Case("tlsldm", MCSymbolRefExpr::VK_TLSLDM)
+ .Case("tlsldm_fdpic", MCSymbolRefExpr::VK_TLSLDM_FDPIC)
+ .Case("tlsldo", MCSymbolRefExpr::VK_ARM_TLSLDO)
+ .Case("tpoff", MCSymbolRefExpr::VK_TPOFF)
+ .Default(MCSymbolRefExpr::VK_Invalid);
+}
+
void ARMAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {
// We need to flush the current implicit IT block on a label, because it is
// not legal to branch into an IT block.
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 1d17bb349f24ba..6cd4badb7704b7 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -29,6 +29,7 @@
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/EndianStream.h"
@@ -1349,7 +1350,9 @@ static MCAsmBackend *createARMAsmBackend(const Target &T,
return new ARMAsmBackendWinCOFF(T, STI.getTargetTriple().isThumb());
case Triple::ELF:
assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target");
- uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
+ uint8_t OSABI = Options.FDPIC
+ ? ELF::ELFOSABI_ARM_FDPIC
+ : MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
return new ARMAsmBackendELF(T, STI.getTargetTriple().isThumb(), OSABI,
Endian);
}
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
index 44695a86c4e36c..baec4a5cb5215a 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
@@ -84,6 +84,11 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
if (Kind >= FirstLiteralRelocationKind)
return Kind - FirstLiteralRelocationKind;
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
+ auto CheckFDPIC = [&]() {
+ if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC)
+ Ctx.reportError(Fixup.getLoc(),
+ "relocation only supported in FDPIC mode");
+ };
if (IsPCRel) {
switch (Fixup.getTargetKind()) {
@@ -240,6 +245,24 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
return ELF::R_ARM_TLS_LDM32;
case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
return ELF::R_ARM_TLS_DESCSEQ;
+ case MCSymbolRefExpr::VK_FUNCDESC:
+ CheckFDPIC();
+ return ELF::R_ARM_FUNCDESC;
+ case MCSymbolRefExpr::VK_GOTFUNCDESC:
+ CheckFDPIC();
+ return ELF::R_ARM_GOTFUNCDESC;
+ case MCSymbolRefExpr::VK_GOTOFFFUNCDESC:
+ CheckFDPIC();
+ return ELF::R_ARM_GOTOFFFUNCDESC;
+ case MCSymbolRefExpr::VK_TLSGD_FDPIC:
+ CheckFDPIC();
+ return ELF::R_ARM_TLS_GD32_FDPIC;
+ case MCSymbolRefExpr::VK_TLSLDM_FDPIC:
+ CheckFDPIC();
+ return ELF::R_ARM_TLS_LDM32_FDPIC;
+ case MCSymbolRefExpr::VK_GOTTPOFF_FDPIC:
+ CheckFDPIC();
+ return ELF::R_ARM_TLS_IE32_FDPIC;
}
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
diff --git a/llvm/test/MC/ARM/fdpic.s b/llvm/test/MC/ARM/fdpic.s
new file mode 100644
index 00000000000000..4f36393d9110e8
--- /dev/null
+++ b/llvm/test/MC/ARM/fdpic.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc -triple=armv7-linux-gnueabi %s | FileCheck %s --check-prefix=ASM
+# RUN: llvm-mc -filetype=obj -triple=armv7-linux-gnueabi --fdpic %s | llvm-readelf -h -r - | FileCheck %s
+
+# RUN: not llvm-mc -filetype=obj -triple=armv7-linux-gnueabi %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+# ASM: .long f(FUNCDESC)
+# ASM-NEXT: .long f(GOTFUNCDESC)
+# ASM-NEXT: .long f(GOTOFFFUNCDESC)
+
+# CHECK: OS/ABI: ARM FDPIC
+# CHECK: Machine: ARM
+# CHECK: Flags: 0x5000000
+
+# CHECK: R_ARM_FUNCDESC 00000000 f
+# CHECK-NEXT: R_ARM_GOTFUNCDESC 00000000 f
+# CHECK-NEXT: R_ARM_GOTOFFFUNCDESC 00000000 f
+# CHECK-NEXT: R_ARM_TLS_GD32_FDPIC 00000000 tls
+# CHECK-NEXT: R_ARM_TLS_LDM32_FDPIC 00000000 tls
+# CHECK-NEXT: R_ARM_TLS_IE32_FDPIC 00000000 tls
+
+.data
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long f(FUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long f(GOTFUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long f(GOTOFFFUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation only supported in FDPIC mode
+.long tls(tlsgd_fdpic)
+.long tls(tlsldm_fdpic)
+.long tls(gottpoff_fdpic)
diff --git a/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test b/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test
index eb60d2a021af63..a48346d6b9c85e 100644
--- a/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test
+++ b/llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test
@@ -192,6 +192,13 @@ FileHeader:
# OSABI-ARM-LLVM: OS/ABI: ARM (0x61)
# OSABI-ARM-GNU: OS/ABI: ARM
+# RUN: yaml2obj %s -DOSABI=ELFOSABI_ARM_FDPIC -DMACHINE=EM_ARM -o %t.osabi.arm_fdpic
+# RUN: llvm-readobj --file-headers %t.osabi.arm_fdpic | FileCheck %s --match-full-lines --check-prefix=OSABI-ARMFDPIC-LLVM
+# RUN: llvm-readelf --file-headers %t.osabi.arm_fdpic | FileCheck %s --match-full-lines --check-prefix=OSABI-ARMFDPIC-GNU
+
+# OSABI-ARMFDPIC-LLVM: OS/ABI: ARM FDPIC (0x41)
+# OSABI-ARMFDPIC-GNU: OS/ABI: ARM FDPIC
+
## Check all EM_TI_C6000 specific values.
# RUN: yaml2obj %s -DOSABI=ELFOSABI_C6000_ELFABI -DMACHINE=EM_TI_C6000 -o %t.osabi.c6000.elfabi
diff --git a/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test b/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test
index 96d6cfed4df3e1..dafe01ba36afb1 100644
--- a/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test
+++ b/llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test
@@ -135,6 +135,13 @@
# CHECK: Type: R_ARM_THM_TLS_DESCSEQ16 (129)
# CHECK: Type: R_ARM_THM_TLS_DESCSEQ32 (130)
# CHECK: Type: R_ARM_IRELATIVE (160)
+# CHECK: Type: R_ARM_GOTFUNCDESC (161)
+# CHECK: Type: R_ARM_GOTOFFFUNCDESC (162)
+# CHECK: Type: R_ARM_FUNCDESC (163)
+# CHECK: Type: R_ARM_FUNCDESC_VALUE (164)
+# CHECK: Type: R_ARM_TLS_GD32_FDPIC (165)
+# CHECK: Type: R_ARM_TLS_LDM32_FDPIC (166)
+# CHECK: Type: R_ARM_TLS_IE32_FDPIC (167)
--- !ELF
FileHeader:
@@ -278,3 +285,10 @@ Sections:
- Type: R_ARM_THM_TLS_DESCSEQ16
- Type: R_ARM_THM_TLS_DESCSEQ32
- Type: R_ARM_IRELATIVE
+ - Type: R_ARM_GOTFUNCDESC
+ - Type: R_ARM_GOTOFFFUNCDESC
+ - Type: R_ARM_FUNCDESC
+ - Type: R_ARM_FUNCDESC_VALUE
+ - Type: R_ARM_TLS_GD32_FDPIC
+ - Type: R_ARM_TLS_LDM32_FDPIC
+ - Type: R_ARM_TLS_IE32_FDPIC
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index fa39e04f4ce9c0..8b8c4aa8d842b5 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -1095,7 +1095,8 @@ const EnumEntry<unsigned> AMDGPUElfOSABI[] = {
};
const EnumEntry<unsigned> ARMElfOSABI[] = {
- {"ARM", "ARM", ELF::ELFOSABI_ARM}
+ {"ARM", "ARM", ELF::ELFOSABI_ARM},
+ {"ARM FDPIC", "ARM FDPIC", ELF::ELFOSABI_ARM_FDPIC},
};
const EnumEntry<unsigned> C6000ElfOSABI[] = {
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BinaryFormat/llvm-readobj aspects looks fine to me, but the assembler side of things goes a bit over my head, so you'll need someone else to review that area.
ELF_RELOC(R_ARM_TLS_GD32_FDPIC, 0xa5) | ||
ELF_RELOC(R_ARM_TLS_LDM32_FDPIC, 0xa6) | ||
ELF_RELOC(R_ARM_TLS_IE32_FDPIC, 0xa7) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be looking in the wrong place, but I couldn't see the values for these three relocations defined in the doc you link in the description?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for checking. https://github.com/mickael-guene/fdpic_doc doesn't define these values, but binutils-gdb defines the values (also referenced by projects like https://github.com/cutty/uld-fdpic/blob/master/include/elf.h). I've checked that llvm-readelf -r
output matches readelf -r
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've checked over the implementation with binutils. Out of interest are you planning on implementing all of fdpic or just enough to get assembler/linker support working?
If you are there are some other GNU options that may be useful to look at as possible intermediate steps. In particular -mno-pic-data-is-text-relative https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-mpic-data-is-text-relative this uses a single static base for the GOT which is sufficient for position independent executables but no shared library support.
@@ -223,6 +223,12 @@ class MCSymbolRefExpr : public MCExpr { | |||
VK_SECREL, | |||
VK_SIZE, // symbol@SIZE | |||
VK_WEAKREF, // The link between the symbols in .weakref foo, bar | |||
VK_FUNCDESC, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While VK_TLSGD_FDPIC are somewhat self documenting, it may be worth a comment for VK_FUNCDESC to VK_GOTOFFUNCDESC to state that these are for FDPIC.
@@ -11358,6 +11361,37 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) { | |||
return false; | |||
} | |||
|
|||
MCSymbolRefExpr::VariantKind | |||
ARMAsmParser::getVariantKindForName(StringRef Name) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see a design trade-off here. By implementing only the expressions that are supported on Arm we find some problems earlier, however we may miss out on generic expressions added to the MCSymbolRefExpr::getVariantKindForName
but not for Arm. I can see these getting out of sync.
Would it be worth calling the MCSymbolRefExpr::getVariantKindForName if the Name isn't found? Ideally we could refactor so that MCSymbolRefExpr::getVariantKindForName contains only generic and no target specific variant kinds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we could refactor so that MCSymbolRefExpr::getVariantKindForName contains only generic and no target specific variant kinds.
I agree with this. I believe that binutils doesn't have a generic operand modifier, so ideally MCSymbolRefExpr::getVariantKindForName
should be a pure virtual function. We will therefore be able to report the unknown modifier error at parsing time, instead of at ELFObjectWriter.
Unfortunately, many architectures add arch-specific modifiers in this list. We should eventually move them to respective lib/Target/XXX files.
In this patch I am only focusing on the ARM specific operand modifiers.
.Case("tlsldm_fdpic", MCSymbolRefExpr::VK_TLSLDM_FDPIC) | ||
.Case("tlsldo", MCSymbolRefExpr::VK_ARM_TLSLDO) | ||
.Case("tpoff", MCSymbolRefExpr::VK_TPOFF) | ||
.Default(MCSymbolRefExpr::VK_Invalid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Arm supports "tlddescseq" from checking this list against binutils. I don't think this was in the original list though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the binutils code contains tlsdescseq
, but there is no (tlsdescseq)
occurrence. GCC doesn't emit (tlsdescseq)
, either.
I suspect that the entry in binutils is not used.
There is a directive named .tlsdescseq
(https://www.fsfla.org/~lxoliva/writeups/TLS/RFC-TLSDESC-ARM.txt), which is for TLS optimization. But GCC doesn't emit this directive.
Clang doesn't support -mtls-dialect=gnu2
for ARM.
@@ -84,6 +84,11 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, | |||
if (Kind >= FirstLiteralRelocationKind) | |||
return Kind - FirstLiteralRelocationKind; | |||
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); | |||
auto CheckFDPIC = [&]() { | |||
if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC) | |||
Ctx.reportError(Fixup.getLoc(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the error message could be improved by giving out the string representation of the relocation code. For example:
relocation R_ARM_FUNCDESC only supported in FDPIC mode
. I think this should be relatively easy to add.
Yes, I plan to implement the codegen part to help me understand FDPIC better and the codegen part of LLVM...
Thanks for the pointers. Yes, it looks like ARM added |
Created using spr 1.3.4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update, I'm happy with the changes. I would like to see more options for position independent code in embedded systems.
The other related embedded position independent option for microcontrollers that I'm aware of is -fropi
and -frwpi
which is already implemented in clang. This is relocation free with just one static data area accessed as an offset from r9. It works quite well for C code, but doesn't support C++ (vtables and RTTI need relocations) and some forms of static initialisation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to approve
Thanks for the comment. ROPI/RWPI seems similar to -mno-pic-data-is-text-relative. In 2013, -mno-pic-data-is-text-relative, generalized from the ARM VxWorks RTP port, was added to assume that text and data segments don't have a fixed displacement. On non-VxWorks-RTP targets, -mno-pic-data-is-text-relative implies -msingle-pic-base: Treat the register used for PIC addressing as read-only, rather than loading it in the prologue for each function. The runtime system is responsible for initializing this register with an appropriate value before execution begins. r9 is used as the static base (`arm_pic_register) in the position-independent data model to access the data segment. Since r9 is not changed, dynamic linking seems unsupported as a DSO needs a different data segment. |
2f900f7
into
users/MaskRay/spr/main.armmc-support-fdpic-relocations
Linux kernel fs/binfmt_elf_fdpic.c supports FDPIC for MMU-less systems. GCC/binutils/qemu support FDPIC ABI for ARM (https://github.com/mickael-guene/fdpic_doc). _ARM FDPIC Toolchain and ABI_ provides a summary. This patch implements FDPIC relocations to the integrated assembler. There are 6 static relocations and 2 dynamic relocations, with R_ARM_FUNCDESC as both static and dynamic. gas requires `--fdpic` to assemble data relocations like `.word f(FUNCDESC)`. This patch adds `MCTargetOptions::FDPIC` and reports an error if FDPIC is not set. Pull Request: #82187
Linux kernel fs/binfmt_elf_fdpic.c supports FDPIC for MMU-less systems.
GCC/binutils/qemu support FDPIC ABI for ARM
(https://github.com/mickael-guene/fdpic_doc).
ARM FDPIC Toolchain and ABI provides a summary.
This patch implements FDPIC relocations to the integrated assembler.
There are 6 static relocations and 2 dynamic relocations, with
R_ARM_FUNCDESC as both static and dynamic.
gas requires
--fdpic
to assemble data relocations like.word f(FUNCDESC)
.This patch adds
MCTargetOptions::FDPIC
and reports an error if FDPICis not set.