[lld] r234473 - [ARM] Add mapping symbols to veneers

Denis Protivensky dprotivensky at accesssoftek.com
Thu Apr 9 02:59:18 PDT 2015


Author: denis-protivensky
Date: Thu Apr  9 04:59:18 2015
New Revision: 234473

URL: http://llvm.org/viewvc/llvm-project?rev=234473&view=rev
Log:
[ARM] Add mapping symbols to veneers

This required splitting up veneer atoms into pieces,
where every piece is paired with mapping atom of
the corresponding type.

Added:
    lld/trunk/test/elf/ARM/veneer-mapping.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp?rev=234473&r1=234472&r2=234473&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp Thu Apr  9 04:59:18 2015
@@ -32,17 +32,21 @@ namespace {
 // ARM B/BL instructions of static relocation veneer.
 // TODO: consider different instruction set for archs below ARMv5
 // (one as for Thumb may be used though it's less optimal).
-static const uint8_t Veneer_ARM_B_BL_StaticAtomContent[8] = {
-    0x04, 0xf0, 0x1f, 0xe5,  // ldr pc, [pc, #-4]
+static const uint8_t Veneer_ARM_B_BL_Static_a_AtomContent[4] = {
+    0x04, 0xf0, 0x1f, 0xe5   // ldr pc, [pc, #-4]
+};
+static const uint8_t Veneer_ARM_B_BL_Static_d_AtomContent[4] = {
     0x00, 0x00, 0x00, 0x00   // <target_symbol_address>
 };
 
 // Thumb B/BL instructions of static relocation veneer.
 // TODO: consider different instruction set for archs above ARMv5
 // (one as for ARM may be used since it's more optimal).
-static const uint8_t Veneer_THM_B_BL_StaticAtomContent[8] = {
+static const uint8_t Veneer_THM_B_BL_Static_t_AtomContent[4] = {
     0x78, 0x47,              // bx pc
-    0x00, 0x00,              // nop
+    0x00, 0x00               // nop
+};
+static const uint8_t Veneer_THM_B_BL_Static_a_AtomContent[4] = {
     0xfe, 0xff, 0xff, 0xea   // b <target_symbol_address>
 };
 
@@ -62,7 +66,6 @@ static const uint8_t ARMPltVeneerAtomCon
     0x00, 0x00               // nop
 };
 
-#ifdef NDEBUG
 // Determine proper names for mapping symbols.
 static std::string getMappingAtomName(DefinedAtom::CodeModel model,
                                       const std::string &part) {
@@ -77,15 +80,14 @@ static std::string getMappingAtomName(De
     llvm_unreachable("Wrong code model of mapping atom");
   }
 }
-#endif
 
 /// \brief Atoms that hold veneer code.
 class VeneerAtom : public SimpleELFDefinedAtom {
   StringRef _section;
 
 public:
-  VeneerAtom(const File &f, StringRef secName)
-      : SimpleELFDefinedAtom(f), _section(secName) {}
+  VeneerAtom(const File &f, StringRef secName, const std::string &name = "")
+      : SimpleELFDefinedAtom(f), _section(secName), _name(name) {}
 
   Scope scope() const override { return DefinedAtom::scopeTranslationUnit; }
 
@@ -106,37 +108,79 @@ public:
   Alignment alignment() const override { return 4; }
 
   StringRef name() const override { return _name; }
+
+private:
   std::string _name;
 };
 
 /// \brief Atoms that hold veneer for statically relocated
 /// ARM B/BL instructions.
-class Veneer_ARM_B_BL_StaticAtom : public VeneerAtom {
+class Veneer_ARM_B_BL_Static_a_Atom : public VeneerAtom {
+public:
+  Veneer_ARM_B_BL_Static_a_Atom(const File &f, StringRef secName,
+                                const std::string &name)
+      : VeneerAtom(f, secName, name) {}
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return llvm::makeArrayRef(Veneer_ARM_B_BL_Static_a_AtomContent);
+  }
+};
+
+class Veneer_ARM_B_BL_Static_d_Atom : public VeneerAtom {
 public:
-  Veneer_ARM_B_BL_StaticAtom(const File &f, StringRef secName)
+  Veneer_ARM_B_BL_Static_d_Atom(const File &f, StringRef secName)
       : VeneerAtom(f, secName) {}
 
   ArrayRef<uint8_t> rawContent() const override {
-    return llvm::makeArrayRef(Veneer_ARM_B_BL_StaticAtomContent);
+    return llvm::makeArrayRef(Veneer_ARM_B_BL_Static_d_AtomContent);
   }
 };
 
 /// \brief Atoms that hold veneer for statically relocated
 /// Thumb B/BL instructions.
-class Veneer_THM_B_BL_StaticAtom : public VeneerAtom {
+class Veneer_THM_B_BL_Static_t_Atom : public VeneerAtom {
 public:
-  Veneer_THM_B_BL_StaticAtom(const File &f, StringRef secName)
-      : VeneerAtom(f, secName) {}
+  Veneer_THM_B_BL_Static_t_Atom(const File &f, StringRef secName,
+                                const std::string &name)
+      : VeneerAtom(f, secName, name) {}
 
   DefinedAtom::CodeModel codeModel() const override {
     return DefinedAtom::codeARMThumb;
   }
 
   ArrayRef<uint8_t> rawContent() const override {
-    return llvm::makeArrayRef(Veneer_THM_B_BL_StaticAtomContent);
+    return llvm::makeArrayRef(Veneer_THM_B_BL_Static_t_AtomContent);
+  }
+};
+
+class Veneer_THM_B_BL_Static_a_Atom : public VeneerAtom {
+public:
+  Veneer_THM_B_BL_Static_a_Atom(const File &f, StringRef secName)
+      : VeneerAtom(f, secName) {}
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return llvm::makeArrayRef(Veneer_THM_B_BL_Static_a_AtomContent);
   }
 };
 
+template <DefinedAtom::CodeModel Model>
+class ARMVeneerMappingAtom : public VeneerAtom {
+public:
+  ARMVeneerMappingAtom(const File &f, StringRef secName, StringRef name)
+      : VeneerAtom(f, secName, getMappingAtomName(Model, name)) {
+    static_assert((Model == DefinedAtom::codeARM_a ||
+                   Model == DefinedAtom::codeARM_d ||
+                   Model == DefinedAtom::codeARM_t),
+                  "Only mapping atom types are allowed");
+  }
+
+  uint64_t size() const override { return 0; }
+
+  ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
+
+  DefinedAtom::CodeModel codeModel() const override { return Model; }
+};
+
 /// \brief Atoms that are used by ARM dynamic linking
 class ARMGOTAtom : public GOTAtom {
 public:
@@ -353,6 +397,20 @@ protected:
     return g;
   }
 
+  /// \brief Add veneer with mapping symbol.
+  template <DefinedAtom::CodeModel Model>
+  void addVeneerWithMapping(const DefinedAtom *da, VeneerAtom *va,
+                            const std::string &name) {
+    assert(_veneerAtoms.lookup(da).empty() &&
+           "Veneer or mapping already exists");
+    auto *ma = new (_file._alloc)
+        ARMVeneerMappingAtom<Model>(_file, va->customSectionName(), name);
+
+    // Fake reference to show connection between the mapping symbol and veneer.
+    va->addReferenceELF_ARM(R_ARM_NONE, 0, ma, 0);
+    _veneerAtoms[da] = VeneerWithMapping(va, ma);
+  }
+
   /// \brief get a veneer for a PLT entry.
   const PLTAtom *getPLTVeneer(const DefinedAtom *da, PLTAtom *pa,
                               StringRef source) {
@@ -539,8 +597,12 @@ public:
     }
     for (auto &veneerKV : _veneerAtoms) {
       auto &veneer = veneerKV.second;
-      veneer->setOrdinal(ordinal++);
-      mf->addAtom(*veneer);
+      auto *m = veneer._mapping;
+      m->setOrdinal(ordinal++);
+      mf->addAtom(*m);
+      auto *v = veneer._veneer;
+      v->setOrdinal(ordinal++);
+      mf->addAtom(*v);
     }
   }
 
@@ -568,7 +630,20 @@ protected:
   llvm::MapVector<const Atom *, PLTWithVeneer> _pltAtoms;
 
   /// \brief Map Atoms to their veneers.
-  llvm::MapVector<const Atom *, VeneerAtom *> _veneerAtoms;
+  struct VeneerWithMapping {
+    VeneerWithMapping(VeneerAtom *v = nullptr, VeneerAtom *m = nullptr)
+        : _veneer(v), _mapping(m) {}
+
+    bool empty() const {
+      assert(((bool)_veneer == (bool)_mapping) &&
+             "Mapping symbol should always be paired with veneer");
+      return !_veneer && !_mapping;
+    }
+
+    VeneerAtom *_veneer;
+    VeneerAtom *_mapping;
+  };
+  llvm::MapVector<const Atom *, VeneerWithMapping> _veneerAtoms;
 
   /// \brief GOT entry that is always 0. Used for undefined weaks.
   GOTAtom *_null = nullptr;
@@ -589,33 +664,47 @@ public:
   /// \brief Get the veneer for ARM B/BL instructions.
   const VeneerAtom *getVeneer_ARM_B_BL(const DefinedAtom *da,
                                        StringRef secName) {
-    if (auto veneer = _veneerAtoms.lookup(da))
-      return veneer;
-    auto v = new (_file._alloc) Veneer_ARM_B_BL_StaticAtom(_file, secName);
-    v->addReferenceELF_ARM(R_ARM_ABS32, 4, da, 0);
-
-    v->_name = "__";
-    v->_name += da->name();
-    v->_name += "_from_arm";
+    auto veneer = _veneerAtoms.lookup(da);
+    if (!veneer.empty())
+      return veneer._veneer;
 
-    _veneerAtoms[da] = v;
-    return v;
+    std::string name = "__";
+    name += da->name();
+    name += "_from_arm";
+    // Create parts of veneer with mapping symbols.
+    auto v_a = new (_file._alloc) Veneer_ARM_B_BL_Static_a_Atom(_file, secName, name);
+    addVeneerWithMapping<DefinedAtom::codeARM_a>(da, v_a, name);
+    auto v_d = new (_file._alloc) Veneer_ARM_B_BL_Static_d_Atom(_file, secName);
+    addVeneerWithMapping<DefinedAtom::codeARM_d>(v_a, v_d, name);
+
+    // Fake reference to show connection between parts of veneer.
+    v_a->addReferenceELF_ARM(R_ARM_NONE, 0, v_d, 0);
+    // Real reference to fixup.
+    v_d->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0);
+    return v_a;
   }
 
   /// \brief Get the veneer for Thumb B/BL instructions.
   const VeneerAtom *getVeneer_THM_B_BL(const DefinedAtom *da,
                                        StringRef secName) {
-    if (auto veneer = _veneerAtoms.lookup(da))
-      return veneer;
-    auto v = new (_file._alloc) Veneer_THM_B_BL_StaticAtom(_file, secName);
-    v->addReferenceELF_ARM(R_ARM_JUMP24, 4, da, 0);
-
-    v->_name = "__";
-    v->_name += da->name();
-    v->_name += "_from_thumb";
+    auto veneer = _veneerAtoms.lookup(da);
+    if (!veneer.empty())
+      return veneer._veneer;
 
-    _veneerAtoms[da] = v;
-    return v;
+    std::string name = "__";
+    name += da->name();
+    name += "_from_thumb";
+    // Create parts of veneer with mapping symbols.
+    auto v_t = new (_file._alloc) Veneer_THM_B_BL_Static_t_Atom(_file, secName, name);
+    addVeneerWithMapping<DefinedAtom::codeARM_t>(da, v_t, name);
+    auto v_a = new (_file._alloc) Veneer_THM_B_BL_Static_a_Atom(_file, secName);
+    addVeneerWithMapping<DefinedAtom::codeARM_a>(v_t, v_a, name);
+
+    // Fake reference to show connection between parts of veneer.
+    v_t->addReferenceELF_ARM(R_ARM_NONE, 0, v_a, 0);
+    // Real reference to fixup.
+    v_a->addReferenceELF_ARM(R_ARM_JUMP24, 0, da, 0);
+    return v_t;
   }
 
   /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc.

Added: lld/trunk/test/elf/ARM/veneer-mapping.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/veneer-mapping.test?rev=234473&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/veneer-mapping.test (added)
+++ lld/trunk/test/elf/ARM/veneer-mapping.test Thu Apr  9 04:59:18 2015
@@ -0,0 +1,94 @@
+# Check that mapping symbols are properly generated for veneers.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
+# RUN: lld -flavor gnu -target arm-linux-gnu --defsym=main=fa \
+# RUN: -Bstatic --noinhibit-exec %t-arm.o %t-thm.o -o %t
+# RUN: llvm-readobj -symbols %t | FileCheck %s
+
+# CHECK: Name: $a.__ft_from_arm
+# CHECK: Name: $d.__ft_from_arm
+# CHECK: Name: $t.__fa_from_thumb
+# CHECK: Name: $a.__fa_from_thumb
+
+# arm.o
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         00482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000008
+        Symbol:          ft
+        Type:            R_ARM_JUMP24
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+Symbols:
+  Global:
+    - Name:            fa
+      Type:            STT_FUNC
+      Section:         .text
+    - Name:            ft
+
+# thm.o
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         80B500AFFFF7FEBF0346184680BD00BF
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000004
+        Symbol:          fa
+        Type:            R_ARM_THM_JUMP24
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+Symbols:
+  Global:
+    - Name:            ft
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            fa
+...





More information about the llvm-commits mailing list