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#include "perf_file_reader.h" 1648f512ceSopenharmony_ci 1748f512ceSopenharmony_ci#include <bitset> 1848f512ceSopenharmony_ci#include <cinttypes> 1948f512ceSopenharmony_ci#include <cstdlib> 2048f512ceSopenharmony_ci#include <memory> 2148f512ceSopenharmony_ci 2248f512ceSopenharmony_ci#include <sys/stat.h> 2348f512ceSopenharmony_ci#include <unistd.h> 2448f512ceSopenharmony_ci 2548f512ceSopenharmony_ci#include "hiperf_hilog.h" 2648f512ceSopenharmony_ci#include "utilities.h" 2748f512ceSopenharmony_ci 2848f512ceSopenharmony_ciusing namespace std::chrono; 2948f512ceSopenharmony_cinamespace OHOS { 3048f512ceSopenharmony_cinamespace Developtools { 3148f512ceSopenharmony_cinamespace HiPerf { 3248f512ceSopenharmony_ciconst int FETURE_MAX = 256; 3348f512ceSopenharmony_ciconst int SIZE_FETURE_COUNT = 8; 3448f512ceSopenharmony_ci 3548f512ceSopenharmony_cistd::unique_ptr<PerfFileReader> PerfFileReader::Instance(const std::string &fileName) 3648f512ceSopenharmony_ci{ 3748f512ceSopenharmony_ci std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); 3848f512ceSopenharmony_ci FILE *fp = fopen(resolvedPath.c_str(), "rb"); 3948f512ceSopenharmony_ci if (fp == nullptr) { 4048f512ceSopenharmony_ci HLOGE("fail to open file %s", fileName.c_str()); 4148f512ceSopenharmony_ci return nullptr; 4248f512ceSopenharmony_ci } 4348f512ceSopenharmony_ci 4448f512ceSopenharmony_ci std::unique_ptr<PerfFileReader> reader = std::make_unique<PerfFileReader>(fileName, fp); 4548f512ceSopenharmony_ci if (!reader->ReadFileHeader()) { 4648f512ceSopenharmony_ci // Fail to read header, maybe its compressed 4748f512ceSopenharmony_ci if (reader->IsGzipFile()) { 4848f512ceSopenharmony_ci fclose(fp); 4948f512ceSopenharmony_ci reader->fp_ = nullptr; 5048f512ceSopenharmony_ci 5148f512ceSopenharmony_ci CHECK_TRUE(!UncompressFile(fileName, ".perf.data"), nullptr, 1, 5248f512ceSopenharmony_ci "Fail to UncompressFile(%s)", fileName.c_str()); 5348f512ceSopenharmony_ci 5448f512ceSopenharmony_ci // open the uncompressed hidden file .perf.data 5548f512ceSopenharmony_ci FILE *fp2 = fopen(".perf.data", "rb"); 5648f512ceSopenharmony_ci if (fp2 == nullptr) { 5748f512ceSopenharmony_ci HLOGE("fail to open uncompressed file .perf.data"); 5848f512ceSopenharmony_ci return nullptr; 5948f512ceSopenharmony_ci } 6048f512ceSopenharmony_ci 6148f512ceSopenharmony_ci reader->fp_ = fp2; 6248f512ceSopenharmony_ci reader->compressData_ = true; 6348f512ceSopenharmony_ci 6448f512ceSopenharmony_ci if (!reader->ReadFileHeader()) { 6548f512ceSopenharmony_ci HLOGE("fail to read header of file .perf.data"); 6648f512ceSopenharmony_ci return nullptr; 6748f512ceSopenharmony_ci } 6848f512ceSopenharmony_ci goto end; 6948f512ceSopenharmony_ci } 7048f512ceSopenharmony_ci return nullptr; 7148f512ceSopenharmony_ci } 7248f512ceSopenharmony_ciend: 7348f512ceSopenharmony_ci CHECK_TRUE(!reader->ReadAttrSection(), nullptr, 0, ""); 7448f512ceSopenharmony_ci return reader; 7548f512ceSopenharmony_ci} 7648f512ceSopenharmony_ci 7748f512ceSopenharmony_ciPerfFileReader::PerfFileReader(const std::string &fileName, FILE *fp) : fp_(fp), fileName_(fileName) 7848f512ceSopenharmony_ci{ 7948f512ceSopenharmony_ci featureSectionOffset_ = 0; 8048f512ceSopenharmony_ci struct stat fileStat; 8148f512ceSopenharmony_ci if (fp != nullptr) { 8248f512ceSopenharmony_ci if (fstat(fileno(fp), &fileStat) != -1 and fileStat.st_size > 0) { 8348f512ceSopenharmony_ci fileSize_ = fileStat.st_size; 8448f512ceSopenharmony_ci } 8548f512ceSopenharmony_ci } 8648f512ceSopenharmony_ci} 8748f512ceSopenharmony_ci 8848f512ceSopenharmony_ciPerfFileReader::~PerfFileReader() 8948f512ceSopenharmony_ci{ 9048f512ceSopenharmony_ci // if file was not closed properly 9148f512ceSopenharmony_ci if (fp_ != nullptr) { 9248f512ceSopenharmony_ci fclose(fp_); 9348f512ceSopenharmony_ci fp_ = nullptr; 9448f512ceSopenharmony_ci } 9548f512ceSopenharmony_ci 9648f512ceSopenharmony_ci // remove the uncompressed .perf.data 9748f512ceSopenharmony_ci if (compressData_) { 9848f512ceSopenharmony_ci if (remove(".perf.data") != 0) { 9948f512ceSopenharmony_ci HLOGE("Fail to remove uncompressed file .perf.data"); 10048f512ceSopenharmony_ci perror("Fail to remove temp file"); 10148f512ceSopenharmony_ci } 10248f512ceSopenharmony_ci } 10348f512ceSopenharmony_ci} 10448f512ceSopenharmony_ci 10548f512ceSopenharmony_cibool PerfFileReader::IsValidDataFile() 10648f512ceSopenharmony_ci{ 10748f512ceSopenharmony_ci return (memcmp(header_.magic, PERF_MAGIC, sizeof(header_.magic)) == 0); 10848f512ceSopenharmony_ci} 10948f512ceSopenharmony_ci 11048f512ceSopenharmony_cibool PerfFileReader::IsGzipFile() 11148f512ceSopenharmony_ci{ 11248f512ceSopenharmony_ci return header_.magic[0] == '\x1f' and header_.magic[1] == '\x8b'; 11348f512ceSopenharmony_ci} 11448f512ceSopenharmony_ci 11548f512ceSopenharmony_cibool PerfFileReader::ReadFileHeader() 11648f512ceSopenharmony_ci{ 11748f512ceSopenharmony_ci if (Read(&header_, sizeof(header_))) { 11848f512ceSopenharmony_ci dataSectionSize_ = header_.data.size; 11948f512ceSopenharmony_ci if (IsValidDataFile()) { 12048f512ceSopenharmony_ci featureSectionOffset_ = header_.data.offset + header_.data.size; 12148f512ceSopenharmony_ci for (int i = 0; i < FETURE_MAX / SIZE_FETURE_COUNT; i++) { 12248f512ceSopenharmony_ci std::bitset<SIZE_FETURE_COUNT> features(header_.features[i]); 12348f512ceSopenharmony_ci for (int j = 0; j < SIZE_FETURE_COUNT; j++) { 12448f512ceSopenharmony_ci if (features.test(j)) { 12548f512ceSopenharmony_ci features_.emplace_back((FEATURE)(((uint64_t)i) * SIZE_FETURE_COUNT + j)); 12648f512ceSopenharmony_ci } 12748f512ceSopenharmony_ci } 12848f512ceSopenharmony_ci } 12948f512ceSopenharmony_ci return true; 13048f512ceSopenharmony_ci } 13148f512ceSopenharmony_ci } 13248f512ceSopenharmony_ci return false; 13348f512ceSopenharmony_ci} 13448f512ceSopenharmony_ci 13548f512ceSopenharmony_cibool PerfFileReader::ReadAttrSection() 13648f512ceSopenharmony_ci{ 13748f512ceSopenharmony_ci if (header_.attrSize != sizeof(perf_file_attr)) { 13848f512ceSopenharmony_ci // 4.19 and 5.1 use diff size , 128 vs 136 13948f512ceSopenharmony_ci HLOGW("attr size %" PRId64 " doesn't match expected size %zu", header_.attrSize, 14048f512ceSopenharmony_ci sizeof(perf_file_attr)); 14148f512ceSopenharmony_ci } 14248f512ceSopenharmony_ci CHECK_TRUE(header_.attrSize == 0, false, 0, ""); 14348f512ceSopenharmony_ci int attrCount = header_.attrs.size / header_.attrSize; 14448f512ceSopenharmony_ci CHECK_TRUE(attrCount == 0, false, 1, "no attr in file"); 14548f512ceSopenharmony_ci if (fseek(fp_, header_.attrs.offset, SEEK_SET) != 0) { 14648f512ceSopenharmony_ci HLOGE("fseek() failed"); 14748f512ceSopenharmony_ci return false; 14848f512ceSopenharmony_ci } 14948f512ceSopenharmony_ci for (int i = 0; i < attrCount; ++i) { 15048f512ceSopenharmony_ci std::vector<char> buf(header_.attrSize); 15148f512ceSopenharmony_ci CHECK_TRUE(!Read(buf.data(), buf.size()), false, 0, ""); 15248f512ceSopenharmony_ci // size of perf_event_attr change between different linux kernel versions. 15348f512ceSopenharmony_ci // can not memcpy to perf_file_attr as a whole 15448f512ceSopenharmony_ci perf_file_attr attr {}; 15548f512ceSopenharmony_ci size_t attrSize = header_.attrSize - sizeof(attr.ids); 15648f512ceSopenharmony_ci 15748f512ceSopenharmony_ci // If the size is smaller, you can use a pointer to point directly. 15848f512ceSopenharmony_ci // Our UAPI is 4.19. is less than 5.1 15948f512ceSopenharmony_ci if (header_.attrSize < sizeof(perf_event_attr)) { 16048f512ceSopenharmony_ci HLOGE("size not match, ptr of perf_event_attr maybe overfollow %zu vs %zu", 16148f512ceSopenharmony_ci sizeof(perf_event_attr), attrSize); 16248f512ceSopenharmony_ci } 16348f512ceSopenharmony_ci 16448f512ceSopenharmony_ci attr.attr = *(reinterpret_cast<perf_event_attr *>(&buf[0])); 16548f512ceSopenharmony_ci attr.ids = *(reinterpret_cast<perf_file_section *>(&buf[attrSize])); 16648f512ceSopenharmony_ci vecAttr_.push_back(attr); 16748f512ceSopenharmony_ci } 16848f512ceSopenharmony_ci 16948f512ceSopenharmony_ci // read ids for attr 17048f512ceSopenharmony_ci for (size_t i = 0; i < vecAttr_.size(); ++i) { 17148f512ceSopenharmony_ci std::vector<uint64_t> ids; 17248f512ceSopenharmony_ci CHECK_TRUE(!ReadIdsForAttr(vecAttr_[i], &ids), false, 0, ""); 17348f512ceSopenharmony_ci vecAttrIds_.push_back(ids); 17448f512ceSopenharmony_ci 17548f512ceSopenharmony_ci // map ids to attr index 17648f512ceSopenharmony_ci for (auto id : ids) { 17748f512ceSopenharmony_ci mapId2Attr_[id] = i; 17848f512ceSopenharmony_ci } 17948f512ceSopenharmony_ci } 18048f512ceSopenharmony_ci 18148f512ceSopenharmony_ci return true; 18248f512ceSopenharmony_ci} 18348f512ceSopenharmony_ci 18448f512ceSopenharmony_cibool PerfFileReader::ReadIdsForAttr(const perf_file_attr &attr, std::vector<uint64_t> *ids) 18548f512ceSopenharmony_ci{ 18648f512ceSopenharmony_ci if (attr.ids.size > 0) { 18748f512ceSopenharmony_ci size_t count = attr.ids.size / sizeof(uint64_t); 18848f512ceSopenharmony_ci if (fseek(fp_, attr.ids.offset, SEEK_SET) != 0) { 18948f512ceSopenharmony_ci HLOGE("fseek() failed"); 19048f512ceSopenharmony_ci return false; 19148f512ceSopenharmony_ci } 19248f512ceSopenharmony_ci CHECK_TRUE(ids == nullptr, false, 0, ""); 19348f512ceSopenharmony_ci ids->resize(count); 19448f512ceSopenharmony_ci CHECK_TRUE(!Read(ids->data(), attr.ids.size), false, 0, ""); 19548f512ceSopenharmony_ci } 19648f512ceSopenharmony_ci return true; 19748f512ceSopenharmony_ci} 19848f512ceSopenharmony_ci 19948f512ceSopenharmony_cistd::vector<AttrWithId> PerfFileReader::GetAttrSection() const 20048f512ceSopenharmony_ci{ 20148f512ceSopenharmony_ci std::vector<AttrWithId> result(vecAttr_.size()); 20248f512ceSopenharmony_ci 20348f512ceSopenharmony_ci for (size_t i = 0; i < vecAttr_.size(); ++i) { 20448f512ceSopenharmony_ci result[i].attr = vecAttr_[i].attr; 20548f512ceSopenharmony_ci result[i].ids = vecAttrIds_[i]; 20648f512ceSopenharmony_ci } 20748f512ceSopenharmony_ci return result; 20848f512ceSopenharmony_ci} 20948f512ceSopenharmony_ci 21048f512ceSopenharmony_cibool PerfFileReader::ReadDataSection(ProcessRecordCB &callback) 21148f512ceSopenharmony_ci{ 21248f512ceSopenharmony_ci if (fseek(fp_, header_.data.offset, SEEK_SET) != 0) { 21348f512ceSopenharmony_ci HLOGE("fseek() failed"); 21448f512ceSopenharmony_ci return false; 21548f512ceSopenharmony_ci } 21648f512ceSopenharmony_ci 21748f512ceSopenharmony_ci HLOGD("dataSection_ at offset %" PRId64 " + %" PRId64 "", header_.data.offset, 21848f512ceSopenharmony_ci header_.data.size); 21948f512ceSopenharmony_ci 22048f512ceSopenharmony_ci CHECK_TRUE(!ReadRecord(callback), false, LOG_TYPE_PRINTF, "some record format is error!\n"); 22148f512ceSopenharmony_ci 22248f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 22348f512ceSopenharmony_ci printf("readRecordTime: %" PRId64 " ms\n", 22448f512ceSopenharmony_ci duration_cast<milliseconds>(readRecordTime_).count()); 22548f512ceSopenharmony_ci printf("readCallbackTime: %" PRId64 " ms\n", 22648f512ceSopenharmony_ci duration_cast<milliseconds>(readCallbackTime_).count()); 22748f512ceSopenharmony_ci#endif 22848f512ceSopenharmony_ci return dataSectionSize_ == 0; 22948f512ceSopenharmony_ci} 23048f512ceSopenharmony_ci 23148f512ceSopenharmony_ciconst perf_event_attr *PerfFileReader::GetDefaultAttr() 23248f512ceSopenharmony_ci{ 23348f512ceSopenharmony_ci CHECK_TRUE(vecAttr_.empty(), nullptr, 0, ""); 23448f512ceSopenharmony_ci return &(vecAttr_[0].attr); 23548f512ceSopenharmony_ci} 23648f512ceSopenharmony_ci 23748f512ceSopenharmony_cibool PerfFileReader::ReadRecord(ProcessRecordCB &callback) 23848f512ceSopenharmony_ci{ 23948f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 24048f512ceSopenharmony_ci const auto startReadTime = steady_clock::now(); 24148f512ceSopenharmony_ci#endif 24248f512ceSopenharmony_ci // record size can not exceed 64K 24348f512ceSopenharmony_ci HIPERF_BUF_ALIGN static uint8_t buf[RECORD_SIZE_LIMIT_SPE]; 24448f512ceSopenharmony_ci // diff with reader 24548f512ceSopenharmony_ci uint64_t remainingSize = header_.data.size; 24648f512ceSopenharmony_ci size_t recordNumber = 0; 24748f512ceSopenharmony_ci const perf_event_attr *attr = GetDefaultAttr(); 24848f512ceSopenharmony_ci CHECK_TRUE(attr == nullptr, false, 1, "attr is null"); 24948f512ceSopenharmony_ci while (remainingSize > 0) { 25048f512ceSopenharmony_ci if (remainingSize < sizeof(perf_event_header)) { 25148f512ceSopenharmony_ci HLOGW("not enough sizeof perf_event_header"); 25248f512ceSopenharmony_ci return false; 25348f512ceSopenharmony_ci } else if (!Read(buf, sizeof(perf_event_header))) { 25448f512ceSopenharmony_ci HLOGW("read perf_event_header failed."); 25548f512ceSopenharmony_ci return false; 25648f512ceSopenharmony_ci } else { 25748f512ceSopenharmony_ci perf_event_header *header = reinterpret_cast<perf_event_header *>(buf); 25848f512ceSopenharmony_ci if (header == nullptr) { 25948f512ceSopenharmony_ci HLOGE("read record header is null"); 26048f512ceSopenharmony_ci return false; 26148f512ceSopenharmony_ci } else if (header->size > RECORD_SIZE_LIMIT) { 26248f512ceSopenharmony_ci HLOGE("read record header size error %hu", header->size); 26348f512ceSopenharmony_ci return false; 26448f512ceSopenharmony_ci } 26548f512ceSopenharmony_ci if (remainingSize >= header->size) { 26648f512ceSopenharmony_ci size_t headerSize = sizeof(perf_event_header); 26748f512ceSopenharmony_ci if (Read(buf + headerSize, header->size - headerSize)) { 26848f512ceSopenharmony_ci size_t speSize = 0; 26948f512ceSopenharmony_ci if (header->type == PERF_RECORD_AUXTRACE) { 27048f512ceSopenharmony_ci struct PerfRecordAuxtraceData *auxtrace = reinterpret_cast<struct PerfRecordAuxtraceData *> 27148f512ceSopenharmony_ci (header + 1); 27248f512ceSopenharmony_ci speSize = auxtrace->size; 27348f512ceSopenharmony_ci if (speSize > 0) { 27448f512ceSopenharmony_ci Read(buf + header->size, auxtrace->size); 27548f512ceSopenharmony_ci } 27648f512ceSopenharmony_ci } 27748f512ceSopenharmony_ci uint8_t *data = buf; 27848f512ceSopenharmony_ci std::unique_ptr<PerfEventRecord> record = GetPerfEventRecord( 27948f512ceSopenharmony_ci static_cast<perf_event_type>(header->type), data, *attr); 28048f512ceSopenharmony_ci // unknown record , break the process 28148f512ceSopenharmony_ci if (!record) { 28248f512ceSopenharmony_ci return false; 28348f512ceSopenharmony_ci } else { 28448f512ceSopenharmony_ci HLOGV("record type %u", record->GetType()); 28548f512ceSopenharmony_ci } 28648f512ceSopenharmony_ci remainingSize = remainingSize - header->size - speSize; 28748f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 28848f512ceSopenharmony_ci const auto startCallbackTime = steady_clock::now(); 28948f512ceSopenharmony_ci#endif 29048f512ceSopenharmony_ci // call callback to process, then destroy record 29148f512ceSopenharmony_ci callback(std::move(record)); 29248f512ceSopenharmony_ci recordNumber++; 29348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 29448f512ceSopenharmony_ci readCallbackTime_ += 29548f512ceSopenharmony_ci duration_cast<microseconds>(steady_clock::now() - startCallbackTime); 29648f512ceSopenharmony_ci#endif 29748f512ceSopenharmony_ci } else { 29848f512ceSopenharmony_ci HLOGE("read record data size failed %zu", header->size - headerSize); 29948f512ceSopenharmony_ci return false; 30048f512ceSopenharmony_ci } 30148f512ceSopenharmony_ci } else { 30248f512ceSopenharmony_ci HLOGE("not enough header->size."); 30348f512ceSopenharmony_ci return false; 30448f512ceSopenharmony_ci } 30548f512ceSopenharmony_ci } 30648f512ceSopenharmony_ci } 30748f512ceSopenharmony_ci HLOGD("read back %zu records", recordNumber); 30848f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 30948f512ceSopenharmony_ci readRecordTime_ += duration_cast<microseconds>(steady_clock::now() - startReadTime); 31048f512ceSopenharmony_ci#endif 31148f512ceSopenharmony_ci return true; 31248f512ceSopenharmony_ci} 31348f512ceSopenharmony_ci 31448f512ceSopenharmony_cibool PerfFileReader::Read(void *buf, size_t len) 31548f512ceSopenharmony_ci{ 31648f512ceSopenharmony_ci if (buf == nullptr || len == 0) { 31748f512ceSopenharmony_ci HLOG_ASSERT(buf != nullptr); 31848f512ceSopenharmony_ci HLOG_ASSERT(len > 0); 31948f512ceSopenharmony_ci return false; 32048f512ceSopenharmony_ci } 32148f512ceSopenharmony_ci 32248f512ceSopenharmony_ci if (fread(buf, len, 1, fp_) != 1) { 32348f512ceSopenharmony_ci printf("failed to read file: %d", errno); 32448f512ceSopenharmony_ci return false; 32548f512ceSopenharmony_ci } 32648f512ceSopenharmony_ci return true; 32748f512ceSopenharmony_ci} 32848f512ceSopenharmony_ci 32948f512ceSopenharmony_ciconst perf_file_header &PerfFileReader::GetHeader() const 33048f512ceSopenharmony_ci{ 33148f512ceSopenharmony_ci return header_; 33248f512ceSopenharmony_ci} 33348f512ceSopenharmony_ci 33448f512ceSopenharmony_cibool PerfFileReader::Read(char *buf, uint64_t offset, size_t len) 33548f512ceSopenharmony_ci{ 33648f512ceSopenharmony_ci if (buf == nullptr || len == 0) { 33748f512ceSopenharmony_ci HLOG_ASSERT(buf != nullptr); 33848f512ceSopenharmony_ci HLOG_ASSERT(len > 0); 33948f512ceSopenharmony_ci return false; 34048f512ceSopenharmony_ci } 34148f512ceSopenharmony_ci if (fseek(fp_, offset, SEEK_SET) != 0) { 34248f512ceSopenharmony_ci HLOGE("fseek() failed"); 34348f512ceSopenharmony_ci return false; 34448f512ceSopenharmony_ci } 34548f512ceSopenharmony_ci 34648f512ceSopenharmony_ci CHECK_TRUE(fread(buf, len, 1, fp_) != 1, false, LOG_TYPE_PRINTF, "failed to read file: %d", errno); 34748f512ceSopenharmony_ci HLOGM("offset %" PRIx64 " len %zu buf %x %x %x %x", offset, len, buf[0], buf[1], buf[2], 34848f512ceSopenharmony_ci buf[3]); 34948f512ceSopenharmony_ci return true; 35048f512ceSopenharmony_ci} 35148f512ceSopenharmony_ciconst std::vector<FEATURE> &PerfFileReader::GetFeatures() const 35248f512ceSopenharmony_ci{ 35348f512ceSopenharmony_ci return features_; 35448f512ceSopenharmony_ci} 35548f512ceSopenharmony_ci 35648f512ceSopenharmony_ciconst std::vector<std::unique_ptr<PerfFileSection>> &PerfFileReader::GetFeatureSections() const 35748f512ceSopenharmony_ci{ 35848f512ceSopenharmony_ci return perfFileSections_; 35948f512ceSopenharmony_ci} 36048f512ceSopenharmony_ci 36148f512ceSopenharmony_ciconst std::string PerfFileReader::GetFeatureString(const FEATURE feature) const 36248f512ceSopenharmony_ci{ 36348f512ceSopenharmony_ci std::string featureName = PerfFileSection::GetFeatureName(feature); 36448f512ceSopenharmony_ci HLOGV("GetFeatureSection %s", featureName.c_str()); 36548f512ceSopenharmony_ci if (!IsFeatrureStringSection(feature)) { 36648f512ceSopenharmony_ci HLOGV("not a string feature: %s", featureName.c_str()); 36748f512ceSopenharmony_ci } else { 36848f512ceSopenharmony_ci const PerfFileSection *featureSection = GetFeatureSection(feature); 36948f512ceSopenharmony_ci if (featureSection != nullptr) { 37048f512ceSopenharmony_ci const PerfFileSectionString *sectionString = 37148f512ceSopenharmony_ci static_cast<const PerfFileSectionString *>(featureSection); 37248f512ceSopenharmony_ci return sectionString->ToString(); 37348f512ceSopenharmony_ci } else { 37448f512ceSopenharmony_ci HLOGV("have not found: %s", featureName.c_str()); 37548f512ceSopenharmony_ci } 37648f512ceSopenharmony_ci } 37748f512ceSopenharmony_ci return EMPTY_STRING; 37848f512ceSopenharmony_ci} 37948f512ceSopenharmony_ci 38048f512ceSopenharmony_ciconst PerfFileSection *PerfFileReader::GetFeatureSection(FEATURE feature) const 38148f512ceSopenharmony_ci{ 38248f512ceSopenharmony_ci for (auto const &it : perfFileSections_) { 38348f512ceSopenharmony_ci HLOGV("perfFileSections"); 38448f512ceSopenharmony_ci if (it->featureId_ == feature) { 38548f512ceSopenharmony_ci return it.get(); 38648f512ceSopenharmony_ci } 38748f512ceSopenharmony_ci } 38848f512ceSopenharmony_ci return nullptr; 38948f512ceSopenharmony_ci} 39048f512ceSopenharmony_ci 39148f512ceSopenharmony_cibool PerfFileReader::ReadFeatureSection() 39248f512ceSopenharmony_ci{ 39348f512ceSopenharmony_ci uint64_t featureSectionOffsetRead = featureSectionOffset_; 39448f512ceSopenharmony_ci HLOGV(" ReadDataSection data offset '0x%" PRIx64 " ", featureSectionOffset_); 39548f512ceSopenharmony_ci 39648f512ceSopenharmony_ci for (FEATURE feature : features_) { 39748f512ceSopenharmony_ci perf_file_section sectionHeader; 39848f512ceSopenharmony_ci // read failed ?? 39948f512ceSopenharmony_ci CHECK_TRUE(!Read((char *)§ionHeader, featureSectionOffsetRead, sizeof(sectionHeader)), 40048f512ceSopenharmony_ci false, LOG_TYPE_PRINTF, 40148f512ceSopenharmony_ci "file format not correct. featureSectionOffsetRead '0x%" PRIx64 "\n", featureSectionOffsetRead); 40248f512ceSopenharmony_ci 40348f512ceSopenharmony_ci HLOGV("process feature %d:%s", feature, PerfFileSection::GetFeatureName(feature).c_str()); 40448f512ceSopenharmony_ci HLOGV(" sectionHeader -> read offset '0x%" PRIx64 " size '0x%" PRIx64 "'", 40548f512ceSopenharmony_ci sectionHeader.offset, sectionHeader.size); 40648f512ceSopenharmony_ci CHECK_TRUE(sectionHeader.size == 0 or sectionHeader.size > fileSize_, false, 1, 40748f512ceSopenharmony_ci "sectionHeader.size %" PRIu64 " is not correct", sectionHeader.size); 40848f512ceSopenharmony_ci 40948f512ceSopenharmony_ci std::vector<char> buf(sectionHeader.size); 41048f512ceSopenharmony_ci // read failed ?? 41148f512ceSopenharmony_ci CHECK_TRUE(!Read(&buf[0], sectionHeader.offset, buf.size()), false, LOG_TYPE_PRINTF, 41248f512ceSopenharmony_ci "file format not correct. featureSectionDataOffset '0x%" PRIx64 "\n", sectionHeader.offset); 41348f512ceSopenharmony_ci if (IsFeatrureStringSection(feature)) { 41448f512ceSopenharmony_ci perfFileSections_.emplace_back( 41548f512ceSopenharmony_ci std::make_unique<PerfFileSectionString>(feature, (char *)&buf[0], buf.size())); 41648f512ceSopenharmony_ci } else if (feature == FEATURE::HIPERF_FILES_SYMBOL) { 41748f512ceSopenharmony_ci perfFileSections_.emplace_back(std::make_unique<PerfFileSectionSymbolsFiles>( 41848f512ceSopenharmony_ci feature, (char *)&buf[0], buf.size())); 41948f512ceSopenharmony_ci } else if (feature == FEATURE::EVENT_DESC) { 42048f512ceSopenharmony_ci perfFileSections_.emplace_back( 42148f512ceSopenharmony_ci std::make_unique<PerfFileSectionEventDesc>(feature, (char *)&buf[0], buf.size())); 42248f512ceSopenharmony_ci } else if (feature == FEATURE::HIPERF_FILES_UNISTACK_TABLE) { 42348f512ceSopenharmony_ci perfFileSections_.emplace_back( 42448f512ceSopenharmony_ci std::make_unique<PerfFileSectionUniStackTable>(feature, (char *)&buf[0], buf.size())); 42548f512ceSopenharmony_ci PerfRecordSample::dumpRemoveStack_ = true; 42648f512ceSopenharmony_ci } else { 42748f512ceSopenharmony_ci HLOGW("still not imp how to process with feature %d", feature); 42848f512ceSopenharmony_ci } 42948f512ceSopenharmony_ci 43048f512ceSopenharmony_ci featureSectionOffsetRead += sizeof(sectionHeader); // next feaure 43148f512ceSopenharmony_ci } 43248f512ceSopenharmony_ci return true; 43348f512ceSopenharmony_ci} 43448f512ceSopenharmony_ci} // namespace HiPerf 43548f512ceSopenharmony_ci} // namespace Developtools 43648f512ceSopenharmony_ci} // namespace OHOS 437