106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci 1606f6ba60Sopenharmony_ci#include "stack_preprocess.h" 1706f6ba60Sopenharmony_ci 1806f6ba60Sopenharmony_ci#include <elf.h> 1906f6ba60Sopenharmony_ci#include <unistd.h> 2006f6ba60Sopenharmony_ci 2106f6ba60Sopenharmony_ci#include "common.h" 2206f6ba60Sopenharmony_ci#include "logging.h" 2306f6ba60Sopenharmony_ci#include "plugin_service_types.pb.h" 2406f6ba60Sopenharmony_ci#include "dfx_elf.h" 2506f6ba60Sopenharmony_ci#include "utilities.h" 2606f6ba60Sopenharmony_ci#include "native_hook_result_standard.pb.h" 2706f6ba60Sopenharmony_ci#include "native_hook_config_standard.pb.h" 2806f6ba60Sopenharmony_ci#include "google/protobuf/text_format.h" 2906f6ba60Sopenharmony_ci#include "trace_file_writer.h" 3006f6ba60Sopenharmony_ci 3106f6ba60Sopenharmony_ci 3206f6ba60Sopenharmony_ciconstexpr static uint32_t SC_LG_TINY_MIN = 3; 3306f6ba60Sopenharmony_ciconstexpr static uint32_t LG_QUANTUM = 4; 3406f6ba60Sopenharmony_ciconstexpr static uint32_t SC_NTINY = LG_QUANTUM - SC_LG_TINY_MIN; 3506f6ba60Sopenharmony_ciconstexpr static uint32_t SC_LG_TINY_MAXCLASS = (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1); 3606f6ba60Sopenharmony_ciconstexpr static uint32_t SC_LG_NGROUP = 2; 3706f6ba60Sopenharmony_ciconstexpr static uint32_t LG_SIZE_CLASS_GROUP = 2; 3806f6ba60Sopenharmony_ciconstexpr static uint32_t NTBINS = 1; 3906f6ba60Sopenharmony_ciconstexpr static uint32_t LG_TINY_MAXCLASS = 3; 4006f6ba60Sopenharmony_ciconstexpr static uint32_t MAX_MATCH_CNT = 1000; 4106f6ba60Sopenharmony_ciconstexpr static uint32_t MAX_MATCH_INTERVAL = 3600; 4206f6ba60Sopenharmony_ciconstexpr static uint32_t LOG_PRINT_TIMES = 10000; 4306f6ba60Sopenharmony_ciconstexpr static uint32_t WAIT_STOP_TIME = 5000; 4406f6ba60Sopenharmony_ciconstexpr static uint32_t WAIT_TIME_ONCE = 10; 4506f6ba60Sopenharmony_ciconstexpr static uint32_t MAX_BATCH_CNT = 40; 4606f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_1 = 1; 4706f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_2 = 2; 4806f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_4 = 4; 4906f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_8 = 8; 5006f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_16 = 16; 5106f6ba60Sopenharmony_ciconstexpr static uint64_t SIZE_MASK = 0xFFFFFF0000000000; 5206f6ba60Sopenharmony_ciconstexpr static uint64_t JS_OFFLINE_IP_MASK = 0xFFFFFE0000000000; 5306f6ba60Sopenharmony_ciconstexpr static uint64_t DWARF_ERROR_ID = 999999; 5406f6ba60Sopenharmony_ciconstexpr static uint64_t DWARF_NAPI_CALLBACK = 999999; 5506f6ba60Sopenharmony_cistatic std::string JS_CALL_STACK_DEPTH_SEP = ","; // ',' is js call stack depth separator 5606f6ba60Sopenharmony_cistatic std::string JS_SYMBOL_FILEPATH_SEP = "|"; // '|' is js symbol and filepath separator 5706f6ba60Sopenharmony_ciconstexpr static int NAPI_CALL_STACK = 2; // just for napi call stack 5806f6ba60Sopenharmony_ciconstexpr static uint32_t FRAME_DEPTH = 2; // add two frames 5906f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG 6006f6ba60Sopenharmony_ciconstexpr static uint32_t LONG_TIME_THRESHOLD = 1000000; 6106f6ba60Sopenharmony_cistatic std::atomic<uint64_t> timeCost = 0; 6206f6ba60Sopenharmony_cistatic std::atomic<uint64_t> unwindTimes = 0; 6306f6ba60Sopenharmony_ci#endif 6406f6ba60Sopenharmony_ci 6506f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::NativeDaemon; 6606f6ba60Sopenharmony_ciusing namespace OHOS::HiviewDFX; 6706f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler; 6806f6ba60Sopenharmony_ci 6906f6ba60Sopenharmony_ciStackPreprocess::StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const NativeHookConfig& hookConfig, 7006f6ba60Sopenharmony_ci clockid_t pluginDataClockId, FILE* fpHookData, bool isHookStandalone, bool isSaService, bool isProtobufSerialize) 7106f6ba60Sopenharmony_ci : dataRepeater_(dataRepeater), hookConfig_(hookConfig), pluginDataClockId_(pluginDataClockId), 7206f6ba60Sopenharmony_ci fpHookData_(fpHookData), isHookStandaloneSerialize_(isHookStandalone), isSaService_(isSaService), 7306f6ba60Sopenharmony_ci isProtobufSerialize_(isProtobufSerialize) 7406f6ba60Sopenharmony_ci{ 7506f6ba60Sopenharmony_ci runtime_instance = std::make_shared<VirtualRuntime>(hookConfig_); 7606f6ba60Sopenharmony_ci 7706f6ba60Sopenharmony_ci if (hookConfig_.malloc_free_matching_interval() > MAX_MATCH_INTERVAL) { 7806f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "Not support set %d", hookConfig_.malloc_free_matching_interval()); 7906f6ba60Sopenharmony_ci hookConfig_.set_malloc_free_matching_interval(MAX_MATCH_INTERVAL); 8006f6ba60Sopenharmony_ci } 8106f6ba60Sopenharmony_ci 8206f6ba60Sopenharmony_ci if (hookConfig_.malloc_free_matching_cnt() > MAX_MATCH_CNT) { 8306f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "Not support set %d", hookConfig_.malloc_free_matching_cnt()); 8406f6ba60Sopenharmony_ci hookConfig_.set_malloc_free_matching_cnt(MAX_MATCH_CNT); 8506f6ba60Sopenharmony_ci } 8606f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "malloc_free_matching_interval = %d malloc_free_matching_cnt = %d\n", 8706f6ba60Sopenharmony_ci hookConfig_.malloc_free_matching_interval(), hookConfig_.malloc_free_matching_cnt()); 8806f6ba60Sopenharmony_ci 8906f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0) { 9006f6ba60Sopenharmony_ci statisticsInterval_ = std::chrono::seconds(hookConfig_.statistics_interval()); 9106f6ba60Sopenharmony_ci recordStatisticsMap_.reserve(STATISTICS_MAP_SZIE); 9206f6ba60Sopenharmony_ci statisticsPeriodData_.reserve(STATISTICS_PERIOD_DATA_SIZE); 9306f6ba60Sopenharmony_ci allocAddrMap_.reserve(ALLOC_ADDRMAMP_SIZE); 9406f6ba60Sopenharmony_ci } 9506f6ba60Sopenharmony_ci if (hookConfig_.malloc_free_matching_interval() > 0) { 9606f6ba60Sopenharmony_ci applyAndReleaseMatchInterval_ = std::chrono::seconds(hookConfig_.malloc_free_matching_interval()); 9706f6ba60Sopenharmony_ci applyAndReleaseMatchIntervallMap_.reserve(MATCH_ADDRMAMP_SIZE); 9806f6ba60Sopenharmony_ci } 9906f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "statistics_interval = %d statisticsInterval_ = %lld \n", 10006f6ba60Sopenharmony_ci hookConfig_.statistics_interval(), statisticsInterval_.count()); 10106f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "applyAndReleaseMatchInterval_ = %lld", applyAndReleaseMatchInterval_.count()); 10206f6ba60Sopenharmony_ci hookDataClockId_ = COMMON::GetClockId(hookConfig_.clock()); 10306f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "StackPreprocess(): pluginDataClockId = %d hookDataClockId = %d \n", 10406f6ba60Sopenharmony_ci pluginDataClockId_, hookDataClockId_); 10506f6ba60Sopenharmony_ci if (hookConfig_.save_file() && fpHookData_ == nullptr) { 10606f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "If you need to save the file, please set the file_name"); 10706f6ba60Sopenharmony_ci } 10806f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "isHookStandaloneSerialize_ = %d", isHookStandaloneSerialize_); 10906f6ba60Sopenharmony_ci#if defined(__arm__) 11006f6ba60Sopenharmony_ci u64regs_.resize(PERF_REG_ARM_MAX); 11106f6ba60Sopenharmony_ci#else 11206f6ba60Sopenharmony_ci u64regs_.resize(PERF_REG_ARM64_MAX); 11306f6ba60Sopenharmony_ci#endif 11406f6ba60Sopenharmony_ci callFrames_.reserve(hookConfig_.max_stack_depth() + hookConfig_.max_js_stack_depth()); 11506f6ba60Sopenharmony_ci if (hookConfig_.fp_unwind() && hookConfig_.js_stack_report() > 0) { 11606f6ba60Sopenharmony_ci fpJsCallStacks_.reserve(hookConfig_.max_js_stack_depth()); 11706f6ba60Sopenharmony_ci } 11806f6ba60Sopenharmony_ci} 11906f6ba60Sopenharmony_ci 12006f6ba60Sopenharmony_ciStackPreprocess::~StackPreprocess() 12106f6ba60Sopenharmony_ci{ 12206f6ba60Sopenharmony_ci isStopTakeData_ = true; 12306f6ba60Sopenharmony_ci if (dataRepeater_) { 12406f6ba60Sopenharmony_ci dataRepeater_->Close(); 12506f6ba60Sopenharmony_ci } 12606f6ba60Sopenharmony_ci if (thread_.joinable()) { 12706f6ba60Sopenharmony_ci thread_.join(); 12806f6ba60Sopenharmony_ci } 12906f6ba60Sopenharmony_ci runtime_instance = nullptr; 13006f6ba60Sopenharmony_ci fpHookData_ = nullptr; 13106f6ba60Sopenharmony_ci} 13206f6ba60Sopenharmony_ci 13306f6ba60Sopenharmony_civoid StackPreprocess::FinishTraceFile() 13406f6ba60Sopenharmony_ci{ 13506f6ba60Sopenharmony_ci if (isSaService_) { 13606f6ba60Sopenharmony_ci std::shared_ptr<TraceFileWriter> tfPtr = std::static_pointer_cast<TraceFileWriter>(writer_); 13706f6ba60Sopenharmony_ci tfPtr->SetDurationTime(); 13806f6ba60Sopenharmony_ci tfPtr->Finish(); 13906f6ba60Sopenharmony_ci } 14006f6ba60Sopenharmony_ci} 14106f6ba60Sopenharmony_ci 14206f6ba60Sopenharmony_civoid StackPreprocess::SetWriter(const std::shared_ptr<Writer>& writer) 14306f6ba60Sopenharmony_ci{ 14406f6ba60Sopenharmony_ci writer_ = writer; 14506f6ba60Sopenharmony_ci if (!isSaService_) { 14606f6ba60Sopenharmony_ci stackData_ = BatchNativeHookData(); 14706f6ba60Sopenharmony_ci } 14806f6ba60Sopenharmony_ci} 14906f6ba60Sopenharmony_ci 15006f6ba60Sopenharmony_civoid StackPreprocess::SetWriter(const WriterStructPtr& writer) 15106f6ba60Sopenharmony_ci{ 15206f6ba60Sopenharmony_ci resultWriter_ = writer; 15306f6ba60Sopenharmony_ci auto ctx = resultWriter_->startReport(resultWriter_); 15406f6ba60Sopenharmony_ci if (ctx == nullptr) { 15506f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__); 15606f6ba60Sopenharmony_ci return; 15706f6ba60Sopenharmony_ci } 15806f6ba60Sopenharmony_ci stackData_ = ProtoEncoder::BatchNativeHookData(ctx); 15906f6ba60Sopenharmony_ci} 16006f6ba60Sopenharmony_ci 16106f6ba60Sopenharmony_cibool StackPreprocess::StartTakeResults() 16206f6ba60Sopenharmony_ci{ 16306f6ba60Sopenharmony_ci CHECK_NOTNULL(dataRepeater_, false, "data repeater null"); 16406f6ba60Sopenharmony_ci 16506f6ba60Sopenharmony_ci std::weak_ptr<StackPreprocess> stackPreprocessPtr(shared_from_this()); 16606f6ba60Sopenharmony_ci std::thread demuxer([stackPreprocessPtr] { 16706f6ba60Sopenharmony_ci if (auto ptr = stackPreprocessPtr.lock(); ptr != nullptr) { 16806f6ba60Sopenharmony_ci ptr->TakeResults(); 16906f6ba60Sopenharmony_ci } 17006f6ba60Sopenharmony_ci }); 17106f6ba60Sopenharmony_ci CHECK_TRUE(demuxer.get_id() != std::thread::id(), false, "demuxer thread invalid"); 17206f6ba60Sopenharmony_ci 17306f6ba60Sopenharmony_ci thread_ = std::move(demuxer); 17406f6ba60Sopenharmony_ci isStopTakeData_ = false; 17506f6ba60Sopenharmony_ci return true; 17606f6ba60Sopenharmony_ci} 17706f6ba60Sopenharmony_ci 17806f6ba60Sopenharmony_cibool StackPreprocess::StopTakeResults() 17906f6ba60Sopenharmony_ci{ 18006f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "start StopTakeResults"); 18106f6ba60Sopenharmony_ci int32_t timerFd = scheduleTaskManager_.ScheduleTask( 18206f6ba60Sopenharmony_ci std::bind(&StackPreprocess::ForceStop, this), WAIT_STOP_TIME, true, false); 18306f6ba60Sopenharmony_ci if (timerFd == -1) { 18406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "StopTakeResults ScheduleTask failed!"); 18506f6ba60Sopenharmony_ci return false; 18606f6ba60Sopenharmony_ci } 18706f6ba60Sopenharmony_ci if (!dataRepeater_) { 18806f6ba60Sopenharmony_ci while (!isStopTakeData_) { 18906f6ba60Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME_ONCE)); 19006f6ba60Sopenharmony_ci } 19106f6ba60Sopenharmony_ci return true; 19206f6ba60Sopenharmony_ci } 19306f6ba60Sopenharmony_ci CHECK_NOTNULL(dataRepeater_, false, "data repeater null"); 19406f6ba60Sopenharmony_ci CHECK_TRUE(thread_.get_id() != std::thread::id(), false, "thread invalid"); 19506f6ba60Sopenharmony_ci 19606f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "StopTakeResults Wait thread join"); 19706f6ba60Sopenharmony_ci 19806f6ba60Sopenharmony_ci if (thread_.joinable()) { 19906f6ba60Sopenharmony_ci thread_.join(); 20006f6ba60Sopenharmony_ci } 20106f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "StopTakeResults Wait thread join success"); 20206f6ba60Sopenharmony_ci return true; 20306f6ba60Sopenharmony_ci} 20406f6ba60Sopenharmony_ci 20506f6ba60Sopenharmony_ciinline void StackPreprocess::IntervalFlushRecordStatistics() 20606f6ba60Sopenharmony_ci{ 20706f6ba60Sopenharmony_ci // interval reporting statistics 20806f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0) { 20906f6ba60Sopenharmony_ci auto currentTime = std::chrono::steady_clock::now(); 21006f6ba60Sopenharmony_ci auto elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(currentTime - lastStatisticsTime_); 21106f6ba60Sopenharmony_ci if (elapsedTime >= statisticsInterval_) { 21206f6ba60Sopenharmony_ci lastStatisticsTime_ = currentTime; 21306f6ba60Sopenharmony_ci FlushRecordStatistics(); 21406f6ba60Sopenharmony_ci } 21506f6ba60Sopenharmony_ci } 21606f6ba60Sopenharmony_ci} 21706f6ba60Sopenharmony_ci 21806f6ba60Sopenharmony_ciinline void StackPreprocess::IntervalFlushApplyAndReleaseMatchData() 21906f6ba60Sopenharmony_ci{ 22006f6ba60Sopenharmony_ci // interval reporting apply and release match data 22106f6ba60Sopenharmony_ci if (hookConfig_.malloc_free_matching_interval() > 0) { 22206f6ba60Sopenharmony_ci static auto lastStatisticsTime = std::chrono::steady_clock::now(); 22306f6ba60Sopenharmony_ci auto currentTime = std::chrono::steady_clock::now(); 22406f6ba60Sopenharmony_ci auto elapsedTime = std::chrono::duration_cast<std::chrono::seconds>(currentTime - lastStatisticsTime); 22506f6ba60Sopenharmony_ci if (elapsedTime >= applyAndReleaseMatchInterval_) { 22606f6ba60Sopenharmony_ci lastStatisticsTime = currentTime; 22706f6ba60Sopenharmony_ci FlushRecordApplyAndReleaseMatchData(); 22806f6ba60Sopenharmony_ci } 22906f6ba60Sopenharmony_ci } 23006f6ba60Sopenharmony_ci} 23106f6ba60Sopenharmony_ci 23206f6ba60Sopenharmony_cibool StackPreprocess::HandleNoStackEvent(RawStackPtr& rawData) 23306f6ba60Sopenharmony_ci{ 23406f6ba60Sopenharmony_ci if (rawData->stackConext->type == MMAP_FILE_TYPE) { 23506f6ba60Sopenharmony_ci BaseStackRawData* mmapRawData = rawData->stackConext; 23606f6ba60Sopenharmony_ci std::string filePath(reinterpret_cast<char *>(rawData->data)); 23706f6ba60Sopenharmony_ci COMMON::AdaptSandboxPath(filePath, rawData->stackConext->pid); 23806f6ba60Sopenharmony_ci PROFILER_LOG_DEBUG(LOG_CORE, "MMAP_FILE_TYPE curMmapAddr=%p, MAP_FIXED=%d, " 23906f6ba60Sopenharmony_ci "PROT_EXEC=%d, offset=%" PRIu64 ", filePath=%s", 24006f6ba60Sopenharmony_ci mmapRawData->addr, mmapRawData->mmapArgs.flags & MAP_FIXED, 24106f6ba60Sopenharmony_ci mmapRawData->mmapArgs.flags & PROT_EXEC, mmapRawData->mmapArgs.offset, filePath.data()); 24206f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 24306f6ba60Sopenharmony_ci runtime_instance->HandleMapInfo({reinterpret_cast<uint64_t>(mmapRawData->addr), 24406f6ba60Sopenharmony_ci mmapRawData->mallocSize, mmapRawData->mmapArgs.flags, mmapRawData->mmapArgs.offset}, filePath, 24506f6ba60Sopenharmony_ci rawData->stackConext->pid, rawData->stackConext->tid); 24606f6ba60Sopenharmony_ci flushBasicData_ = true; 24706f6ba60Sopenharmony_ci } else if (rawData->stackConext->type == THREAD_NAME_MSG) { 24806f6ba60Sopenharmony_ci std::string threadName = reinterpret_cast<char*>(rawData->data); 24906f6ba60Sopenharmony_ci ReportThreadNameMap(rawData->stackConext->tid, threadName); 25006f6ba60Sopenharmony_ci } else { 25106f6ba60Sopenharmony_ci return false; 25206f6ba60Sopenharmony_ci } 25306f6ba60Sopenharmony_ci return true; 25406f6ba60Sopenharmony_ci} 25506f6ba60Sopenharmony_ci 25606f6ba60Sopenharmony_civoid StackPreprocess::ForceStop() 25706f6ba60Sopenharmony_ci{ 25806f6ba60Sopenharmony_ci isStopTakeData_ = true; 25906f6ba60Sopenharmony_ci if (dataRepeater_ != nullptr) { 26006f6ba60Sopenharmony_ci dataRepeater_->Close(); 26106f6ba60Sopenharmony_ci } 26206f6ba60Sopenharmony_ci} 26306f6ba60Sopenharmony_ci 26406f6ba60Sopenharmony_civoid StackPreprocess::TakeResultsFromShmem(const std::shared_ptr<EventNotifier>& eventNotifier, 26506f6ba60Sopenharmony_ci const std::shared_ptr<ShareMemoryBlock>& shareMemoryBlock) 26606f6ba60Sopenharmony_ci{ 26706f6ba60Sopenharmony_ci eventNotifier->Take(); 26806f6ba60Sopenharmony_ci StackDataRepeater::RawStack rawStack; 26906f6ba60Sopenharmony_ci RawStackPtr rawData(&rawStack, [](StackDataRepeater::RawStack* del) {}); 27006f6ba60Sopenharmony_ci while (!isStopTakeData_) { 27106f6ba60Sopenharmony_ci bool ret = shareMemoryBlock->TakeData( 27206f6ba60Sopenharmony_ci [&](const int8_t data[], uint32_t size) -> bool { 27306f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG 27406f6ba60Sopenharmony_ci struct timespec start = {}; 27506f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &start); 27606f6ba60Sopenharmony_ci#endif 27706f6ba60Sopenharmony_ci if (size == sizeof(uint64_t)) { 27806f6ba60Sopenharmony_ci uint64_t addr = *reinterpret_cast<uint64_t *>(const_cast<int8_t *>(data)); 27906f6ba60Sopenharmony_ci SetFreeStatisticsData(addr); 28006f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG 28106f6ba60Sopenharmony_ci struct timespec end = {}; 28206f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &end); 28306f6ba60Sopenharmony_ci uint64_t curTimeCost = (end.tv_sec - start.tv_sec) * MAX_MATCH_CNT * MAX_MATCH_CNT * MAX_MATCH_CNT + 28406f6ba60Sopenharmony_ci (end.tv_nsec - start.tv_nsec); 28506f6ba60Sopenharmony_ci timeCost += curTimeCost; 28606f6ba60Sopenharmony_ci unwindTimes++; 28706f6ba60Sopenharmony_ci if (unwindTimes % LOG_PRINT_TIMES == 0) { 28806f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, 28906f6ba60Sopenharmony_ci "unwindTimes %" PRIu64" cost time = %" PRIu64" mean cost = %" PRIu64"\n", 29006f6ba60Sopenharmony_ci unwindTimes.load(), timeCost.load(), timeCost.load() / unwindTimes.load()); 29106f6ba60Sopenharmony_ci } 29206f6ba60Sopenharmony_ci#endif 29306f6ba60Sopenharmony_ci return true; 29406f6ba60Sopenharmony_ci } 29506f6ba60Sopenharmony_ci CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!"); 29606f6ba60Sopenharmony_ci rawData->stackConext = reinterpret_cast<BaseStackRawData *>(const_cast<int8_t *>(data)); 29706f6ba60Sopenharmony_ci rawData->data = reinterpret_cast<uint8_t*>(const_cast<int8_t *>(data)) + sizeof(BaseStackRawData); 29806f6ba60Sopenharmony_ci rawData->fpDepth = (size - sizeof(BaseStackRawData)) / sizeof(uint64_t); 29906f6ba60Sopenharmony_ci if (isStopTakeData_) { 30006f6ba60Sopenharmony_ci return false; 30106f6ba60Sopenharmony_ci } else if (rawData->stackConext->type == MEMORY_TAG) { 30206f6ba60Sopenharmony_ci std::string tagName = reinterpret_cast<char*>(rawData->data); 30306f6ba60Sopenharmony_ci SaveMemTag(rawData->stackConext->tagId, tagName); 30406f6ba60Sopenharmony_ci return true; 30506f6ba60Sopenharmony_ci } else if (HandleNoStackEvent(rawData)) { 30606f6ba60Sopenharmony_ci return true; 30706f6ba60Sopenharmony_ci } else if (rawData->stackConext->type == MUNMAP_MSG) { 30806f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 30906f6ba60Sopenharmony_ci runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr)); 31006f6ba60Sopenharmony_ci } else if (rawData->stackConext->type == NMD_MSG) { 31106f6ba60Sopenharmony_ci const char* nmdResult = reinterpret_cast<const char*>(rawData->data); 31206f6ba60Sopenharmony_ci lseek(nmdFd_, 0, SEEK_END); 31306f6ba60Sopenharmony_ci (void)write(nmdFd_, nmdResult, strlen(nmdResult)); 31406f6ba60Sopenharmony_ci return true; 31506f6ba60Sopenharmony_ci } else if (rawData->stackConext->type == END_MSG) { 31606f6ba60Sopenharmony_ci isStopTakeData_ = true; 31706f6ba60Sopenharmony_ci return true; 31806f6ba60Sopenharmony_ci } 31906f6ba60Sopenharmony_ci { 32006f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 32106f6ba60Sopenharmony_ci runtime_instance->UpdateThread(rawData->stackConext->pid, rawData->stackConext->tid); 32206f6ba60Sopenharmony_ci } 32306f6ba60Sopenharmony_ci ReportOfflineSymbolizationData(); 32406f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 32506f6ba60Sopenharmony_ci SetHookData(rawData, stackData); 32606f6ba60Sopenharmony_ci FlushCheck(stackData); 32706f6ba60Sopenharmony_ci }, stackData_); 32806f6ba60Sopenharmony_ci IntervalFlushRecordStatistics(); 32906f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG 33006f6ba60Sopenharmony_ci struct timespec end = {}; 33106f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &end); 33206f6ba60Sopenharmony_ci uint64_t curTimeCost = (end.tv_sec - start.tv_sec) * MAX_MATCH_CNT * MAX_MATCH_CNT * MAX_MATCH_CNT + 33306f6ba60Sopenharmony_ci (end.tv_nsec - start.tv_nsec); 33406f6ba60Sopenharmony_ci if (curTimeCost >= LONG_TIME_THRESHOLD) { 33506f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "bigTimeCost %" PRIu64 " event=%d fpDepth=%u", 33606f6ba60Sopenharmony_ci curTimeCost, rawData->stackConext->type, rawData->fpDepth); 33706f6ba60Sopenharmony_ci } 33806f6ba60Sopenharmony_ci timeCost += curTimeCost; 33906f6ba60Sopenharmony_ci unwindTimes++; 34006f6ba60Sopenharmony_ci if (unwindTimes % LOG_PRINT_TIMES == 0) { 34106f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "unwindTimes %" PRIu64" cost time = %" PRIu64" mean cost = %" PRIu64"\n", 34206f6ba60Sopenharmony_ci unwindTimes.load(), timeCost.load(), timeCost.load() / unwindTimes.load()); 34306f6ba60Sopenharmony_ci } 34406f6ba60Sopenharmony_ci#endif 34506f6ba60Sopenharmony_ci return true; 34606f6ba60Sopenharmony_ci }); 34706f6ba60Sopenharmony_ci if (!ret) { 34806f6ba60Sopenharmony_ci break; 34906f6ba60Sopenharmony_ci } 35006f6ba60Sopenharmony_ci } 35106f6ba60Sopenharmony_ci} 35206f6ba60Sopenharmony_ci 35306f6ba60Sopenharmony_civoid StackPreprocess::TakeResults() 35406f6ba60Sopenharmony_ci{ 35506f6ba60Sopenharmony_ci if (!dataRepeater_) { 35606f6ba60Sopenharmony_ci return; 35706f6ba60Sopenharmony_ci } 35806f6ba60Sopenharmony_ci 35906f6ba60Sopenharmony_ci size_t minStackDepth = hookConfig_.max_stack_depth() > MIN_STACK_DEPTH 36006f6ba60Sopenharmony_ci ? MIN_STACK_DEPTH : hookConfig_.max_stack_depth(); 36106f6ba60Sopenharmony_ci if (hookConfig_.blocked()) { 36206f6ba60Sopenharmony_ci minStackDepth = static_cast<size_t>(hookConfig_.max_stack_depth()); 36306f6ba60Sopenharmony_ci } 36406f6ba60Sopenharmony_ci minStackDepth += FILTER_STACK_DEPTH; 36506f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "TakeResults thread %d, start!", gettid()); 36606f6ba60Sopenharmony_ci while (1) { 36706f6ba60Sopenharmony_ci RawStackPtr batchRawStack[MAX_BATCH_CNT] = {nullptr}; 36806f6ba60Sopenharmony_ci if (isStopTakeData_) { 36906f6ba60Sopenharmony_ci break; 37006f6ba60Sopenharmony_ci } 37106f6ba60Sopenharmony_ci uint32_t during = 0; 37206f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0) { 37306f6ba60Sopenharmony_ci auto currentTime = std::chrono::steady_clock::now(); 37406f6ba60Sopenharmony_ci auto timeDiff = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastStatisticsTime_); 37506f6ba60Sopenharmony_ci int tempDuring = 37606f6ba60Sopenharmony_ci std::chrono::duration_cast<std::chrono::milliseconds>(statisticsInterval_).count() - timeDiff.count(); 37706f6ba60Sopenharmony_ci during = tempDuring > 0 ? static_cast<uint32_t>(tempDuring) : 0; 37806f6ba60Sopenharmony_ci } 37906f6ba60Sopenharmony_ci bool isTimeOut = false; 38006f6ba60Sopenharmony_ci auto result = dataRepeater_->TakeRawData(during, hookDataClockId_, MAX_BATCH_CNT, batchRawStack, 38106f6ba60Sopenharmony_ci hookConfig_.statistics_interval(), isTimeOut); 38206f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0 && isTimeOut && result == nullptr) { // statistics mode 38306f6ba60Sopenharmony_ci IntervalFlushRecordStatistics(); 38406f6ba60Sopenharmony_ci continue; 38506f6ba60Sopenharmony_ci } 38606f6ba60Sopenharmony_ci if (!result) { 38706f6ba60Sopenharmony_ci break; 38806f6ba60Sopenharmony_ci } 38906f6ba60Sopenharmony_ci for (unsigned int i = 0; i < MAX_BATCH_CNT; i++) { 39006f6ba60Sopenharmony_ci auto rawData = batchRawStack[i]; 39106f6ba60Sopenharmony_ci if (!rawData || isStopTakeData_) { 39206f6ba60Sopenharmony_ci break; 39306f6ba60Sopenharmony_ci } 39406f6ba60Sopenharmony_ci if (rawData->baseStackData == nullptr) { 39506f6ba60Sopenharmony_ci if (rawData->freeData) { 39606f6ba60Sopenharmony_ci SetFreeStatisticsData(rawData->freeData); 39706f6ba60Sopenharmony_ci } 39806f6ba60Sopenharmony_ci continue; 39906f6ba60Sopenharmony_ci } 40006f6ba60Sopenharmony_ci if (rawData->stackConext == nullptr) { 40106f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "StackPreprocess take results rawData->stackConext is nullptr"); 40206f6ba60Sopenharmony_ci continue; 40306f6ba60Sopenharmony_ci } 40406f6ba60Sopenharmony_ci if (rawData->stackConext->type == NMD_MSG) { 40506f6ba60Sopenharmony_ci continue; 40606f6ba60Sopenharmony_ci } else if (rawData->stackConext->type == END_MSG) { 40706f6ba60Sopenharmony_ci isStopTakeData_ = true; 40806f6ba60Sopenharmony_ci break; 40906f6ba60Sopenharmony_ci } 41006f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG 41106f6ba60Sopenharmony_ci struct timespec start = {}; 41206f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &start); 41306f6ba60Sopenharmony_ci#endif 41406f6ba60Sopenharmony_ci if (HandleNoStackEvent(rawData)) { 41506f6ba60Sopenharmony_ci continue; 41606f6ba60Sopenharmony_ci } else if (rawData->stackConext->type == MUNMAP_MSG) { 41706f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 41806f6ba60Sopenharmony_ci runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr)); 41906f6ba60Sopenharmony_ci } 42006f6ba60Sopenharmony_ci 42106f6ba60Sopenharmony_ci if (!rawData->reportFlag) { 42206f6ba60Sopenharmony_ci ignoreCnts_++; 42306f6ba60Sopenharmony_ci if (ignoreCnts_ % LOG_PRINT_TIMES == 0) { 42406f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "ignoreCnts_ = %d quene size = %zu\n", 42506f6ba60Sopenharmony_ci ignoreCnts_, dataRepeater_->Size()); 42606f6ba60Sopenharmony_ci } 42706f6ba60Sopenharmony_ci continue; 42806f6ba60Sopenharmony_ci } 42906f6ba60Sopenharmony_ci eventCnts_++; 43006f6ba60Sopenharmony_ci if (eventCnts_ % LOG_PRINT_TIMES == 0) { 43106f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "eventCnts_ = %d quene size = %zu\n", eventCnts_, dataRepeater_->Size()); 43206f6ba60Sopenharmony_ci } 43306f6ba60Sopenharmony_ci callFrames_.clear(); 43406f6ba60Sopenharmony_ci if (hookConfig_.fp_unwind()) { 43506f6ba60Sopenharmony_ci FillFpNativeIp(rawData); 43606f6ba60Sopenharmony_ci if (rawData->stackConext->jsChainId > 0 && rawData->jsStackData && hookConfig_.js_stack_report() > 0) { 43706f6ba60Sopenharmony_ci FillFpJsData(rawData); 43806f6ba60Sopenharmony_ci } 43906f6ba60Sopenharmony_ci } else if (rawData->stackConext->type != PR_SET_VMA_MSG) { 44006f6ba60Sopenharmony_ci if (rawData->stackSize == 0) { 44106f6ba60Sopenharmony_ci FillDwarfErrorStack(); 44206f6ba60Sopenharmony_ci } else { 44306f6ba60Sopenharmony_ci#if defined(__arm__) 44406f6ba60Sopenharmony_ci uint32_t *regAddrArm = reinterpret_cast<uint32_t *>(rawData->data); 44506f6ba60Sopenharmony_ci u64regs_.assign(regAddrArm, regAddrArm + PERF_REG_ARM_MAX); 44606f6ba60Sopenharmony_ci#else 44706f6ba60Sopenharmony_ci if (memcpy_s(u64regs_.data(), sizeof(uint64_t) * PERF_REG_ARM64_MAX, rawData->data, 44806f6ba60Sopenharmony_ci sizeof(uint64_t) * PERF_REG_ARM64_MAX) != EOK) { 44906f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s regs failed"); 45006f6ba60Sopenharmony_ci } 45106f6ba60Sopenharmony_ci#endif 45206f6ba60Sopenharmony_ci } 45306f6ba60Sopenharmony_ci } 45406f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG 45506f6ba60Sopenharmony_ci size_t realFrameDepth = callFrames_.size(); 45606f6ba60Sopenharmony_ci#endif 45706f6ba60Sopenharmony_ci size_t stackDepth = ((size_t)hookConfig_.max_stack_depth() > MAX_CALL_FRAME_UNWIND_SIZE) 45806f6ba60Sopenharmony_ci ? MAX_CALL_FRAME_UNWIND_SIZE 45906f6ba60Sopenharmony_ci : hookConfig_.max_stack_depth() + FILTER_STACK_DEPTH; 46006f6ba60Sopenharmony_ci if (rawData->reduceStackFlag) { 46106f6ba60Sopenharmony_ci stackDepth = minStackDepth; 46206f6ba60Sopenharmony_ci } 46306f6ba60Sopenharmony_ci if ((hookConfig_.fp_unwind()) || rawData->stackSize > 0) { 46406f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 46506f6ba60Sopenharmony_ci if (rawData->stackConext->type != PR_SET_VMA_MSG) { 46606f6ba60Sopenharmony_ci bool ret = runtime_instance->UnwindStack(u64regs_, rawData->stackData, rawData->stackSize, 46706f6ba60Sopenharmony_ci rawData->stackConext->pid, rawData->stackConext->tid, callFrames_, stackDepth); 46806f6ba60Sopenharmony_ci if (!ret) { 46906f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "unwind fatal error"); 47006f6ba60Sopenharmony_ci continue; 47106f6ba60Sopenharmony_ci } 47206f6ba60Sopenharmony_ci } 47306f6ba60Sopenharmony_ci } 47406f6ba60Sopenharmony_ci if ((hookConfig_.fp_unwind()) || rawData->stackSize > 0) { 47506f6ba60Sopenharmony_ci ReportOfflineSymbolizationData(); 47606f6ba60Sopenharmony_ci } 47706f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 47806f6ba60Sopenharmony_ci if (hookConfig_.save_file() && hookConfig_.file_name() != "" && isHookStandaloneSerialize_) { 47906f6ba60Sopenharmony_ci SetHookData(rawData, callFrames_, stackData); 48006f6ba60Sopenharmony_ci } else if (hookConfig_.save_file() && hookConfig_.file_name() != "") { 48106f6ba60Sopenharmony_ci WriteFrames(rawData, callFrames_); 48206f6ba60Sopenharmony_ci } else if (!hookConfig_.save_file()) { 48306f6ba60Sopenharmony_ci if (hookConfig_.malloc_free_matching_interval() > 0) { 48406f6ba60Sopenharmony_ci SetApplyAndReleaseMatchFrame(rawData, callFrames_, stackData); 48506f6ba60Sopenharmony_ci } else { 48606f6ba60Sopenharmony_ci SetHookData(rawData, callFrames_, stackData); 48706f6ba60Sopenharmony_ci } 48806f6ba60Sopenharmony_ci } 48906f6ba60Sopenharmony_ci }, stackData_); 49006f6ba60Sopenharmony_ci 49106f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG 49206f6ba60Sopenharmony_ci struct timespec end = {}; 49306f6ba60Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &end); 49406f6ba60Sopenharmony_ci uint64_t curTimeCost = (end.tv_sec - start.tv_sec) * MAX_MATCH_CNT * MAX_MATCH_CNT * MAX_MATCH_CNT + 49506f6ba60Sopenharmony_ci (end.tv_nsec - start.tv_nsec); 49606f6ba60Sopenharmony_ci if (curTimeCost >= LONG_TIME_THRESHOLD) { 49706f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "bigTimeCost %" PRIu64 " event=%d, realFrameDepth=%zu, " 49806f6ba60Sopenharmony_ci "callFramesDepth=%zu\n", 49906f6ba60Sopenharmony_ci curTimeCost, rawData->stackConext->type, realFrameDepth, callFrames_.size()); 50006f6ba60Sopenharmony_ci } 50106f6ba60Sopenharmony_ci timeCost += curTimeCost; 50206f6ba60Sopenharmony_ci unwindTimes++; 50306f6ba60Sopenharmony_ci if (unwindTimes % LOG_PRINT_TIMES == 0) { 50406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "unwindTimes %" PRIu64" cost time = %" PRIu64" mean cost = %" PRIu64"\n", 50506f6ba60Sopenharmony_ci unwindTimes.load(), timeCost.load(), timeCost.load() / unwindTimes.load()); 50606f6ba60Sopenharmony_ci } 50706f6ba60Sopenharmony_ci#endif 50806f6ba60Sopenharmony_ci } // for 50906f6ba60Sopenharmony_ci for (unsigned int i = 0; i < MAX_BATCH_CNT; i++) { 51006f6ba60Sopenharmony_ci if (!batchRawStack[i]) { 51106f6ba60Sopenharmony_ci break; 51206f6ba60Sopenharmony_ci } 51306f6ba60Sopenharmony_ci dataRepeater_->ReturnRawStack(std::move(batchRawStack[i])); 51406f6ba60Sopenharmony_ci } 51506f6ba60Sopenharmony_ci if (hookConfig_.save_file() && hookConfig_.file_name() != "" && !isHookStandaloneSerialize_) { 51606f6ba60Sopenharmony_ci continue; 51706f6ba60Sopenharmony_ci } 51806f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() == 0) { 51906f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 52006f6ba60Sopenharmony_ci FlushCheck(stackData); 52106f6ba60Sopenharmony_ci }, stackData_); 52206f6ba60Sopenharmony_ci } 52306f6ba60Sopenharmony_ci IntervalFlushRecordStatistics(); 52406f6ba60Sopenharmony_ci IntervalFlushApplyAndReleaseMatchData(); 52506f6ba60Sopenharmony_ci } // while 52606f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "TakeResults thread %d, exit!", gettid()); 52706f6ba60Sopenharmony_ci} 52806f6ba60Sopenharmony_ci 52906f6ba60Sopenharmony_ciinline void StackPreprocess::ReportThreadNameMap(uint32_t tid, const std::string& tname) 53006f6ba60Sopenharmony_ci{ 53106f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 53206f6ba60Sopenharmony_ci auto it = threadNameMap_.find(tid); 53306f6ba60Sopenharmony_ci if (it == threadNameMap_.end() || it->second != tname) { 53406f6ba60Sopenharmony_ci threadNameMap_[tid] = tname; 53506f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 53606f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 53706f6ba60Sopenharmony_ci auto thread = hookData->mutable_thread_name_map(); 53806f6ba60Sopenharmony_ci thread->set_id(tid); 53906f6ba60Sopenharmony_ci thread->set_name(tname); 54006f6ba60Sopenharmony_ci thread->set_pid(pid_); 54106f6ba60Sopenharmony_ci FlushCheck(stackData); 54206f6ba60Sopenharmony_ci }, stackData_); 54306f6ba60Sopenharmony_ci } 54406f6ba60Sopenharmony_ci} 54506f6ba60Sopenharmony_ci 54606f6ba60Sopenharmony_citemplate <typename T> 54706f6ba60Sopenharmony_ciinline void StackPreprocess::FillOfflineCallStack(std::vector<CallFrame>& callFrames, size_t idx, T& stackData) 54806f6ba60Sopenharmony_ci{ 54906f6ba60Sopenharmony_ci for (; idx < callFrames.size(); ++idx) { 55006f6ba60Sopenharmony_ci if (callFrames[idx].isJsFrame_) { 55106f6ba60Sopenharmony_ci ReportFrameMap(callFrames[idx], stackData); 55206f6ba60Sopenharmony_ci callStack_.push_back(callFrames[idx].callFrameId_ | JS_OFFLINE_IP_MASK); 55306f6ba60Sopenharmony_ci continue; 55406f6ba60Sopenharmony_ci } 55506f6ba60Sopenharmony_ci callStack_.push_back(callFrames[idx].ip_); 55606f6ba60Sopenharmony_ci } 55706f6ba60Sopenharmony_ci} 55806f6ba60Sopenharmony_ci 55906f6ba60Sopenharmony_citemplate <typename T> 56006f6ba60Sopenharmony_ciinline void StackPreprocess::FillCallStack(std::vector<CallFrame>& callFrames, size_t idx, T& stackData) 56106f6ba60Sopenharmony_ci{ 56206f6ba60Sopenharmony_ci for (; idx < callFrames.size(); ++idx) { 56306f6ba60Sopenharmony_ci ReportFrameMap(callFrames[idx], stackData); 56406f6ba60Sopenharmony_ci // for call stack id 56506f6ba60Sopenharmony_ci callStack_.push_back(callFrames[idx].callFrameId_); 56606f6ba60Sopenharmony_ci } 56706f6ba60Sopenharmony_ci} 56806f6ba60Sopenharmony_ci 56906f6ba60Sopenharmony_ciinline uint32_t StackPreprocess::FindCallStackId(std::vector<uint64_t>& callStack) 57006f6ba60Sopenharmony_ci{ 57106f6ba60Sopenharmony_ci if (hookConfig_.response_library_mode()) { 57206f6ba60Sopenharmony_ci auto itStack = responseLibraryMap_.find(callStack[0]); 57306f6ba60Sopenharmony_ci if (itStack != responseLibraryMap_.end()) { 57406f6ba60Sopenharmony_ci return itStack->second; 57506f6ba60Sopenharmony_ci } 57606f6ba60Sopenharmony_ci } else { 57706f6ba60Sopenharmony_ci auto itStack = callStackMap_.find(callStack); 57806f6ba60Sopenharmony_ci if (itStack != callStackMap_.end()) { 57906f6ba60Sopenharmony_ci return itStack->second; 58006f6ba60Sopenharmony_ci } 58106f6ba60Sopenharmony_ci } 58206f6ba60Sopenharmony_ci return 0; 58306f6ba60Sopenharmony_ci} 58406f6ba60Sopenharmony_ci 58506f6ba60Sopenharmony_ci/** 58606f6ba60Sopenharmony_ci * @return '0' is invalid stack id, '> 0' is valid stack id 58706f6ba60Sopenharmony_ci */ 58806f6ba60Sopenharmony_citemplate <typename T> 58906f6ba60Sopenharmony_ciinline uint32_t StackPreprocess::SetCallStackMap(T& stackData) 59006f6ba60Sopenharmony_ci{ 59106f6ba60Sopenharmony_ci uint32_t stackId = 0; 59206f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 59306f6ba60Sopenharmony_ci auto stackmap = hookData->mutable_stack_map(); 59406f6ba60Sopenharmony_ci if (hookConfig_.response_library_mode()) { 59506f6ba60Sopenharmony_ci stackId = responseLibraryMap_.size() + 1; 59606f6ba60Sopenharmony_ci } else { 59706f6ba60Sopenharmony_ci stackId = callStackMap_.size() + 1; 59806f6ba60Sopenharmony_ci } 59906f6ba60Sopenharmony_ci stackmap->set_id(stackId); 60006f6ba60Sopenharmony_ci // offline symbolization use ip, other use frame_map_id 60106f6ba60Sopenharmony_ci if (hookConfig_.offline_symbolization()) { 60206f6ba60Sopenharmony_ci if constexpr (std::is_same<T, ProtoEncoder::BatchNativeHookData>::value) { 60306f6ba60Sopenharmony_ci stackmap->add_ip(callStack_); 60406f6ba60Sopenharmony_ci } else { 60506f6ba60Sopenharmony_ci for (size_t i = 0; i < callStack_.size(); i++) { 60606f6ba60Sopenharmony_ci stackmap->add_ip(callStack_[i]); 60706f6ba60Sopenharmony_ci } 60806f6ba60Sopenharmony_ci } 60906f6ba60Sopenharmony_ci } else { 61006f6ba60Sopenharmony_ci if constexpr (std::is_same<T, ProtoEncoder::BatchNativeHookData>::value) { 61106f6ba60Sopenharmony_ci stackmap->add_frame_map_id(callStack_); 61206f6ba60Sopenharmony_ci } else { 61306f6ba60Sopenharmony_ci for (size_t i = 0; i < callStack_.size(); i++) { 61406f6ba60Sopenharmony_ci stackmap->add_frame_map_id(callStack_[i]); 61506f6ba60Sopenharmony_ci } 61606f6ba60Sopenharmony_ci } 61706f6ba60Sopenharmony_ci } 61806f6ba60Sopenharmony_ci stackmap->set_pid(pid_); 61906f6ba60Sopenharmony_ci if (hookConfig_.response_library_mode()) { 62006f6ba60Sopenharmony_ci responseLibraryMap_[callStack_[0]] = stackId; 62106f6ba60Sopenharmony_ci } else { 62206f6ba60Sopenharmony_ci callStackMap_[callStack_] = stackId; 62306f6ba60Sopenharmony_ci } 62406f6ba60Sopenharmony_ci return stackId; 62506f6ba60Sopenharmony_ci} 62606f6ba60Sopenharmony_ci 62706f6ba60Sopenharmony_ci/** 62806f6ba60Sopenharmony_ci * @return '0' is invalid stack id, '> 0' is valid stack id 62906f6ba60Sopenharmony_ci */ 63006f6ba60Sopenharmony_citemplate <typename T> 63106f6ba60Sopenharmony_ciinline uint32_t StackPreprocess::GetCallStackId(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 63206f6ba60Sopenharmony_ci T& stackData) 63306f6ba60Sopenharmony_ci{ 63406f6ba60Sopenharmony_ci // ignore the first two frame if dwarf unwind 63506f6ba60Sopenharmony_ci size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; 63606f6ba60Sopenharmony_ci // if free_stack_report or munmap_stack_report is false, don't need to record. 63706f6ba60Sopenharmony_ci if ((rawStack->stackConext->type == FREE_MSG) && !hookConfig_.free_stack_report()) { 63806f6ba60Sopenharmony_ci return 0; 63906f6ba60Sopenharmony_ci } else if ((rawStack->stackConext->type == MUNMAP_MSG) && !hookConfig_.munmap_stack_report()) { 64006f6ba60Sopenharmony_ci return 0; 64106f6ba60Sopenharmony_ci } 64206f6ba60Sopenharmony_ci callStack_.clear(); 64306f6ba60Sopenharmony_ci bool isNapi = false; 64406f6ba60Sopenharmony_ci if (rawStack->stackConext->type == MEMORY_USING_MSG && hookConfig_.js_stack_report() == NAPI_CALL_STACK) { 64506f6ba60Sopenharmony_ci std::string tagName; 64606f6ba60Sopenharmony_ci GetMemTag(rawStack->stackConext->tagId, tagName); 64706f6ba60Sopenharmony_ci if (tagName.find("napi") != std::string::npos) { 64806f6ba60Sopenharmony_ci callStack_.reserve(callFrames.size() + 1); // 1 : insert a frame 64906f6ba60Sopenharmony_ci callStack_.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK); 65006f6ba60Sopenharmony_ci isNapi = true; 65106f6ba60Sopenharmony_ci } 65206f6ba60Sopenharmony_ci } else { 65306f6ba60Sopenharmony_ci callStack_.reserve(callFrames.size()); 65406f6ba60Sopenharmony_ci } 65506f6ba60Sopenharmony_ci if (!hookConfig_.offline_symbolization()) { 65606f6ba60Sopenharmony_ci FillCallStack(callFrames, idx, stackData); 65706f6ba60Sopenharmony_ci } else { 65806f6ba60Sopenharmony_ci if ((!hookConfig_.fp_unwind()) && rawStack->stackSize == 0) { 65906f6ba60Sopenharmony_ci idx = 0; 66006f6ba60Sopenharmony_ci } 66106f6ba60Sopenharmony_ci FillOfflineCallStack(callFrames, idx, stackData); 66206f6ba60Sopenharmony_ci } 66306f6ba60Sopenharmony_ci if (isNapi) { 66406f6ba60Sopenharmony_ci // insert a frame 66506f6ba60Sopenharmony_ci std::string tagName; 66606f6ba60Sopenharmony_ci GetMemTag(rawStack->stackConext->tagId, tagName); 66706f6ba60Sopenharmony_ci FillNapiStack(tagName, callFrames, napiIndex_); 66806f6ba60Sopenharmony_ci ReportFrameMap(callFrames.back(), stackData); 66906f6ba60Sopenharmony_ci ++napiIndex_; 67006f6ba60Sopenharmony_ci } 67106f6ba60Sopenharmony_ci // return call stack id 67206f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 67306f6ba60Sopenharmony_ci uint32_t stackId = FindCallStackId(callStack_); 67406f6ba60Sopenharmony_ci if (stackId > 0) { 67506f6ba60Sopenharmony_ci return stackId; 67606f6ba60Sopenharmony_ci } else { 67706f6ba60Sopenharmony_ci return SetCallStackMap(stackData); 67806f6ba60Sopenharmony_ci } 67906f6ba60Sopenharmony_ci} 68006f6ba60Sopenharmony_ci 68106f6ba60Sopenharmony_citemplate <typename T> 68206f6ba60Sopenharmony_civoid StackPreprocess::SetEventFrame(const ReportEventBaseData& rawStack, 68306f6ba60Sopenharmony_ci T* event, uint32_t stackMapId, const std::string& type) 68406f6ba60Sopenharmony_ci{ 68506f6ba60Sopenharmony_ci event->set_pid(pid_); 68606f6ba60Sopenharmony_ci event->set_tid(rawStack.tid); 68706f6ba60Sopenharmony_ci event->set_addr(rawStack.addr); 68806f6ba60Sopenharmony_ci if constexpr (std::is_same<T, ::MmapEvent>::value || std::is_same<T, ProtoEncoder::MmapEvent>::value) { 68906f6ba60Sopenharmony_ci event->set_type(type); 69006f6ba60Sopenharmony_ci } 69106f6ba60Sopenharmony_ci 69206f6ba60Sopenharmony_ci if constexpr (!std::is_same<T, ::FreeEvent>::value && !std::is_same<T, ProtoEncoder::FreeEvent>::value) { 69306f6ba60Sopenharmony_ci auto size = static_cast<uint64_t>(rawStack.mallocSize); 69406f6ba60Sopenharmony_ci#ifdef USE_JEMALLOC 69506f6ba60Sopenharmony_ci if constexpr (std::is_same<T, ::AllocEvent>::value || std::is_same<T, ProtoEncoder::AllocEvent>::value) { 69606f6ba60Sopenharmony_ci size = static_cast<uint64_t>(ComputeAlign(size)); 69706f6ba60Sopenharmony_ci } 69806f6ba60Sopenharmony_ci#endif 69906f6ba60Sopenharmony_ci event->set_size(size); 70006f6ba60Sopenharmony_ci } 70106f6ba60Sopenharmony_ci if (hookConfig_.callframe_compress() && stackMapId != 0) { 70206f6ba60Sopenharmony_ci event->set_thread_name_id(rawStack.tid); 70306f6ba60Sopenharmony_ci event->set_stack_id(stackMapId); 70406f6ba60Sopenharmony_ci } 70506f6ba60Sopenharmony_ci event->set_thread_name_id(rawStack.tid); 70606f6ba60Sopenharmony_ci} 70706f6ba60Sopenharmony_ci 70806f6ba60Sopenharmony_citemplate <typename T> 70906f6ba60Sopenharmony_civoid StackPreprocess::SetEventFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 71006f6ba60Sopenharmony_ci T* event, uint32_t stackMapId, const std::string& type) 71106f6ba60Sopenharmony_ci{ 71206f6ba60Sopenharmony_ci // ignore the first two frame if dwarf unwind 71306f6ba60Sopenharmony_ci size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; 71406f6ba60Sopenharmony_ci event->set_pid(rawStack->stackConext->pid); 71506f6ba60Sopenharmony_ci event->set_tid(rawStack->stackConext->tid); 71606f6ba60Sopenharmony_ci event->set_addr((uint64_t)rawStack->stackConext->addr); 71706f6ba60Sopenharmony_ci 71806f6ba60Sopenharmony_ci if constexpr (std::is_same<T, ::MmapEvent>::value || std::is_same<T, ProtoEncoder::MmapEvent>::value) { 71906f6ba60Sopenharmony_ci event->set_type(type); 72006f6ba60Sopenharmony_ci } 72106f6ba60Sopenharmony_ci 72206f6ba60Sopenharmony_ci if constexpr (!std::is_same<T, ::FreeEvent>::value && !std::is_same<T, ProtoEncoder::FreeEvent>::value) { 72306f6ba60Sopenharmony_ci auto size = static_cast<uint64_t>(rawStack->stackConext->mallocSize); 72406f6ba60Sopenharmony_ci#ifdef USE_JEMALLOC 72506f6ba60Sopenharmony_ci if constexpr (std::is_same<T, ::AllocEvent>::value || std::is_same<T, ProtoEncoder::AllocEvent>::value) { 72606f6ba60Sopenharmony_ci size = static_cast<uint64_t>(ComputeAlign(size)); 72706f6ba60Sopenharmony_ci } 72806f6ba60Sopenharmony_ci#endif 72906f6ba60Sopenharmony_ci event->set_size(size); 73006f6ba60Sopenharmony_ci } 73106f6ba60Sopenharmony_ci 73206f6ba60Sopenharmony_ci if (hookConfig_.callframe_compress() && stackMapId != 0) { 73306f6ba60Sopenharmony_ci event->set_thread_name_id(rawStack->stackConext->tid); 73406f6ba60Sopenharmony_ci event->set_stack_id(stackMapId); 73506f6ba60Sopenharmony_ci } else { 73606f6ba60Sopenharmony_ci for (; idx < callFrames.size(); ++idx) { 73706f6ba60Sopenharmony_ci auto frame = event->add_frame_info(); 73806f6ba60Sopenharmony_ci SetFrameInfo(*frame, callFrames[idx]); 73906f6ba60Sopenharmony_ci } 74006f6ba60Sopenharmony_ci event->set_thread_name_id(rawStack->stackConext->tid); 74106f6ba60Sopenharmony_ci } 74206f6ba60Sopenharmony_ci} 74306f6ba60Sopenharmony_ci 74406f6ba60Sopenharmony_civoid StackPreprocess::FillNapiStack(std::string& tagName, std::vector<CallFrame>& callFrames, uint64_t napiIndex) 74506f6ba60Sopenharmony_ci{ 74606f6ba60Sopenharmony_ci #if defined(__aarch64__) 74706f6ba60Sopenharmony_ci uintptr_t pacMask = 0xFFFFFF8000000000; 74806f6ba60Sopenharmony_ci#else 74906f6ba60Sopenharmony_ci uintptr_t pacMask = 0; 75006f6ba60Sopenharmony_ci#endif 75106f6ba60Sopenharmony_ci CallFrame& jsCallFrame = callFrames_.emplace_back(0 & (~pacMask)); 75206f6ba60Sopenharmony_ci jsCallFrame.symbolName_ = tagName; 75306f6ba60Sopenharmony_ci jsCallFrame.isJsFrame_ = true; 75406f6ba60Sopenharmony_ci jsCallFrame.needReport_ |= CALL_FRAME_REPORT; 75506f6ba60Sopenharmony_ci jsCallFrame.needReport_ |= SYMBOL_NAME_ID_REPORT; 75606f6ba60Sopenharmony_ci jsCallFrame.needReport_ |= FILE_PATH_ID_REPORT; 75706f6ba60Sopenharmony_ci jsCallFrame.callFrameId_ = DWARF_NAPI_CALLBACK + napiIndex; 75806f6ba60Sopenharmony_ci jsCallFrame.symbolNameId_ = DWARF_NAPI_CALLBACK + napiIndex; 75906f6ba60Sopenharmony_ci jsCallFrame.filePathId_ = DWARF_NAPI_CALLBACK + napiIndex; 76006f6ba60Sopenharmony_ci jsCallFrame.filePath_ = "no-napi-file-path"; 76106f6ba60Sopenharmony_ci} 76206f6ba60Sopenharmony_ci 76306f6ba60Sopenharmony_citemplate <typename T> 76406f6ba60Sopenharmony_civoid StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 76506f6ba60Sopenharmony_ci T& stackData) 76606f6ba60Sopenharmony_ci{ 76706f6ba60Sopenharmony_ci // ignore the first two frame if dwarf unwind 76806f6ba60Sopenharmony_ci size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; 76906f6ba60Sopenharmony_ci callStack_.clear(); 77006f6ba60Sopenharmony_ci bool isNapi = false; 77106f6ba60Sopenharmony_ci if (hookConfig_.js_stack_report() == NAPI_CALL_STACK) { 77206f6ba60Sopenharmony_ci std::string tagName; 77306f6ba60Sopenharmony_ci GetMemTag(rawStack->stackConext->tagId, tagName); 77406f6ba60Sopenharmony_ci if (tagName.find("napi") != std::string::npos) { 77506f6ba60Sopenharmony_ci callStack_.reserve(callFrames.size() + FRAME_DEPTH); // insert a frame 77606f6ba60Sopenharmony_ci callStack_.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK); 77706f6ba60Sopenharmony_ci isNapi = true; 77806f6ba60Sopenharmony_ci } 77906f6ba60Sopenharmony_ci } else { 78006f6ba60Sopenharmony_ci callStack_.reserve(callFrames.size() + 1); 78106f6ba60Sopenharmony_ci } 78206f6ba60Sopenharmony_ci callStack_.push_back(rawStack->stackConext->mallocSize | SIZE_MASK); 78306f6ba60Sopenharmony_ci if (!hookConfig_.offline_symbolization()) { 78406f6ba60Sopenharmony_ci FillCallStack(callFrames, idx, stackData); 78506f6ba60Sopenharmony_ci } else { 78606f6ba60Sopenharmony_ci FillOfflineCallStack(callFrames, idx, stackData); 78706f6ba60Sopenharmony_ci } 78806f6ba60Sopenharmony_ci // insert a frame 78906f6ba60Sopenharmony_ci if (isNapi) { 79006f6ba60Sopenharmony_ci std::string tagName; 79106f6ba60Sopenharmony_ci GetMemTag(rawStack->stackConext->tagId, tagName); 79206f6ba60Sopenharmony_ci FillNapiStack(tagName, callFrames, napiIndex_); 79306f6ba60Sopenharmony_ci ReportFrameMap(callFrames.back(), stackData); 79406f6ba60Sopenharmony_ci ++napiIndex_; 79506f6ba60Sopenharmony_ci } 79606f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 79706f6ba60Sopenharmony_ci // by call stack id set alloc statistics data. 79806f6ba60Sopenharmony_ci uint32_t stackId = FindCallStackId(callStack_); 79906f6ba60Sopenharmony_ci if (stackId > 0) { 80006f6ba60Sopenharmony_ci SetAllocStatisticsData(rawStack, stackId, true); 80106f6ba60Sopenharmony_ci } else { 80206f6ba60Sopenharmony_ci stackId = SetCallStackMap(stackData); 80306f6ba60Sopenharmony_ci statisticsModelFlushCallstack_ = true; 80406f6ba60Sopenharmony_ci SetAllocStatisticsData(rawStack, stackId); 80506f6ba60Sopenharmony_ci } 80606f6ba60Sopenharmony_ci} 80706f6ba60Sopenharmony_ci 80806f6ba60Sopenharmony_citemplate <typename T> 80906f6ba60Sopenharmony_civoid StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, T& stackData) 81006f6ba60Sopenharmony_ci{ 81106f6ba60Sopenharmony_ci callStack_.resize(rawStack->fpDepth + 1); 81206f6ba60Sopenharmony_ci callStack_[0] = (rawStack->stackConext->mallocSize | SIZE_MASK); 81306f6ba60Sopenharmony_ci if (memcpy_s(callStack_.data() + 1, sizeof(uint64_t) * rawStack->fpDepth, 81406f6ba60Sopenharmony_ci rawStack->data, sizeof(uint64_t) * rawStack->fpDepth) != EOK) { 81506f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s callStack_ failed"); 81606f6ba60Sopenharmony_ci return; 81706f6ba60Sopenharmony_ci } 81806f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 81906f6ba60Sopenharmony_ci // by call stack id set alloc statistics data. 82006f6ba60Sopenharmony_ci uint32_t stackId = FindCallStackId(callStack_); 82106f6ba60Sopenharmony_ci if (stackId > 0) { 82206f6ba60Sopenharmony_ci SetAllocStatisticsData(rawStack, stackId, true); 82306f6ba60Sopenharmony_ci } else { 82406f6ba60Sopenharmony_ci stackId = SetCallStackMap(stackData); 82506f6ba60Sopenharmony_ci statisticsModelFlushCallstack_ = true; 82606f6ba60Sopenharmony_ci SetAllocStatisticsData(rawStack, stackId); 82706f6ba60Sopenharmony_ci } 82806f6ba60Sopenharmony_ci} 82906f6ba60Sopenharmony_ci 83006f6ba60Sopenharmony_citemplate <typename T> 83106f6ba60Sopenharmony_civoid StackPreprocess::SetHookData(RawStackPtr rawStack, T& stackData) 83206f6ba60Sopenharmony_ci{ 83306f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0) { 83406f6ba60Sopenharmony_ci // statistical reporting must is compressed and accurate. 83506f6ba60Sopenharmony_ci switch (rawStack->stackConext->type) { 83606f6ba60Sopenharmony_ci case FREE_MSG: 83706f6ba60Sopenharmony_ci case MUNMAP_MSG: 83806f6ba60Sopenharmony_ci case MEMORY_UNUSING_MSG: { 83906f6ba60Sopenharmony_ci SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr); 84006f6ba60Sopenharmony_ci break; 84106f6ba60Sopenharmony_ci } 84206f6ba60Sopenharmony_ci case MALLOC_MSG: 84306f6ba60Sopenharmony_ci rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize); 84406f6ba60Sopenharmony_ci case MMAP_MSG: 84506f6ba60Sopenharmony_ci case MMAP_FILE_PAGE_MSG: 84606f6ba60Sopenharmony_ci case MEMORY_USING_MSG: { 84706f6ba60Sopenharmony_ci SetAllocStatisticsFrame(rawStack, stackData); 84806f6ba60Sopenharmony_ci break; 84906f6ba60Sopenharmony_ci } 85006f6ba60Sopenharmony_ci case PR_SET_VMA_MSG: { 85106f6ba60Sopenharmony_ci break; 85206f6ba60Sopenharmony_ci } 85306f6ba60Sopenharmony_ci default: { 85406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "statistics event type: error"); 85506f6ba60Sopenharmony_ci break; 85606f6ba60Sopenharmony_ci } 85706f6ba60Sopenharmony_ci } 85806f6ba60Sopenharmony_ci return; 85906f6ba60Sopenharmony_ci } 86006f6ba60Sopenharmony_ci} 86106f6ba60Sopenharmony_ci 86206f6ba60Sopenharmony_civoid StackPreprocess::ReportOfflineSymbolizationData() 86306f6ba60Sopenharmony_ci{ 86406f6ba60Sopenharmony_ci if (hookConfig_.offline_symbolization() && flushBasicData_) { 86506f6ba60Sopenharmony_ci SetMapsInfo(); 86606f6ba60Sopenharmony_ci flushBasicData_ = false; 86706f6ba60Sopenharmony_ci } 86806f6ba60Sopenharmony_ci} 86906f6ba60Sopenharmony_ci 87006f6ba60Sopenharmony_citemplate <typename T> 87106f6ba60Sopenharmony_civoid StackPreprocess::SetApplyAndReleaseMatchFrame(RawStackPtr rawStack, std::vector<CallFrame>& callFrames, 87206f6ba60Sopenharmony_ci T& stackData) 87306f6ba60Sopenharmony_ci{ 87406f6ba60Sopenharmony_ci uint32_t stackMapId = 0; 87506f6ba60Sopenharmony_ci if (rawStack->stackConext->type != PR_SET_VMA_MSG) { 87606f6ba60Sopenharmony_ci stackMapId = GetCallStackId(rawStack, callFrames, stackData); 87706f6ba60Sopenharmony_ci } else { 87806f6ba60Sopenharmony_ci rawStack->stackConext->tagId = prctlPeriodTags_.size(); 87906f6ba60Sopenharmony_ci prctlPeriodTags_.emplace_back(reinterpret_cast<char*>(rawStack->data)); 88006f6ba60Sopenharmony_ci applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackConext); 88106f6ba60Sopenharmony_ci } 88206f6ba60Sopenharmony_ci if (rawStack->stackConext->type == MALLOC_MSG) { 88306f6ba60Sopenharmony_ci rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize); 88406f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == PR_SET_VMA_MSG) { 88506f6ba60Sopenharmony_ci return; 88606f6ba60Sopenharmony_ci } 88706f6ba60Sopenharmony_ci uint64_t addr = reinterpret_cast<uint64_t>(rawStack->stackConext->addr); 88806f6ba60Sopenharmony_ci auto iter = applyAndReleaseMatchIntervallMap_.find(addr); 88906f6ba60Sopenharmony_ci if (iter != applyAndReleaseMatchIntervallMap_.end()) { 89006f6ba60Sopenharmony_ci applyAndReleaseMatchPeriodListData_.erase(iter->second); 89106f6ba60Sopenharmony_ci applyAndReleaseMatchIntervallMap_.erase(addr); 89206f6ba60Sopenharmony_ci } else { 89306f6ba60Sopenharmony_ci applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackConext, stackMapId); 89406f6ba60Sopenharmony_ci applyAndReleaseMatchIntervallMap_.emplace(addr, std::prev(applyAndReleaseMatchPeriodListData_.end())); 89506f6ba60Sopenharmony_ci } 89606f6ba60Sopenharmony_ci} 89706f6ba60Sopenharmony_ci 89806f6ba60Sopenharmony_citemplate <typename T> 89906f6ba60Sopenharmony_civoid StackPreprocess::SetHookData(RawStackPtr rawStack, std::vector<CallFrame>& callFrames, T& stackData) 90006f6ba60Sopenharmony_ci{ 90106f6ba60Sopenharmony_ci // statistical reporting must is compressed and accurate. 90206f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0) { 90306f6ba60Sopenharmony_ci switch (rawStack->stackConext->type) { 90406f6ba60Sopenharmony_ci case FREE_MSG: 90506f6ba60Sopenharmony_ci case MUNMAP_MSG: 90606f6ba60Sopenharmony_ci case MEMORY_UNUSING_MSG: { 90706f6ba60Sopenharmony_ci SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr); 90806f6ba60Sopenharmony_ci break; 90906f6ba60Sopenharmony_ci } 91006f6ba60Sopenharmony_ci case MALLOC_MSG: 91106f6ba60Sopenharmony_ci rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize); 91206f6ba60Sopenharmony_ci case MMAP_MSG: 91306f6ba60Sopenharmony_ci case MMAP_FILE_PAGE_MSG: 91406f6ba60Sopenharmony_ci case MEMORY_USING_MSG: { 91506f6ba60Sopenharmony_ci SetAllocStatisticsFrame(rawStack, callFrames, stackData); 91606f6ba60Sopenharmony_ci break; 91706f6ba60Sopenharmony_ci } 91806f6ba60Sopenharmony_ci case PR_SET_VMA_MSG: { 91906f6ba60Sopenharmony_ci break; 92006f6ba60Sopenharmony_ci } 92106f6ba60Sopenharmony_ci default: { 92206f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "statistics event type:%d error", rawStack->stackConext->type); 92306f6ba60Sopenharmony_ci break; 92406f6ba60Sopenharmony_ci } 92506f6ba60Sopenharmony_ci } 92606f6ba60Sopenharmony_ci return; 92706f6ba60Sopenharmony_ci } 92806f6ba60Sopenharmony_ci 92906f6ba60Sopenharmony_ci uint32_t stackMapId = 0; 93006f6ba60Sopenharmony_ci if (hookConfig_.callframe_compress() && 93106f6ba60Sopenharmony_ci !(rawStack->stackConext->type == MEMORY_TAG || rawStack->stackConext->type == PR_SET_VMA_MSG)) { 93206f6ba60Sopenharmony_ci stackMapId = GetCallStackId(rawStack, callFrames, stackData); 93306f6ba60Sopenharmony_ci } 93406f6ba60Sopenharmony_ci 93506f6ba60Sopenharmony_ci if ((!hookConfig_.callframe_compress() || stackMapId == 0) && hookConfig_.string_compressed()) { 93606f6ba60Sopenharmony_ci size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; 93706f6ba60Sopenharmony_ci for (; idx < callFrames.size(); ++idx) { 93806f6ba60Sopenharmony_ci ReportSymbolNameMap(callFrames[idx], stackData); 93906f6ba60Sopenharmony_ci ReportFilePathMap(callFrames[idx], stackData); 94006f6ba60Sopenharmony_ci } 94106f6ba60Sopenharmony_ci } 94206f6ba60Sopenharmony_ci 94306f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 94406f6ba60Sopenharmony_ci hookData->set_tv_sec(rawStack->stackConext->ts.tv_sec); 94506f6ba60Sopenharmony_ci hookData->set_tv_nsec(rawStack->stackConext->ts.tv_nsec); 94606f6ba60Sopenharmony_ci 94706f6ba60Sopenharmony_ci if (rawStack->stackConext->type == MALLOC_MSG) { 94806f6ba60Sopenharmony_ci auto allocEvent = hookData->mutable_alloc_event(); 94906f6ba60Sopenharmony_ci SetEventFrame(rawStack, callFrames, allocEvent, stackMapId); 95006f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == FREE_MSG) { 95106f6ba60Sopenharmony_ci auto freeEvent = hookData->mutable_free_event(); 95206f6ba60Sopenharmony_ci SetEventFrame(rawStack, callFrames, freeEvent, stackMapId); 95306f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == MMAP_MSG) { 95406f6ba60Sopenharmony_ci auto mmapEvent = hookData->mutable_mmap_event(); 95506f6ba60Sopenharmony_ci SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId); 95606f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == MMAP_FILE_PAGE_MSG) { 95706f6ba60Sopenharmony_ci auto mmapEvent = hookData->mutable_mmap_event(); 95806f6ba60Sopenharmony_ci const std::string prefix = "FilePage:"; 95906f6ba60Sopenharmony_ci std::string tagName; 96006f6ba60Sopenharmony_ci if (GetMemTag(rawStack->stackConext->tagId, tagName)) { 96106f6ba60Sopenharmony_ci tagName = prefix + tagName; 96206f6ba60Sopenharmony_ci } 96306f6ba60Sopenharmony_ci SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId, tagName); 96406f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == MUNMAP_MSG) { 96506f6ba60Sopenharmony_ci auto munmapEvent = hookData->mutable_munmap_event(); 96606f6ba60Sopenharmony_ci SetEventFrame(rawStack, callFrames, munmapEvent, stackMapId); 96706f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == PR_SET_VMA_MSG) { 96806f6ba60Sopenharmony_ci auto tagEvent = hookData->mutable_tag_event(); 96906f6ba60Sopenharmony_ci const std::string prefix = "Anonymous:"; 97006f6ba60Sopenharmony_ci std::string tagName(reinterpret_cast<char*>(rawStack->data)); 97106f6ba60Sopenharmony_ci tagEvent->set_addr((uint64_t)rawStack->stackConext->addr); 97206f6ba60Sopenharmony_ci tagEvent->set_size(rawStack->stackConext->mallocSize); 97306f6ba60Sopenharmony_ci tagEvent->set_tag(prefix + tagName); 97406f6ba60Sopenharmony_ci tagEvent->set_pid(pid_); 97506f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == MEMORY_USING_MSG) { 97606f6ba60Sopenharmony_ci auto mmapEvent = hookData->mutable_mmap_event(); 97706f6ba60Sopenharmony_ci std::string tagName; 97806f6ba60Sopenharmony_ci GetMemTag(rawStack->stackConext->tagId, tagName); 97906f6ba60Sopenharmony_ci SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId, tagName); 98006f6ba60Sopenharmony_ci } else if (rawStack->stackConext->type == MEMORY_UNUSING_MSG) { 98106f6ba60Sopenharmony_ci auto munmapEvent = hookData->mutable_munmap_event(); 98206f6ba60Sopenharmony_ci SetEventFrame(rawStack, callFrames, munmapEvent, stackMapId); 98306f6ba60Sopenharmony_ci } 98406f6ba60Sopenharmony_ci} 98506f6ba60Sopenharmony_ci 98606f6ba60Sopenharmony_ciinline bool StackPreprocess::SetFreeStatisticsData(uint64_t addr) 98706f6ba60Sopenharmony_ci{ 98806f6ba60Sopenharmony_ci // through the addr lookup record 98906f6ba60Sopenharmony_ci auto addrIter = allocAddrMap_.find(addr); 99006f6ba60Sopenharmony_ci if (addrIter != allocAddrMap_.end()) { 99106f6ba60Sopenharmony_ci auto& record = addrIter->second.second; 99206f6ba60Sopenharmony_ci ++record->releaseCount; 99306f6ba60Sopenharmony_ci record->releaseSize += addrIter->second.first; 99406f6ba60Sopenharmony_ci statisticsPeriodData_[record->callstackId] = record; 99506f6ba60Sopenharmony_ci allocAddrMap_.erase(addr); 99606f6ba60Sopenharmony_ci return true; 99706f6ba60Sopenharmony_ci } 99806f6ba60Sopenharmony_ci return false; 99906f6ba60Sopenharmony_ci} 100006f6ba60Sopenharmony_ci 100106f6ba60Sopenharmony_ciinline void StackPreprocess::SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists) 100206f6ba60Sopenharmony_ci{ 100306f6ba60Sopenharmony_ci // if the record exists, it is updated.Otherwise Add 100406f6ba60Sopenharmony_ci if (isExists) { 100506f6ba60Sopenharmony_ci auto recordIter = recordStatisticsMap_.find(stackId); 100606f6ba60Sopenharmony_ci if (recordIter != recordStatisticsMap_.end()) { 100706f6ba60Sopenharmony_ci auto& record = recordIter->second; 100806f6ba60Sopenharmony_ci ++record.applyCount; 100906f6ba60Sopenharmony_ci record.applySize += rawStack->stackConext->mallocSize; 101006f6ba60Sopenharmony_ci allocAddrMap_[(uint64_t)rawStack->stackConext->addr] = 101106f6ba60Sopenharmony_ci std::pair(rawStack->stackConext->mallocSize, &recordIter->second); 101206f6ba60Sopenharmony_ci statisticsPeriodData_[stackId] = &recordIter->second; 101306f6ba60Sopenharmony_ci } 101406f6ba60Sopenharmony_ci } else { 101506f6ba60Sopenharmony_ci RecordStatistic record; 101606f6ba60Sopenharmony_ci record.pid = rawStack->stackConext->pid; 101706f6ba60Sopenharmony_ci record.callstackId = stackId; 101806f6ba60Sopenharmony_ci record.applyCount = 1; 101906f6ba60Sopenharmony_ci record.applySize = rawStack->stackConext->mallocSize; 102006f6ba60Sopenharmony_ci switch (rawStack->stackConext->type) { 102106f6ba60Sopenharmony_ci case MALLOC_MSG: { 102206f6ba60Sopenharmony_ci record.type = RecordStatisticsEvent::MALLOC; 102306f6ba60Sopenharmony_ci break; 102406f6ba60Sopenharmony_ci } 102506f6ba60Sopenharmony_ci case MMAP_MSG: { 102606f6ba60Sopenharmony_ci record.type = RecordStatisticsEvent::MMAP; 102706f6ba60Sopenharmony_ci break; 102806f6ba60Sopenharmony_ci } 102906f6ba60Sopenharmony_ci case MMAP_FILE_PAGE_MSG: { 103006f6ba60Sopenharmony_ci record.type = RecordStatisticsEvent::FILE_PAGE_MSG; 103106f6ba60Sopenharmony_ci break; 103206f6ba60Sopenharmony_ci } 103306f6ba60Sopenharmony_ci case MEMORY_USING_MSG: { 103406f6ba60Sopenharmony_ci record.type = RecordStatisticsEvent::MEMORY_USING_MSG; 103506f6ba60Sopenharmony_ci record.tagId = rawStack->stackConext->tagId; 103606f6ba60Sopenharmony_ci break; 103706f6ba60Sopenharmony_ci } 103806f6ba60Sopenharmony_ci default: { 103906f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "SetAllocStatisticsData event type error"); 104006f6ba60Sopenharmony_ci break; 104106f6ba60Sopenharmony_ci } 104206f6ba60Sopenharmony_ci } 104306f6ba60Sopenharmony_ci 104406f6ba60Sopenharmony_ci auto [recordIter, stat] = recordStatisticsMap_.emplace(stackId, record); 104506f6ba60Sopenharmony_ci allocAddrMap_[(uint64_t)rawStack->stackConext->addr] = 104606f6ba60Sopenharmony_ci std::pair(rawStack->stackConext->mallocSize, &recordIter->second); 104706f6ba60Sopenharmony_ci statisticsPeriodData_[stackId] = &recordIter->second; 104806f6ba60Sopenharmony_ci } 104906f6ba60Sopenharmony_ci} 105006f6ba60Sopenharmony_ci 105106f6ba60Sopenharmony_civoid StackPreprocess::WriteFrames(RawStackPtr rawStack, const std::vector<CallFrame>& callFrames) 105206f6ba60Sopenharmony_ci{ 105306f6ba60Sopenharmony_ci CHECK_TRUE(fpHookData_ != nullptr, NO_RETVAL, "fpHookData_ is nullptr, please check file_name(%s)", 105406f6ba60Sopenharmony_ci hookConfig_.file_name().c_str()); 105506f6ba60Sopenharmony_ci if (rawStack->stackConext->type == PR_SET_VMA_MSG) { 105606f6ba60Sopenharmony_ci const std::string prefix = "Anonymous:"; 105706f6ba60Sopenharmony_ci std::string tagName(reinterpret_cast<char*>(rawStack->data)); 105806f6ba60Sopenharmony_ci fprintf(fpHookData_, "prctl;%u;%u;%" PRId64 ";%ld;0x%" PRIx64 ":tag:%s\n", 105906f6ba60Sopenharmony_ci rawStack->stackConext->pid, rawStack->stackConext->tid, 106006f6ba60Sopenharmony_ci (int64_t)rawStack->stackConext->ts.tv_sec, rawStack->stackConext->ts.tv_nsec, 106106f6ba60Sopenharmony_ci (uint64_t)rawStack->stackConext->addr, (prefix + tagName).c_str()); 106206f6ba60Sopenharmony_ci return; 106306f6ba60Sopenharmony_ci } 106406f6ba60Sopenharmony_ci std::string tag = ""; 106506f6ba60Sopenharmony_ci switch (rawStack->stackConext->type) { 106606f6ba60Sopenharmony_ci case FREE_MSG: 106706f6ba60Sopenharmony_ci tag = "free"; 106806f6ba60Sopenharmony_ci break; 106906f6ba60Sopenharmony_ci case MALLOC_MSG: 107006f6ba60Sopenharmony_ci tag = "malloc"; 107106f6ba60Sopenharmony_ci break; 107206f6ba60Sopenharmony_ci case MMAP_MSG: 107306f6ba60Sopenharmony_ci tag = "mmap"; 107406f6ba60Sopenharmony_ci break; 107506f6ba60Sopenharmony_ci case MUNMAP_MSG: 107606f6ba60Sopenharmony_ci tag = "munmap"; 107706f6ba60Sopenharmony_ci break; 107806f6ba60Sopenharmony_ci default: 107906f6ba60Sopenharmony_ci break; 108006f6ba60Sopenharmony_ci } 108106f6ba60Sopenharmony_ci 108206f6ba60Sopenharmony_ci fprintf(fpHookData_, "%s;%u;%u;%" PRId64 ";%ld;0x%" PRIx64 ";%zu\n", tag.c_str(), 108306f6ba60Sopenharmony_ci rawStack->stackConext->pid, rawStack->stackConext->tid, (int64_t)rawStack->stackConext->ts.tv_sec, 108406f6ba60Sopenharmony_ci rawStack->stackConext->ts.tv_nsec, (uint64_t)rawStack->stackConext->addr, rawStack->stackConext->mallocSize); 108506f6ba60Sopenharmony_ci size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; 108606f6ba60Sopenharmony_ci for (; idx < callFrames.size(); ++idx) { 108706f6ba60Sopenharmony_ci (void)fprintf(fpHookData_, "0x%" PRIx64 ";0x%" PRIx64 ";%s;%s;0x%" PRIx64 ";%" PRIu64 "\n", 108806f6ba60Sopenharmony_ci callFrames[idx].ip_, callFrames[idx].sp_, std::string(callFrames[idx].symbolName_).c_str(), 108906f6ba60Sopenharmony_ci std::string(callFrames[idx].filePath_).c_str(), callFrames[idx].offset_, callFrames[idx].symbolOffset_); 109006f6ba60Sopenharmony_ci } 109106f6ba60Sopenharmony_ci} 109206f6ba60Sopenharmony_ci 109306f6ba60Sopenharmony_citemplate <typename T> 109406f6ba60Sopenharmony_ciinline void StackPreprocess::SetFrameInfo(T& frame, CallFrame& callFrame) 109506f6ba60Sopenharmony_ci{ 109606f6ba60Sopenharmony_ci frame.set_ip(callFrame.ip_); 109706f6ba60Sopenharmony_ci if (hookConfig_.offline_symbolization()) { 109806f6ba60Sopenharmony_ci // when js mixes offline symbols, the js call stack is reported according to the online symbolization 109906f6ba60Sopenharmony_ci if (callFrame.isJsFrame_ && callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) { 110006f6ba60Sopenharmony_ci frame.set_sp(callFrame.sp_); 110106f6ba60Sopenharmony_ci frame.set_offset(callFrame.offset_); 110206f6ba60Sopenharmony_ci frame.set_symbol_offset(callFrame.symbolOffset_); 110306f6ba60Sopenharmony_ci frame.set_symbol_name_id(callFrame.symbolNameId_); 110406f6ba60Sopenharmony_ci frame.set_file_path_id(callFrame.filePathId_); 110506f6ba60Sopenharmony_ci } 110606f6ba60Sopenharmony_ci return; 110706f6ba60Sopenharmony_ci } 110806f6ba60Sopenharmony_ci frame.set_sp(callFrame.sp_); 110906f6ba60Sopenharmony_ci if (!(callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0)) { 111006f6ba60Sopenharmony_ci frame.set_symbol_name(std::string(callFrame.symbolName_)); 111106f6ba60Sopenharmony_ci frame.set_file_path(std::string(callFrame.filePath_)); 111206f6ba60Sopenharmony_ci } 111306f6ba60Sopenharmony_ci frame.set_offset(callFrame.offset_); 111406f6ba60Sopenharmony_ci frame.set_symbol_offset(callFrame.symbolOffset_); 111506f6ba60Sopenharmony_ci if (callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) { 111606f6ba60Sopenharmony_ci frame.set_symbol_name_id(callFrame.symbolNameId_); 111706f6ba60Sopenharmony_ci frame.set_file_path_id(callFrame.filePathId_); 111806f6ba60Sopenharmony_ci } 111906f6ba60Sopenharmony_ci} 112006f6ba60Sopenharmony_ci 112106f6ba60Sopenharmony_citemplate <typename T> 112206f6ba60Sopenharmony_ciinline void StackPreprocess::ReportSymbolNameMap(CallFrame& callFrame, T& stackData) 112306f6ba60Sopenharmony_ci{ 112406f6ba60Sopenharmony_ci if (callFrame.needReport_ & SYMBOL_NAME_ID_REPORT) { 112506f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 112606f6ba60Sopenharmony_ci auto symbolMap = hookData->mutable_symbol_name(); 112706f6ba60Sopenharmony_ci symbolMap->set_id(callFrame.symbolNameId_); 112806f6ba60Sopenharmony_ci symbolMap->set_name(std::string(callFrame.symbolName_)); 112906f6ba60Sopenharmony_ci symbolMap->set_pid(pid_); 113006f6ba60Sopenharmony_ci } 113106f6ba60Sopenharmony_ci} 113206f6ba60Sopenharmony_ci 113306f6ba60Sopenharmony_citemplate <typename T> 113406f6ba60Sopenharmony_ciinline void StackPreprocess::ReportFilePathMap(CallFrame& callFrame, T& stackData) 113506f6ba60Sopenharmony_ci{ 113606f6ba60Sopenharmony_ci if (callFrame.needReport_ & FILE_PATH_ID_REPORT) { 113706f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 113806f6ba60Sopenharmony_ci auto filePathMap = hookData->mutable_file_path(); 113906f6ba60Sopenharmony_ci filePathMap->set_id(callFrame.filePathId_); 114006f6ba60Sopenharmony_ci filePathMap->set_name(std::string(callFrame.filePath_)); 114106f6ba60Sopenharmony_ci filePathMap->set_pid(pid_); 114206f6ba60Sopenharmony_ci } 114306f6ba60Sopenharmony_ci} 114406f6ba60Sopenharmony_ci 114506f6ba60Sopenharmony_citemplate <typename T> 114606f6ba60Sopenharmony_ciinline void StackPreprocess::ReportFrameMap(CallFrame& callFrame, T& stackData) 114706f6ba60Sopenharmony_ci{ 114806f6ba60Sopenharmony_ci if (callFrame.needReport_ & CALL_FRAME_REPORT) { 114906f6ba60Sopenharmony_ci if ((!hookConfig_.fp_unwind()) && callFrame.callFrameId_ == DWARF_ERROR_ID && !unwindFailReport_) { 115006f6ba60Sopenharmony_ci return; 115106f6ba60Sopenharmony_ci } else if ((!hookConfig_.fp_unwind()) && callFrame.callFrameId_ == DWARF_ERROR_ID && unwindFailReport_) { 115206f6ba60Sopenharmony_ci unwindFailReport_ = false; 115306f6ba60Sopenharmony_ci } 115406f6ba60Sopenharmony_ci ReportSymbolNameMap(callFrame, stackData); 115506f6ba60Sopenharmony_ci ReportFilePathMap(callFrame, stackData); 115606f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 115706f6ba60Sopenharmony_ci auto frameMap = hookData->mutable_frame_map(); 115806f6ba60Sopenharmony_ci frameMap->set_id(callFrame.callFrameId_); 115906f6ba60Sopenharmony_ci auto frame = frameMap->mutable_frame(); 116006f6ba60Sopenharmony_ci SetFrameInfo(*frame, callFrame); 116106f6ba60Sopenharmony_ci frameMap->set_pid(pid_); 116206f6ba60Sopenharmony_ci } 116306f6ba60Sopenharmony_ci} 116406f6ba60Sopenharmony_ci 116506f6ba60Sopenharmony_civoid StackPreprocess::SetMapsInfo() 116606f6ba60Sopenharmony_ci{ 116706f6ba60Sopenharmony_ci std::lock_guard<std::mutex> guard(mtx_); 116806f6ba60Sopenharmony_ci for (auto& itemSoBegin : runtime_instance->GetOfflineMaps()) { 116906f6ba60Sopenharmony_ci auto& maps = runtime_instance->GetMapsCache(); 117006f6ba60Sopenharmony_ci auto mapsIter = maps.find(itemSoBegin); 117106f6ba60Sopenharmony_ci if (mapsIter == maps.end()) { 117206f6ba60Sopenharmony_ci continue; 117306f6ba60Sopenharmony_ci } 117406f6ba60Sopenharmony_ci 117506f6ba60Sopenharmony_ci ElfSymbolTable symbolInfo; 117606f6ba60Sopenharmony_ci auto& curMemMaps = mapsIter->second; 117706f6ba60Sopenharmony_ci GetSymbols(curMemMaps->name_, symbolInfo); 117806f6ba60Sopenharmony_ci if (symbolInfo.symEntSize == 0) { 117906f6ba60Sopenharmony_ci continue; 118006f6ba60Sopenharmony_ci } 118106f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 118206f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 118306f6ba60Sopenharmony_ci auto filepathMap = hookData->mutable_file_path(); 118406f6ba60Sopenharmony_ci filepathMap->set_id(curMemMaps->filePathId_); 118506f6ba60Sopenharmony_ci filepathMap->set_name(curMemMaps->name_); 118606f6ba60Sopenharmony_ci filepathMap->set_pid(pid_); 118706f6ba60Sopenharmony_ci SetSymbolInfo(curMemMaps->filePathId_, symbolInfo, stackData); 118806f6ba60Sopenharmony_ci 118906f6ba60Sopenharmony_ci for (auto& map : curMemMaps->GetMaps()) { 119006f6ba60Sopenharmony_ci if (map->prots & PROT_EXEC) { 119106f6ba60Sopenharmony_ci auto nativeHookData = stackData.add_events(); 119206f6ba60Sopenharmony_ci auto mapSerialize = nativeHookData->mutable_maps_info(); 119306f6ba60Sopenharmony_ci mapSerialize->set_pid(pid_); 119406f6ba60Sopenharmony_ci mapSerialize->set_start(map->begin); 119506f6ba60Sopenharmony_ci mapSerialize->set_end(map->end); 119606f6ba60Sopenharmony_ci mapSerialize->set_offset(map->offset); 119706f6ba60Sopenharmony_ci mapSerialize->set_file_path_id(curMemMaps->filePathId_); 119806f6ba60Sopenharmony_ci } 119906f6ba60Sopenharmony_ci } 120006f6ba60Sopenharmony_ci FlushData(stackData); 120106f6ba60Sopenharmony_ci }, stackData_); 120206f6ba60Sopenharmony_ci } 120306f6ba60Sopenharmony_ci runtime_instance->ClearOfflineMaps(); 120406f6ba60Sopenharmony_ci} 120506f6ba60Sopenharmony_ci 120606f6ba60Sopenharmony_citemplate <typename T> 120706f6ba60Sopenharmony_civoid StackPreprocess::SetSymbolInfo(uint32_t filePathId, ElfSymbolTable& symbolInfo, T& batchNativeHookData) 120806f6ba60Sopenharmony_ci{ 120906f6ba60Sopenharmony_ci if (symbolInfo.symEntSize == 0) { 121006f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "SetSymbolInfo get symbolInfo failed"); 121106f6ba60Sopenharmony_ci return; 121206f6ba60Sopenharmony_ci } 121306f6ba60Sopenharmony_ci auto hookData = batchNativeHookData.add_events(); 121406f6ba60Sopenharmony_ci auto symTable = hookData->mutable_symbol_tab(); 121506f6ba60Sopenharmony_ci symTable->set_file_path_id(filePathId); 121606f6ba60Sopenharmony_ci symTable->set_text_exec_vaddr(symbolInfo.textVaddr); 121706f6ba60Sopenharmony_ci symTable->set_text_exec_vaddr_file_offset(symbolInfo.textOffset); 121806f6ba60Sopenharmony_ci symTable->set_sym_entry_size(symbolInfo.symEntSize); 121906f6ba60Sopenharmony_ci symTable->set_sym_table(symbolInfo.symTable.data(), symbolInfo.symTable.size()); 122006f6ba60Sopenharmony_ci symTable->set_str_table(symbolInfo.strTable.data(), symbolInfo.strTable.size()); 122106f6ba60Sopenharmony_ci symTable->set_pid(pid_); 122206f6ba60Sopenharmony_ci} 122306f6ba60Sopenharmony_ci 122406f6ba60Sopenharmony_citemplate <typename T> 122506f6ba60Sopenharmony_civoid StackPreprocess::FlushCheck(T& stackData) 122606f6ba60Sopenharmony_ci{ 122706f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0) { 122806f6ba60Sopenharmony_ci if (!statisticsModelFlushCallstack_) { 122906f6ba60Sopenharmony_ci return; 123006f6ba60Sopenharmony_ci } 123106f6ba60Sopenharmony_ci if constexpr (std::is_same<T, ::BatchNativeHookData>::value) { 123206f6ba60Sopenharmony_ci FlushData(stackData); 123306f6ba60Sopenharmony_ci } else { 123406f6ba60Sopenharmony_ci uint64_t dataLen = static_cast<uint64_t>(stackData.Size()); 123506f6ba60Sopenharmony_ci if (dataLen > flushSize_) { 123606f6ba60Sopenharmony_ci FlushData(stackData); 123706f6ba60Sopenharmony_ci } 123806f6ba60Sopenharmony_ci } 123906f6ba60Sopenharmony_ci statisticsModelFlushCallstack_ = false; 124006f6ba60Sopenharmony_ci } else { 124106f6ba60Sopenharmony_ci FlushData(stackData); 124206f6ba60Sopenharmony_ci } 124306f6ba60Sopenharmony_ci} 124406f6ba60Sopenharmony_ci 124506f6ba60Sopenharmony_civoid StackPreprocess::FlushData(BatchNativeHookData& stackData) 124606f6ba60Sopenharmony_ci{ 124706f6ba60Sopenharmony_ci if (buffer_ == nullptr) { 124806f6ba60Sopenharmony_ci return; 124906f6ba60Sopenharmony_ci } 125006f6ba60Sopenharmony_ci if (stackData.events().size() > 0) { 125106f6ba60Sopenharmony_ci size_t length = stackData.ByteSizeLong(); 125206f6ba60Sopenharmony_ci stackData.SerializeToArray(buffer_.get(), length); 125306f6ba60Sopenharmony_ci if (length < bufferSize_) { 125406f6ba60Sopenharmony_ci if (isHookStandaloneSerialize_) { 125506f6ba60Sopenharmony_ci std::string str; 125606f6ba60Sopenharmony_ci ForStandard::BatchNativeHookData StandardStackData; 125706f6ba60Sopenharmony_ci StandardStackData.ParseFromArray(buffer_.get(), length); 125806f6ba60Sopenharmony_ci google::protobuf::TextFormat::PrintToString(StandardStackData, &str); 125906f6ba60Sopenharmony_ci size_t n = fwrite(str.data(), 1, str.size(), fpHookData_); 126006f6ba60Sopenharmony_ci fflush(fpHookData_); 126106f6ba60Sopenharmony_ci std::get<::BatchNativeHookData>(stackData_).clear_events(); 126206f6ba60Sopenharmony_ci PROFILER_LOG_DEBUG(LOG_CORE, "Flush Data fwrite n = %zu str.size() = %zu", n, str.size()); 126306f6ba60Sopenharmony_ci } else { 126406f6ba60Sopenharmony_ci Flush(buffer_.get(), length); 126506f6ba60Sopenharmony_ci } 126606f6ba60Sopenharmony_ci } else { 126706f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "the data is larger than MAX_BUFFER_SIZE, flush failed"); 126806f6ba60Sopenharmony_ci } 126906f6ba60Sopenharmony_ci } 127006f6ba60Sopenharmony_ci} 127106f6ba60Sopenharmony_ci 127206f6ba60Sopenharmony_civoid StackPreprocess::FlushData(ProtoEncoder::BatchNativeHookData& stackData) 127306f6ba60Sopenharmony_ci{ 127406f6ba60Sopenharmony_ci if (stackData.Size() == 0) { 127506f6ba60Sopenharmony_ci return; 127606f6ba60Sopenharmony_ci } 127706f6ba60Sopenharmony_ci 127806f6ba60Sopenharmony_ci int messageLen = stackData.Finish(); 127906f6ba60Sopenharmony_ci RandomWriteCtx* ctx = nullptr; 128006f6ba60Sopenharmony_ci if (!isSaService_) { 128106f6ba60Sopenharmony_ci resultWriter_->finishReport(resultWriter_, messageLen); 128206f6ba60Sopenharmony_ci resultWriter_->flush(resultWriter_); 128306f6ba60Sopenharmony_ci ctx = resultWriter_->startReport(resultWriter_); 128406f6ba60Sopenharmony_ci } else { 128506f6ba60Sopenharmony_ci profilerPluginData_.finishAdd_data(messageLen); 128606f6ba60Sopenharmony_ci FinishReport(); 128706f6ba60Sopenharmony_ci ctx = StartReport(); 128806f6ba60Sopenharmony_ci } 128906f6ba60Sopenharmony_ci 129006f6ba60Sopenharmony_ci if (ctx == nullptr) { 129106f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__); 129206f6ba60Sopenharmony_ci return; 129306f6ba60Sopenharmony_ci } 129406f6ba60Sopenharmony_ci stackData_ = ProtoEncoder::BatchNativeHookData(ctx); 129506f6ba60Sopenharmony_ci} 129606f6ba60Sopenharmony_ci 129706f6ba60Sopenharmony_civoid StackPreprocess::Flush(const uint8_t* src, size_t size) 129806f6ba60Sopenharmony_ci{ 129906f6ba60Sopenharmony_ci if (src == nullptr) { 130006f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "Flush src is nullptr"); 130106f6ba60Sopenharmony_ci return; 130206f6ba60Sopenharmony_ci } 130306f6ba60Sopenharmony_ci 130406f6ba60Sopenharmony_ci if (writer_ == nullptr) { 130506f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "Flush writer_ is nullptr"); 130606f6ba60Sopenharmony_ci return; 130706f6ba60Sopenharmony_ci } 130806f6ba60Sopenharmony_ci writer_->Write(src, size); 130906f6ba60Sopenharmony_ci writer_->Flush(); 131006f6ba60Sopenharmony_ci 131106f6ba60Sopenharmony_ci std::get<::BatchNativeHookData>(stackData_).clear_events(); 131206f6ba60Sopenharmony_ci} 131306f6ba60Sopenharmony_ci 131406f6ba60Sopenharmony_civoid StackPreprocess::GetSymbols(const std::string& filePath, ElfSymbolTable& symbols) 131506f6ba60Sopenharmony_ci{ 131606f6ba60Sopenharmony_ci std::shared_ptr<DfxElf> elfPtr = std::make_shared<DfxElf>(filePath); 131706f6ba60Sopenharmony_ci 131806f6ba60Sopenharmony_ci symbols.textVaddr = elfPtr->GetStartVaddr(); 131906f6ba60Sopenharmony_ci symbols.textOffset = elfPtr->GetStartOffset(); 132006f6ba60Sopenharmony_ci if (symbols.textVaddr == (std::numeric_limits<uint64_t>::max)()) { 132106f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get textVaddr failed"); 132206f6ba60Sopenharmony_ci return; 132306f6ba60Sopenharmony_ci } 132406f6ba60Sopenharmony_ci 132506f6ba60Sopenharmony_ci std::string symSecName; 132606f6ba60Sopenharmony_ci std::string strSecName; 132706f6ba60Sopenharmony_ci ShdrInfo shdr; 132806f6ba60Sopenharmony_ci if (elfPtr->GetSectionInfo(shdr, ".symtab")) { 132906f6ba60Sopenharmony_ci symSecName = ".symtab"; 133006f6ba60Sopenharmony_ci strSecName = ".strtab"; 133106f6ba60Sopenharmony_ci } else if (elfPtr->GetSectionInfo(shdr, ".dynsym")) { 133206f6ba60Sopenharmony_ci symSecName = ".dynsym"; 133306f6ba60Sopenharmony_ci strSecName = ".dynstr"; 133406f6ba60Sopenharmony_ci } else { 133506f6ba60Sopenharmony_ci return; 133606f6ba60Sopenharmony_ci } 133706f6ba60Sopenharmony_ci symbols.symEntSize = shdr.entSize; 133806f6ba60Sopenharmony_ci symbols.symTable.resize(shdr.size); 133906f6ba60Sopenharmony_ci if (!elfPtr->GetSectionData(symbols.symTable.data(), shdr.size, symSecName)) { 134006f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get symbol section data failed"); 134106f6ba60Sopenharmony_ci return; 134206f6ba60Sopenharmony_ci } 134306f6ba60Sopenharmony_ci if (!elfPtr->GetSectionInfo(shdr, strSecName)) { 134406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get str section failed"); 134506f6ba60Sopenharmony_ci return; 134606f6ba60Sopenharmony_ci } 134706f6ba60Sopenharmony_ci symbols.strTable.resize(shdr.size); 134806f6ba60Sopenharmony_ci if (!elfPtr->GetSectionData(symbols.strTable.data(), shdr.size, strSecName)) { 134906f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get str section failed"); 135006f6ba60Sopenharmony_ci return; 135106f6ba60Sopenharmony_ci } 135206f6ba60Sopenharmony_ci} 135306f6ba60Sopenharmony_ci 135406f6ba60Sopenharmony_cibool StackPreprocess::FlushRecordStatistics() 135506f6ba60Sopenharmony_ci{ 135606f6ba60Sopenharmony_ci if (statisticsPeriodData_.empty()) { 135706f6ba60Sopenharmony_ci return false; 135806f6ba60Sopenharmony_ci } 135906f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 136006f6ba60Sopenharmony_ci FlushData(stackData); 136106f6ba60Sopenharmony_ci }, stackData_); 136206f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 136306f6ba60Sopenharmony_ci struct timespec ts; 136406f6ba60Sopenharmony_ci clock_gettime(hookDataClockId_, &ts); 136506f6ba60Sopenharmony_ci for (auto [addr, statistics] : statisticsPeriodData_) { 136606f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 136706f6ba60Sopenharmony_ci hookData->set_tv_sec(ts.tv_sec); 136806f6ba60Sopenharmony_ci hookData->set_tv_nsec(ts.tv_nsec); 136906f6ba60Sopenharmony_ci auto recordEvent = hookData->mutable_statistics_event(); 137006f6ba60Sopenharmony_ci recordEvent->set_pid(statistics->pid); 137106f6ba60Sopenharmony_ci recordEvent->set_callstack_id(statistics->callstackId); 137206f6ba60Sopenharmony_ci recordEvent->set_type(statistics->type); 137306f6ba60Sopenharmony_ci recordEvent->set_apply_count(statistics->applyCount); 137406f6ba60Sopenharmony_ci recordEvent->set_release_count(statistics->releaseCount); 137506f6ba60Sopenharmony_ci recordEvent->set_apply_size(statistics->applySize); 137606f6ba60Sopenharmony_ci recordEvent->set_release_size(statistics->releaseSize); 137706f6ba60Sopenharmony_ci } 137806f6ba60Sopenharmony_ci FlushData(stackData); 137906f6ba60Sopenharmony_ci }, stackData_); 138006f6ba60Sopenharmony_ci statisticsPeriodData_.clear(); 138106f6ba60Sopenharmony_ci return true; 138206f6ba60Sopenharmony_ci} 138306f6ba60Sopenharmony_ci 138406f6ba60Sopenharmony_civoid StackPreprocess::SaveMemTag(uint32_t tagId, const std::string& tagName) 138506f6ba60Sopenharmony_ci{ 138606f6ba60Sopenharmony_ci std::string temp; 138706f6ba60Sopenharmony_ci bool res = memTagMap_.Find(tagId, temp); 138806f6ba60Sopenharmony_ci if (!res) { 138906f6ba60Sopenharmony_ci memTagMap_.EnsureInsert(tagId, tagName); 139006f6ba60Sopenharmony_ci } 139106f6ba60Sopenharmony_ci} 139206f6ba60Sopenharmony_ci 139306f6ba60Sopenharmony_cibool StackPreprocess::GetMemTag(uint32_t tagId, std::string& tagName) 139406f6ba60Sopenharmony_ci{ 139506f6ba60Sopenharmony_ci return memTagMap_.Find(tagId, tagName); 139606f6ba60Sopenharmony_ci} 139706f6ba60Sopenharmony_ci 139806f6ba60Sopenharmony_civoid StackPreprocess::SaveJsRawStack(uint64_t jsChainId, const char* jsRawStack) 139906f6ba60Sopenharmony_ci{ 140006f6ba60Sopenharmony_ci auto iterChainId = jsStackMap_.find(jsChainId); 140106f6ba60Sopenharmony_ci if (iterChainId == jsStackMap_.end()) { 140206f6ba60Sopenharmony_ci auto iterRawStack = jsStackSet_.find(jsRawStack); 140306f6ba60Sopenharmony_ci if (iterRawStack == jsStackSet_.end()) { 140406f6ba60Sopenharmony_ci auto iter = jsStackSet_.insert(jsRawStack); 140506f6ba60Sopenharmony_ci jsStackMap_[jsChainId] = iter.first->c_str(); 140606f6ba60Sopenharmony_ci } else { 140706f6ba60Sopenharmony_ci jsStackMap_[jsChainId] = iterRawStack->c_str(); 140806f6ba60Sopenharmony_ci } 140906f6ba60Sopenharmony_ci } 141006f6ba60Sopenharmony_ci} 141106f6ba60Sopenharmony_ci 141206f6ba60Sopenharmony_ciconst char* StackPreprocess::GetJsRawStack(uint64_t jsChainId) 141306f6ba60Sopenharmony_ci{ 141406f6ba60Sopenharmony_ci auto iter = jsStackMap_.find(jsChainId); 141506f6ba60Sopenharmony_ci if (iter != jsStackMap_.end()) { 141606f6ba60Sopenharmony_ci return iter->second; 141706f6ba60Sopenharmony_ci } 141806f6ba60Sopenharmony_ci return nullptr; 141906f6ba60Sopenharmony_ci} 142006f6ba60Sopenharmony_ci 142106f6ba60Sopenharmony_ciunsigned StackPreprocess::LgFloor(unsigned long val) 142206f6ba60Sopenharmony_ci{ 142306f6ba60Sopenharmony_ci val |= (val >> RIGHT_MOVE_1); 142406f6ba60Sopenharmony_ci val |= (val >> RIGHT_MOVE_2); 142506f6ba60Sopenharmony_ci val |= (val >> RIGHT_MOVE_4); 142606f6ba60Sopenharmony_ci val |= (val >> RIGHT_MOVE_8); 142706f6ba60Sopenharmony_ci val |= (val >> RIGHT_MOVE_16); 142806f6ba60Sopenharmony_ci if (sizeof(val) > 4) { // 4: sizeThreshold 142906f6ba60Sopenharmony_ci int constant = sizeof(val) * 4; // 4: sizeThreshold 143006f6ba60Sopenharmony_ci val |= (val >> constant); 143106f6ba60Sopenharmony_ci } 143206f6ba60Sopenharmony_ci val++; 143306f6ba60Sopenharmony_ci if (val == 0) { 143406f6ba60Sopenharmony_ci return 8 * sizeof(val) - 1; // 8: 8byte 143506f6ba60Sopenharmony_ci } 143606f6ba60Sopenharmony_ci return __builtin_ffsl(val) - 2; // 2: adjustment 143706f6ba60Sopenharmony_ci} 143806f6ba60Sopenharmony_ci 143906f6ba60Sopenharmony_ciuint64_t StackPreprocess::PowCeil(uint64_t val) 144006f6ba60Sopenharmony_ci{ 144106f6ba60Sopenharmony_ci size_t msbIndex = LgFloor(val - 1); 144206f6ba60Sopenharmony_ci return 1ULL << (msbIndex + 1); 144306f6ba60Sopenharmony_ci} 144406f6ba60Sopenharmony_ci 144506f6ba60Sopenharmony_cisize_t StackPreprocess::ComputeAlign(size_t size) 144606f6ba60Sopenharmony_ci{ 144706f6ba60Sopenharmony_ci if (size == 0) { 144806f6ba60Sopenharmony_ci return 0; 144906f6ba60Sopenharmony_ci } 145006f6ba60Sopenharmony_ci unsigned index = 0; 145106f6ba60Sopenharmony_ci if (size <= (size_t(1) << SC_LG_TINY_MAXCLASS)) { 145206f6ba60Sopenharmony_ci unsigned lgTmin = SC_LG_TINY_MAXCLASS - SC_NTINY + 1; 145306f6ba60Sopenharmony_ci unsigned lgCeil = LgFloor(PowCeil(size)); 145406f6ba60Sopenharmony_ci index = (lgCeil < lgTmin) ? 0 : lgCeil - lgTmin; 145506f6ba60Sopenharmony_ci } else { 145606f6ba60Sopenharmony_ci unsigned floor = LgFloor((size << 1) - 1); 145706f6ba60Sopenharmony_ci unsigned shift = (floor < SC_LG_NGROUP + LG_QUANTUM) ? 0 : floor - (SC_LG_NGROUP + LG_QUANTUM); 145806f6ba60Sopenharmony_ci unsigned grp = shift << SC_LG_NGROUP; 145906f6ba60Sopenharmony_ci unsigned lgDelta = (floor < SC_LG_NGROUP + LG_QUANTUM + 1) ? LG_QUANTUM : floor - SC_LG_NGROUP - 1; 146006f6ba60Sopenharmony_ci size_t deltaInverseMask = size_t(-1) << lgDelta; 146106f6ba60Sopenharmony_ci unsigned mod = ((((size - 1) & deltaInverseMask) >> lgDelta)) & ((size_t(1) << SC_LG_NGROUP) - 1); 146206f6ba60Sopenharmony_ci index = SC_NTINY + grp + mod; 146306f6ba60Sopenharmony_ci } 146406f6ba60Sopenharmony_ci 146506f6ba60Sopenharmony_ci if (index < NTBINS) { 146606f6ba60Sopenharmony_ci return (size_t(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index)); 146706f6ba60Sopenharmony_ci } 146806f6ba60Sopenharmony_ci size_t reducedIndex = index - NTBINS; 146906f6ba60Sopenharmony_ci size_t grpVal = reducedIndex >> LG_SIZE_CLASS_GROUP; 147006f6ba60Sopenharmony_ci size_t modVal = reducedIndex & ((size_t(1) << LG_SIZE_CLASS_GROUP) - 1); 147106f6ba60Sopenharmony_ci size_t grpSizeMask = ~((!!grpVal) - 1); 147206f6ba60Sopenharmony_ci size_t grpSize = ((size_t(1) << (LG_QUANTUM + (LG_SIZE_CLASS_GROUP - 1))) << grpVal) & grpSizeMask; 147306f6ba60Sopenharmony_ci size_t shiftVal = (grpVal == 0) ? 1 : grpVal; 147406f6ba60Sopenharmony_ci size_t lgDeltaVal = shiftVal + (LG_QUANTUM - 1); 147506f6ba60Sopenharmony_ci size_t modSize = (modVal + 1) << lgDeltaVal; 147606f6ba60Sopenharmony_ci size_t usize = grpSize + modSize; 147706f6ba60Sopenharmony_ci return usize; 147806f6ba60Sopenharmony_ci} 147906f6ba60Sopenharmony_ci 148006f6ba60Sopenharmony_civoid StackPreprocess::WriteHookConfig() 148106f6ba60Sopenharmony_ci{ 148206f6ba60Sopenharmony_ci const size_t configSize = hookConfig_.ByteSizeLong(); 148306f6ba60Sopenharmony_ci auto buffer = std::make_unique<uint8_t[]>(configSize); 148406f6ba60Sopenharmony_ci hookConfig_.SerializeToArray(buffer.get(), configSize); 148506f6ba60Sopenharmony_ci 148606f6ba60Sopenharmony_ci writer_->ResetPos(); 148706f6ba60Sopenharmony_ci profilerPluginData_.Reset(writer_->GetCtx()); 148806f6ba60Sopenharmony_ci profilerPluginData_.set_name("nativehook_config"); 148906f6ba60Sopenharmony_ci profilerPluginData_.set_version("1.02"); 149006f6ba60Sopenharmony_ci profilerPluginData_.set_status(0); 149106f6ba60Sopenharmony_ci profilerPluginData_.set_data(buffer.get(), configSize); 149206f6ba60Sopenharmony_ci 149306f6ba60Sopenharmony_ci FinishReport(); 149406f6ba60Sopenharmony_ci 149506f6ba60Sopenharmony_ci auto ctx = StartReport(); 149606f6ba60Sopenharmony_ci if (ctx == nullptr) { 149706f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__); 149806f6ba60Sopenharmony_ci return; 149906f6ba60Sopenharmony_ci } 150006f6ba60Sopenharmony_ci stackData_ = ProtoEncoder::BatchNativeHookData(ctx); 150106f6ba60Sopenharmony_ci} 150206f6ba60Sopenharmony_ci 150306f6ba60Sopenharmony_ciRandomWriteCtx* StackPreprocess::StartReport() 150406f6ba60Sopenharmony_ci{ 150506f6ba60Sopenharmony_ci writer_->ResetPos(); 150606f6ba60Sopenharmony_ci profilerPluginData_.Reset(writer_->GetCtx()); 150706f6ba60Sopenharmony_ci profilerPluginData_.set_name("nativehook"); 150806f6ba60Sopenharmony_ci profilerPluginData_.set_version("1.02"); 150906f6ba60Sopenharmony_ci profilerPluginData_.set_status(0); 151006f6ba60Sopenharmony_ci return profilerPluginData_.startAdd_data(); 151106f6ba60Sopenharmony_ci} 151206f6ba60Sopenharmony_ci 151306f6ba60Sopenharmony_civoid StackPreprocess::FinishReport() 151406f6ba60Sopenharmony_ci{ 151506f6ba60Sopenharmony_ci struct timespec ts; 151606f6ba60Sopenharmony_ci clock_gettime(pluginDataClockId_, &ts); 151706f6ba60Sopenharmony_ci profilerPluginData_.set_clock_id(static_cast<ProfilerPluginData_ClockId>(pluginDataClockId_)); 151806f6ba60Sopenharmony_ci profilerPluginData_.set_tv_sec(ts.tv_sec); 151906f6ba60Sopenharmony_ci profilerPluginData_.set_tv_nsec(ts.tv_nsec); 152006f6ba60Sopenharmony_ci 152106f6ba60Sopenharmony_ci int32_t len = profilerPluginData_.Finish(); 152206f6ba60Sopenharmony_ci if (writer_ == nullptr) { 152306f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s: the writer is nullptr!", __func__); 152406f6ba60Sopenharmony_ci return; 152506f6ba60Sopenharmony_ci } 152606f6ba60Sopenharmony_ci writer_->FinishReport(len); 152706f6ba60Sopenharmony_ci} 152806f6ba60Sopenharmony_ci 152906f6ba60Sopenharmony_civoid StackPreprocess::FillFpNativeIp(RawStackPtr& rawData) 153006f6ba60Sopenharmony_ci{ 153106f6ba60Sopenharmony_ci#if defined(__aarch64__) 153206f6ba60Sopenharmony_ci uintptr_t pacMask = 0xFFFFFF8000000000; 153306f6ba60Sopenharmony_ci#else 153406f6ba60Sopenharmony_ci uintptr_t pacMask = 0; 153506f6ba60Sopenharmony_ci#endif 153606f6ba60Sopenharmony_ci uint64_t* fpIp = reinterpret_cast<uint64_t *>(rawData->data); 153706f6ba60Sopenharmony_ci for (uint8_t idx = 0; idx < rawData->fpDepth ; ++idx) { 153806f6ba60Sopenharmony_ci if (fpIp[idx] == 0) { 153906f6ba60Sopenharmony_ci break; 154006f6ba60Sopenharmony_ci } 154106f6ba60Sopenharmony_ci callFrames_.emplace_back(fpIp[idx] & (~pacMask)); 154206f6ba60Sopenharmony_ci } 154306f6ba60Sopenharmony_ci} 154406f6ba60Sopenharmony_ci 154506f6ba60Sopenharmony_civoid StackPreprocess::FillFpJsData(RawStackPtr& rawData) 154606f6ba60Sopenharmony_ci{ 154706f6ba60Sopenharmony_ci if (hookConfig_.statistics_interval() > 0) { 154806f6ba60Sopenharmony_ci switch (rawData->stackConext->type) { 154906f6ba60Sopenharmony_ci case FREE_MSG: 155006f6ba60Sopenharmony_ci case MUNMAP_MSG: 155106f6ba60Sopenharmony_ci case MEMORY_UNUSING_MSG: 155206f6ba60Sopenharmony_ci return; 155306f6ba60Sopenharmony_ci default: 155406f6ba60Sopenharmony_ci break; 155506f6ba60Sopenharmony_ci } 155606f6ba60Sopenharmony_ci } 155706f6ba60Sopenharmony_ci fpJsCallStacks_.clear(); 155806f6ba60Sopenharmony_ci /** 155906f6ba60Sopenharmony_ci * jsStackData: 156006f6ba60Sopenharmony_ci * ts_malloc1|entry/src/main/ets/pages/Index.ets:5:5,ts_malloc2|entry/src/main/ets/pages/Index.ets:8:5 156106f6ba60Sopenharmony_ci * | | 156206f6ba60Sopenharmony_ci * JS_SYMBOL_FILEPATH_SEP JS_CALL_STACK_DEPTH_SEP 156306f6ba60Sopenharmony_ci * jsCallStack: 156406f6ba60Sopenharmony_ci * ts_malloc1|entry/src/main/ets/pages/Index.ets:5:5 156506f6ba60Sopenharmony_ci * / \ 156606f6ba60Sopenharmony_ci * | | 156706f6ba60Sopenharmony_ci * jsSymbolFilePathSepPos | 156806f6ba60Sopenharmony_ci * jsFilePathPos = jsSymbolFilePathSepPos + 1 156906f6ba60Sopenharmony_ci */ 157006f6ba60Sopenharmony_ci AdvancedSplitString(rawData->jsStackData, JS_CALL_STACK_DEPTH_SEP, fpJsCallStacks_); 157106f6ba60Sopenharmony_ci for (std::string& jsCallStack: fpJsCallStacks_) { 157206f6ba60Sopenharmony_ci std::string::size_type jsSymbolFilePathSepPos = jsCallStack.find_first_of(JS_SYMBOL_FILEPATH_SEP); 157306f6ba60Sopenharmony_ci if (jsSymbolFilePathSepPos == std::string::npos) { 157406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s: jsCallStack find FAILED!", __func__); 157506f6ba60Sopenharmony_ci continue; 157606f6ba60Sopenharmony_ci } 157706f6ba60Sopenharmony_ci std::string::size_type jsFilePathPos = jsSymbolFilePathSepPos + 1; 157806f6ba60Sopenharmony_ci jsCallStack[jsSymbolFilePathSepPos] = '\0'; // "ts_malloc1'\0'entry/src/main/ets/pages/Index.ets:5:5" 157906f6ba60Sopenharmony_ci CallFrame& jsCallFrame = callFrames_.emplace_back(0, 0, true); 158006f6ba60Sopenharmony_ci jsCallFrame.symbolName_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str()); 158106f6ba60Sopenharmony_ci jsCallFrame.filePath_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str() + jsFilePathPos); 158206f6ba60Sopenharmony_ci if (hookConfig_.offline_symbolization()) { 158306f6ba60Sopenharmony_ci DfxSymbol symbol; 158406f6ba60Sopenharmony_ci if (!runtime_instance->ArktsGetSymbolCache(jsCallFrame, symbol)) { 158506f6ba60Sopenharmony_ci symbol.filePathId_ = runtime_instance->FillArkTsFilePath(jsCallFrame.filePath_); 158606f6ba60Sopenharmony_ci symbol.symbolName_ = jsCallFrame.symbolName_; 158706f6ba60Sopenharmony_ci symbol.module_ = jsCallFrame.filePath_; 158806f6ba60Sopenharmony_ci symbol.symbolId_ = runtime_instance->GetJsSymbolCacheSize(); 158906f6ba60Sopenharmony_ci runtime_instance->FillSymbolNameId(jsCallFrame, symbol); 159006f6ba60Sopenharmony_ci runtime_instance->FillFileSet(jsCallFrame, symbol); 159106f6ba60Sopenharmony_ci jsCallFrame.needReport_ |= CALL_FRAME_REPORT; 159206f6ba60Sopenharmony_ci runtime_instance->FillJsSymbolCache(jsCallFrame, symbol); 159306f6ba60Sopenharmony_ci } 159406f6ba60Sopenharmony_ci jsCallFrame.callFrameId_ = symbol.symbolId_; 159506f6ba60Sopenharmony_ci jsCallFrame.symbolNameId_ = symbol.symbolNameId_; 159606f6ba60Sopenharmony_ci jsCallFrame.filePathId_ = symbol.filePathId_; 159706f6ba60Sopenharmony_ci jsCallFrame.filePath_ = symbol.module_; 159806f6ba60Sopenharmony_ci jsCallFrame.symbolName_ = symbol.symbolName_; 159906f6ba60Sopenharmony_ci } 160006f6ba60Sopenharmony_ci } 160106f6ba60Sopenharmony_ci} 160206f6ba60Sopenharmony_ci 160306f6ba60Sopenharmony_civoid StackPreprocess::FillDwarfErrorStack() 160406f6ba60Sopenharmony_ci{ 160506f6ba60Sopenharmony_ci#if defined(__aarch64__) 160606f6ba60Sopenharmony_ci uintptr_t pacMask = 0xFFFFFF8000000000; 160706f6ba60Sopenharmony_ci#else 160806f6ba60Sopenharmony_ci uintptr_t pacMask = 0; 160906f6ba60Sopenharmony_ci#endif 161006f6ba60Sopenharmony_ci CallFrame& jsCallFrame = callFrames_.emplace_back(0 & (~pacMask)); 161106f6ba60Sopenharmony_ci jsCallFrame.symbolName_ = "UnwindErrorDwarf"; 161206f6ba60Sopenharmony_ci jsCallFrame.isJsFrame_ = true; 161306f6ba60Sopenharmony_ci jsCallFrame.needReport_ |= CALL_FRAME_REPORT; 161406f6ba60Sopenharmony_ci jsCallFrame.needReport_ |= SYMBOL_NAME_ID_REPORT; 161506f6ba60Sopenharmony_ci jsCallFrame.needReport_ |= FILE_PATH_ID_REPORT; 161606f6ba60Sopenharmony_ci jsCallFrame.callFrameId_ = DWARF_ERROR_ID; 161706f6ba60Sopenharmony_ci jsCallFrame.symbolNameId_ = DWARF_ERROR_ID; 161806f6ba60Sopenharmony_ci jsCallFrame.filePathId_ = DWARF_ERROR_ID; 161906f6ba60Sopenharmony_ci jsCallFrame.filePath_ = "no-file-path"; 162006f6ba60Sopenharmony_ci} 162106f6ba60Sopenharmony_ci 162206f6ba60Sopenharmony_civoid StackPreprocess::FlushRecordApplyAndReleaseMatchData() 162306f6ba60Sopenharmony_ci{ 162406f6ba60Sopenharmony_ci if (applyAndReleaseMatchPeriodListData_.empty()) { 162506f6ba60Sopenharmony_ci return; 162606f6ba60Sopenharmony_ci } 162706f6ba60Sopenharmony_ci std::visit([&](auto& stackData) { 162806f6ba60Sopenharmony_ci for (const auto& rawStack: applyAndReleaseMatchPeriodListData_) { 162906f6ba60Sopenharmony_ci auto hookData = stackData.add_events(); 163006f6ba60Sopenharmony_ci hookData->set_tv_sec(rawStack.ts.tv_sec); 163106f6ba60Sopenharmony_ci hookData->set_tv_nsec(rawStack.ts.tv_nsec); 163206f6ba60Sopenharmony_ci if (rawStack.type == MALLOC_MSG) { 163306f6ba60Sopenharmony_ci auto allocEvent = hookData->mutable_alloc_event(); 163406f6ba60Sopenharmony_ci SetEventFrame(rawStack, allocEvent, rawStack.stackMapId); 163506f6ba60Sopenharmony_ci } else if (rawStack.type == FREE_MSG) { 163606f6ba60Sopenharmony_ci auto freeEvent = hookData->mutable_free_event(); 163706f6ba60Sopenharmony_ci SetEventFrame(rawStack, freeEvent, rawStack.stackMapId); 163806f6ba60Sopenharmony_ci } else if (rawStack.type == MMAP_MSG) { 163906f6ba60Sopenharmony_ci auto mmapEvent = hookData->mutable_mmap_event(); 164006f6ba60Sopenharmony_ci SetEventFrame(rawStack, mmapEvent, rawStack.stackMapId); 164106f6ba60Sopenharmony_ci } else if (rawStack.type == MMAP_FILE_PAGE_MSG) { 164206f6ba60Sopenharmony_ci auto mmapEvent = hookData->mutable_mmap_event(); 164306f6ba60Sopenharmony_ci const std::string prefix = "FilePage:"; 164406f6ba60Sopenharmony_ci std::string tagName; 164506f6ba60Sopenharmony_ci if (GetMemTag(rawStack.tagId, tagName)) { 164606f6ba60Sopenharmony_ci tagName = prefix + tagName; 164706f6ba60Sopenharmony_ci } 164806f6ba60Sopenharmony_ci SetEventFrame(rawStack, mmapEvent, rawStack.stackMapId, tagName); 164906f6ba60Sopenharmony_ci } else if (rawStack.type == MUNMAP_MSG) { 165006f6ba60Sopenharmony_ci auto munmapEvent = hookData->mutable_munmap_event(); 165106f6ba60Sopenharmony_ci SetEventFrame(rawStack, munmapEvent, rawStack.stackMapId); 165206f6ba60Sopenharmony_ci } else if (rawStack.type == PR_SET_VMA_MSG) { 165306f6ba60Sopenharmony_ci auto tagEvent = hookData->mutable_tag_event(); 165406f6ba60Sopenharmony_ci const std::string prefix = "Anonymous:"; 165506f6ba60Sopenharmony_ci tagEvent->set_addr(rawStack.addr); 165606f6ba60Sopenharmony_ci tagEvent->set_size(rawStack.mallocSize); 165706f6ba60Sopenharmony_ci tagEvent->set_tag(prefix + prctlPeriodTags_[rawStack.tagId]); 165806f6ba60Sopenharmony_ci tagEvent->set_pid(pid_); 165906f6ba60Sopenharmony_ci } else if (rawStack.type == MEMORY_USING_MSG) { 166006f6ba60Sopenharmony_ci auto mmapEvent = hookData->mutable_mmap_event(); 166106f6ba60Sopenharmony_ci std::string tagName; 166206f6ba60Sopenharmony_ci GetMemTag(rawStack.tagId, tagName); 166306f6ba60Sopenharmony_ci SetEventFrame(rawStack, mmapEvent, rawStack.stackMapId, tagName); 166406f6ba60Sopenharmony_ci } else if (rawStack.type == MEMORY_UNUSING_MSG) { 166506f6ba60Sopenharmony_ci auto munmapEvent = hookData->mutable_munmap_event(); 166606f6ba60Sopenharmony_ci SetEventFrame(rawStack, munmapEvent, rawStack.stackMapId); 166706f6ba60Sopenharmony_ci } 166806f6ba60Sopenharmony_ci } 166906f6ba60Sopenharmony_ci FlushData(stackData); 167006f6ba60Sopenharmony_ci }, stackData_); 167106f6ba60Sopenharmony_ci applyAndReleaseMatchPeriodListData_.clear(); 167206f6ba60Sopenharmony_ci applyAndReleaseMatchIntervallMap_.clear(); 167306f6ba60Sopenharmony_ci prctlPeriodTags_.clear(); 167406f6ba60Sopenharmony_ci}