// escape to shared objects. isInIplt indicates a non-preemptible ifunc. Its
// address may escape if referenced by a direct relocation. The condition is
// conservative.
- bool hasBti = btiHeader && (sym.hasFlag(NEEDS_COPY) || sym.isInIplt);
+ bool hasBti = btiHeader &&
+ (sym.hasFlag(NEEDS_COPY) || sym.isInIplt || sym.thunkAccessed);
if (hasBti) {
memcpy(buf, btiData, sizeof(btiData));
buf += sizeof(btiData);
using namespace lld;
using namespace lld::elf;
-static_assert(sizeof(SymbolUnion) <= 64, "SymbolUnion too large");
+static_assert(sizeof(SymbolUnion) <= 72, "SymbolUnion too large");
template <typename T> struct AssertSymbol {
static_assert(std::is_trivially_destructible<T>(),
// True if defined in a DSO as protected visibility.
uint8_t dsoProtected : 1;
+ // True if targeted by a range extension thunk.
+ uint8_t thunkAccessed : 1;
+
// Temporary flags used to communicate which symbol entries need PLT and GOT
// entries during postScanRelocations();
std::atomic<uint16_t> flags;
return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14;
}
-Thunk::Thunk(Symbol &d, int64_t a) : destination(d), addend(a), offset(0) {}
+Thunk::Thunk(Symbol &d, int64_t a) : destination(d), addend(a), offset(0) {
+ destination.thunkAccessed = true;
+}
Thunk::~Thunk() = default;