diff --git a/include/subcommand_record.h b/include/subcommand_record.h index 35f06d2edffd651f85d81f42e7726543cae94820..8ddf3ab088d8d437ee64fa7f498cc3837dcd46d2 100644 --- a/include/subcommand_record.h +++ b/include/subcommand_record.h @@ -238,6 +238,7 @@ private: bool kernelCallChain_ = true; bool callChainUserOnly_ = false; bool report_ = false; + const bool isRoot_ = IsRoot(); float timeStopSec_ = PerfEvents::DEFAULT_TIMEOUT; int frequency_ = 0; int period_ = 0; @@ -245,6 +246,7 @@ private: int mmapPages_ = MAX_PERF_MMAP_PAGE; int cmdlinesSize_ = DEFAULT_SAVED_CMDLINES_SIZE; int oldCmdlinesSize_ = 0; + static uint32_t random_; std::vector symbolDir_ = {}; std::string outputFilename_ = "/data/local/tmp/perf.data"; std::string appPackage_ = {}; @@ -350,6 +352,8 @@ private: // callback to process record bool ProcessRecord(PerfEventRecord& record); bool SaveRecord(const PerfEventRecord& record); + void UpdateAddr(PerfEventRecord& record); + void UpdateIps(PerfEventRecord& record); // file format like as 0,1-3,4-6,7,8 uint32_t GetCountFromFile(const std::string &fileName); diff --git a/include/symbols_file.h b/include/symbols_file.h index b7eb68e57d3dbb5002c9e53d398a5761ecca21e9..8a3a3ac749449db4179217c72d0133e15f56c867 100644 --- a/include/symbols_file.h +++ b/include/symbols_file.h @@ -199,6 +199,7 @@ public: // will try read some elf in runtime path static bool onRecording_; static bool needParseJsFunc_; + static uint32_t randomNum_; std::vector symbols_ {}; std::vector matchedSymbols_ {}; std::map symbolsMap_; diff --git a/src/subcommand_record.cpp b/src/subcommand_record.cpp index a58bb8463f6c3f36a61e7fa23ffbcd048b1f4c62..97451aa4f8fd61f174ab0043f79008bca492cbc1 100644 --- a/src/subcommand_record.cpp +++ b/src/subcommand_record.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #if defined(CONFIG_HAS_SYSPARA) #include #endif @@ -114,6 +115,8 @@ uint64_t GetBranchSampleType(const std::string &name) } } +uint32_t SubCommandRecord::random_ = 0; + SubCommandRecord::~SubCommandRecord() { CloseClientThread(); @@ -1010,6 +1013,9 @@ void SubCommandRecord::PrepareKernelMaps() bool SubCommandRecord::PrepareVirtualRuntime() { auto saveRecord = [this](PerfEventRecord& record) -> bool { + if (!isRoot_) { + UpdateAddr(record); + } return this->SaveRecord(record); }; virtualRuntime_.SetRecordMode(saveRecord); @@ -1457,6 +1463,11 @@ void SubCommandRecord::WaitFifoReply(int fd, const std::chrono::milliseconds &ti HiperfError SubCommandRecord::OnSubCommand(std::vector& args) { HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord onSubCommand start"); + std::random_device rd; + SubCommandRecord::random_ = rd(); + if (!isRoot_) { + SymbolsFile::randomNum_ = SubCommandRecord::random_; + } if (!ProcessControl()) { return HiperfError::PROCESS_CONTROL_FAIL; } else if (isFifoClient_) { @@ -1602,6 +1613,10 @@ bool SubCommandRecord::ProcessRecord(PerfEventRecord& record) #ifdef HIPERF_DEBUG_TIME prcessRecordTimes_ += duration_cast(steady_clock::now() - startTime); #endif + if (!isRoot_) { + UpdateIps(record); + UpdateAddr(record); + } return SaveRecord(record); #endif } @@ -1654,6 +1669,41 @@ bool SubCommandRecord::SaveRecord(const PerfEventRecord& record) return false; } +void SubCommandRecord::UpdateAddr(PerfEventRecord& record) +{ + if (record.GetType() == PERF_RECORD_MMAP) { + auto recordMmap = static_cast(&record); + if (strcmp(recordMmap->data_.filename, "[kernel.kallsyms]") == 0) { + return; + } + recordMmap->data_.addr += SubCommandRecord::random_; + } else if (record.GetType() == PERF_RECORD_MMAP2) { + auto recordMmap2 = static_cast(&record); + if (strcmp(recordMmap2->data_.filename, "[kernel.kallsyms]") == 0) { + return; + } + recordMmap2->data_.addr += SubCommandRecord::random_; + } +} + +void SubCommandRecord::UpdateIps(PerfEventRecord& record) +{ + if (record.GetType() == PERF_RECORD_SAMPLE) { + auto sample = static_cast(&record); + if (sample->data_.ip < 0xffff000000000000) { + sample->data_.ip += SubCommandRecord::random_; + } + for (u64 i = 0; i < sample->data_.nr; i++) { + if (sample->data_.ips[i] >= PERF_CONTEXT_MAX) { + continue; + } + if (sample->data_.ips[i] < 0xffff000000000000) { + sample->data_.ips[i] += SubCommandRecord::random_; + } + } + } +} + uint32_t SubCommandRecord::GetCountFromFile(const std::string &fileName) { uint32_t ret = 0; @@ -1956,6 +2006,9 @@ void SubCommandRecord::CollectSymbol(PerfRecordSample *sample) context = PERF_CONTEXT_USER; } } else { + if (!isRoot_ && sample->data_.ips[i] <= 0xffff000000000000) { + sample->data_.ips[i] -= SubCommandRecord::random_; + } serverPid = sample->GetServerPidof(i); if (virtualRuntime_.IsKernelThread(serverPid)) { kernelThreadSymbolsHits_[serverPid].insert(sample->data_.ips[i]); diff --git a/src/symbols_file.cpp b/src/symbols_file.cpp index 5afa02a04f8d4a02625f2149a849e18acd6ff05c..fd507c2f52312885a18013479ea82f240071d87e 100644 --- a/src/symbols_file.cpp +++ b/src/symbols_file.cpp @@ -49,6 +49,7 @@ namespace Developtools { namespace HiPerf { bool SymbolsFile::onRecording_ = true; bool SymbolsFile::needParseJsFunc_ = false; +uint32_t SymbolsFile::randomNum_ = 0; const std::string SymbolsFile::GetBuildId() const { @@ -1057,23 +1058,24 @@ public: HLOGD("failed to call ParseArkFrameInfo, the symbol file is : %s", map->name.c_str()); return DfxSymbol(ip, ""); } - this->symbolsMap_.insert(std::make_pair(ip, - DfxSymbol(ip, + this->symbolsMap_.insert(std::make_pair(ip + SymbolsFile::randomNum_, + DfxSymbol(ip + SymbolsFile::randomNum_, jsFunc.codeBegin, jsFunc.functionName, jsFunc.ToString(), map->name))); - DfxSymbol &foundSymbol = symbolsMap_[ip]; + DfxSymbol &foundSymbol = symbolsMap_[ip + SymbolsFile::randomNum_]; if (!foundSymbol.matched_) { foundSymbol.matched_ = true; foundSymbol.symbolFileIndex_ = id_; - matchedSymbols_.push_back(&(symbolsMap_[ip])); + matchedSymbols_.push_back(&(symbolsMap_[ip + SymbolsFile::randomNum_])); } - HLOGD("ip : 0x%" PRIx64 " the symbol file is : %s, function is %s demangle_ : %s", ip, - symbolsMap_[ip].module_.data(), jsFunc.functionName, matchedSymbols_.back()->demangle_.data()); - return symbolsMap_[ip]; + HLOGD("ip : 0x%" PRIx64 " the symbol file is : %s, function is %s demangle_ : %s", + ip + SymbolsFile::randomNum_, symbolsMap_[ip + SymbolsFile::randomNum_].module_.data(), + jsFunc.functionName, matchedSymbols_.back()->demangle_.data()); + return symbolsMap_[ip + SymbolsFile::randomNum_]; } #endif DfxSymbol symbol(ip, "");