1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 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 #include <mutex> 24 25 #include "logging.h" 26 #include "nocopyable.h" 27 #include "stack_data_repeater.h" 28 #include "buffer_writer.h" 29 #include "virtual_runtime.h" 30 #include "hook_common.h" 31 #include "native_hook_config.pb.h" 32 #include "native_hook_result.pb.h" 33 #include "safe_map.h" 34 35 class StackPreprocess { 36 public: 37 struct RecordStatistic { 38 uint32_t pid {0}; 39 uint32_t callstackId {0}; 40 uint32_t tagId {0}; 41 RecordStatisticsEvent::MemoryType type {RecordStatisticsEvent::MALLOC}; 42 uint64_t applyCount {0}; 43 uint64_t releaseCount {0}; 44 uint64_t applySize {0}; 45 uint64_t releaseSize {0}; 46 }; 47 48 explicit StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const NativeHookConfig& hookConfig, 49 clockid_t pluginDataClockId, FILE* fpHookData = nullptr, bool isHookStandalone = false); 50 ~StackPreprocess(); 51 void SetWriter(const std::shared_ptr<Writer>& writer); 52 bool StartTakeResults(); 53 bool StopTakeResults(); 54 bool FlushRecordStatistics(); 55 void SetSerializeMode(bool isProtobufSerialize); SetPid(int32_t pid)56 inline void SetPid(int32_t pid) 57 { 58 pid_ = pid; 59 } 60 void SaveMemTag(uint32_t tagId, const std::string& tagName); 61 bool GetMemTag(uint32_t tagId, std::string& tagName); 62 void SaveThreadName(uint32_t tid, const std::string& tname); 63 void ReportBasicData(); 64 void WriteHookConfig(); SetSaServiceFlag(bool flag)65 inline void SetSaServiceFlag(bool flag) 66 { 67 isSaService_ = flag; 68 } 69 void TakeResultsFromShmem(const std::shared_ptr<EventNotifier>&, const std::shared_ptr<ShareMemoryBlock>&); 70 71 private: 72 using CallFrame = OHOS::Developtools::NativeDaemon::CallFrame; 73 struct ElfSymbolTable { 74 uint64_t textVaddr; 75 uint32_t textOffset; 76 uint32_t symEntSize; 77 std::vector<uint8_t> strTable; 78 std::vector<uint8_t> symTable; 79 }; 80 81 enum RecordStatisticsLimit : std::size_t { 82 STATISTICS_MAP_SZIE = 100000, 83 STATISTICS_PERIOD_DATA_SIZE = 100000, 84 ALLOC_ADDRMAMP_SIZE = 100000, 85 }; 86 87 private: 88 void TakeResults(); 89 void SetHookData(RawStackPtr RawStack, std::vector<CallFrame>& callFrames, 90 BatchNativeHookData& batchNativeHookData); 91 void SetHookData(RawStackPtr rawStack, BatchNativeHookData& batchNativeHookData); 92 void WriteFrames(RawStackPtr RawStack, const std::vector<CallFrame>& callFrames); 93 void SetFrameInfo(Frame& frame, CallFrame& callFrame); 94 void ReportSymbolNameMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData); 95 void ReportFilePathMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData); 96 void ReportFrameMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData); 97 void ReportThreadNameMap(uint32_t tid, const std::string& tname, BatchNativeHookData& batchNativeHookData); 98 void SetMapsInfo(pid_t pid); 99 void SetSymbolInfo(uint32_t filePathId, ElfSymbolTable& symbolInfo, 100 BatchNativeHookData& batchNativeHookData); 101 void FlushData(BatchNativeHookData& stackData); 102 void Flush(const uint8_t* src, size_t size); 103 void GetSymbols(const std::string& filePath, ElfSymbolTable& symbols); 104 105 void FillOfflineCallStack(std::vector<CallFrame>& callFrames, size_t idx); 106 void FillCallStack(std::vector<CallFrame>& callFrames, 107 BatchNativeHookData& batchNativeHookData, size_t idx); 108 uint32_t SetCallStackMap(BatchNativeHookData& batchNativeHookData); 109 uint32_t GetCallStackId(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 110 BatchNativeHookData& batchNativeHookData); 111 uint32_t FindCallStackId(std::vector<uint64_t>& callStack); 112 template <typename T> 113 void SetEventFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 114 BatchNativeHookData& batchNativeHookData, T* event, uint32_t stackId); 115 void SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames, 116 BatchNativeHookData& batchNativeHookData); 117 void SetAllocStatisticsFrame(const RawStackPtr& rawStack, BatchNativeHookData& batchNativeHookData); 118 bool SetFreeStatisticsData(uint64_t addr); 119 void SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists = false); 120 void IntervalFlushRecordStatistics(BatchNativeHookData& stackData); 121 bool HandleNoStackEvent(RawStackPtr& rawStack, BatchNativeHookData& stackData); 122 unsigned LgFloor(unsigned long x); 123 uint64_t PowCeil(uint64_t x); 124 size_t ComputeAlign(size_t size); 125 private: 126 std::shared_ptr<Writer> writer_ = nullptr; 127 StackDataRepeaterPtr dataRepeater_ = nullptr; 128 std::thread thread_ {}; 129 std::unique_ptr<uint8_t[]> buffer_; 130 std::atomic_bool isStopTakeData_ = false; 131 std::shared_ptr<OHOS::Developtools::NativeDaemon::VirtualRuntime> runtime_instance; 132 DISALLOW_COPY_AND_MOVE(StackPreprocess); 133 OHOS::SafeMap<uint32_t, std::string> memTagMap_ = {}; 134 std::unordered_map<uint32_t, std::string> threadNameMap_ = {}; 135 NativeHookConfig hookConfig_; 136 uint32_t ignoreCnts_ = 0; 137 uint32_t eventCnts_ = 0; 138 bool flushBasicData_ {true}; 139 std::vector<u64> u64regs_; 140 std::vector<CallFrame> callFrames_; 141 std::vector<uint64_t> callStack_; 142 // Key is callStack_, value is call stack id 143 std::map<std::vector<uint64_t>, uint32_t> callStackMap_; 144 // Key is ip , response_library_mode used 145 std::unordered_map<uint64_t, uint32_t> responseLibraryMap_; 146 std::chrono::seconds statisticsInterval_ {0}; 147 // Key is call stack id, value is recordstatistic data 148 std::unordered_map<uint32_t, RecordStatistic> recordStatisticsMap_ {STATISTICS_MAP_SZIE}; 149 // Key is call stack id, value is recordstatistic data pointer 150 std::unordered_map<uint32_t, RecordStatistic*> statisticsPeriodData_ {STATISTICS_PERIOD_DATA_SIZE}; 151 // Key is alloc or mmap address, value first is mallocsize, second is recordstatistic data pointer 152 std::unordered_map<uint64_t, std::pair<uint64_t, RecordStatistic*>> allocAddrMap_ {ALLOC_ADDRMAMP_SIZE}; 153 bool isProtobufSerialize_ = true; 154 // used for plugin data 155 clockid_t pluginDataClockId_ = CLOCK_REALTIME; 156 // used for clac wait time in StackDataRepeater::TakeRawData() or statistics HookData 157 clockid_t hookDataClockId_ = CLOCK_REALTIME; 158 FILE* fpHookData_ {nullptr}; 159 bool isHookStandaloneSerialize_ {false}; 160 int32_t pid_ {-1}; 161 std::mutex mtx_; 162 bool isSaService_{false}; 163 std::mutex mtex_; 164 }; 165 166 #endif // STACK_PREPROCESS_H