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#ifndef STACK_PREPROCESS_H 1606f6ba60Sopenharmony_ci#define STACK_PREPROCESS_H 1706f6ba60Sopenharmony_ci 1806f6ba60Sopenharmony_ci#include <chrono> 1906f6ba60Sopenharmony_ci#include <thread> 2006f6ba60Sopenharmony_ci#include <unordered_map> 2106f6ba60Sopenharmony_ci#include <list> 2206f6ba60Sopenharmony_ci#include <algorithm> 2306f6ba60Sopenharmony_ci#include <mutex> 2406f6ba60Sopenharmony_ci#include <variant> 2506f6ba60Sopenharmony_ci 2606f6ba60Sopenharmony_ci#include "logging.h" 2706f6ba60Sopenharmony_ci#include "nocopyable.h" 2806f6ba60Sopenharmony_ci#include "stack_data_repeater.h" 2906f6ba60Sopenharmony_ci#include "buffer_writer.h" 3006f6ba60Sopenharmony_ci#include "virtual_runtime.h" 3106f6ba60Sopenharmony_ci#include "hook_common.h" 3206f6ba60Sopenharmony_ci#include "native_hook_config.pb.h" 3306f6ba60Sopenharmony_ci#include "native_hook_result.pb.h" 3406f6ba60Sopenharmony_ci#include "native_hook_result.pbencoder.h" 3506f6ba60Sopenharmony_ci#include "safe_map.h" 3606f6ba60Sopenharmony_ci#include "schedule_task_manager.h" 3706f6ba60Sopenharmony_ci 3806f6ba60Sopenharmony_ciusing WriterStructPtr = std::unique_ptr<WriterStruct>::pointer; 3906f6ba60Sopenharmony_ciclass StackPreprocess : public std::enable_shared_from_this<StackPreprocess> { 4006f6ba60Sopenharmony_cipublic: 4106f6ba60Sopenharmony_ci struct RecordStatistic { 4206f6ba60Sopenharmony_ci uint32_t pid {0}; 4306f6ba60Sopenharmony_ci uint32_t callstackId {0}; 4406f6ba60Sopenharmony_ci uint32_t tagId {0}; 4506f6ba60Sopenharmony_ci RecordStatisticsEvent::MemoryType type {RecordStatisticsEvent::MALLOC}; 4606f6ba60Sopenharmony_ci uint64_t applyCount {0}; 4706f6ba60Sopenharmony_ci uint64_t releaseCount {0}; 4806f6ba60Sopenharmony_ci uint64_t applySize {0}; 4906f6ba60Sopenharmony_ci uint64_t releaseSize {0}; 5006f6ba60Sopenharmony_ci }; 5106f6ba60Sopenharmony_ci 5206f6ba60Sopenharmony_ci explicit StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const NativeHookConfig& hookConfig, 5306f6ba60Sopenharmony_ci clockid_t pluginDataClockId, FILE* fpHookData = nullptr, bool isHookStandalone = false, 5406f6ba60Sopenharmony_ci bool isSaService = false, bool isProtobufSerialize = true); 5506f6ba60Sopenharmony_ci ~StackPreprocess(); 5606f6ba60Sopenharmony_ci void SetWriter(const std::shared_ptr<Writer>& writer); 5706f6ba60Sopenharmony_ci void SetWriter(const WriterStructPtr& writer); 5806f6ba60Sopenharmony_ci bool StartTakeResults(); 5906f6ba60Sopenharmony_ci bool StopTakeResults(); 6006f6ba60Sopenharmony_ci void FinishTraceFile(); 6106f6ba60Sopenharmony_ci bool FlushRecordStatistics(); 6206f6ba60Sopenharmony_ci void FlushRecordApplyAndReleaseMatchData(); 6306f6ba60Sopenharmony_ci void ForceStop(); 6406f6ba60Sopenharmony_ci inline void SetPid(int32_t pid) 6506f6ba60Sopenharmony_ci { 6606f6ba60Sopenharmony_ci pid_ = pid; 6706f6ba60Sopenharmony_ci } 6806f6ba60Sopenharmony_ci inline void InitStatisticsTime() 6906f6ba60Sopenharmony_ci { 7006f6ba60Sopenharmony_ci lastStatisticsTime_ = std::chrono::steady_clock::now(); 7106f6ba60Sopenharmony_ci } 7206f6ba60Sopenharmony_ci void SaveMemTag(uint32_t tagId, const std::string& tagName); 7306f6ba60Sopenharmony_ci bool GetMemTag(uint32_t tagId, std::string& tagName); 7406f6ba60Sopenharmony_ci void SaveJsRawStack(uint64_t jsChainId, const char* jsRawStack); 7506f6ba60Sopenharmony_ci const char* GetJsRawStack(uint64_t jsChainId); 7606f6ba60Sopenharmony_ci void ReportBasicData(); 7706f6ba60Sopenharmony_ci void WriteHookConfig(); 7806f6ba60Sopenharmony_ci void TakeResultsFromShmem(const std::shared_ptr<EventNotifier>&, const std::shared_ptr<ShareMemoryBlock>&); 7906f6ba60Sopenharmony_ci void SetNmdFd(uint32_t fd) 8006f6ba60Sopenharmony_ci { 8106f6ba60Sopenharmony_ci nmdFd_ = fd; 8206f6ba60Sopenharmony_ci } 8306f6ba60Sopenharmony_ci void SetFlushSize(uint64_t size) 8406f6ba60Sopenharmony_ci { 8506f6ba60Sopenharmony_ci double tenth = static_cast<double>(size) / 10.0; 8606f6ba60Sopenharmony_ci flushSize_ = static_cast<uint64_t>(std::ceil(tenth)); 8706f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "SetFlushSize size: %" PRIu64 ", flushSize_: %" PRIu64 "", size, flushSize_); 8806f6ba60Sopenharmony_ci if (isProtobufSerialize_) { 8906f6ba60Sopenharmony_ci bufferSize_ = flushSize_ << 1; 9006f6ba60Sopenharmony_ci buffer_ = std::make_unique<uint8_t[]>(bufferSize_); 9106f6ba60Sopenharmony_ci } 9206f6ba60Sopenharmony_ci } 9306f6ba60Sopenharmony_ci 9406f6ba60Sopenharmony_ciprivate: 9506f6ba60Sopenharmony_ci using CallFrame = OHOS::Developtools::NativeDaemon::CallFrame; 9606f6ba60Sopenharmony_ci struct ElfSymbolTable { 9706f6ba60Sopenharmony_ci uint64_t textVaddr; 9806f6ba60Sopenharmony_ci uint32_t textOffset; 9906f6ba60Sopenharmony_ci uint32_t symEntSize; 10006f6ba60Sopenharmony_ci std::vector<uint8_t> strTable; 10106f6ba60Sopenharmony_ci std::vector<uint8_t> symTable; 10206f6ba60Sopenharmony_ci }; 10306f6ba60Sopenharmony_ci 10406f6ba60Sopenharmony_ci enum RecordStatisticsLimit : std::size_t { 10506f6ba60Sopenharmony_ci STATISTICS_MAP_SZIE = 100000, 10606f6ba60Sopenharmony_ci STATISTICS_PERIOD_DATA_SIZE = 100000, 10706f6ba60Sopenharmony_ci ALLOC_ADDRMAMP_SIZE = 100000, 10806f6ba60Sopenharmony_ci MATCH_ADDRMAMP_SIZE = 100000, 10906f6ba60Sopenharmony_ci }; 11006f6ba60Sopenharmony_ci 11106f6ba60Sopenharmony_ci struct ScopedLockFile { 11206f6ba60Sopenharmony_ci ScopedLockFile(FILE* fpHook): fpHookData(fpHook) 11306f6ba60Sopenharmony_ci { 11406f6ba60Sopenharmony_ci flockfile(fpHookData); 11506f6ba60Sopenharmony_ci } 11606f6ba60Sopenharmony_ci ~ScopedLockFile() 11706f6ba60Sopenharmony_ci { 11806f6ba60Sopenharmony_ci funlockfile(fpHookData); 11906f6ba60Sopenharmony_ci } 12006f6ba60Sopenharmony_ci FILE* fpHookData {nullptr}; 12106f6ba60Sopenharmony_ci }; 12206f6ba60Sopenharmony_ci 12306f6ba60Sopenharmony_ciprivate: 12406f6ba60Sopenharmony_ci void TakeResults(); 12506f6ba60Sopenharmony_ci template <typename T> 12606f6ba60Sopenharmony_ci void SetHookData(RawStackPtr rawStack, T& stackData); 12706f6ba60Sopenharmony_ci template <typename T> 12806f6ba60Sopenharmony_ci void SetHookData(RawStackPtr rawStack, std::vector<CallFrame>& callFrames, T& stackData); 12906f6ba60Sopenharmony_ci void WriteFrames(RawStackPtr RawStack, const std::vector<CallFrame>& callFrames); 13006f6ba60Sopenharmony_ci template <typename T> 13106f6ba60Sopenharmony_ci void SetFrameInfo(T& frame, CallFrame& callFrame); 13206f6ba60Sopenharmony_ci template <typename T> 13306f6ba60Sopenharmony_ci void ReportSymbolNameMap(CallFrame& callFrame, T& stackData); 13406f6ba60Sopenharmony_ci template <typename T> 13506f6ba60Sopenharmony_ci void ReportFilePathMap(CallFrame& callFrame, T& stackData); 13606f6ba60Sopenharmony_ci template <typename T> 13706f6ba60Sopenharmony_ci void ReportFrameMap(CallFrame& callFrame, T& stackData); 13806f6ba60Sopenharmony_ci void ReportThreadNameMap(uint32_t tid, const std::string& tname); 13906f6ba60Sopenharmony_ci void SetMapsInfo(); 14006f6ba60Sopenharmony_ci template <typename T> 14106f6ba60Sopenharmony_ci void SetSymbolInfo(uint32_t filePathId, ElfSymbolTable& symbolInfo, T& batchNativeHookData); 14206f6ba60Sopenharmony_ci template <typename T> 14306f6ba60Sopenharmony_ci void FlushCheck(T& stackData); 14406f6ba60Sopenharmony_ci void FlushData(BatchNativeHookData& stackData); 14506f6ba60Sopenharmony_ci void FlushData(OHOS::Developtools::Profiler::ProtoEncoder::BatchNativeHookData& stackData); 14606f6ba60Sopenharmony_ci void Flush(const uint8_t* src, size_t size); 14706f6ba60Sopenharmony_ci void GetSymbols(const std::string& filePath, ElfSymbolTable& symbols); 14806f6ba60Sopenharmony_ci template <typename T> 14906f6ba60Sopenharmony_ci void FillOfflineCallStack(std::vector<CallFrame>& callFrames, size_t idx, T& stackData); 15006f6ba60Sopenharmony_ci template <typename T> 15106f6ba60Sopenharmony_ci void FillCallStack(std::vector<CallFrame>& callFrames, size_t idx, T& stackData); 15206f6ba60Sopenharmony_ci template <typename T> 15306f6ba60Sopenharmony_ci uint32_t SetCallStackMap(T& stackData); 15406f6ba60Sopenharmony_ci template <typename T> 15506f6ba60Sopenharmony_ci uint32_t GetCallStackId(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, T& stackData); 15606f6ba60Sopenharmony_ci uint32_t FindCallStackId(std::vector<uint64_t>& callStack); 15706f6ba60Sopenharmony_ci template <typename T> 15806f6ba60Sopenharmony_ci void SetEventFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 15906f6ba60Sopenharmony_ci T* event, uint32_t stackId, const std::string& type = ""); 16006f6ba60Sopenharmony_ci template <typename T> 16106f6ba60Sopenharmony_ci void SetEventFrame(const ReportEventBaseData& rawStack, T* event, uint32_t stackMapId, 16206f6ba60Sopenharmony_ci const std::string& type = ""); 16306f6ba60Sopenharmony_ci template <typename T> 16406f6ba60Sopenharmony_ci void SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, T& stackData); 16506f6ba60Sopenharmony_ci template <typename T> 16606f6ba60Sopenharmony_ci void SetAllocStatisticsFrame(const RawStackPtr& rawStack, T& stackData); 16706f6ba60Sopenharmony_ci template <typename T> 16806f6ba60Sopenharmony_ci void SetApplyAndReleaseMatchFrame(RawStackPtr rawStack, std::vector<CallFrame>& callFrames, T& stackData); 16906f6ba60Sopenharmony_ci void IntervalFlushRecordStatistics(); 17006f6ba60Sopenharmony_ci void IntervalFlushApplyAndReleaseMatchData(); 17106f6ba60Sopenharmony_ci bool HandleNoStackEvent(RawStackPtr& rawStack); 17206f6ba60Sopenharmony_ci bool SetFreeStatisticsData(uint64_t addr); 17306f6ba60Sopenharmony_ci void SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists = false); 17406f6ba60Sopenharmony_ci unsigned LgFloor(unsigned long x); 17506f6ba60Sopenharmony_ci uint64_t PowCeil(uint64_t x); 17606f6ba60Sopenharmony_ci size_t ComputeAlign(size_t size); 17706f6ba60Sopenharmony_ci void ReportOfflineSymbolizationData(); 17806f6ba60Sopenharmony_ci 17906f6ba60Sopenharmony_ci RandomWriteCtx* StartReport(); 18006f6ba60Sopenharmony_ci void FinishReport(); 18106f6ba60Sopenharmony_ci void FillFpNativeIp(RawStackPtr& rawData); 18206f6ba60Sopenharmony_ci void FillFpJsData(RawStackPtr& rawData); 18306f6ba60Sopenharmony_ci void FillDwarfErrorStack(); 18406f6ba60Sopenharmony_ci void FillNapiStack(std::string& tagName, std::vector<CallFrame>& callFrames, uint64_t napiIndex); 18506f6ba60Sopenharmony_ciprivate: 18606f6ba60Sopenharmony_ci std::chrono::steady_clock::time_point lastStatisticsTime_ = std::chrono::steady_clock::now(); 18706f6ba60Sopenharmony_ci std::shared_ptr<Writer> writer_ = nullptr; 18806f6ba60Sopenharmony_ci StackDataRepeaterPtr dataRepeater_ = nullptr; 18906f6ba60Sopenharmony_ci std::thread thread_ {}; 19006f6ba60Sopenharmony_ci std::unique_ptr<uint8_t[]> buffer_; 19106f6ba60Sopenharmony_ci std::atomic_bool isStopTakeData_ = false; 19206f6ba60Sopenharmony_ci std::shared_ptr<OHOS::Developtools::NativeDaemon::VirtualRuntime> runtime_instance; 19306f6ba60Sopenharmony_ci DISALLOW_COPY_AND_MOVE(StackPreprocess); 19406f6ba60Sopenharmony_ci OHOS::SafeMap<uint32_t, std::string> memTagMap_ = {}; 19506f6ba60Sopenharmony_ci std::unordered_map<uint32_t, std::string> threadNameMap_ = {}; 19606f6ba60Sopenharmony_ci NativeHookConfig hookConfig_; 19706f6ba60Sopenharmony_ci uint32_t ignoreCnts_ = 0; 19806f6ba60Sopenharmony_ci uint32_t eventCnts_ = 0; 19906f6ba60Sopenharmony_ci bool flushBasicData_ {true}; 20006f6ba60Sopenharmony_ci std::vector<u64> u64regs_; 20106f6ba60Sopenharmony_ci std::vector<CallFrame> callFrames_; 20206f6ba60Sopenharmony_ci std::vector<uint64_t> callStack_; 20306f6ba60Sopenharmony_ci // Key is callStack_, value is call stack id 20406f6ba60Sopenharmony_ci std::map<std::vector<uint64_t>, uint32_t> callStackMap_; 20506f6ba60Sopenharmony_ci // Key is ip , response_library_mode used 20606f6ba60Sopenharmony_ci std::unordered_map<uint64_t, uint32_t> responseLibraryMap_; 20706f6ba60Sopenharmony_ci std::chrono::seconds statisticsInterval_ {0}; 20806f6ba60Sopenharmony_ci // Key is call stack id, value is recordstatistic data 20906f6ba60Sopenharmony_ci std::unordered_map<uint32_t, RecordStatistic> recordStatisticsMap_; 21006f6ba60Sopenharmony_ci // Key is call stack id, value is recordstatistic data pointer 21106f6ba60Sopenharmony_ci std::unordered_map<uint32_t, RecordStatistic*> statisticsPeriodData_; 21206f6ba60Sopenharmony_ci // Key is alloc or mmap address, value first is mallocsize, second is recordstatistic data pointer 21306f6ba60Sopenharmony_ci std::unordered_map<uint64_t, std::pair<uint64_t, RecordStatistic*>> allocAddrMap_; 21406f6ba60Sopenharmony_ci // Key is alloc or mmap address, value is ReportEventBaseData list iterator 21506f6ba60Sopenharmony_ci std::unordered_map<uint64_t, std::list<ReportEventBaseData>::iterator> applyAndReleaseMatchIntervallMap_; 21606f6ba60Sopenharmony_ci std::list<ReportEventBaseData> applyAndReleaseMatchPeriodListData_; 21706f6ba60Sopenharmony_ci std::chrono::seconds applyAndReleaseMatchInterval_{0}; 21806f6ba60Sopenharmony_ci // used for plugin data 21906f6ba60Sopenharmony_ci clockid_t pluginDataClockId_ = CLOCK_REALTIME; 22006f6ba60Sopenharmony_ci // used for clac wait time in StackDataRepeater::TakeRawData() or statistics HookData 22106f6ba60Sopenharmony_ci clockid_t hookDataClockId_ = CLOCK_REALTIME; 22206f6ba60Sopenharmony_ci FILE* fpHookData_ {nullptr}; 22306f6ba60Sopenharmony_ci bool isHookStandaloneSerialize_ {false}; 22406f6ba60Sopenharmony_ci int32_t pid_ {-1}; 22506f6ba60Sopenharmony_ci std::mutex mtx_; 22606f6ba60Sopenharmony_ci bool isSaService_{false}; 22706f6ba60Sopenharmony_ci std::mutex allocAddrMapMtx_; 22806f6ba60Sopenharmony_ci bool isProtobufSerialize_{true}; 22906f6ba60Sopenharmony_ci WriterStructPtr resultWriter_{nullptr}; 23006f6ba60Sopenharmony_ci std::variant<BatchNativeHookData, OHOS::Developtools::Profiler::ProtoEncoder::BatchNativeHookData> stackData_; 23106f6ba60Sopenharmony_ci uint64_t flushSize_{0}; 23206f6ba60Sopenharmony_ci uint64_t bufferSize_{0}; 23306f6ba60Sopenharmony_ci bool statisticsModelFlushCallstack_{false}; 23406f6ba60Sopenharmony_ci OHOS::Developtools::Profiler::ProtoEncoder::ProfilerPluginData profilerPluginData_; 23506f6ba60Sopenharmony_ci // Key is js stack id , value is js raw stack pointer 23606f6ba60Sopenharmony_ci std::map<uint64_t, const char*> jsStackMap_ = {}; 23706f6ba60Sopenharmony_ci std::set<std::string> jsStackSet_ = {}; 23806f6ba60Sopenharmony_ci bool unwindFailReport_ = true; 23906f6ba60Sopenharmony_ci std::vector<std::string> prctlPeriodTags_; // applyAndReleaseMatchInterval mode used 24006f6ba60Sopenharmony_ci std::vector<std::string> fpJsCallStacks_; 24106f6ba60Sopenharmony_ci std::atomic<uint64_t> napiIndex_{1}; 24206f6ba60Sopenharmony_ci ScheduleTaskManager scheduleTaskManager_; 24306f6ba60Sopenharmony_ci uint32_t nmdFd_ = 0; 24406f6ba60Sopenharmony_ci}; 24506f6ba60Sopenharmony_ci 24606f6ba60Sopenharmony_ci#endif // STACK_PREPROCESS_H