Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions bolt/lib/Core/BinaryContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,10 @@ BinaryContext::getBaseAddressForMapping(uint64_t MMapAddress,
// Only consider executable segments.
if (!SegInfo.IsExecutable)
continue;
// For Linux kernel perf files, SegInfo.FileOffset and FileOffset are
// irrelvent.
if (IsLinuxKernel)
return MMapAddress - SegInfo.Address;
// FileOffset is got from perf event,
// and it is equal to alignDown(SegInfo.FileOffset, pagesize).
// If the pagesize is not equal to SegInfo.Alignment.
Expand Down
44 changes: 27 additions & 17 deletions bolt/lib/Profile/DataAggregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,26 +530,18 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
};

if (BC.IsLinuxKernel) {
// Current MMap parsing logic does not work with linux kernel.
// MMap entries for linux kernel uses PERF_RECORD_MMAP
// format instead of typical PERF_RECORD_MMAP2 format.
// Since linux kernel address mapping is absolute (same as
// in the ELF file), we avoid parsing MMap in linux kernel mode.
// While generating optimized linux kernel binary, we may need
// to parse MMap entries.

// In linux kernel mode, we analyze and optimize
// all linux kernel binary instructions, irrespective
// of whether they are due to system calls or due to
// interrupts. Therefore, we cannot ignore interrupt
// in Linux kernel mode.
opts::IgnoreInterruptLBR = false;
} else {
prepareToParse("mmap events", MMapEventsPPI, ErrorCallback);
if (parseMMapEvents())
errs() << "PERF2BOLT: failed to parse mmap events\n";
}

prepareToParse("mmap events", MMapEventsPPI, ErrorCallback);
if (parseMMapEvents())
errs() << "PERF2BOLT: failed to parse mmap events\n";

prepareToParse("task events", TaskEventsPPI, ErrorCallback);
if (parseTaskEvents())
errs() << "PERF2BOLT: failed to parse task events\n";
Expand Down Expand Up @@ -1102,6 +1094,11 @@ ErrorOr<DataAggregator::PerfBranchSample> DataAggregator::parseBranchSample() {
return make_error_code(errc::no_such_process);
}

if (BC->IsLinuxKernel) {
// "-1" is the pid for the Linux kernel
MMapInfoIter = BinaryMMapInfo.find(-1);
}

while (checkAndConsumeFS()) {
}

Expand Down Expand Up @@ -1936,14 +1933,18 @@ DataAggregator::parseMMapEvent() {
}
StringRef Line = ParsingBuf.substr(0, LineEnd);

size_t Pos = Line.find("PERF_RECORD_MMAP2");
// This would match both PERF_RECORD_MMAP and PERF_RECORD_MMAP2
size_t Pos = Line.find("PERF_RECORD_MMAP");
if (Pos == StringRef::npos) {
consumeRestOfLine();
return std::make_pair(StringRef(), ParsedInfo);
}

// Line:
// {<name> .* <sec>.<usec>: }PERF_RECORD_MMAP2 <pid>/<tid>: .* <file_name>
// Or:
// {<name> .* <sec>.<usec>: }PERF_RECORD_MMAP <-1 | pid>/<tid>: .*
// <file_name>

const StringRef TimeStr =
Line.substr(0, Pos).rsplit(':').first.rsplit(FieldSeparator).second;
Expand All @@ -1954,9 +1955,14 @@ DataAggregator::parseMMapEvent() {

// Line:
// PERF_RECORD_MMAP2 <pid>/<tid>: [<hexbase>(<hexsize>) .*]: .* <file_name>
// Or:
// PERF_RECORD_MMAP <-1 | pid>/<tid>: [<hexbase>(<hexsize>) .*]: .*
// <file_name>

StringRef FileName = Line.rsplit(FieldSeparator).second;
if (FileName.starts_with("//") || FileName.starts_with("[")) {
if (FileName == "[kernel.kallsyms]_text")
FileName = "[kernel.kallsyms]";
else if (FileName.starts_with("//") || FileName.starts_with("[")) {
consumeRestOfLine();
return std::make_pair(StringRef(), ParsedInfo);
}
Expand All @@ -1983,8 +1989,11 @@ DataAggregator::parseMMapEvent() {
return make_error_code(llvm::errc::io_error);
}

const StringRef OffsetStr =
Line.split('@').second.ltrim().split(FieldSeparator).first;
const StringRef OffsetStr = Line.split('@')
.second.ltrim()
.split(FieldSeparator)
.first.split(']')
.first;
if (OffsetStr.getAsInteger(0, ParsedInfo.Offset)) {
reportError("expected mmaped page-aligned offset");
Diag << "Found: " << OffsetStr << "in '" << Line << "'\n";
Expand All @@ -2008,7 +2017,8 @@ std::error_code DataAggregator::parseMMapEvents() {
return EC;

std::pair<StringRef, MMapInfo> FileMMapInfo = FileMMapInfoRes.get();
if (FileMMapInfo.second.PID == -1)
if (FileMMapInfo.first != "[kernel.kallsyms]" &&
FileMMapInfo.second.PID == -1)
continue;
if (FileMMapInfo.first == "(deleted)")
continue;
Expand Down
14 changes: 11 additions & 3 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,11 @@ Error RewriteInstance::discoverStorage() {
Phdr.p_vaddr, Phdr.p_memsz, Phdr.p_offset,
Phdr.p_filesz, Phdr.p_align, ((Phdr.p_flags & ELF::PF_X) != 0)};
if (BC->TheTriple->getArch() == llvm::Triple::x86_64 &&
Phdr.p_vaddr >= BinaryContext::KernelStartX86_64)
Phdr.p_vaddr >= BinaryContext::KernelStartX86_64) {
BC->IsLinuxKernel = true;
BC->HasFixedLoadAddress = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to detect KASLR by looking at vmlinux ELF and only then set HasFixedLoadAddress.

}

break;
case ELF::PT_INTERP:
BC->HasInterpHeader = true;
Expand Down Expand Up @@ -995,8 +998,13 @@ void RewriteInstance::discoverFileObjects() {
}

if (!Section->isText()) {
assert(SymbolType != SymbolRef::ST_Function &&
"unexpected function inside non-code section");
// In kernel, a function can live in a non-text section. For Example,
// lkdtm_rodata_do_nothing() in ./drivers/misc/lkdtm/rodata.c is in
// the rodata section.
if (!BC->IsLinuxKernel) {
assert(SymbolType != SymbolRef::ST_Function &&
"unexpected function inside non-code section");
}
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: rejecting as symbol is not in code\n");
registerName(SymbolSize);
continue;
Expand Down
Loading