mirror of
https://github.com/intel/llvm.git
synced 2026-01-15 12:25:46 +08:00
Add `RSeqRewriter` to detect code references from `__rseq_cs` section and ignore function referenced from that section. Code references are detected via relocations (static or dynamic). Note that the abort handler is preceded by a 4-byte signature byte sequence and we cannot relocate the handler without that the signature, otherwise the application may crash. Thus we are ignoring the function, i.e. making sure it's not separated from its signature.
73 lines
2.4 KiB
C++
73 lines
2.4 KiB
C++
//===- bolt/Rewrite/RSeqRewriter.cpp --------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Basic support for restartable sequences used by tcmalloc. Prevent critical
|
|
// section overrides by ignoring optimizations in containing functions.
|
|
//
|
|
// References:
|
|
// * https://google.github.io/tcmalloc/rseq.html
|
|
// * tcmalloc/internal/percpu_rseq_x86_64.S
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "bolt/Core/BinaryFunction.h"
|
|
#include "bolt/Rewrite/MetadataRewriter.h"
|
|
#include "bolt/Rewrite/MetadataRewriters.h"
|
|
#include "llvm/Support/Errc.h"
|
|
|
|
using namespace llvm;
|
|
using namespace bolt;
|
|
|
|
namespace {
|
|
|
|
class RSeqRewriter final : public MetadataRewriter {
|
|
public:
|
|
RSeqRewriter(StringRef Name, BinaryContext &BC)
|
|
: MetadataRewriter(Name, BC) {}
|
|
|
|
Error preCFGInitializer() override {
|
|
for (const BinarySection &Section : BC.allocatableSections()) {
|
|
if (Section.getName() != "__rseq_cs")
|
|
continue;
|
|
|
|
auto handleRelocation = [&](const Relocation &Rel, bool IsDynamic) {
|
|
BinaryFunction *BF = nullptr;
|
|
if (Rel.Symbol)
|
|
BF = BC.getFunctionForSymbol(Rel.Symbol);
|
|
else if (Relocation::isRelative(Rel.Type))
|
|
BF = BC.getBinaryFunctionContainingAddress(Rel.Addend);
|
|
|
|
if (!BF) {
|
|
BC.errs() << "BOLT-WARNING: no function found matching "
|
|
<< (IsDynamic ? "dynamic " : "")
|
|
<< "relocation in __rseq_cs\n";
|
|
} else if (!BF->isIgnored()) {
|
|
BC.outs() << "BOLT-INFO: restartable sequence reference detected in "
|
|
<< *BF << ". Function will not be optimized\n";
|
|
BF->setIgnored();
|
|
}
|
|
};
|
|
|
|
for (const Relocation &Rel : Section.dynamicRelocations())
|
|
handleRelocation(Rel, /*IsDynamic*/ true);
|
|
|
|
for (const Relocation &Rel : Section.relocations())
|
|
handleRelocation(Rel, /*IsDynamic*/ false);
|
|
}
|
|
|
|
return Error::success();
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
std::unique_ptr<MetadataRewriter>
|
|
llvm::bolt::createRSeqRewriter(BinaryContext &BC) {
|
|
return std::make_unique<RSeqRewriter>("rseq-cs-rewriter", BC);
|
|
}
|