forked from OSchip/llvm-project
[perf2bolt] Better mmap event matching
Summary: When perf tool reports a mapping address of a binary, it is not always the address of the first loadable segment we were checking against. As a result, perf2botl was not working properly for binaries where the first segment was not executable. The fix is to check if the address reported by mmap event matches any of the loadable segments. Note that the segment alignment has to be applied to get real loadable address of the segment. Fixes facebookincubator/BOLT#65 (cherry picked from FBD19146419)
This commit is contained in:
parent
16a497c627
commit
d414acfbb6
|
@ -63,6 +63,7 @@ namespace bolt {
|
|||
class BinaryFunction;
|
||||
class BinaryBasicBlock;
|
||||
class DataReader;
|
||||
class ExecutableFileMemoryManager;
|
||||
|
||||
enum class MemoryContentsType : char {
|
||||
UNKNOWN = 0, /// Unknown contents.
|
||||
|
@ -196,6 +197,10 @@ public:
|
|||
FilterIterator<binary_data_const_iterator>;
|
||||
using FilteredBinaryDataIterator = FilterIterator<binary_data_iterator>;
|
||||
|
||||
/// Memory manager for sections and segments. Used to communicate with ORC
|
||||
/// among other things.
|
||||
std::shared_ptr<ExecutableFileMemoryManager> EFMM;
|
||||
|
||||
/// Return BinaryFunction containing a given \p Address or nullptr if
|
||||
/// no registered function has it.
|
||||
///
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "BinaryFunction.h"
|
||||
#include "BoltAddressTranslation.h"
|
||||
#include "DataAggregator.h"
|
||||
#include "ExecutableFileMemoryManager.h"
|
||||
#include "Heatmap.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
@ -1857,11 +1858,22 @@ std::error_code DataAggregator::parseMMapEvents() {
|
|||
|
||||
auto Range = GlobalMMapInfo.equal_range(NameToUse);
|
||||
for (auto I = Range.first; I != Range.second; ++I) {
|
||||
if (BC->HasFixedLoadAddress && I->second.BaseAddress &&
|
||||
I->second.BaseAddress != BC->FirstAllocAddress) {
|
||||
errs() << "PERF2BOLT-WARNING: ignoring mapping of " << NameToUse
|
||||
<< " at 0x" << Twine::utohexstr(I->second.BaseAddress) << '\n';
|
||||
continue;
|
||||
if (BC->HasFixedLoadAddress && I->second.BaseAddress) {
|
||||
// Check that the binary mapping matches one of the segments.
|
||||
bool MatchFound{false};
|
||||
for (auto &KV : BC->EFMM->SegmentMapInfo) {
|
||||
auto &SegInfo = KV.second;
|
||||
const auto MapAddress = alignDown(SegInfo.Address, SegInfo.Alignment);
|
||||
if (I->second.BaseAddress == MapAddress) {
|
||||
MatchFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!MatchFound) {
|
||||
errs() << "PERF2BOLT-WARNING: ignoring mapping of " << NameToUse
|
||||
<< " at 0x" << Twine::utohexstr(I->second.BaseAddress) << '\n';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
BinaryMMapInfo.insert(std::make_pair(I->second.PID, I->second));
|
||||
|
|
|
@ -27,13 +27,15 @@ struct SegmentInfo {
|
|||
uint64_t Size; /// Size of the segment in memory.
|
||||
uint64_t FileOffset; /// Offset in the file.
|
||||
uint64_t FileSize; /// Size in file.
|
||||
uint64_t Alignment; /// Alignment of the segment.
|
||||
|
||||
void print(raw_ostream &OS) const {
|
||||
OS << "SegmentInfo { Address: 0x"
|
||||
<< Twine::utohexstr(Address) << ", Size: 0x"
|
||||
<< Twine::utohexstr(Size) << ", FileOffset: 0x"
|
||||
<< Twine::utohexstr(FileOffset) << ", FileSize: 0x"
|
||||
<< Twine::utohexstr(FileSize) << "}";
|
||||
<< Twine::utohexstr(FileSize) << ", Alignment: 0x"
|
||||
<< Twine::utohexstr(Alignment) << "}";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -780,7 +780,7 @@ void RewriteInstance::discoverStorage() {
|
|||
// sections accounting for stubs when we need those sections to match the
|
||||
// same size seen in the input binary, in case this section is a copy
|
||||
// of the original one seen in the binary.
|
||||
EFMM.reset(new ExecutableFileMemoryManager(*BC, /*AllowStubs*/ false));
|
||||
BC->EFMM.reset(new ExecutableFileMemoryManager(*BC, /*AllowStubs*/ false));
|
||||
|
||||
auto ELF64LEFile = dyn_cast<ELF64LEObjectFile>(InputFile);
|
||||
if (!ELF64LEFile) {
|
||||
|
@ -808,10 +808,11 @@ void RewriteInstance::discoverStorage() {
|
|||
NextAvailableOffset = std::max(NextAvailableOffset,
|
||||
Phdr.p_offset + Phdr.p_filesz);
|
||||
|
||||
EFMM->SegmentMapInfo[Phdr.p_vaddr] = SegmentInfo{Phdr.p_vaddr,
|
||||
Phdr.p_memsz,
|
||||
Phdr.p_offset,
|
||||
Phdr.p_filesz};
|
||||
BC->EFMM->SegmentMapInfo[Phdr.p_vaddr] = SegmentInfo{Phdr.p_vaddr,
|
||||
Phdr.p_memsz,
|
||||
Phdr.p_offset,
|
||||
Phdr.p_filesz,
|
||||
Phdr.p_align};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2969,7 +2970,7 @@ void RewriteInstance::emitAndLink() {
|
|||
auto Resolver = orc::createLegacyLookupResolver(
|
||||
[&](const std::string &Name) -> JITSymbol {
|
||||
DEBUG(dbgs() << "BOLT: looking for " << Name << "\n");
|
||||
if (EFMM->ObjectsLoaded) {
|
||||
if (BC->EFMM->ObjectsLoaded) {
|
||||
auto Result = OLT->findSymbol(Name, false);
|
||||
if (cantFail(Result.getAddress()) == 0) {
|
||||
// Resolve to a PLT entry if possible
|
||||
|
@ -3008,7 +3009,7 @@ void RewriteInstance::emitAndLink() {
|
|||
*ES,
|
||||
[this, &Resolver](orc::VModuleKey Key) {
|
||||
orc::RTDyldObjectLinkingLayer::Resources R;
|
||||
R.MemMgr = EFMM;
|
||||
R.MemMgr = BC->EFMM;
|
||||
R.Resolver = Resolver;
|
||||
// Get memory manager
|
||||
return R;
|
||||
|
@ -4934,8 +4935,8 @@ uint64_t RewriteInstance::getFileOffsetForAddress(uint64_t Address) const {
|
|||
}
|
||||
|
||||
// Find an existing segment that matches the address.
|
||||
const auto SegmentInfoI = EFMM->SegmentMapInfo.upper_bound(Address);
|
||||
if (SegmentInfoI == EFMM->SegmentMapInfo.begin())
|
||||
const auto SegmentInfoI = BC->EFMM->SegmentMapInfo.upper_bound(Address);
|
||||
if (SegmentInfoI == BC->EFMM->SegmentMapInfo.begin())
|
||||
return 0;
|
||||
|
||||
const auto &SegmentInfo = std::prev(SegmentInfoI)->second;
|
||||
|
|
|
@ -343,10 +343,6 @@ private:
|
|||
std::unique_ptr<BinaryContext> BC;
|
||||
std::unique_ptr<CFIReaderWriter> CFIRdWrt;
|
||||
|
||||
/// Memory manager for sections and segments. Used to communicate with ORC
|
||||
/// among other things.
|
||||
std::shared_ptr<ExecutableFileMemoryManager> EFMM;
|
||||
|
||||
std::unique_ptr<orc::SymbolStringPool> SSP;
|
||||
std::unique_ptr<orc::ExecutionSession> ES;
|
||||
|
||||
|
|
Loading…
Reference in New Issue