summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp51
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h5
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp2
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h2
-rw-r--r--lld/test/elf/Hexagon/dynlib-gotoff.test235
5 files changed, 291 insertions, 4 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
index d63eb918493..c456ac57b70 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
@@ -206,6 +206,35 @@ int relocHexGOT11_X(uint8_t *location, uint64_t G) {
return 0;
}
+int relocHexGOTREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
+ uint64_t GOT, int shiftBits = 0) {
+ uint32_t result = (uint32_t)((S + A - GOT) >> shiftBits);
+ result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
+ *reinterpret_cast<llvm::support::ulittle32_t *>(location) =
+ result |
+ (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location);
+ return 0;
+}
+
+int relocHexGOTREL_HILO16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
+ uint64_t GOT, int shiftBits = 0) {
+ uint32_t result = (uint32_t)((S + A - GOT) >> shiftBits);
+ result = lld::scatterBits<uint32_t>(result, 0x00c03fff);
+ *reinterpret_cast<llvm::support::ulittle32_t *>(location) =
+ result |
+ (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location);
+ return 0;
+}
+
+int relocHexGOTREL_32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
+ uint64_t GOT) {
+ uint32_t result = (uint32_t)(S + A - GOT);
+ *reinterpret_cast<llvm::support::ulittle32_t *>(location) =
+ result |
+ (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location);
+ return 0;
+}
+
} // end anon namespace
ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation(
@@ -288,6 +317,18 @@ ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation(
case R_HEX_JMP_SLOT:
case R_HEX_GLOB_DAT:
break;
+ case R_HEX_GOTREL_32:
+ relocHexGOTREL_32(location, relocVAddress, targetVAddress, ref.addend(),
+ _targetHandler.getGOTSymAddr());
+ break;
+ case R_HEX_GOTREL_LO16:
+ relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(),
+ _targetHandler.getGOTSymAddr());
+ break;
+ case R_HEX_GOTREL_HI16:
+ relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(),
+ _targetHandler.getGOTSymAddr(), 16);
+ break;
case R_HEX_GOT_LO16:
relocHexGOTLO16(location, targetVAddress);
break;
@@ -309,6 +350,16 @@ ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation(
case R_HEX_GOT_11_X:
relocHexGOT11_X(location, targetVAddress);
break;
+ case R_HEX_GOTREL_32_6_X:
+ relocHexGOTREL(location, relocVAddress, targetVAddress, ref.addend(),
+ _targetHandler.getGOTSymAddr(), 6);
+ break;
+ case R_HEX_GOTREL_16_X:
+ case R_HEX_GOTREL_11_X:
+ relocHexGOTREL(location, relocVAddress, targetVAddress, ref.addend(),
+ _targetHandler.getGOTSymAddr());
+ break;
+
case lld::Reference::kindLayoutAfter:
case lld::Reference::kindLayoutBefore:
case lld::Reference::kindInGroup:
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
index 24f02eec2b5..ad63e733b62 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
@@ -25,15 +25,16 @@ class HexagonTargetRelocationHandler LLVM_FINAL :
public TargetRelocationHandler<HexagonELFType> {
public:
HexagonTargetRelocationHandler(
- const HexagonTargetInfo &ti,
+ const HexagonTargetInfo &ti, const HexagonTargetHandler &tH,
const HexagonTargetLayout<HexagonELFType> &layout)
- : _targetInfo(ti), _targetLayout(layout) {}
+ : _targetInfo(ti), _targetHandler(tH), _targetLayout(layout) {}
virtual ErrorOr<void>
applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &,
const Reference &) const;
private:
const HexagonTargetInfo &_targetInfo;
+ const HexagonTargetHandler &_targetHandler;
const HexagonTargetLayout<HexagonELFType> &_targetLayout;
};
} // elf
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
index 8e5aadc67df..a2779b7e781 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
@@ -18,7 +18,7 @@ using namespace llvm::ELF;
HexagonTargetHandler::HexagonTargetHandler(HexagonTargetInfo &targetInfo)
: DefaultTargetHandler(targetInfo), _targetLayout(targetInfo),
- _relocationHandler(targetInfo, _targetLayout),
+ _relocationHandler(targetInfo, *this, _targetLayout),
_hexagonRuntimeFile(targetInfo) {}
namespace {
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
index fc2753e1cb5..1e6bec7f2f0 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
@@ -195,7 +195,7 @@ public:
}
}
- uint64_t getGOTSymAddr() { return _gotSymAtom->_virtualAddr; }
+ uint64_t getGOTSymAddr() const { return _gotSymAtom->_virtualAddr; }
private:
HexagonTargetLayout<HexagonELFType> _targetLayout;
diff --git a/lld/test/elf/Hexagon/dynlib-gotoff.test b/lld/test/elf/Hexagon/dynlib-gotoff.test
new file mode 100644
index 00000000000..07308deab34
--- /dev/null
+++ b/lld/test/elf/Hexagon/dynlib-gotoff.test
@@ -0,0 +1,235 @@
+RUN: lld -core -target hexagon %p/Inputs/dynobj.o \
+RUN: -output=%t -emit-yaml -noinhibit-exec -output-type=shared
+RUN: FileCheck -check-prefix=CHECKGOTPLT %s < %t
+
+ - name: __got_c
+CHECKGOTPLT: type: got
+CHECKGOTPLT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECKGOTPLT: alignment: 2^3
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .got
+CHECKGOTPLT: permissions: rw-
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_GLOB_DAT
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: c
+ - name: __got_shankar
+CHECKGOTPLT: type: got
+CHECKGOTPLT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECKGOTPLT: alignment: 2^3
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .got
+CHECKGOTPLT: permissions: rw-
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_GLOB_DAT
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: shankar
+ - name: __got_fn
+CHECKGOTPLT: type: got
+CHECKGOTPLT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECKGOTPLT: alignment: 2^3
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .got.plt
+CHECKGOTPLT: permissions: rw-
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_JMP_SLOT
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn
+CHECKGOTPLT: - kind: R_HEX_32
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: .PLT0
+ - name: __got_fn1
+CHECKGOTPLT: type: got
+CHECKGOTPLT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECKGOTPLT: alignment: 2^3
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .got.plt
+CHECKGOTPLT: permissions: rw-
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_JMP_SLOT
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn1
+CHECKGOTPLT: - kind: R_HEX_32
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: .PLT0
+ - name: __got_fn2
+CHECKGOTPLT: type: got
+CHECKGOTPLT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECKGOTPLT: alignment: 2^3
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .got.plt
+CHECKGOTPLT: permissions: rw-
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_JMP_SLOT
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn2
+CHECKGOTPLT: - kind: R_HEX_32
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: .PLT0
+CHECKGOTPLT: - name: .text
+CHECKGOTPLT: alignment: 2^2
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .text
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn2
+CHECKGOTPLT: - name: fn2
+CHECKGOTPLT: scope: global
+CHECKGOTPLT: content: [ 00, C0, 9D, A0, 00, C0, 00, 78, 1E, C0, 1E, 96 ]
+CHECKGOTPLT: alignment: 2^2
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .text
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: .text
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn1
+CHECKGOTPLT: - name: fn1
+CHECKGOTPLT: scope: global
+CHECKGOTPLT: content: [ 00, C0, 9D, A0, 00, C0, 00, 78, 1E, C0, 1E, 96 ]
+CHECKGOTPLT: alignment: 2^2
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .text
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn2
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn
+CHECKGOTPLT: - name: fn
+CHECKGOTPLT: scope: global
+CHECKGOTPLT: content: [ 01, C0, 9D, A0, 01, D8, 9D, A1, 00, 40, 00, 00,
+CHECKGOTPLT: 18, C0, 49, 6A, 00, 40, 00, 00, 00, C0, 49, 6A,
+CHECKGOTPLT: 0A, C0, 40, 3C, 00, 40, 00, 00, 00, C0, 49, 6A,
+CHECKGOTPLT: 14, C0, 40, 3C, 00, 40, 00, 00, 00, C0, 98, 91,
+CHECKGOTPLT: 0A, C0, 40, 3C, 00, 40, 00, 00, 00, C0, 98, 91,
+CHECKGOTPLT: 14, C0, 40, 3C, 00, C0, 00, 78, 38, C0, 9D, 91,
+CHECKGOTPLT: 1E, C0, 1E, 96 ]
+CHECKGOTPLT: alignment: 2^2
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .text
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
+CHECKGOTPLT: offset: 8
+CHECKGOTPLT: target: _GLOBAL_OFFSET_TABLE_
+CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
+CHECKGOTPLT: offset: 12
+CHECKGOTPLT: target: _GLOBAL_OFFSET_TABLE_
+CHECKGOTPLT: addend: 4
+CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
+CHECKGOTPLT: offset: 16
+CHECKGOTPLT: target: .sbss.4
+CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
+CHECKGOTPLT: offset: 20
+CHECKGOTPLT: target: .sbss.4
+CHECKGOTPLT: addend: 4
+CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
+CHECKGOTPLT: offset: 28
+CHECKGOTPLT: target: .sbss.4
+CHECKGOTPLT: addend: 4
+CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
+CHECKGOTPLT: offset: 32
+CHECKGOTPLT: target: .sbss.4
+CHECKGOTPLT: addend: 8
+CHECKGOTPLT: - kind: R_HEX_GOT_32_6_X
+CHECKGOTPLT: offset: 40
+ target: __got_c
+CHECKGOTPLT: - kind: R_HEX_GOT_11_X
+CHECKGOTPLT: offset: 44
+ target: __got_c
+CHECKGOTPLT: - kind: R_HEX_GOT_32_6_X
+CHECKGOTPLT: offset: 52
+ target: __got_shankar
+CHECKGOTPLT: - kind: R_HEX_GOT_11_X
+CHECKGOTPLT: offset: 56
+ target: __got_shankar
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn1
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn3
+CHECKGOTPLT: - name: fn3
+CHECKGOTPLT: scope: global
+CHECKGOTPLT: content: [ 00, C0, 9D, A0, 00, C0, 00, 5A, 00, C0, 00, 5A,
+CHECKGOTPLT: 00, C0, 00, 5A, 00, C0, 00, 78, 1E, C0, 1E, 96 ]
+CHECKGOTPLT: alignment: 2^2
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .text
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_B22_PCREL
+CHECKGOTPLT: offset: 4
+ target: __plt_fn
+CHECKGOTPLT: - kind: R_HEX_B22_PCREL
+CHECKGOTPLT: offset: 8
+ target: __plt_fn1
+CHECKGOTPLT: - kind: R_HEX_B22_PCREL
+CHECKGOTPLT: offset: 12
+ target: __plt_fn2
+CHECKGOTPLT: - kind: <unknown>
+CHECKGOTPLT: offset: 0
+CHECKGOTPLT: target: fn
+ - name: .PLT0
+CHECKGOTPLT: type: stub
+CHECKGOTPLT: content: [ 00, 40, 00, 00, 1C, C0, 49, 6A, 0E, 42, 9C, E2,
+CHECKGOTPLT: 4F, 40, 9C, 91, 3C, C0, 9C, 91, 0E, 42, 0E, 8C,
+CHECKGOTPLT: 00, C0, 9C, 52 ]
+CHECKGOTPLT: alignment: 2^4
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .plt
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
+CHECKGOTPLT: offset: 0
+ target: __got0
+CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
+CHECKGOTPLT: offset: 4
+ target: __got0
+ - name: __plt_fn
+CHECKGOTPLT: type: stub
+CHECKGOTPLT: content: [ 00, 40, 00, 00, 0E, C0, 49, 6A, 1C, C0, 8E, 91,
+CHECKGOTPLT: 00, C0, 9C, 52 ]
+CHECKGOTPLT: alignment: 2^4
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .plt
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
+CHECKGOTPLT: offset: 0
+ target: __got_fn
+CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
+CHECKGOTPLT: offset: 4
+ target: __got_fn
+CHECKGOTPLT: addend: 4
+ - name: __plt_fn1
+CHECKGOTPLT: type: stub
+CHECKGOTPLT: content: [ 00, 40, 00, 00, 0E, C0, 49, 6A, 1C, C0, 8E, 91,
+CHECKGOTPLT: 00, C0, 9C, 52 ]
+CHECKGOTPLT: alignment: 2^4
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .plt
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
+CHECKGOTPLT: offset: 0
+ target: __got_fn1
+CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
+CHECKGOTPLT: offset: 4
+ target: __got_fn1
+CHECKGOTPLT: addend: 4
+ - name: __plt_fn2
+CHECKGOTPLT: type: stub
+CHECKGOTPLT: content: [ 00, 40, 00, 00, 0E, C0, 49, 6A, 1C, C0, 8E, 91,
+CHECKGOTPLT: 00, C0, 9C, 52 ]
+CHECKGOTPLT: alignment: 2^4
+CHECKGOTPLT: section-choice: custom-required
+CHECKGOTPLT: section-name: .plt
+CHECKGOTPLT: references:
+CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
+CHECKGOTPLT: offset: 0
+ target: __got_fn2
+CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
+CHECKGOTPLT: offset: 4
+ target: __got_fn2
+CHECKGOTPLT: addend: 4
OpenPOWER on IntegriCloud