[lld] r228680 - [ELF][ARM] Add veneer generation to branch instructions

Denis Protivensky dprotivensky at accesssoftek.com
Tue Feb 10 01:31:43 PST 2015


Author: denis-protivensky
Date: Tue Feb 10 03:31:42 2015
New Revision: 228680

URL: http://llvm.org/viewvc/llvm-project?rev=228680&view=rev
Log:
[ELF][ARM] Add veneer generation to branch instructions

When calling ARM code from Thumb and vice versa,
a veneer that switches instruction set should be generated.
Added veneer generation for ARM_JUMP24 ARM_THM_JUMP24 instructions.

Differential Revision: http://reviews.llvm.org/D7502

Added:
    lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-b.test
    lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-bl.test
    lld/trunk/test/elf/ARM/rel-thm-jump24-veneer.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=228680&r1=228679&r2=228680&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp Tue Feb 10 03:31:42 2015
@@ -31,6 +31,85 @@ using namespace lld::elf;
 using namespace llvm::ELF;
 
 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).
+const uint8_t Veneer_ARM_B_BL_StaticAtomContent[8] = {
+    0x04, 0xf0, 0x1f, 0xe5,  // ldr pc, [pc, #-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).
+const uint8_t Veneer_THM_B_BL_StaticAtomContent[8] = {
+    0x78, 0x47,              // bx pc
+    0x00, 0x00,              // nop
+    0xfe, 0xff, 0xff, 0xea   // b <target_symbol_address>
+};
+
+/// \brief Atoms that hold veneer code.
+class VeneerAtom : public SimpleELFDefinedAtom {
+  StringRef _section;
+
+public:
+  VeneerAtom(const File &f, StringRef secName)
+      : SimpleELFDefinedAtom(f), _section(secName) {}
+
+  Scope scope() const override { return DefinedAtom::scopeTranslationUnit; }
+
+  SectionChoice sectionChoice() const override {
+    return DefinedAtom::sectionBasedOnContent;
+  }
+
+  StringRef customSectionName() const override { return _section; }
+
+  ContentType contentType() const override {
+    return DefinedAtom::typeCode;
+  }
+
+  uint64_t size() const override { return rawContent().size(); }
+
+  ContentPermissions permissions() const override { return permR_X; }
+
+  Alignment alignment() const override { return Alignment(2); }
+
+#ifndef NDEBUG
+  StringRef name() const override { return _name; }
+  std::string _name;
+#else
+  StringRef name() const override { return ""; }
+#endif
+};
+
+/// \brief Atoms that hold veneer for statically relocated
+/// ARM B/BL instructions.
+class Veneer_ARM_B_BL_StaticAtom : public VeneerAtom {
+public:
+  Veneer_ARM_B_BL_StaticAtom(const File &f, StringRef secName)
+      : VeneerAtom(f, secName) {}
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return llvm::makeArrayRef(Veneer_ARM_B_BL_StaticAtomContent);
+  }
+};
+
+/// \brief Atoms that hold veneer for statically relocated
+/// Thumb B/BL instructions.
+class Veneer_THM_B_BL_StaticAtom : public VeneerAtom {
+public:
+  Veneer_THM_B_BL_StaticAtom(const File &f, StringRef secName)
+      : VeneerAtom(f, secName) {}
+
+  DefinedAtom::CodeModel codeModel() const override {
+    return DefinedAtom::codeARMThumb;
+  }
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return llvm::makeArrayRef(Veneer_THM_B_BL_StaticAtomContent);
+  }
+};
+
 class ELFPassFile : public SimpleFile {
 public:
   ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
@@ -51,12 +130,67 @@ template <class Derived> class ARMReloca
     if (ref.kindNamespace() != Reference::KindNamespace::ELF)
       return;
     assert(ref.kindArch() == Reference::KindArch::ARM);
+    switch (ref.kindValue()) {
+    case R_ARM_JUMP24:
+    case R_ARM_THM_JUMP24:
+      static_cast<Derived *>(this)->handleVeneer(atom, ref);
+      break;
+    }
   }
 
 protected:
+  std::error_code handleVeneer(const DefinedAtom &atom, const Reference &ref) {
+    // Target symbol and relocated place should have different
+    // instruction sets in order a veneer to be generated in between.
+    const auto *target = dyn_cast_or_null<DefinedAtom>(ref.target());
+    if (!target || target->codeModel() == atom.codeModel())
+      return std::error_code();
+
+    // TODO: For unconditional jump instructions (R_ARM_CALL and R_ARM_THM_CALL)
+    // fixup isn't possible without veneer generation for archs below ARMv5.
+
+    // Veneers may only be generated for STT_FUNC target symbols
+    // or for symbols located in sections different to the place of relocation.
+    const auto kindValue = ref.kindValue();
+    StringRef secName = atom.customSectionName();
+    if (DefinedAtom::typeCode != target->contentType() &&
+        !target->customSectionName().equals(secName)) {
+      StringRef kindValStr;
+      if (!this->_ctx.registry().referenceKindToString(
+              ref.kindNamespace(), ref.kindArch(), kindValue, kindValStr)) {
+        kindValStr = "unknown";
+      }
+
+      std::string errStr =
+          (Twine("Reference of type ") + Twine(kindValue) + " (" + kindValStr +
+           ") from " + atom.name() + "+" + Twine(ref.offsetInAtom()) + " to " +
+           ref.target()->name() + "+" + Twine(ref.addend()) +
+           " cannot be effected without a veneer").str();
+
+      llvm_unreachable(errStr.c_str());
+    }
+
+    const Atom *veneer = nullptr;
+    switch (kindValue) {
+    case R_ARM_JUMP24:
+      veneer = static_cast<Derived *>(this)
+                   ->getVeneer_ARM_B_BL(target, secName);
+      break;
+    case R_ARM_THM_JUMP24:
+      veneer = static_cast<Derived *>(this)
+                   ->getVeneer_THM_B_BL(target, secName);
+      break;
+    default:
+      llvm_unreachable("Unhandled reference type for veneer generation");
+    }
+
+    assert(veneer && "The veneer is not set");
+    const_cast<Reference &>(ref).setTarget(veneer);
+    return std::error_code();
+  }
+
 public:
-  ARMRelocationPass(const ELFLinkingContext &ctx)
-      : _file(ctx), _ctx(ctx) {}
+  ARMRelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
 
   /// \brief Do the pass.
   ///
@@ -99,12 +233,25 @@ public:
         handleReference(*atom, *ref);
       }
     }
+
+    // Add all created atoms to the link.
+    uint64_t ordinal = 0;
+    for (auto &veneer : _veneerVector) {
+      veneer->setOrdinal(ordinal++);
+      mf->addAtom(*veneer);
+    }
   }
 
 protected:
   /// \brief Owner of all the Atoms created by this pass.
   ELFPassFile _file;
   const ELFLinkingContext &_ctx;
+
+  /// \brief Map Atoms to their veneers.
+  llvm::DenseMap<const Atom *, VeneerAtom *> _veneerMap;
+
+  /// \brief the list of veneer atoms.
+  std::vector<VeneerAtom *> _veneerVector;
 };
 
 /// This implements the static relocation model. Meaning GOT and PLT entries are
@@ -118,6 +265,44 @@ class ARMStaticRelocationPass final
 public:
   ARMStaticRelocationPass(const elf::ARMLinkingContext &ctx)
       : ARMRelocationPass(ctx) {}
+
+  /// \brief Get the veneer for ARM B/BL instructions.
+  const VeneerAtom *getVeneer_ARM_B_BL(const DefinedAtom *da,
+                                       StringRef secName) {
+    auto veneer = _veneerMap.find(da);
+    if (_veneerMap.end() != veneer)
+      return veneer->second;
+
+    auto v = new (_file._alloc) Veneer_ARM_B_BL_StaticAtom(_file, secName);
+    v->addReferenceELF_ARM(R_ARM_ABS32, 4, da, 0);
+#ifndef NDEBUG
+    v->_name = "__";
+    v->_name += da->name();
+    v->_name += "_from_arm";
+#endif
+    _veneerMap[da] = v;
+    _veneerVector.push_back(v);
+    return v;
+  }
+
+  /// \brief Get the veneer for Thumb B/BL instructions.
+  const VeneerAtom *getVeneer_THM_B_BL(const DefinedAtom *da,
+                                       StringRef secName) {
+    auto veneer = _veneerMap.find(da);
+    if (_veneerMap.end() != veneer)
+      return veneer->second;
+
+    auto v = new (_file._alloc) Veneer_THM_B_BL_StaticAtom(_file, secName);
+    v->addReferenceELF_ARM(R_ARM_JUMP24, 4, da, 0);
+#ifndef NDEBUG
+    v->_name = "__";
+    v->_name += da->name();
+    v->_name += "_from_thumb";
+#endif
+    _veneerMap[da] = v;
+    _veneerVector.push_back(v);
+    return v;
+  }
 };
 
 } // end of anon namespace

Added: lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-b.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-b.test?rev=228680&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-b.test (added)
+++ lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-b.test Tue Feb 10 03:31:42 2015
@@ -0,0 +1,101 @@
+# Check veneer generation for R_ARM_JUMP24 relocation (B instruction call).
+
+# 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 -m armelf_linux_eabi -Bstatic \
+# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
+
+# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=B-VENEER %s
+# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=B-ADDR %s
+
+# B-VENEER: Contents of section .text:
+# B-VENEER: 400074 010000ea
+# Call from main:
+#       offset = 0x4  ^^
+#               call site   offset  PC(arm)   ___Z1fv_from_arm addr
+#               0x400074  +  0x4  +  0x8   =   0x400080
+#
+# Code of the veneer:
+# B-VENEER:                 {{[0-9a-f]+}} {{[0-9a-f]+}} 04f01fe5
+# B-VENEER: 400084 79004000
+# call addr = 0x400079 ^^
+#               call addr   _Z1fv addr  Thumb mode
+#               0x400079  =  0x400078  |  0x1
+#
+# B-ADDR: SYMBOL TABLE:
+# B-ADDR: 00400080 l     F .text  {{[0-9a-f]+}} ___Z1fv_from_arm
+# B-ADDR: 00400074 g     F .text  {{[0-9a-f]+}} main
+# B-ADDR: 00400078 g     F .text  {{[0-9a-f]+}} _Z1fv
+
+# 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:         FEFFFFEA
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          _Z1fv
+        Type:            R_ARM_JUMP24
+        Addend:          0
+  - 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:            main
+      Type:            STT_FUNC
+      Section:         .text
+    - Name:            _Z1fv
+
+# 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:         4FF0000318467047
+  - 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:            _Z1fv
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+...

Added: lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-bl.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-bl.test?rev=228680&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-bl.test (added)
+++ lld/trunk/test/elf/ARM/rel-arm-jump24-veneer-bl.test Tue Feb 10 03:31:42 2015
@@ -0,0 +1,100 @@
+# Check veneer generation for R_ARM_JUMP24 relocation (BL<c> instruction call).
+
+# 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 -m armelf_linux_eabi -Bstatic \
+# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
+
+# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=BL-VENEER %s
+# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=BL-ADDR %s
+
+# BL-VENEER: Contents of section .text:
+# BL-VENEER: 400084 0400000b
+# Call from main:
+#      offset = 0x10  ^^
+#               call site   offset   PC(arm)   ___Z1fv_from_arm addr
+#               0x400084  +  0x10  +  0x8   =   0x40009c
+#
+# Code of the veneer:
+# BL-VENEER: 400094 {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 95004000
+#                                           call addr = 0x400095 ^^
+#               call addr   _Z1fv addr  Thumb mode
+#               0x400095  =  0x400094  |  0x1
+#
+# BL-ADDR: SYMBOL TABLE:
+# BL-ADDR: 0040009c l     F .text  {{[0-9a-f]+}} ___Z1fv_from_arm
+# BL-ADDR: 00400074 g     F .text  {{[0-9a-f]+}} main
+# BL-ADDR: 00400094 g     F .text  {{[0-9a-f]+}} _Z1fv
+
+# 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:         00482DE904B08DE20030A0E3000053E3FEFFFF0B0030A0E30300A0E10088BDE8
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000010
+        Symbol:          _Z1fv
+        Type:            R_ARM_JUMP24
+        Addend:          0
+  - 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:            main
+      Type:            STT_FUNC
+      Section:         .text
+    - Name:            _Z1fv
+
+# 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:         4FF0000318467047
+  - 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:            _Z1fv
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+...

Added: lld/trunk/test/elf/ARM/rel-thm-jump24-veneer.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-thm-jump24-veneer.test?rev=228680&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/rel-thm-jump24-veneer.test (added)
+++ lld/trunk/test/elf/ARM/rel-thm-jump24-veneer.test Tue Feb 10 03:31:42 2015
@@ -0,0 +1,100 @@
+# Check veneer generation for R_ARM_THM_JUMP24 relocation (B instruction call).
+
+# 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 -m armelf_linux_eabi -Bstatic \
+# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
+
+# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=B-VENEER %s
+# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=B-ADDR %s
+
+# B-VENEER: Contents of section .text:
+# B-VENEER: 400074 {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 00f000b8
+# Call from main:
+#                                                 offset = 0x0  ^^
+#               call site   offset  PC(thm)   ___Z1fv_from_thumb addr
+#               0x400080  +  0x0  +  0x4   =   0x400084
+#
+# Code of the veneer:
+# B-VENEER: 400084 78470000 f9ffffea
+#               offset = -0x1C ^^
+#               call site    offset   PC(arm)      _Z1fv
+#               0x400088  + (-0x1C) +  0x8   =   0x400074
+#
+# B-ADDR: SYMBOL TABLE:
+# B-ADDR: 00400084 l     F .text  {{[0-9a-f]+}} ___Z1fv_from_thumb
+# B-ADDR: 00400074 g     F .text  {{[0-9a-f]+}} _Z1fv
+# B-ADDR: 00400080 g     F .text  {{[0-9a-f]+}} main
+
+# 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:         0030A0E30300A0E11EFF2FE1
+  - 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:            _Z1fv
+      Type:            STT_FUNC
+      Section:         .text
+
+# 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:         FFF7FEBF
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          _Z1fv
+        Type:            R_ARM_THM_JUMP24
+        Addend:          0
+  - 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:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            _Z1fv
+...





More information about the llvm-commits mailing list