1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef STACK_PREPROCESS_H 16 #define STACK_PREPROCESS_H 17 18 #include <chrono> 19 #include <thread> 20 #include <unordered_map> 21 #include <list> 22 #include <algorithm> 23 24 #include "logging.h" 25 #include "nocopyable.h" 26 #include "stack_data_repeater.h" 27 #include "buffer_writer.h" 28 #include "virtual_runtime.h" 29 #include "hook_common.h" 30 #include "native_hook_config.pb.h" 31 #include "native_hook_result.pb.h" 32 #include "safe_map.h" 33 34 class StackPreprocess { 35 public: 36 struct RecordStatistic { 37 uint32_t pid {0}; 38 uint32_t callstackId {0}; 39 uint32_t tagId {0}; 40 RecordStatisticsEvent::MemoryType type {RecordStatisticsEvent::MALLOC}; 41 uint64_t applyCount {0}; 42 uint64_t releaseCount {0}; 43 uint64_t applySize {0}; 44 uint64_t releaseSize {0}; 45 }; 46 47 explicit StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const NativeHookConfig& hookConfig, 48 clockid_t pluginDataClockId, bool isHookStandalone = false); 49 explicit StackPreprocess(bool fpUnwind); 50 ~StackPreprocess(); 51 void SetWriter(const std::shared_ptr<BufferWriter>& writer); 52 bool StartTakeResults(); 53 bool StopTakeResults(); 54 bool FlushRecordStatistics(); 55 void SetSerializeMode(bool protobufSerialize); 56 void SaveMemTag(uint32_t tagId, const std::string& tagName); 57 bool GetMemTag(uint32_t tagId, std::string& tagName); 58 void SaveThreadName(uint32_t tid, const std::string& tname); 59 60 private: 61 using CallFrame = OHOS::Developtools::NativeDaemon::CallFrame; 62 struct ElfSymbolTable { 63 uint64_t textVaddr; 64 uint32_t textOffset; 65 uint32_t symEntSize; 66 std::vector<uint8_t> strTable; 67 std::vector<uint8_t> symTable; 68 }; 69 70 enum RecordStatisticsLimit : std::size_t { 71 STATISTICS_MAP_SZIE = 2048, 72 STATISTICS_PERIOD_DATA_SIZE = 256, 73 ALLOC_ADDRMAMP_SIZE = 2048, 74 }; 75 76 private: 77 void TakeResults(); 78 void SetHookData(RawStackPtr RawStack, std::vector<CallFrame>& callFrames, 79 BatchNativeHookData& batchNativeHookData); 80 void WriteFrames(RawStackPtr RawStack, const std::vector<CallFrame>& callFrames); 81 void SetFrameInfo(Frame& frame, CallFrame& callFrame); 82 void ReportSymbolNameMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData); 83 void ReportFilePathMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData); 84 void ReportFrameMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData); 85 void ReportThreadNameMap(uint32_t tid, const std::string& tname, BatchNativeHookData& batchNativeHookData); 86 void SetMapsInfo(pid_t pid); 87 void SetSymbolInfo(uint32_t filePathId, ElfSymbolTable& symbolInfo, 88 BatchNativeHookData& batchNativeHookData); 89 void FlushData(BatchNativeHookData& stackData); 90 void Flush(const uint8_t* src, size_t size); 91 void GetSymbols(const std::string& filePath, ElfSymbolTable& symbols); 92 93 void FillOfflineCallStack(std::vector<CallFrame>& callFrames, size_t idx); 94 void FillCallStack(std::vector<CallFrame>& callFrames, 95 BatchNativeHookData& batchNativeHookData, size_t idx); 96 uint32_t SetCallStackMap(BatchNativeHookData& batchNativeHookData); 97 uint32_t GetCallStackId(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 98 BatchNativeHookData& batchNativeHookData); 99 template <typename T> 100 void SetEventFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 101 BatchNativeHookData& batchNativeHookData, T* event, uint32_t stackId); 102 void SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 103 BatchNativeHookData& batchNativeHookData); 104 bool SetFreeStatisticsData(uint64_t addr); 105 void SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists = false); 106 private: 107 std::shared_ptr<BufferWriter> writer_ = nullptr; 108 StackDataRepeaterPtr dataRepeater_ = nullptr; 109 std::thread thread_ {}; 110 std::unique_ptr<uint8_t[]> buffer_; 111 bool isStopTakeData_ = false; 112 std::shared_ptr<OHOS::Developtools::NativeDaemon::VirtualRuntime> runtime_instance; 113 DISALLOW_COPY_AND_MOVE(StackPreprocess); 114 OHOS::SafeMap<uint32_t, std::string> memTagMap_ = {}; 115 std::unordered_map<uint32_t, std::string> threadNameMap_ = {}; 116 NativeHookConfig hookConfig_; 117 std::unique_ptr<FILE, decltype(&fclose)> fpHookData_; 118 uint32_t ignoreCnts_ = 0; 119 uint32_t eventCnts_ = 0; 120 bool flushBasicData_ {true}; 121 std::vector<u64> u64regs_; 122 std::vector<CallFrame> callFrames_; 123 std::vector<uint64_t> callStack_; 124 // Key is callStack_, value is call stack id 125 std::map<std::vector<uint64_t>, uint32_t> callStackMap_; 126 std::chrono::seconds statisticsInterval_ {0}; 127 std::chrono::steady_clock::time_point lastStatisticsTime_; 128 // Key is call stack id, value is recordstatistic data 129 std::unordered_map<uint32_t, RecordStatistic> recordStatisticsMap_ {STATISTICS_MAP_SZIE}; 130 // Key is call stack id, value is recordstatistic data pointer 131 std::unordered_map<uint32_t, RecordStatistic*> statisticsPeriodData_ {STATISTICS_PERIOD_DATA_SIZE}; 132 // Key is alloc or mmap address, value first is mallocsize, second is recordstatistic data pointer 133 std::unordered_map<uint64_t, std::pair<uint64_t, RecordStatistic*>> allocAddrMap_ {ALLOC_ADDRMAMP_SIZE}; 134 bool isProtobufSerialize_ = true; 135 // used for plugin data 136 clockid_t pluginDataClockId_ = CLOCK_REALTIME; 137 // used for clac wait time in StackDataRepeater::TakeRawData() or statistics HookData 138 clockid_t hookDataClockId_ = CLOCK_REALTIME; 139 bool isHookStandaloneSerialize_ = false; 140 }; 141 142 #endif // STACK_PREPROCESS_H