summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2024-02-21 09:40:50 -0800
committerGitHub <noreply@github.com>2024-02-21 09:40:50 -0800
commit2f900f7d1e0fce4c245286f09b96205e999cc0e4 (patch)
tree788abb6025ef69fe4d7ad4122143ef367db109b8
parent37a3b014f5a6f27ac1d948f2cae328501f3f4d82 (diff)
[ARM,MC] Support FDPIC relocations (#82187)upstream/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.
-rw-r--r--llvm/include/llvm/BinaryFormat/ELF.h1
-rw-r--r--llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def7
-rw-r--r--llvm/include/llvm/MC/MCExpr.h6
-rw-r--r--llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h4
-rw-r--r--llvm/include/llvm/MC/MCTargetOptions.h1
-rw-r--r--llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h2
-rw-r--r--llvm/lib/MC/MCExpr.cpp15
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp2
-rw-r--r--llvm/lib/MC/MCTargetOptions.cpp2
-rw-r--r--llvm/lib/MC/MCTargetOptionsCommandFlags.cpp5
-rw-r--r--llvm/lib/ObjectYAML/ELFYAML.cpp1
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp34
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp5
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp21
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/CMakeLists.txt1
-rw-r--r--llvm/test/MC/ARM/fdpic.s33
-rw-r--r--llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test7
-rw-r--r--llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test14
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp3
19 files changed, 153 insertions, 11 deletions
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 124bba76c177..bace3a92677a 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 47084d1eb0aa..7e9fe965241f 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 67836292874f..b31196093720 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -223,6 +223,12 @@ public:
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 fe905f2c3ba5..7edd3f8ce490 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -525,6 +525,10 @@ public:
// 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 e2dd1e0433db..a7295879e15f 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -51,6 +51,7 @@ public:
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 7f6ee6c8be22..ba3784cab5b1 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 80def6dfc24b..485fd1885ddb 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 8e508dbdb1c6..a1c32eee3286 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 07c6e752cb61..bff4b8da2fb1 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 8a4923e4792f..fb8334d626cb 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 de1ef2458152..9c1a28db592a 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 c82ab57bdf80..37bfb76a494d 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -737,6 +737,9 @@ public:
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 1d17bb349f24..6cd4badb7704 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 44695a86c4e3..de7449a400a7 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
@@ -16,6 +16,7 @@
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/Object/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
@@ -84,6 +85,14 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
if (Kind >= FirstLiteralRelocationKind)
return Kind - FirstLiteralRelocationKind;
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
+ auto CheckFDPIC = [&](uint32_t Type) {
+ if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC)
+ Ctx.reportError(Fixup.getLoc(),
+ "relocation " +
+ object::getELFRelocationTypeName(ELF::EM_ARM, Type) +
+ " only supported in FDPIC mode");
+ return Type;
+ };
if (IsPCRel) {
switch (Fixup.getTargetKind()) {
@@ -240,6 +249,18 @@ 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:
+ return CheckFDPIC(ELF::R_ARM_FUNCDESC);
+ case MCSymbolRefExpr::VK_GOTFUNCDESC:
+ return CheckFDPIC(ELF::R_ARM_GOTFUNCDESC);
+ case MCSymbolRefExpr::VK_GOTOFFFUNCDESC:
+ return CheckFDPIC(ELF::R_ARM_GOTOFFFUNCDESC);
+ case MCSymbolRefExpr::VK_TLSGD_FDPIC:
+ return CheckFDPIC(ELF::R_ARM_TLS_GD32_FDPIC);
+ case MCSymbolRefExpr::VK_TLSLDM_FDPIC:
+ return CheckFDPIC(ELF::R_ARM_TLS_LDM32_FDPIC);
+ case MCSymbolRefExpr::VK_GOTTPOFF_FDPIC:
+ return CheckFDPIC(ELF::R_ARM_TLS_IE32_FDPIC);
}
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
index 687d9a9e918d..8b3ef0ee651e 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
@@ -21,6 +21,7 @@ add_llvm_component_library(LLVMARMDesc
CodeGenTypes
MC
MCDisassembler
+ Object
Support
TargetParser
diff --git a/llvm/test/MC/ARM/fdpic.s b/llvm/test/MC/ARM/fdpic.s
new file mode 100644
index 000000000000..1dfedc59ada6
--- /dev/null
+++ b/llvm/test/MC/ARM/fdpic.s
@@ -0,0 +1,33 @@
+# 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 R_ARM_FUNCDESC only supported in FDPIC mode
+.long f(FUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation R_ARM_GOTFUNCDESC only supported in FDPIC mode
+.long f(GOTFUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation R_ARM_GOTOFFFUNCDESC only supported in FDPIC mode
+.long f(GOTOFFFUNCDESC)
+# ERR: [[#@LINE+1]]:7: error: relocation R_ARM_TLS_GD32_FDPIC only supported in FDPIC mode
+.long tls(tlsgd_fdpic)
+# ERR: [[#@LINE+1]]:7: error: relocation R_ARM_TLS_LDM32_FDPIC only supported in FDPIC mode
+.long tls(tlsldm_fdpic)
+# ERR: [[#@LINE+1]]:7: error: relocation R_ARM_TLS_IE32_FDPIC only supported in FDPIC mode
+.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 eb60d2a021af..a48346d6b9c8 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 96d6cfed4df3..dafe01ba36af 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 f937a074649a..4be678df4412 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[] = {