[llvm-branch-commits] [ARM, MC] Support FDPIC relocations (PR #82187)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Feb 18 11:28:25 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

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.


---
Full diff: https://github.com/llvm/llvm-project/pull/82187.diff


18 Files Affected:

- (modified) llvm/include/llvm/BinaryFormat/ELF.h (+1) 
- (modified) llvm/include/llvm/BinaryFormat/ELFRelocs/ARM.def (+7) 
- (modified) llvm/include/llvm/MC/MCExpr.h (+6) 
- (modified) llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h (+4) 
- (modified) llvm/include/llvm/MC/MCTargetOptions.h (+1) 
- (modified) llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h (+2) 
- (modified) llvm/lib/MC/MCExpr.cpp (+8-7) 
- (modified) llvm/lib/MC/MCParser/AsmParser.cpp (+1-1) 
- (modified) llvm/lib/MC/MCTargetOptions.cpp (+1-1) 
- (modified) llvm/lib/MC/MCTargetOptionsCommandFlags.cpp (+5) 
- (modified) llvm/lib/ObjectYAML/ELFYAML.cpp (+1) 
- (modified) llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (+34) 
- (modified) llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (+4-1) 
- (modified) llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp (+23) 
- (added) llvm/test/MC/ARM/fdpic.s (+31) 
- (modified) llvm/test/tools/llvm-readobj/ELF/file-header-os-abi.test (+7) 
- (modified) llvm/test/tools/llvm-readobj/ELF/reloc-types-arm.test (+14) 
- (modified) llvm/tools/llvm-readobj/ELFDumper.cpp (+2-1) 


``````````diff
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 at 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[] = {

``````````

</details>


https://github.com/llvm/llvm-project/pull/82187


More information about the llvm-branch-commits mailing list