148f512ceSopenharmony_ci/* 248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 448f512ceSopenharmony_ci * you may not use this file except in compliance with the License. 548f512ceSopenharmony_ci * You may obtain a copy of the License at 648f512ceSopenharmony_ci * 748f512ceSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 848f512ceSopenharmony_ci * 948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and 1348f512ceSopenharmony_ci * limitations under the License. 1448f512ceSopenharmony_ci */ 1548f512ceSopenharmony_ci#define HILOG_TAG "Dump" 1648f512ceSopenharmony_ci 1748f512ceSopenharmony_ci#include "subcommand_dump.h" 1848f512ceSopenharmony_ci 1948f512ceSopenharmony_ci#include <cerrno> 2048f512ceSopenharmony_ci#include <cinttypes> 2148f512ceSopenharmony_ci#include <cstring> 2248f512ceSopenharmony_ci#include <iostream> 2348f512ceSopenharmony_ci#include <memory> 2448f512ceSopenharmony_ci 2548f512ceSopenharmony_ci#include "debug_logger.h" 2648f512ceSopenharmony_ci#include "hiperf_hilog.h" 2748f512ceSopenharmony_ci#include "option.h" 2848f512ceSopenharmony_ci#include "perf_event_record.h" 2948f512ceSopenharmony_ci#include "perf_events.h" 3048f512ceSopenharmony_ci#include "register.h" 3148f512ceSopenharmony_ci#include "spe_decoder.h" 3248f512ceSopenharmony_ci#include "symbols_file.h" 3348f512ceSopenharmony_ci#include "utilities.h" 3448f512ceSopenharmony_ci#include "virtual_runtime.h" 3548f512ceSopenharmony_ci 3648f512ceSopenharmony_cinamespace OHOS { 3748f512ceSopenharmony_cinamespace Developtools { 3848f512ceSopenharmony_cinamespace HiPerf { 3948f512ceSopenharmony_ciusing namespace OHOS::HiviewDFX; 4048f512ceSopenharmony_ci 4148f512ceSopenharmony_cistatic const std::string DEFAULT_DUMP_FILENAME = "perf.data"; 4248f512ceSopenharmony_ci 4348f512ceSopenharmony_cibool SubCommandDump::CheckInputFile() 4448f512ceSopenharmony_ci{ 4548f512ceSopenharmony_ci if (!dumpFileName_.empty()) { 4648f512ceSopenharmony_ci if (elfFileName_.empty() && protobufDumpFileName_.empty()) { 4748f512ceSopenharmony_ci return true; 4848f512ceSopenharmony_ci } 4948f512ceSopenharmony_ci } else if (!elfFileName_.empty()) { 5048f512ceSopenharmony_ci if (protobufDumpFileName_.empty()) { 5148f512ceSopenharmony_ci return true; 5248f512ceSopenharmony_ci } 5348f512ceSopenharmony_ci } else if (!protobufDumpFileName_.empty()) { 5448f512ceSopenharmony_ci return true; 5548f512ceSopenharmony_ci } else { // all is empty 5648f512ceSopenharmony_ci dumpFileName_ = DEFAULT_DUMP_FILENAME; 5748f512ceSopenharmony_ci return true; 5848f512ceSopenharmony_ci } 5948f512ceSopenharmony_ci 6048f512ceSopenharmony_ci printf("options conflict, please check usage\n"); 6148f512ceSopenharmony_ci return false; 6248f512ceSopenharmony_ci} 6348f512ceSopenharmony_ci 6448f512ceSopenharmony_cibool SubCommandDump::ParseOption(std::vector<std::string> &args) 6548f512ceSopenharmony_ci{ 6648f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--head", dumpHeader_)) { 6748f512ceSopenharmony_ci HLOGD("get option --head failed"); 6848f512ceSopenharmony_ci return false; 6948f512ceSopenharmony_ci } 7048f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-f", dumpFeatures_)) { 7148f512ceSopenharmony_ci HLOGD("get option -f failed"); 7248f512ceSopenharmony_ci return false; 7348f512ceSopenharmony_ci } 7448f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-d", dumpData_)) { 7548f512ceSopenharmony_ci HLOGD("get option -d failed"); 7648f512ceSopenharmony_ci return false; 7748f512ceSopenharmony_ci } 7848f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--sympath", dumpSymbolsPaths_)) { 7948f512ceSopenharmony_ci HLOGD("get option --sympath failed"); 8048f512ceSopenharmony_ci return false; 8148f512ceSopenharmony_ci } 8248f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--elf", elfFileName_)) { 8348f512ceSopenharmony_ci HLOGD("get option --elf failed"); 8448f512ceSopenharmony_ci return false; 8548f512ceSopenharmony_ci } 8648f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-i", dumpFileName_)) { 8748f512ceSopenharmony_ci return false; 8848f512ceSopenharmony_ci } 8948f512ceSopenharmony_ci#if defined(HAVE_PROTOBUF) && HAVE_PROTOBUF 9048f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--proto", protobufDumpFileName_)) { 9148f512ceSopenharmony_ci HLOGD("get option --proto failed"); 9248f512ceSopenharmony_ci return false; 9348f512ceSopenharmony_ci } 9448f512ceSopenharmony_ci#endif 9548f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-o", outputFilename_)) { 9648f512ceSopenharmony_ci return false; 9748f512ceSopenharmony_ci } 9848f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--export", exportSampleIndex_)) { 9948f512ceSopenharmony_ci HLOGD("get option --export failed"); 10048f512ceSopenharmony_ci return false; 10148f512ceSopenharmony_ci } 10248f512ceSopenharmony_ci 10348f512ceSopenharmony_ci if (dumpHeader_ || dumpFeatures_ || dumpData_) { 10448f512ceSopenharmony_ci dumpAll_ = false; 10548f512ceSopenharmony_ci } 10648f512ceSopenharmony_ci if (!args.empty()) { 10748f512ceSopenharmony_ci printf("'%s' option usage error, please check usage.\n", VectorToString(args).c_str()); 10848f512ceSopenharmony_ci return false; 10948f512ceSopenharmony_ci } 11048f512ceSopenharmony_ci 11148f512ceSopenharmony_ci return CheckInputFile(); 11248f512ceSopenharmony_ci} 11348f512ceSopenharmony_ci 11448f512ceSopenharmony_cibool SubCommandDump::PrepareDumpOutput() 11548f512ceSopenharmony_ci{ 11648f512ceSopenharmony_ci if (outputFilename_.empty()) { 11748f512ceSopenharmony_ci return true; 11848f512ceSopenharmony_ci } 11948f512ceSopenharmony_ci std::string resolvedPath = CanonicalizeSpecPath(outputFilename_.c_str()); 12048f512ceSopenharmony_ci g_outputDump = fopen(resolvedPath.c_str(), "w"); 12148f512ceSopenharmony_ci if (g_outputDump == nullptr) { 12248f512ceSopenharmony_ci printf("unable open file to '%s' because '%d'\n", outputFilename_.c_str(), errno); 12348f512ceSopenharmony_ci return false; 12448f512ceSopenharmony_ci } 12548f512ceSopenharmony_ci printf("dump result will save at '%s'\n", outputFilename_.c_str()); 12648f512ceSopenharmony_ci return true; 12748f512ceSopenharmony_ci} 12848f512ceSopenharmony_ci 12948f512ceSopenharmony_ciSubCommandDump::~SubCommandDump() 13048f512ceSopenharmony_ci{ 13148f512ceSopenharmony_ci if (g_outputDump != nullptr && g_outputDump != stdout) { 13248f512ceSopenharmony_ci fclose(g_outputDump); 13348f512ceSopenharmony_ci } 13448f512ceSopenharmony_ci SymbolsFile::onRecording_ = true; // back to default for UT 13548f512ceSopenharmony_ci} 13648f512ceSopenharmony_ci 13748f512ceSopenharmony_cibool SubCommandDump::OnSubCommand(std::vector<std::string> &args) 13848f512ceSopenharmony_ci{ 13948f512ceSopenharmony_ci if (!PrepareDumpOutput()) { 14048f512ceSopenharmony_ci return false; 14148f512ceSopenharmony_ci } 14248f512ceSopenharmony_ci 14348f512ceSopenharmony_ci if (!elfFileName_.empty()) { 14448f512ceSopenharmony_ci return DumpElfFile(); 14548f512ceSopenharmony_ci } 14648f512ceSopenharmony_ci 14748f512ceSopenharmony_ci#if defined(HAVE_PROTOBUF) && HAVE_PROTOBUF 14848f512ceSopenharmony_ci if (!protobufDumpFileName_.empty()) { 14948f512ceSopenharmony_ci return DumpProtoFile(); 15048f512ceSopenharmony_ci } 15148f512ceSopenharmony_ci#endif 15248f512ceSopenharmony_ci 15348f512ceSopenharmony_ci if (access(dumpFileName_.c_str(), F_OK) != 0) { 15448f512ceSopenharmony_ci printf("Can not access data file %s\n", dumpFileName_.c_str()); 15548f512ceSopenharmony_ci return false; 15648f512ceSopenharmony_ci } 15748f512ceSopenharmony_ci // only one file should created 15848f512ceSopenharmony_ci HLOG_ASSERT_MESSAGE(reader_ == nullptr, " perf file reader for %s\n", dumpFileName_.c_str()); 15948f512ceSopenharmony_ci reader_ = PerfFileReader::Instance(dumpFileName_); 16048f512ceSopenharmony_ci if (reader_ == nullptr) { 16148f512ceSopenharmony_ci HLOGE("HiperfFileReader::Instance(%s) return null", dumpFileName_.c_str()); 16248f512ceSopenharmony_ci return false; 16348f512ceSopenharmony_ci } 16448f512ceSopenharmony_ci 16548f512ceSopenharmony_ci // any way tell symbols this is not on device 16648f512ceSopenharmony_ci SymbolsFile::onRecording_ = false; 16748f512ceSopenharmony_ci // we need unwind it (for function name match) even not give us path 16848f512ceSopenharmony_ci vr_.SetDisableUnwind(false); 16948f512ceSopenharmony_ci 17048f512ceSopenharmony_ci if (!dumpSymbolsPaths_.empty()) { 17148f512ceSopenharmony_ci // user give us path , we enable unwind 17248f512ceSopenharmony_ci if (!vr_.SetSymbolsPaths(dumpSymbolsPaths_)) { 17348f512ceSopenharmony_ci printf("Failed to set symbol path(%s)\n", VectorToString(dumpSymbolsPaths_).c_str()); 17448f512ceSopenharmony_ci return false; 17548f512ceSopenharmony_ci } 17648f512ceSopenharmony_ci } 17748f512ceSopenharmony_ci 17848f512ceSopenharmony_ci if (dumpHeader_ || dumpAll_) { 17948f512ceSopenharmony_ci DumpPrintFileHeader(indent_); 18048f512ceSopenharmony_ci DumpAttrPortion(indent_); 18148f512ceSopenharmony_ci } 18248f512ceSopenharmony_ci 18348f512ceSopenharmony_ci if (dumpAll_ || dumpData_) { 18448f512ceSopenharmony_ci // before load data section 18548f512ceSopenharmony_ci SetHM(); 18648f512ceSopenharmony_ci DumpDataPortion(indent_); 18748f512ceSopenharmony_ci DumpSpeReport(); 18848f512ceSopenharmony_ci } 18948f512ceSopenharmony_ci 19048f512ceSopenharmony_ci if (dumpFeatures_ || dumpAll_) { 19148f512ceSopenharmony_ci DumpFeaturePortion(indent_); 19248f512ceSopenharmony_ci } 19348f512ceSopenharmony_ci 19448f512ceSopenharmony_ci return true; 19548f512ceSopenharmony_ci} 19648f512ceSopenharmony_ci 19748f512ceSopenharmony_cibool SubCommandDump::DumpElfFile() 19848f512ceSopenharmony_ci{ 19948f512ceSopenharmony_ci printf("dump elf: '%s'\n", elfFileName_.c_str()); 20048f512ceSopenharmony_ci auto elf = SymbolsFile::CreateSymbolsFile(elfFileName_); 20148f512ceSopenharmony_ci if (!elf->LoadSymbols(nullptr, "")) { 20248f512ceSopenharmony_ci printf("load elf failed.\n"); 20348f512ceSopenharmony_ci return false; 20448f512ceSopenharmony_ci } else { 20548f512ceSopenharmony_ci printf("load elf succeed.\n"); 20648f512ceSopenharmony_ci } 20748f512ceSopenharmony_ci return true; 20848f512ceSopenharmony_ci} 20948f512ceSopenharmony_ci#if defined(HAVE_PROTOBUF) && HAVE_PROTOBUF 21048f512ceSopenharmony_cibool SubCommandDump::DumpProtoFile() 21148f512ceSopenharmony_ci{ 21248f512ceSopenharmony_ci printf("dump protobuf file: '%s'\n", protobufDumpFileName_.c_str()); 21348f512ceSopenharmony_ci protobufInputFileReader_ = std::make_unique<ReportProtobufFileReader>(); 21448f512ceSopenharmony_ci if (!protobufInputFileReader_->Dump(protobufDumpFileName_)) { 21548f512ceSopenharmony_ci printf("load proto failed.\n"); 21648f512ceSopenharmony_ci return false; 21748f512ceSopenharmony_ci } 21848f512ceSopenharmony_ci return true; 21948f512ceSopenharmony_ci} 22048f512ceSopenharmony_ci#endif 22148f512ceSopenharmony_ci 22248f512ceSopenharmony_civoid SubCommandDump::PrintHeaderInfo(const int &indent) 22348f512ceSopenharmony_ci{ 22448f512ceSopenharmony_ci const perf_file_header &header = reader_->GetHeader(); 22548f512ceSopenharmony_ci // magic 22648f512ceSopenharmony_ci PRINT_INDENT(indent, "magic: "); 22748f512ceSopenharmony_ci for (size_t i = 0; i < sizeof(header.magic); ++i) { 22848f512ceSopenharmony_ci PRINT_INDENT(indent, "%c", header.magic[i]); 22948f512ceSopenharmony_ci } 23048f512ceSopenharmony_ci PRINT_INDENT(indent, "\n"); 23148f512ceSopenharmony_ci PRINT_INDENT(indent, "header_size: %" PRId64 "\n", header.size); 23248f512ceSopenharmony_ci if (header.size != sizeof(header)) { 23348f512ceSopenharmony_ci HLOGW("record file header size doesn't match"); 23448f512ceSopenharmony_ci } 23548f512ceSopenharmony_ci PRINT_INDENT(indent, "attr_size: %" PRId64 "\n", header.attrSize); 23648f512ceSopenharmony_ci if (header.attrSize != sizeof(perf_file_attr)) { 23748f512ceSopenharmony_ci HLOGW("attr size doesn't match"); 23848f512ceSopenharmony_ci } 23948f512ceSopenharmony_ci // attr 24048f512ceSopenharmony_ci PRINT_INDENT(indent, "attrs[file section]: offset %" PRId64 ", size %" PRId64 "\n", 24148f512ceSopenharmony_ci header.attrs.offset, header.attrs.size); 24248f512ceSopenharmony_ci // data 24348f512ceSopenharmony_ci PRINT_INDENT(indent, "data[file section]: offset %" PRId64 ", size %" PRId64 "\n", 24448f512ceSopenharmony_ci header.data.offset, header.data.size); 24548f512ceSopenharmony_ci PRINT_INDENT(indent, "event_types[file section]: offset %" PRId64 ", size %" PRId64 "\n", 24648f512ceSopenharmony_ci header.eventTypes.offset, header.eventTypes.size); 24748f512ceSopenharmony_ci // feature 24848f512ceSopenharmony_ci PRINT_INDENT(indent, 24948f512ceSopenharmony_ci "adds_features[]: 0x%" PRIX64 " 0x%" PRIX64 " 0x%" PRIX64 " 0x%" PRIX64 "\n", 25048f512ceSopenharmony_ci *(reinterpret_cast<const uint64_t *>(&header.features[0])), 25148f512ceSopenharmony_ci *(reinterpret_cast<const uint64_t *>(&header.features[8])), 25248f512ceSopenharmony_ci *(reinterpret_cast<const uint64_t *>(&header.features[16])), 25348f512ceSopenharmony_ci *(reinterpret_cast<const uint64_t *>(&header.features[24]))); 25448f512ceSopenharmony_ci} 25548f512ceSopenharmony_ci 25648f512ceSopenharmony_civoid SubCommandDump::DumpPrintFileHeader(int indent) 25748f512ceSopenharmony_ci{ 25848f512ceSopenharmony_ci // print header 25948f512ceSopenharmony_ci PrintHeaderInfo(indent); 26048f512ceSopenharmony_ci 26148f512ceSopenharmony_ci // print feature 26248f512ceSopenharmony_ci auto features = reader_->GetFeatures(); 26348f512ceSopenharmony_ci for (auto feature : features) { 26448f512ceSopenharmony_ci PRINT_INDENT(indent, "feature: %s\n", PerfFileSection::GetFeatureName(feature).c_str()); 26548f512ceSopenharmony_ci } 26648f512ceSopenharmony_ci 26748f512ceSopenharmony_ci // read here , because we need found symbols 26848f512ceSopenharmony_ci reader_->ReadFeatureSection(); 26948f512ceSopenharmony_ci 27048f512ceSopenharmony_ci SetDeviceArch(GetArchTypeFromUname(reader_->GetFeatureString(FEATURE::ARCH))); 27148f512ceSopenharmony_ci 27248f512ceSopenharmony_ci // found symbols in file 27348f512ceSopenharmony_ci for (auto &featureSection : reader_->GetFeatureSections()) { 27448f512ceSopenharmony_ci if (featureSection.get()->featureId_ == FEATURE::HIPERF_FILES_SYMBOL) { 27548f512ceSopenharmony_ci const PerfFileSectionSymbolsFiles *sectionSymbolsFiles = 27648f512ceSopenharmony_ci static_cast<const PerfFileSectionSymbolsFiles *>(featureSection.get()); 27748f512ceSopenharmony_ci vr_.UpdateFromPerfData(sectionSymbolsFiles->symbolFileStructs_); 27848f512ceSopenharmony_ci } else if (featureSection.get()->featureId_ == FEATURE::HIPERF_FILES_UNISTACK_TABLE) { 27948f512ceSopenharmony_ci const PerfFileSectionUniStackTable *sectionUniStackTable = 28048f512ceSopenharmony_ci static_cast<const PerfFileSectionUniStackTable *>(featureSection.get()); 28148f512ceSopenharmony_ci vr_.ImportUniqueStackNodes(sectionUniStackTable->uniStackTableInfos_); 28248f512ceSopenharmony_ci vr_.SetDedupStack(); 28348f512ceSopenharmony_ci } 28448f512ceSopenharmony_ci } 28548f512ceSopenharmony_ci} 28648f512ceSopenharmony_ci 28748f512ceSopenharmony_cistatic std::map<int, std::string> g_sampleTypeNames = { 28848f512ceSopenharmony_ci {PERF_SAMPLE_IP, "ip"}, 28948f512ceSopenharmony_ci {PERF_SAMPLE_TID, "tid"}, 29048f512ceSopenharmony_ci {PERF_SAMPLE_TIME, "time"}, 29148f512ceSopenharmony_ci {PERF_SAMPLE_ADDR, "addr"}, 29248f512ceSopenharmony_ci {PERF_SAMPLE_READ, "read"}, 29348f512ceSopenharmony_ci {PERF_SAMPLE_CALLCHAIN, "callchain"}, 29448f512ceSopenharmony_ci {PERF_SAMPLE_ID, "id"}, 29548f512ceSopenharmony_ci {PERF_SAMPLE_CPU, "cpu"}, 29648f512ceSopenharmony_ci {PERF_SAMPLE_PERIOD, "period"}, 29748f512ceSopenharmony_ci {PERF_SAMPLE_STREAM_ID, "stream_id"}, 29848f512ceSopenharmony_ci {PERF_SAMPLE_RAW, "raw"}, 29948f512ceSopenharmony_ci {PERF_SAMPLE_BRANCH_STACK, "stack"}, 30048f512ceSopenharmony_ci {PERF_SAMPLE_REGS_USER, "regs_user"}, 30148f512ceSopenharmony_ci {PERF_SAMPLE_STACK_USER, "stack_user"}, 30248f512ceSopenharmony_ci {PERF_SAMPLE_WEIGHT, "weight"}, 30348f512ceSopenharmony_ci {PERF_SAMPLE_DATA_SRC, "data_src"}, 30448f512ceSopenharmony_ci {PERF_SAMPLE_IDENTIFIER, "identifier"}, 30548f512ceSopenharmony_ci {PERF_SAMPLE_TRANSACTION, "transaction"}, 30648f512ceSopenharmony_ci {PERF_SAMPLE_REGS_INTR, "reg_intr"}, 30748f512ceSopenharmony_ci {PERF_SAMPLE_SERVER_PID, "server_pid"}, 30848f512ceSopenharmony_ci}; 30948f512ceSopenharmony_ci 31048f512ceSopenharmony_civoid SubCommandDump::DumpSampleType(uint64_t sampleType, int indent) 31148f512ceSopenharmony_ci{ 31248f512ceSopenharmony_ci std::string names; 31348f512ceSopenharmony_ci for (auto &pair : g_sampleTypeNames) { 31448f512ceSopenharmony_ci if (sampleType & pair.first) { 31548f512ceSopenharmony_ci if (!names.empty()) { 31648f512ceSopenharmony_ci names.append(","); 31748f512ceSopenharmony_ci } 31848f512ceSopenharmony_ci names.append(pair.second); 31948f512ceSopenharmony_ci } 32048f512ceSopenharmony_ci } 32148f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "sample_type names: %s\n", names.c_str()); 32248f512ceSopenharmony_ci} 32348f512ceSopenharmony_ci 32448f512ceSopenharmony_civoid SubCommandDump::DumpPrintEventAttr(const perf_event_attr &attr, int indent) 32548f512ceSopenharmony_ci{ 32648f512ceSopenharmony_ci PRINT_INDENT(indent, "event_attr: \n"); 32748f512ceSopenharmony_ci 32848f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "type %u, size %u, config %llu\n", attr.type, attr.size, attr.config); 32948f512ceSopenharmony_ci 33048f512ceSopenharmony_ci if (attr.freq != 0) { 33148f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "sample_freq %llu\n", attr.sample_freq); 33248f512ceSopenharmony_ci } else { 33348f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "sample_period %llu\n", attr.sample_period); 33448f512ceSopenharmony_ci } 33548f512ceSopenharmony_ci 33648f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "sample_type (0x%llx) \n", attr.sample_type); 33748f512ceSopenharmony_ci DumpSampleType(attr.sample_type, indent); 33848f512ceSopenharmony_ci 33948f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "read_format (0x%llx) \n", attr.read_format); 34048f512ceSopenharmony_ci 34148f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "disabled %u, inherit %u, pinned %u, exclusive %u\n", attr.disabled, 34248f512ceSopenharmony_ci attr.inherit, attr.pinned, attr.exclusive); 34348f512ceSopenharmony_ci 34448f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "exclude_user %u, exclude_kernel %u, exclude_hv %u, exclude_idle %u\n", 34548f512ceSopenharmony_ci attr.exclude_user, attr.exclude_kernel, attr.exclude_hv, attr.exclude_idle); 34648f512ceSopenharmony_ci 34748f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "mmap %u, mmap2 %u, comm %u, comm_exec %u, freq %u\n", attr.mmap, 34848f512ceSopenharmony_ci attr.mmap2, attr.comm, attr.comm_exec, attr.freq); 34948f512ceSopenharmony_ci 35048f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "inherit_stat %u, enable_on_exec %u, task %u, use_clockid %u\n", 35148f512ceSopenharmony_ci attr.inherit_stat, attr.enable_on_exec, attr.task, attr.use_clockid); 35248f512ceSopenharmony_ci 35348f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "watermark %u, precise_ip %u, mmap_data %u, clockid %d\n", attr.watermark, 35448f512ceSopenharmony_ci attr.precise_ip, attr.mmap_data, attr.clockid); 35548f512ceSopenharmony_ci 35648f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "sample_id_all %u, exclude_host %u, exclude_guest %u\n", attr.sample_id_all, 35748f512ceSopenharmony_ci attr.exclude_host, attr.exclude_guest); 35848f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "branch_sample_type 0x%llx\n", attr.branch_sample_type); 35948f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "exclude_callchain_kernel %u, exclude_callchain_user %u\n", 36048f512ceSopenharmony_ci attr.exclude_callchain_kernel, attr.exclude_callchain_user); 36148f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "sample_regs_user 0x%llx\n", attr.sample_regs_user); 36248f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "sample_stack_user 0x%x\n", attr.sample_stack_user); 36348f512ceSopenharmony_ci} 36448f512ceSopenharmony_ci 36548f512ceSopenharmony_civoid SubCommandDump::DumpAttrPortion(int indent) 36648f512ceSopenharmony_ci{ 36748f512ceSopenharmony_ci attrIds_ = reader_->GetAttrSection(); 36848f512ceSopenharmony_ci for (size_t i = 0; i < attrIds_.size(); ++i) { 36948f512ceSopenharmony_ci const AttrWithId &attr = attrIds_[i]; 37048f512ceSopenharmony_ci PRINT_INDENT(indent, "attr %zu:\n", i + 1); 37148f512ceSopenharmony_ci DumpPrintEventAttr(attr.attr, indent_ + 1); 37248f512ceSopenharmony_ci if (!attr.ids.empty()) { 37348f512ceSopenharmony_ci PRINT_INDENT(indent, " ids:"); 37448f512ceSopenharmony_ci for (const auto &id : attr.ids) { 37548f512ceSopenharmony_ci PRINT_INDENT(indent, " %" PRId64, id); 37648f512ceSopenharmony_ci } 37748f512ceSopenharmony_ci PRINT_INDENT(indent, "\n"); 37848f512ceSopenharmony_ci } 37948f512ceSopenharmony_ci } 38048f512ceSopenharmony_ci} 38148f512ceSopenharmony_ci 38248f512ceSopenharmony_civoid SubCommandDump::ExprotUserStack(const PerfRecordSample &recordSample) 38348f512ceSopenharmony_ci{ 38448f512ceSopenharmony_ci if (recordSample.data_.reg_nr > 0 and recordSample.data_.dyn_size > 0) { 38548f512ceSopenharmony_ci // <pid>_<tid>_user_regs_<time> 38648f512ceSopenharmony_ci std::string userRegs = 38748f512ceSopenharmony_ci StringPrintf("hiperf_%d_%d_user_regs_%zu.dump", recordSample.data_.pid, 38848f512ceSopenharmony_ci recordSample.data_.tid, exportSampleIndex_); 38948f512ceSopenharmony_ci std::string resolvedPath = CanonicalizeSpecPath(userRegs.c_str()); 39048f512ceSopenharmony_ci std::unique_ptr<FILE, decltype(&fclose)> fpUserRegs(fopen(resolvedPath.c_str(), "wb"), fclose); 39148f512ceSopenharmony_ci fwrite(recordSample.data_.user_regs, sizeof(u64), recordSample.data_.reg_nr, 39248f512ceSopenharmony_ci fpUserRegs.get()); 39348f512ceSopenharmony_ci 39448f512ceSopenharmony_ci std::string userData = 39548f512ceSopenharmony_ci StringPrintf("hiperf_%d_%d_user_data_%zu.dump", recordSample.data_.pid, 39648f512ceSopenharmony_ci recordSample.data_.tid, exportSampleIndex_); 39748f512ceSopenharmony_ci std::string resolvePath = CanonicalizeSpecPath(userData.c_str()); 39848f512ceSopenharmony_ci std::unique_ptr<FILE, decltype(&fclose)> fpUserData(fopen(resolvePath.c_str(), "wb"), fclose); 39948f512ceSopenharmony_ci fwrite(recordSample.data_.stack_data, sizeof(u8), recordSample.data_.dyn_size, 40048f512ceSopenharmony_ci fpUserData.get()); 40148f512ceSopenharmony_ci } 40248f512ceSopenharmony_ci} 40348f512ceSopenharmony_ci 40448f512ceSopenharmony_civoid SubCommandDump::ExprotUserData(std::unique_ptr<PerfEventRecord> &record) 40548f512ceSopenharmony_ci{ 40648f512ceSopenharmony_ci if (record->GetType() == PERF_RECORD_SAMPLE) { 40748f512ceSopenharmony_ci if (currectSampleIndex_++ != exportSampleIndex_) { 40848f512ceSopenharmony_ci return; 40948f512ceSopenharmony_ci } 41048f512ceSopenharmony_ci PerfRecordSample *recordSample = static_cast<PerfRecordSample *>(record.get()); 41148f512ceSopenharmony_ci ExprotUserStack(*recordSample); 41248f512ceSopenharmony_ci 41348f512ceSopenharmony_ci std::string userData = 41448f512ceSopenharmony_ci StringPrintf("hiperf_%d_%d_sample_record_%zu_%" PRIu64 ".dump", recordSample->data_.pid, 41548f512ceSopenharmony_ci recordSample->data_.tid, exportSampleIndex_, recordSample->data_.time); 41648f512ceSopenharmony_ci std::string resolvedPath = CanonicalizeSpecPath(userData.c_str()); 41748f512ceSopenharmony_ci std::unique_ptr<FILE, decltype(&fclose)> fpUserData(fopen(resolvedPath.c_str(), "wb"), fclose); 41848f512ceSopenharmony_ci static std::vector<u8> buf(RECORD_SIZE_LIMIT); 41948f512ceSopenharmony_ci CHECK_TRUE(!recordSample->GetBinary(buf), NO_RETVAL, 1, "export user sample data failed"); 42048f512ceSopenharmony_ci fwrite(buf.data(), sizeof(u8), recordSample->GetSize(), fpUserData.get()); 42148f512ceSopenharmony_ci 42248f512ceSopenharmony_ci HLOGD("export user data index %d time %llu", exportSampleIndex_, recordSample->data_.time); 42348f512ceSopenharmony_ci } 42448f512ceSopenharmony_ci} 42548f512ceSopenharmony_ci 42648f512ceSopenharmony_civoid SubCommandDump::DumpCallChain(int indent, std::unique_ptr<PerfRecordSample> &sample) 42748f512ceSopenharmony_ci{ 42848f512ceSopenharmony_ci PRINT_INDENT(indent, "\n callchain: %zu\n", sample->callFrames_.size()); 42948f512ceSopenharmony_ci if (sample->callFrames_.size() > 0) { 43048f512ceSopenharmony_ci indent += indent + 1; 43148f512ceSopenharmony_ci for (auto frameIt = sample->callFrames_.begin(); frameIt != sample->callFrames_.end(); 43248f512ceSopenharmony_ci frameIt++) { 43348f512ceSopenharmony_ci PRINT_INDENT(indent, "%02zd:%s\n", std::distance(frameIt, sample->callFrames_.end()), 43448f512ceSopenharmony_ci frameIt->ToSymbolString().c_str()); 43548f512ceSopenharmony_ci } 43648f512ceSopenharmony_ci } 43748f512ceSopenharmony_ci} 43848f512ceSopenharmony_ci 43948f512ceSopenharmony_civoid SubCommandDump::DumpDataPortion(int indent) 44048f512ceSopenharmony_ci{ 44148f512ceSopenharmony_ci int recordCount = 0; 44248f512ceSopenharmony_ci auto recordcCallback = [&](std::unique_ptr<PerfEventRecord> record) { 44348f512ceSopenharmony_ci CHECK_TRUE(record == nullptr, false, 0, ""); // return false in callback can stop the read process 44448f512ceSopenharmony_ci 44548f512ceSopenharmony_ci // for UT 44648f512ceSopenharmony_ci if (exportSampleIndex_ > 0) { 44748f512ceSopenharmony_ci ExprotUserData(record); 44848f512ceSopenharmony_ci } 44948f512ceSopenharmony_ci 45048f512ceSopenharmony_ci // tell process tree what happend for rebuild symbols 45148f512ceSopenharmony_ci vr_.UpdateFromRecord(*record); 45248f512ceSopenharmony_ci 45348f512ceSopenharmony_ci recordCount++; 45448f512ceSopenharmony_ci record->Dump(indent, outputFilename_, g_outputDump); 45548f512ceSopenharmony_ci 45648f512ceSopenharmony_ci if (record->GetType() == PERF_RECORD_SAMPLE) { 45748f512ceSopenharmony_ci std::unique_ptr<PerfRecordSample> sample( 45848f512ceSopenharmony_ci static_cast<PerfRecordSample *>(record.release())); 45948f512ceSopenharmony_ci DumpCallChain(indent, sample); 46048f512ceSopenharmony_ci } 46148f512ceSopenharmony_ci 46248f512ceSopenharmony_ci return true; 46348f512ceSopenharmony_ci }; 46448f512ceSopenharmony_ci 46548f512ceSopenharmony_ci reader_->ReadDataSection(recordcCallback); 46648f512ceSopenharmony_ci 46748f512ceSopenharmony_ci PRINT_INDENT(indent, "\n ======= there are %d records ======== \n", recordCount); 46848f512ceSopenharmony_ci} 46948f512ceSopenharmony_ci 47048f512ceSopenharmony_civoid SubCommandDump::PrintSymbolFile(const int &indent, const SymbolFileStruct &symbolFileStruct) 47148f512ceSopenharmony_ci{ 47248f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "filePath:%s\n", symbolFileStruct.filePath_.c_str()); 47348f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "symbolType:%u\n", symbolFileStruct.symbolType_); 47448f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "minExecAddr:0x%" PRIx64 "\n", symbolFileStruct.textExecVaddr_); 47548f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "minExecAddrFileOffset:0x%08" PRIx64 "\n", 47648f512ceSopenharmony_ci symbolFileStruct.textExecVaddrFileOffset_); 47748f512ceSopenharmony_ci if (!symbolFileStruct.buildId_.empty()) { 47848f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "buildId:'%s'\n", symbolFileStruct.buildId_.c_str()); 47948f512ceSopenharmony_ci } 48048f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "symbol number: %zu\n", symbolFileStruct.symbolStructs_.size()); 48148f512ceSopenharmony_ci int symbolid = 0; 48248f512ceSopenharmony_ci for (auto &symbolStruct : symbolFileStruct.symbolStructs_) { 48348f512ceSopenharmony_ci PRINT_INDENT(indent + 3, "%05d [0x%016" PRIx64 "@0x%08x] %s\n", symbolid, symbolStruct.vaddr_, 48448f512ceSopenharmony_ci symbolStruct.len_, symbolStruct.symbolName_.c_str()); 48548f512ceSopenharmony_ci symbolid++; 48648f512ceSopenharmony_ci } 48748f512ceSopenharmony_ci} 48848f512ceSopenharmony_ci 48948f512ceSopenharmony_civoid SubCommandDump::PrintFeatureEventdesc(int indent, 49048f512ceSopenharmony_ci const PerfFileSectionEventDesc §ionEventdesc) 49148f512ceSopenharmony_ci{ 49248f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "Event descriptions: %zu\n", sectionEventdesc.eventDesces_.size()); 49348f512ceSopenharmony_ci for (size_t i = 0; i < sectionEventdesc.eventDesces_.size(); i++) { 49448f512ceSopenharmony_ci const AttrWithId &desc = sectionEventdesc.eventDesces_[i]; 49548f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "event name[%zu]: %s ids: %s\n", i, desc.name.c_str(), 49648f512ceSopenharmony_ci VectorToString(desc.ids).c_str()); 49748f512ceSopenharmony_ci 49848f512ceSopenharmony_ci // attr is duplicated the attrs section 49948f512ceSopenharmony_ci } 50048f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "\n"); 50148f512ceSopenharmony_ci} 50248f512ceSopenharmony_ci 50348f512ceSopenharmony_civoid SubCommandDump::DumpFeaturePortion(int indent) 50448f512ceSopenharmony_ci{ 50548f512ceSopenharmony_ci PRINT_INDENT(indent, "\n ==== features ====\n"); 50648f512ceSopenharmony_ci auto features = reader_->GetFeatures(); 50748f512ceSopenharmony_ci for (auto feature : features) { 50848f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "feature %d:%s\n", feature, 50948f512ceSopenharmony_ci PerfFileSection::GetFeatureName(feature).c_str()); 51048f512ceSopenharmony_ci } 51148f512ceSopenharmony_ci 51248f512ceSopenharmony_ci const auto &featureSections = reader_->GetFeatureSections(); 51348f512ceSopenharmony_ci HLOGV("featureSections: %zu ", featureSections.size()); 51448f512ceSopenharmony_ci 51548f512ceSopenharmony_ci PRINT_INDENT(indent, "\n ==== feature sections ====\n"); 51648f512ceSopenharmony_ci 51748f512ceSopenharmony_ci for (auto &featureSection : featureSections) { 51848f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "feature %d:%s content: \n", featureSection.get()->featureId_, 51948f512ceSopenharmony_ci PerfFileSection::GetFeatureName(featureSection.get()->featureId_).c_str()); 52048f512ceSopenharmony_ci if (reader_->IsFeatrureStringSection(featureSection.get()->featureId_)) { 52148f512ceSopenharmony_ci const PerfFileSectionString *sectionString = 52248f512ceSopenharmony_ci static_cast<const PerfFileSectionString *>(featureSection.get()); 52348f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "%s\n", sectionString->ToString().c_str()); 52448f512ceSopenharmony_ci continue; 52548f512ceSopenharmony_ci } else if (featureSection.get()->featureId_ == FEATURE::EVENT_DESC) { 52648f512ceSopenharmony_ci PrintFeatureEventdesc( 52748f512ceSopenharmony_ci indent, *static_cast<const PerfFileSectionEventDesc *>(featureSection.get())); 52848f512ceSopenharmony_ci continue; 52948f512ceSopenharmony_ci } else if (featureSection.get()->featureId_ == FEATURE::HIPERF_FILES_SYMBOL) { 53048f512ceSopenharmony_ci const PerfFileSectionSymbolsFiles *sectionSymbolsFiles = 53148f512ceSopenharmony_ci static_cast<const PerfFileSectionSymbolsFiles *>(featureSection.get()); 53248f512ceSopenharmony_ci if (sectionSymbolsFiles != nullptr) { 53348f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "SymbolFiles:%zu\n", 53448f512ceSopenharmony_ci sectionSymbolsFiles->symbolFileStructs_.size()); 53548f512ceSopenharmony_ci 53648f512ceSopenharmony_ci int fileid = 0; 53748f512ceSopenharmony_ci for (auto &symbolFileStruct : sectionSymbolsFiles->symbolFileStructs_) { 53848f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "\n"); 53948f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "fileid:%d\n", fileid); 54048f512ceSopenharmony_ci fileid++; 54148f512ceSopenharmony_ci // symbol file info 54248f512ceSopenharmony_ci PrintSymbolFile(indent, symbolFileStruct); 54348f512ceSopenharmony_ci } 54448f512ceSopenharmony_ci } else { 54548f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "get SymbolFiles failed\n"); 54648f512ceSopenharmony_ci } 54748f512ceSopenharmony_ci continue; 54848f512ceSopenharmony_ci } else if (featureSection.get()->featureId_ == FEATURE::HIPERF_FILES_UNISTACK_TABLE) { 54948f512ceSopenharmony_ci const PerfFileSectionUniStackTable *sectioniStackTable = 55048f512ceSopenharmony_ci static_cast<PerfFileSectionUniStackTable *>(const_cast<PerfFileSection *>(featureSection.get())); 55148f512ceSopenharmony_ci if (sectioniStackTable != nullptr) { 55248f512ceSopenharmony_ci DumpUniqueStackTableNode(indent + 1, *sectioniStackTable); 55348f512ceSopenharmony_ci } else { 55448f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "get StackTable failed\n"); 55548f512ceSopenharmony_ci } 55648f512ceSopenharmony_ci continue; 55748f512ceSopenharmony_ci } else { 55848f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "not support dump this feature(%d).\n", featureSection.get()->featureId_); 55948f512ceSopenharmony_ci } 56048f512ceSopenharmony_ci } 56148f512ceSopenharmony_ci} 56248f512ceSopenharmony_ci 56348f512ceSopenharmony_civoid SubCommandDump::DumpUniqueStackTableNode(int indent, const PerfFileSectionUniStackTable &uniStackTable) 56448f512ceSopenharmony_ci{ 56548f512ceSopenharmony_ci int tableid = 0; 56648f512ceSopenharmony_ci PRINT_INDENT(indent + 1, "TableNums: %zu\n\n", uniStackTable.uniStackTableInfos_.size()); 56748f512ceSopenharmony_ci for (const auto& uniStackTableInfo : uniStackTable.uniStackTableInfos_) { 56848f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "tableid: %d\n", tableid); 56948f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "pid: %" PRIu32 "\n", uniStackTableInfo.pid); 57048f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "tableSize: %" PRIu32 "\n", uniStackTableInfo.tableSize); 57148f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "numNodes: %" PRIu32 "\n", uniStackTableInfo.numNodes); 57248f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "%-7s %-7s %-8s\n", "no", "index", "node"); 57348f512ceSopenharmony_ci for (size_t i = 0; i < uniStackTableInfo.nodes.size(); i++) { 57448f512ceSopenharmony_ci UniStackNode node = uniStackTableInfo.nodes[i]; 57548f512ceSopenharmony_ci PRINT_INDENT(indent + INDENT_TWO, "%-7zu %-7" PRIu32 " 0x%-8" PRIx64 "\n", i, node.index, node.node.value); 57648f512ceSopenharmony_ci } 57748f512ceSopenharmony_ci tableid++; 57848f512ceSopenharmony_ci } 57948f512ceSopenharmony_ci} 58048f512ceSopenharmony_ci 58148f512ceSopenharmony_cibool SubCommandDump::RegisterSubCommandDump() 58248f512ceSopenharmony_ci{ 58348f512ceSopenharmony_ci return SubCommand::RegisterSubCommand("dump", std::make_unique<SubCommandDump>()); 58448f512ceSopenharmony_ci} 58548f512ceSopenharmony_ci 58648f512ceSopenharmony_civoid SubCommandDump::SetHM() 58748f512ceSopenharmony_ci{ 58848f512ceSopenharmony_ci std::string os = reader_->GetFeatureString(FEATURE::OSRELEASE); 58948f512ceSopenharmony_ci isHM_ = os.find(HMKERNEL) != std::string::npos; 59048f512ceSopenharmony_ci vr_.SetHM(isHM_); 59148f512ceSopenharmony_ci HLOGD("Set isHM_: %d", isHM_); 59248f512ceSopenharmony_ci if (isHM_) { 59348f512ceSopenharmony_ci pid_t devhost = -1; 59448f512ceSopenharmony_ci std::string str = reader_->GetFeatureString(FEATURE::HIPERF_HM_DEVHOST); 59548f512ceSopenharmony_ci if (str != EMPTY_STRING) { 59648f512ceSopenharmony_ci devhost = std::stoll(str); 59748f512ceSopenharmony_ci } 59848f512ceSopenharmony_ci vr_.SetDevhostPid(devhost); 59948f512ceSopenharmony_ci } 60048f512ceSopenharmony_ci} 60148f512ceSopenharmony_ci 60248f512ceSopenharmony_civoid SubCommandDump::DumpSpeReport() 60348f512ceSopenharmony_ci{ 60448f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 60548f512ceSopenharmony_ci std::string cmdline = reader_->GetFeatureString(FEATURE::CMDLINE); 60648f512ceSopenharmony_ci if (cmdline.find("-e arm_spe_0") != std::string::npos) { 60748f512ceSopenharmony_ci HLOGD("dump spe report data"); 60848f512ceSopenharmony_ci UpdateHeating(); 60948f512ceSopenharmony_ci DumpSpeReportData(indent_, g_outputDump); 61048f512ceSopenharmony_ci } 61148f512ceSopenharmony_ci#endif 61248f512ceSopenharmony_ci} 61348f512ceSopenharmony_ci 61448f512ceSopenharmony_ci} // namespace HiPerf 61548f512ceSopenharmony_ci} // namespace Developtools 61648f512ceSopenharmony_ci} // namespace OHOS 617