mirror of
https://gitee.com/openharmony/developtools_hiperf
synced 2024-11-23 15:39:47 +00:00
Merge branch 'master' of https://gitee.com/yuyanqinghw/developtools_hiperf_1
This commit is contained in:
commit
cd66ef8ffc
@ -557,9 +557,10 @@ size_t CallStack::DoExpandCallStack(std::vector<DfxFrame> &newCallFrames,
|
||||
// in case1 newIt -> C
|
||||
// in case2 newIt -> B
|
||||
const auto newIt = newCallFrames.end() - expandLimit;
|
||||
|
||||
HLOGM("try find new call chain bottom %s for limit %zu", newIt->ToString().c_str(),
|
||||
expandLimit);
|
||||
if (newIt != newCallFrames.end()) {
|
||||
HLOGM("try find new call chain bottom %s for limit %zu", newIt->ToString().c_str(),
|
||||
expandLimit);
|
||||
}
|
||||
|
||||
// first frame search, from called - > caller
|
||||
// for case 2 it should found B
|
||||
@ -682,6 +683,9 @@ bool CallStack::DoUnwind2(const VirtualThread &thread, std::vector<DfxFrame> &ca
|
||||
static std::shared_ptr<DfxRegs> regs = std::make_shared<DfxRegsArm64>();
|
||||
regs->SetRegsData((uintptr_t*)(regs_), regsNum_);
|
||||
#endif
|
||||
if (unwinder == nullptr) {
|
||||
return false;
|
||||
}
|
||||
unwinder->SetRegs(regs);
|
||||
unwinder->Unwind(&unwindInfo);
|
||||
callStack = unwinder->GetFrames();
|
||||
@ -690,7 +694,8 @@ bool CallStack::DoUnwind2(const VirtualThread &thread, std::vector<DfxFrame> &ca
|
||||
HLOGD("pc 0x%" PRIx64 " sp 0x%" PRIx64 "", frame.pc, frame.sp);
|
||||
}
|
||||
auto lastIt = callStack.end() - 1;
|
||||
if (lastIt->pc == (lastIt - 1)->pc && lastIt->sp == (lastIt - 1)->sp) {
|
||||
auto preIt = lastIt - 1;
|
||||
if (callStack.size() > 1 && lastIt->pc == preIt->pc && lastIt->sp == preIt->sp) {
|
||||
callStack.erase(lastIt);
|
||||
HLOGD("remove last callframe");
|
||||
}
|
||||
@ -712,6 +717,9 @@ int CallStack::FillUnwindTable(SymbolsFile *symbolsFile, std::shared_ptr<DfxMap>
|
||||
uintptr_t pc, UnwindTableInfo& outTableInfo)
|
||||
{
|
||||
HLOGM("try search debug info at %s", symbolsFile->filePath_.c_str());
|
||||
if (unwindInfoPtr == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
auto &tableInfoMap = unwindInfoPtr->callStack.unwindTableInfoMap_;
|
||||
// all the thread in same process have same mmap and symbols
|
||||
if (tableInfoMap.find(unwindInfoPtr->thread.pid_) == tableInfoMap.end()) {
|
||||
@ -748,6 +756,9 @@ int CallStack::FillUnwindTable(SymbolsFile *symbolsFile, std::shared_ptr<DfxMap>
|
||||
int CallStack::FindUnwindTable(uintptr_t pc, UnwindTableInfo& outTableInfo, void *arg)
|
||||
{
|
||||
UnwindInfo *unwindInfoPtr = static_cast<UnwindInfo *>(arg);
|
||||
if (unwindInfoPtr == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
int64_t mapIndex = unwindInfoPtr->thread.FindMapIndexByAddr(pc);
|
||||
if (mapIndex >= 0) {
|
||||
auto map = unwindInfoPtr->thread.GetMaps()[mapIndex];
|
||||
@ -775,8 +786,9 @@ int CallStack::AccessMem2(uintptr_t addr, uintptr_t *val, void *arg)
|
||||
*val = 0;
|
||||
|
||||
/* Check overflow. */
|
||||
if (addr + sizeof(uintptr_t) < addr) {
|
||||
HLOGE("address overflow at 0x%" UNW_WORD_PFLAG " increase 0x%zu", addr, sizeof(uintptr_t));
|
||||
if (unwindInfoPtr == nullptr || addr + sizeof(uintptr_t) < addr) {
|
||||
HLOGE("unwindInfoPtr is null or address overflow at 0x%" UNW_WORD_PFLAG " increase 0x%zu",
|
||||
addr, sizeof(uintptr_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,9 @@ bool RegisterMainOption(const std::string &optionName, const std::string &help,
|
||||
|
||||
if (g_MainOptions.count(optionName) == 0) {
|
||||
g_MainOptions[optionName] = std::make_unique<MainOption>();
|
||||
if (g_MainOptions[optionName].get() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
g_MainOptions[optionName].get()->help = help;
|
||||
g_MainOptions[optionName].get()->callBackFunction = std::move(callBackFunction);
|
||||
return true;
|
||||
|
@ -597,21 +597,23 @@ PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, std::shared_pt
|
||||
{
|
||||
data_.pid = pid;
|
||||
data_.tid = tid;
|
||||
data_.addr = item->begin;
|
||||
data_.len = item->end - item->begin;
|
||||
data_.pgoff = item->offset;
|
||||
data_.maj = item->major;
|
||||
data_.min = item->minor;
|
||||
data_.ino = item->inode;
|
||||
data_.ino_generation = 0;
|
||||
// r--p 00000000 103:3e 12307 /data/storage/el1/bundle/entry.hap
|
||||
// why prot get from this is 7. rwxp
|
||||
DfxMap::PermsToProts(item->perms, data_.prot, data_.flags);
|
||||
if (strncpy_s(data_.filename, KILO, item->name.c_str(), item->name.size()) != 0) {
|
||||
HLOGE("strncpy_s failed");
|
||||
}
|
||||
if (item != nullptr) {
|
||||
data_.addr = item->begin;
|
||||
data_.len = item->end - item->begin;
|
||||
data_.pgoff = item->offset;
|
||||
data_.maj = item->major;
|
||||
data_.min = item->minor;
|
||||
data_.ino = item->inode;
|
||||
data_.ino_generation = 0;
|
||||
// r--p 00000000 103:3e 12307 /data/storage/el1/bundle/entry.hap
|
||||
// why prot get from this is 7. rwxp
|
||||
DfxMap::PermsToProts(item->perms, data_.prot, data_.flags);
|
||||
if (strncpy_s(data_.filename, KILO, item->name.c_str(), item->name.size()) != 0) {
|
||||
HLOGE("strncpy_s failed");
|
||||
}
|
||||
|
||||
header.size = sizeof(header) + sizeof(data_) - KILO + item->name.size() + 1;
|
||||
header.size = sizeof(header) + sizeof(data_) - KILO + item->name.size() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool PerfRecordMmap2::GetBinary(std::vector<uint8_t> &buf) const
|
||||
|
@ -705,7 +705,8 @@ void PerfEvents::LoadTracepointEventTypesFromSystem()
|
||||
for (const auto &concreteEvent : GetSubDirs(eventPath)) {
|
||||
std::string idPath = eventPath + "/" + concreteEvent + "/id";
|
||||
{
|
||||
std::ifstream ifs {idPath};
|
||||
std::string resolvedPath = CanonicalizeSpecPath(idPath.c_str());
|
||||
std::ifstream ifs {resolvedPath};
|
||||
// clang-format off
|
||||
const std::string idStr = {
|
||||
std::istream_iterator<char>(ifs),
|
||||
|
@ -344,6 +344,9 @@ bool PerfFileSectionUniStackTable::GetBinary(char *buf, size_t size)
|
||||
Write(uint32_t(processStackTable_->size()));
|
||||
for (auto it = processStackTable_->begin(); it != processStackTable_->end(); ++it) {
|
||||
const auto &table = it->second;
|
||||
if (table == nullptr) {
|
||||
continue;
|
||||
}
|
||||
Write(table->GetPid());
|
||||
Write(table->GetTabelSize());
|
||||
const auto &idxs = table->GetUsedIndexes();
|
||||
@ -352,6 +355,9 @@ bool PerfFileSectionUniStackTable::GetBinary(char *buf, size_t size)
|
||||
Node *node = nullptr;
|
||||
for (const auto idx : idxs) {
|
||||
node = head + idx;
|
||||
if (node == nullptr) {
|
||||
continue;
|
||||
}
|
||||
Write(idx);
|
||||
Write(node->value);
|
||||
}
|
||||
|
@ -199,7 +199,9 @@ bool PerfFileReader::ReadIdsForAttr(const perf_file_attr &attr, std::vector<uint
|
||||
HLOGE("fseek() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ids == nullptr) {
|
||||
return false;
|
||||
}
|
||||
ids->resize(count);
|
||||
if (!Read(ids->data(), attr.ids.size)) {
|
||||
return false;
|
||||
@ -270,7 +272,7 @@ bool PerfFileReader::ReadRecord(ProcessRecordCB &callback)
|
||||
return false;
|
||||
} else {
|
||||
perf_event_header *header = reinterpret_cast<perf_event_header *>(buf);
|
||||
if (header->size > sizeof(buf)) {
|
||||
if (header == nullptr || header->size > sizeof(buf)) {
|
||||
HLOGE("read record header size error %hu", header->size);
|
||||
return false;
|
||||
}
|
||||
|
@ -312,6 +312,9 @@ bool PerfFileWriter::WriteAttrAndId(const std::vector<AttrWithId> &attrIds)
|
||||
static bool LeftLessRight(const std::unique_ptr<PerfFileSection> &l,
|
||||
const std::unique_ptr<PerfFileSection> &r)
|
||||
{
|
||||
if (l == nullptr || r == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return l->featureId_ < r->featureId_;
|
||||
}
|
||||
// to write perf_file_header to file
|
||||
|
@ -69,17 +69,19 @@ void Report::AddReportItem(const PerfRecordSample &sample, bool includeCallStack
|
||||
}
|
||||
} else {
|
||||
auto frameIt = sample.callFrames_.begin();
|
||||
HLOG_ASSERT(frameIt->pc < PERF_CONTEXT_MAX);
|
||||
// for arkjs frame, skip the stub.an frame
|
||||
if (StringEndsWith(frameIt->mapName, "stub.an")) {
|
||||
HLOGV("stub.an frame, go to next, mapname %s", frameIt->mapName.c_str());
|
||||
frameIt++;
|
||||
if (frameIt != sample.callFrames_.end()) {
|
||||
HLOG_ASSERT(frameIt->pc < PERF_CONTEXT_MAX);
|
||||
// for arkjs frame, skip the stub.an frame
|
||||
if (StringEndsWith(frameIt->mapName, "stub.an")) {
|
||||
HLOGV("stub.an frame, go to next, mapname %s", frameIt->mapName.c_str());
|
||||
frameIt++;
|
||||
}
|
||||
ReportItem &item = configs_[configIndex].reportItems_.emplace_back(
|
||||
sample.data_.pid, sample.data_.tid, thread.name_, frameIt->mapName,
|
||||
frameIt->funcName, frameIt->funcOffset, sample.data_.period);
|
||||
HLOGV("%s", item.ToDebugString().c_str());
|
||||
HLOG_ASSERT(!item.func_.empty());
|
||||
}
|
||||
ReportItem &item = configs_[configIndex].reportItems_.emplace_back(
|
||||
sample.data_.pid, sample.data_.tid, thread.name_, frameIt->mapName,
|
||||
frameIt->funcName, frameIt->funcOffset, sample.data_.period);
|
||||
HLOGV("%s", item.ToDebugString().c_str());
|
||||
HLOG_ASSERT(!item.func_.empty());
|
||||
}
|
||||
}
|
||||
configs_[configIndex].sampleCount_++;
|
||||
@ -391,7 +393,7 @@ void Report::OutputStdHead(ReportEventConfigItem &config, bool diffMode)
|
||||
if (remainingWidth == 0) {
|
||||
key.maxLen_ = 0;
|
||||
}
|
||||
if (fprintf(output_, "%-*s ", (remainingWidth > 0) ? static_cast<int>(key.maxLen_) : 0,
|
||||
if (fprintf(output_, "%-*s ", (remainingWidth > 0) ? static_cast<unsigned int>(key.maxLen_) : 0,
|
||||
key.keyName_.c_str()) < 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -104,6 +104,9 @@ uint8_t *RingBuffer::GetReadData()
|
||||
}
|
||||
// else |---readPos<---data--->writePos---|
|
||||
perf_event_header *header = reinterpret_cast<perf_event_header *>(buf_.get() + readPos);
|
||||
if (header == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
readSize_ += header->size;
|
||||
return buf_.get() + readPos;
|
||||
}
|
||||
|
@ -42,14 +42,19 @@ bool SubCommandHelp::OnHelp(std::vector<std::string> &args)
|
||||
|
||||
printf("options:\n");
|
||||
for (const auto &commandOption : mainOptions) {
|
||||
printf("\t%-20s\t%s\n", commandOption.first.c_str(),
|
||||
commandOption.second->help.c_str());
|
||||
if (commandOption.second != nullptr) {
|
||||
printf("\t%-20s\t%s\n", commandOption.first.c_str(),
|
||||
commandOption.second->help.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
auto &commands = SubCommand::GetSubCommands();
|
||||
HLOGD("%zu cmds found:", commands.size());
|
||||
printf("command:\n");
|
||||
for (const auto &command : commands) {
|
||||
if (command.second == nullptr) {
|
||||
continue;
|
||||
}
|
||||
printf("\t%s:\t%s\n", command.second->Name().c_str(), command.second->Brief().c_str());
|
||||
}
|
||||
printf("\nSee 'hiperf help [command]' for more information on a specific command.\n\n");
|
||||
|
@ -1614,6 +1614,9 @@ void SubCommandRecord::SymbolicHits()
|
||||
|
||||
bool SubCommandRecord::CollectionSymbol(std::unique_ptr<PerfEventRecord> record)
|
||||
{
|
||||
if (record == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
||||
PerfRecordSample *sample = static_cast<PerfRecordSample *>(record.get());
|
||||
#if USE_COLLECT_SYMBOLIC
|
||||
@ -1629,6 +1632,9 @@ bool SubCommandRecord::CollectionSymbol(std::unique_ptr<PerfEventRecord> record)
|
||||
|
||||
void SubCommandRecord::CollectSymbol(PerfRecordSample *sample)
|
||||
{
|
||||
if (sample == nullptr) {
|
||||
return;
|
||||
}
|
||||
perf_callchain_context context = sample->inKernel() ? PERF_CONTEXT_KERNEL
|
||||
: PERF_CONTEXT_USER;
|
||||
pid_t server_pid;
|
||||
|
@ -359,6 +359,9 @@ void SubCommandReport::LoadEventDesc()
|
||||
{
|
||||
const PerfFileSection *featureSection =
|
||||
recordFileReader_->GetFeatureSection(FEATURE::EVENT_DESC);
|
||||
if (featureSection == nullptr) {
|
||||
return;
|
||||
}
|
||||
const PerfFileSectionEventDesc §ionEventdesc =
|
||||
*static_cast<const PerfFileSectionEventDesc *>(featureSection);
|
||||
HLOGV("Event descriptions: %zu", sectionEventdesc.eventDesces_.size());
|
||||
|
@ -189,6 +189,9 @@ void SubCommandStat::PrintPerHead()
|
||||
void SubCommandStat::PrintPerValue(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, const float &ratio,
|
||||
std::string &configName)
|
||||
{
|
||||
if (reportSum == nullptr) {
|
||||
return;
|
||||
}
|
||||
// print value
|
||||
std::string strEventCount = std::to_string(reportSum->eventCountSum);
|
||||
for (size_t i = strEventCount.size() - 1, j = 1; i > 0; --i, ++j) {
|
||||
@ -219,6 +222,9 @@ void SubCommandStat::PrintPerValue(const std::unique_ptr<PerfEvents::ReportSum>
|
||||
void SubCommandStat::InitPerMap(const std::unique_ptr<PerfEvents::ReportSum> &newPerMap,
|
||||
const PerfEvents::Summary &summary, VirtualRuntime& virtualInstance)
|
||||
{
|
||||
if (newPerMap == nullptr) {
|
||||
return;
|
||||
}
|
||||
newPerMap->cpu = summary.cpu;
|
||||
if (g_reportCpuFlag && !g_reportThreadFlag) {
|
||||
return;
|
||||
@ -251,7 +257,7 @@ void SubCommandStat::ReportDetailInfos(
|
||||
std::string perKey = "";
|
||||
std::map<std::string, std::unique_ptr<PerfEvents::ReportSum>> perMaps;
|
||||
for (auto event = countEvents.begin(); event != countEvents.end(); ++event) {
|
||||
if (event->second->eventCount == 0) {
|
||||
if (event->second == nullptr || event->second->eventCount == 0) {
|
||||
continue;
|
||||
}
|
||||
constexpr float ratio {100.0};
|
||||
@ -264,6 +270,9 @@ void SubCommandStat::ReportDetailInfos(
|
||||
InitPerMap(perMap, it, runtimeInstance_);
|
||||
perMaps[perKey] = std::move(perMap);
|
||||
}
|
||||
if (perMaps[perKey] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
perMaps[perKey]->configName = GetDetailComments(event->second, perMaps[perKey]->commentSum,
|
||||
it, configName);
|
||||
perMaps[perKey]->eventCountSum += it.eventCount;
|
||||
@ -351,7 +360,7 @@ std::string SubCommandStat::GetCommentConfigName(
|
||||
|
||||
void SubCommandStat::MakeComments(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, std::string &commentStr)
|
||||
{
|
||||
if (reportSum->commentSum == 0) {
|
||||
if (reportSum == nullptr || reportSum->commentSum == 0) {
|
||||
return;
|
||||
}
|
||||
if (reportSum->configName == "sw-task-clock") {
|
||||
|
@ -256,6 +256,10 @@ protected:
|
||||
if (StringEndsWith(elfPath, ".hap")) {
|
||||
filePath_ = elfPath + "!" + elfFile_->GetElfName();
|
||||
HLOGD("update path for so in hap %s.", filePath_.c_str());
|
||||
if (map == nullptr) {
|
||||
HLOGW("map should not be nullptr.");
|
||||
return false;
|
||||
}
|
||||
map->name = filePath_;
|
||||
map->elf = elfFile_;
|
||||
map->prevMap->name = filePath_;
|
||||
@ -344,6 +348,9 @@ private:
|
||||
bool LoadEhFrameHDR(const unsigned char *buffer, size_t bufferSize, uint64_t shdrOffset)
|
||||
{
|
||||
eh_frame_hdr *ehFrameHdr = (eh_frame_hdr *)buffer;
|
||||
if (ehFrameHdr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const uint8_t *dataPtr = ehFrameHdr->encode_data;
|
||||
DwarfEncoding dwEhFramePtr(ehFrameHdr->eh_frame_ptr_enc, dataPtr);
|
||||
DwarfEncoding dwFdeCount(ehFrameHdr->fde_count_enc, dataPtr);
|
||||
@ -922,10 +929,6 @@ public:
|
||||
HLOGD("the symbol file is %s.", filePath_.c_str());
|
||||
if (StringEndsWith(filePath_, ".hap") || StringEndsWith(filePath_, ".hsp")) {
|
||||
dfxExtractor_ = std::make_unique<DfxExtractor>(filePath_);
|
||||
if (dfxExtractor_ == nullptr) {
|
||||
HLOGD("DfxExtractor create failed.");
|
||||
return false;
|
||||
}
|
||||
if (!dfxExtractor_->GetHapAbcInfo(loadOffSet_, abcDataPtr_, abcDataSize_)) {
|
||||
HLOGD("failed to call GetHapAbcInfo, the symbol file is:%s", filePath_.c_str());
|
||||
return false;
|
||||
@ -1150,6 +1153,9 @@ void SymbolsFile::SortMatchedSymbols()
|
||||
return;
|
||||
}
|
||||
sort(matchedSymbols_.begin(), matchedSymbols_.end(), [](const DfxSymbol* a, const DfxSymbol* b) {
|
||||
if (a == nullptr || b == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return a->funcVaddr_ < b->funcVaddr_;
|
||||
});
|
||||
}
|
||||
@ -1198,14 +1204,16 @@ const DfxSymbol SymbolsFile::GetSymbolWithVaddr(uint64_t vaddrInFile)
|
||||
*/
|
||||
if (found != symbols_.begin()) {
|
||||
found = std::prev(found);
|
||||
if (found->Contain(vaddrInFile)) {
|
||||
found->offsetToVaddr_ = vaddrInFile - found->funcVaddr_;
|
||||
if (!found->matched_) {
|
||||
found->matched_ = true;
|
||||
matchedSymbols_.push_back(&(*found));
|
||||
if (found != symbols_.end()) {
|
||||
if (found->Contain(vaddrInFile)) {
|
||||
found->offsetToVaddr_ = vaddrInFile - found->funcVaddr_;
|
||||
if (!found->matched_) {
|
||||
found->matched_ = true;
|
||||
matchedSymbols_.push_back(&(*found));
|
||||
}
|
||||
symbol = *found; // copy
|
||||
HLOGV("found '%s' for vaddr 0x%016" PRIx64 "", symbol.ToString().c_str(), vaddrInFile);
|
||||
}
|
||||
symbol = *found; // copy
|
||||
HLOGV("found '%s' for vaddr 0x%016" PRIx64 "", symbol.ToString().c_str(), vaddrInFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,9 @@ uint64_t UniqueStackTable::PutIpInSlot(uint64_t thisIp, uint64_t prevIdx)
|
||||
node.section.inKernel = !!(thisIp & IP_IN_KERNEL);
|
||||
while (currentDeconflictTimes_--) {
|
||||
Node* tableNode = reinterpret_cast<Node *>(tableHead_) + curIpIdx;
|
||||
|
||||
if (tableNode == nullptr) {
|
||||
continue;
|
||||
}
|
||||
// empty case
|
||||
if (tableNode->value == 0) {
|
||||
tableNode->value = node.value;
|
||||
@ -133,7 +135,9 @@ uint64_t UniqueStackTable::PutIpsInTable(StackId *stackId, u64 *ips, u64 nr)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (stackId == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
stackId->section.id = prev;
|
||||
stackId->section.nr = nr;
|
||||
return prev;
|
||||
|
@ -279,7 +279,8 @@ std::string PlatformPathConvert(const std::string &path)
|
||||
|
||||
std::string ReadFileToString(const std::string &fileName)
|
||||
{
|
||||
std::ifstream inputString(fileName, std::ios::in);
|
||||
std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str());
|
||||
std::ifstream inputString(resolvedPath, std::ios::in);
|
||||
if (!inputString or !inputString.is_open()) {
|
||||
return EMPTY_STRING;
|
||||
}
|
||||
@ -314,7 +315,8 @@ bool ReadFileToString(const std::string &fileName, std::string &fileData, size_t
|
||||
|
||||
bool WriteStringToFile(const std::string &fileName, const std::string &value)
|
||||
{
|
||||
std::ofstream output(fileName, std::ios::out);
|
||||
std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str());
|
||||
std::ofstream output(resolvedPath, std::ios::out);
|
||||
if (!output) {
|
||||
return false;
|
||||
}
|
||||
|
@ -185,6 +185,9 @@ VirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid, const std::str
|
||||
|
||||
bool VirtualRuntime::UpdateHapSymbols(std::shared_ptr<DfxMap> map)
|
||||
{
|
||||
if (map == nullptr) {
|
||||
return false;
|
||||
}
|
||||
// found it by name
|
||||
auto symbolsFile = SymbolsFile::CreateSymbolsFile(map->name);
|
||||
if (symbolsFile == nullptr) {
|
||||
@ -354,12 +357,14 @@ void VirtualRuntime::UpdatekernelMap(uint64_t begin, uint64_t end, uint64_t offs
|
||||
|
||||
void VirtualRuntime::DedupFromRecord(PerfRecordSample *recordSample)
|
||||
{
|
||||
if (recordSample == nullptr) {
|
||||
return;
|
||||
}
|
||||
u64 nr = recordSample->data_.nr;
|
||||
if (nr == 0) {
|
||||
collectSymbolCallBack_(recordSample);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 pid = recordSample->data_.pid;
|
||||
u64 *ips = recordSample->data_.ips;
|
||||
StackId stackId;
|
||||
@ -372,7 +377,9 @@ void VirtualRuntime::DedupFromRecord(PerfRecordSample *recordSample)
|
||||
table = std::make_shared<UniqueStackTable>(pid);
|
||||
processStackMap_[pid] = table;
|
||||
}
|
||||
|
||||
if (table == nullptr) {
|
||||
return;
|
||||
}
|
||||
while (table->PutIpsInTable(&stackId, ips, nr) == 0) {
|
||||
// try expand hashtable if collison can not resolved
|
||||
if (!table->Resize()) {
|
||||
@ -381,7 +388,6 @@ void VirtualRuntime::DedupFromRecord(PerfRecordSample *recordSample)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// callstack dedup success
|
||||
recordSample->stackId_.value = stackId.value;
|
||||
recordSample->header.size -= (sizeof(u64) * nr - sizeof(stackId));
|
||||
@ -398,11 +404,17 @@ void VirtualRuntime::CollectDedupSymbol(kSymbolsHits &kernelSymbolsHits,
|
||||
u32 pid;
|
||||
for (const auto &tableEntry : processStackMap_) {
|
||||
const auto &table = tableEntry.second;
|
||||
if (table == nullptr) {
|
||||
continue;
|
||||
}
|
||||
pid = table->GetPid();
|
||||
head = table->GetHeadNode();
|
||||
const auto &idxes = table->GetUsedIndexes();
|
||||
for (const auto idx : idxes) {
|
||||
node = head + idx;
|
||||
if (node == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (node->value != 0) {
|
||||
if (node->section.inKernel) {
|
||||
uint64_t ip = node->section.ip | KERNEL_PREFIX;
|
||||
@ -492,7 +504,9 @@ bool VirtualRuntime::RecoverCallStack(PerfRecordSample &recordSample)
|
||||
return false;
|
||||
}
|
||||
recordSample.ips_.clear();
|
||||
StackTable->second->GetIpsByStackId(recordSample.stackId_, recordSample.ips_);
|
||||
if (StackTable->second != nullptr) {
|
||||
StackTable->second->GetIpsByStackId(recordSample.stackId_, recordSample.ips_);
|
||||
}
|
||||
recordSample.RecoverCallStack();
|
||||
return true;
|
||||
}
|
||||
@ -795,7 +809,7 @@ void VirtualRuntime::UpdateSymbols(std::shared_ptr<DfxMap> map, pid_t pid)
|
||||
HLOGD("try to find symbols for file: %s", map->name.c_str());
|
||||
for (size_t i = 0; i < symbolsFiles_.size(); ++i) {
|
||||
if (symbolsFiles_[i]->filePath_ == map->name) {
|
||||
map->symbolFileIndex = i;
|
||||
map->symbolFileIndex = static_cast<int32_t>(i);
|
||||
HLOGV("already have '%s'", map->name.c_str());
|
||||
return;
|
||||
}
|
||||
@ -904,6 +918,9 @@ const DfxSymbol VirtualRuntime::GetKernelThreadSymbol(uint64_t ip, const Virtual
|
||||
}
|
||||
|
||||
auto map = thread.GetMaps()[mapIndex];
|
||||
if (map == nullptr) {
|
||||
return vaddrSymbol;
|
||||
}
|
||||
HLOGM("found addr 0x%" PRIx64 " in kthread map 0x%" PRIx64 " - 0x%" PRIx64 " from %s",
|
||||
ip, map->begin, map->end, map->name.c_str());
|
||||
// found symbols by file name
|
||||
@ -1069,6 +1086,9 @@ DfxSymbol VirtualRuntime::GetSymbol(uint64_t ip, pid_t pid, pid_t tid, const per
|
||||
bool VirtualRuntime::SetSymbolsPaths(const std::vector<std::string> &symbolsPaths)
|
||||
{
|
||||
std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE);
|
||||
if (symbolsFile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
// we need check if the path is accessible
|
||||
bool accessible = symbolsFile->setSymbolsFilePath(symbolsPaths);
|
||||
if (accessible) {
|
||||
@ -1094,7 +1114,9 @@ void VirtualRuntime::UpdateFromPerfData(const std::vector<SymbolFileStruct> &sym
|
||||
|
||||
// load from symbolFileStruct (perf.data)
|
||||
std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::LoadSymbolsFromSaved(symbolFileStruct);
|
||||
|
||||
if (symbolsFile == nullptr) {
|
||||
continue;
|
||||
}
|
||||
// reaload from sybol path If it exists
|
||||
if (symbolsPaths_.size() > 0) {
|
||||
HLOGV("try again with symbolsPaths setup");
|
||||
@ -1247,11 +1269,17 @@ void VirtualRuntime::UpdateDevhostSymbols()
|
||||
koMaps[symbol.module_] =
|
||||
SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_THREAD_FILE, filename);
|
||||
}
|
||||
if (koMaps[symbol.module_] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
koMaps[symbol.module_]->AddSymbol(std::move(symbol));
|
||||
}
|
||||
|
||||
HLOGD("devhost loaded %zu symbolfiles", koMaps.size());
|
||||
for (auto &it : koMaps) {
|
||||
if (it.second == nullptr) {
|
||||
continue;
|
||||
}
|
||||
HLOGD("Load %zu symbols to %s", it.second->GetSymbols().size(),
|
||||
it.second->filePath_.c_str());
|
||||
symbolsFiles_.emplace_back(std::move(it.second));
|
||||
|
@ -142,8 +142,8 @@ std::shared_ptr<DfxMap> VirtualThread::FindMapByFileInfo(const std::string name,
|
||||
|
||||
std::shared_ptr<DfxMap> VirtualThread::FindFirstMapByFileInfo(const std::string name) const
|
||||
{
|
||||
for (auto &map : memMaps_) {
|
||||
if (name != map->name) {
|
||||
for (const auto &map : memMaps_) {
|
||||
if (map == nullptr || name != map->name) {
|
||||
continue;
|
||||
}
|
||||
return map;
|
||||
@ -154,6 +154,9 @@ std::shared_ptr<DfxMap> VirtualThread::FindFirstMapByFileInfo(const std::string
|
||||
|
||||
SymbolsFile *VirtualThread::FindSymbolsFileByMap(std::shared_ptr<DfxMap> map) const
|
||||
{
|
||||
if (map == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (map->symbolFileIndex != -1) {
|
||||
// no need further operation
|
||||
if (symbolsFiles_[map->symbolFileIndex]->LoadDebugInfo(map)) {
|
||||
@ -166,7 +169,7 @@ SymbolsFile *VirtualThread::FindSymbolsFileByMap(std::shared_ptr<DfxMap> map) co
|
||||
HLOGD("found symbol for map '%s'", map->name.c_str());
|
||||
if (symbolsFiles_[i]->LoadDebugInfo(map)) {
|
||||
HLOGD("found symbol for map '%s'", map->name.c_str());
|
||||
map->symbolFileIndex = i;
|
||||
map->symbolFileIndex = static_cast<int32_t>(i);
|
||||
return symbolsFiles_[i].get();
|
||||
}
|
||||
}
|
||||
@ -196,6 +199,9 @@ void VirtualThread::ReportVaddrMapMiss(uint64_t vaddr) const
|
||||
missedRuntimeVaddr_.insert(vaddr);
|
||||
HLOGV("vaddr %" PRIx64 " not found in any map", vaddr);
|
||||
for (auto &map : memMaps_) {
|
||||
if (map == nullptr) {
|
||||
return;
|
||||
}
|
||||
HLOGV("map %s ", map->ToString().c_str());
|
||||
}
|
||||
}
|
||||
@ -222,23 +228,25 @@ bool VirtualThread::ReadRoMemory(uint64_t vaddr, uint8_t *data, size_t size) con
|
||||
}
|
||||
if (memMapIndex != illegal) {
|
||||
auto map = memMaps_[memMapIndex];
|
||||
if (map->elf == nullptr) {
|
||||
SymbolsFile* symFile = FindSymbolsFileByMap(map);
|
||||
if (symFile == nullptr) {
|
||||
return false;
|
||||
if (map != nullptr) {
|
||||
if (map->elf == nullptr) {
|
||||
SymbolsFile* symFile = FindSymbolsFileByMap(map);
|
||||
if (symFile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
map->elf = symFile->GetElfFile();
|
||||
}
|
||||
map->elf = symFile->GetElfFile();
|
||||
}
|
||||
if (map->elf != nullptr) {
|
||||
// default base offset is zero
|
||||
uint64_t foff = vaddr - map->begin + map->offset - map->elf->GetBaseOffset();
|
||||
if (map->elf->Read(foff, data, size)) {
|
||||
return true;
|
||||
if (map->elf != nullptr) {
|
||||
// default base offset is zero
|
||||
uint64_t foff = vaddr - map->begin + map->offset - map->elf->GetBaseOffset();
|
||||
if (map->elf->Read(foff, data, size)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
HLOGW("find addr %" PRIx64 "in map but not loaded symbole %s", vaddr, map->name.c_str());
|
||||
}
|
||||
} else {
|
||||
HLOGW("find addr %" PRIx64 "in map but not loaded symbole %s", vaddr, map->name.c_str());
|
||||
}
|
||||
} else {
|
||||
#ifdef HIPERF_DEBUG
|
||||
|
@ -96,12 +96,12 @@ UnwindStep:unwind:12: ip 0x457ffe sp 0xb6ca1d28
|
||||
UnwindStep:unwind:13: ip 0xb6f01f73 sp 0xb6ca1d38
|
||||
*/
|
||||
static const std::vector<frame> TEST_DWARF_FRAMES = {
|
||||
{0x4575BC, 0xB6CA1C18}, // base ip sp
|
||||
{0x45765e, 0xb6ca1c68}, {0x45768a, 0xb6ca1c78}, {0x4576ce, 0xb6ca1c88},
|
||||
{0x457712, 0xb6ca1c98}, {0x457756, 0xb6ca1ca8}, {0x45779a, 0xb6ca1cb8},
|
||||
{0x4577de, 0xb6ca1cc8}, {0x457822, 0xb6ca1cd8}, {0x457866, 0xb6ca1ce8},
|
||||
{0x4578aa, 0xb6ca1cf8}, {0x4578ee, 0xb6ca1d08}, {0x45793c, 0xb6ca1d18},
|
||||
{0x457ffe, 0xb6ca1d28}, {0xb6f01f73, 0xb6ca1d38},
|
||||
{0x4575bc, 0xb6ca1c18}, // base ip sp
|
||||
{0x45765f, 0xb6ca1c68}, {0x45768b, 0xb6ca1c78}, {0x4576cf, 0xb6ca1c88},
|
||||
{0x457713, 0xb6ca1c98}, {0x457757, 0xb6ca1ca8}, {0x45779b, 0xb6ca1cb8},
|
||||
{0x4577df, 0xb6ca1cc8}, {0x457823, 0xb6ca1cd8}, {0x457867, 0xb6ca1ce8},
|
||||
{0x4578ab, 0xb6ca1cf8}, {0x4578ef, 0xb6ca1d08}, {0x45793d, 0xb6ca1d18},
|
||||
{0x457fff, 0xb6ca1d28},
|
||||
};
|
||||
#else
|
||||
static const std::string TEST_DWARF_ELF = "hiperf_example_cmd_64";
|
||||
@ -151,7 +151,7 @@ static const std::vector<frame> TEST_DWARF_FRAMES = {
|
||||
{0x5591ef7b10, 0x7f9aec7860}, {0x5591ef7bd0, 0x7f9aec78a0}, {0x5591ef7c90, 0x7f9aec78e0},
|
||||
{0x5591ef7d50, 0x7f9aec7920}, {0x5591ef7e10, 0x7f9aec7960}, {0x5591ef7ed0, 0x7f9aec79a0},
|
||||
{0x5591ef7f90, 0x7f9aec79e0}, {0x5591ef8050, 0x7f9aec7a20}, {0x5591ef80e8, 0x7f9aec7a60},
|
||||
{0x5591ef95dc, 0x7f9aec7a80}, {0x7f9b0fa59c, 0x7f9aec7aa0},
|
||||
{0x5591ef95dc, 0x7f9aec7a80},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user