Skip to content

Commit 14cf49c

Browse files
Addressing reviewers
1 parent 44ce750 commit 14cf49c

File tree

3 files changed

+45
-13
lines changed

3 files changed

+45
-13
lines changed

bolt/include/bolt/Profile/DataAggregator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ class DataAggregator : public DataReader {
170170
std::string BuildIDBinaryName;
171171

172172
/// Memory map info for a single file as recorded in perf.data
173+
/// When a binary has multiple text segments, the Size is computed as the
174+
/// difference of the last address of these segments from the BaseAddress.
175+
/// The base addresses of all text segments must be the same.
173176
struct MMapInfo {
174177
uint64_t BaseAddress{0}; /// Base address of the mapped binary.
175178
uint64_t MMapAddress{0}; /// Address of the executable segment.

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ void DataAggregator::filterBinaryMMapInfo() {
471471
int DataAggregator::prepareToParse(StringRef Name, PerfProcessInfo &Process,
472472
PerfProcessErrorCallbackTy Callback) {
473473
if (!opts::ReadPerfEvents.empty()) {
474-
dbgs() << "PERF2BOLT: using pre-processed perf events for '" << Name
474+
outs() << "PERF2BOLT: using pre-processed perf events for '" << Name
475475
<< "' (perf-script-events)\n";
476476
ParsingBuf = opts::ReadPerfEvents;
477477
return 0;
@@ -2081,10 +2081,14 @@ std::error_code DataAggregator::parseMMapEvents() {
20812081
MMapInfo.BaseAddress = *BaseAddress;
20822082
}
20832083

2084-
// Try to add MMapInfo to the map and update its size. Large binaries
2085-
// may span multiple text segments, so the mapping is inserted only on the
2086-
// first occurrence. If a larger section size is found, it will be updated.
2087-
BinaryMMapInfo.insert(std::make_pair(MMapInfo.PID, MMapInfo));
2084+
// Try to add MMapInfo to the map and update its size. Large binaries may
2085+
// span to multiple text segments, so the mapping is inserted only on the
2086+
// first occurrence.
2087+
if (!BinaryMMapInfo.insert(std::make_pair(MMapInfo.PID, MMapInfo)).second)
2088+
assert(MMapInfo.BaseAddress == BinaryMMapInfo[MMapInfo.PID].BaseAddress &&
2089+
"Base address on multiple segment mappings should match");
2090+
2091+
// Update section size.
20882092
uint64_t EndAddress = MMapInfo.MMapAddress + MMapInfo.Size;
20892093
uint64_t Size = EndAddress - BinaryMMapInfo[MMapInfo.PID].BaseAddress;
20902094
if (Size > BinaryMMapInfo[MMapInfo.PID].Size)

bolt/unittests/Core/MemoryMaps.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ extern cl::opt<std::string> ReadPerfEvents;
2525
} // namespace opts
2626

2727
namespace {
28+
29+
/// Perform checks on memory map events normally captured in perf. Tests use
30+
/// the 'opts::ReadPerfEvents' flag to emulate these events, passing a custom
31+
/// 'perf script' output to DataAggregator.
2832
struct MemoryMapsTester : public testing::TestWithParam<Triple::ArchType> {
2933
void SetUp() override {
3034
initalizeLLVM();
@@ -81,8 +85,7 @@ INSTANTIATE_TEST_SUITE_P(AArch64, MemoryMapsTester,
8185
#endif
8286

8387
/// Check that the correct mmap size is computed when we have multiple text
84-
/// segment mappings. Uses 'opts::ReadPerfEvents' flag to pass a custom 'perf
85-
/// script' output, along with two text segments (SegmentInfo).
88+
/// segment mappings.
8689
TEST_P(MemoryMapsTester, ParseMultipleSegments) {
8790
const int Pid = 1234;
8891
StringRef Filename = "BINARY";
@@ -94,13 +97,9 @@ TEST_P(MemoryMapsTester, ParseMultipleSegments) {
9497
Pid, Filename);
9598

9699
BC->SegmentMapInfo[0x11da000] =
97-
SegmentInfo{0x11da000, 0x10da000, 0x11ca000, 0x10da000, 0x10000};
100+
SegmentInfo{0x11da000, 0x10da000, 0x11ca000, 0x10da000, 0x10000, true};
98101
BC->SegmentMapInfo[0x31d0000] =
99-
SegmentInfo{0x31d0000, 0x51ac82c, 0x31d0000, 0x3000000, 0x200000};
100-
101-
// Dont show DataAggregators out/err output.
102-
testing::internal::CaptureStdout();
103-
testing::internal::CaptureStderr();
102+
SegmentInfo{0x31d0000, 0x51ac82c, 0x31d0000, 0x3000000, 0x200000, true};
104103

105104
DataAggregator DA("");
106105
BC->setFilename(Filename);
@@ -115,3 +114,29 @@ TEST_P(MemoryMapsTester, ParseMultipleSegments) {
115114
ASSERT_NE(El, BinaryMMapInfo.end());
116115
ASSERT_EQ(El->second.Size, static_cast<uint64_t>(0xb1d0000));
117116
}
117+
118+
/// Check that DataAggregator aborts when pre-processing an input binary
119+
/// with multiple text segments that have different base addresses.
120+
TEST_P(MemoryMapsTester, MultipleSegmentsMismatchedBaseAddress) {
121+
const int Pid = 1234;
122+
StringRef Filename = "BINARY";
123+
opts::ReadPerfEvents = formatv(
124+
"name 0 [000] 0.000000: PERF_RECORD_MMAP2 {0}/{0}: "
125+
"[0xabc0000000(0x1000000) @ 0x11c0000 103:01 1573523 0]: r-xp {1}\n"
126+
"name 0 [000] 0.000000: PERF_RECORD_MMAP2 {0}/{0}: "
127+
"[0xabc2000000(0x8000000) @ 0x31d0000 103:01 1573523 0]: r-xp {1}\n",
128+
Pid, Filename);
129+
130+
BC->SegmentMapInfo[0x11da000] =
131+
SegmentInfo{0x11da000, 0x10da000, 0x11ca000, 0x10da000, 0x10000, true};
132+
// Using '0x31d0fff' FileOffset which triggers a different base address
133+
// for this second text segment.
134+
BC->SegmentMapInfo[0x31d0000] =
135+
SegmentInfo{0x31d0000, 0x51ac82c, 0x31d0fff, 0x3000000, 0x200000, true};
136+
137+
DataAggregator DA("");
138+
BC->setFilename(Filename);
139+
ASSERT_DEATH(
140+
{ Error Err = DA.preprocessProfile(*BC); },
141+
"Base address on multiple segment mappings should match");
142+
}

0 commit comments

Comments
 (0)