[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