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 HIPERF_VIRTUAL_RUNTIME_H 16 #define HIPERF_VIRTUAL_RUNTIME_H 17 #include <unistd.h> 18 #include <sys/types.h> 19 #include <pthread.h> 20 #include <functional> 21 #include <map> 22 #include "callstack.h" 23 #include "perf_event_record.h" 24 #include "symbols.h" 25 #include "virtual_thread.h" 26 27 namespace OHOS { 28 namespace Developtools { 29 namespace NativeDaemon { 30 /* 31 This Class contains userspace thread objects. and kernel space objects 32 It represents a virtual operating environment, mainly referring to the relationship between pid, 33 mmaps, and symbols. 34 35 It mainly receives data is ip pointer (virtual address), pid 36 According to these data, it will find the corresponding mmap and its corresponding elf (also called 37 DSO) 38 39 Then find the corresponding symbol in the corresponding elf symbol file according to the offset 40 recorded in the corresponding mmap. 41 */ 42 43 class VirtualRuntime { 44 public: 45 VirtualRuntime(); 46 virtual ~VirtualRuntime(); 47 // thread need hook the record 48 // from the record , it will call back to write some Simulated Record 49 // case 1. some mmap will be create when it read mmaps for each new process (from record sample) 50 51 // set symbols path , it will send to every symobile file for search 52 bool SetSymbolsPaths(const std::vector<std::string> &symbolsPaths); 53 54 // any mode 55 static_assert(sizeof(pid_t) == sizeof(int)); 56 GetSymbolsFiles()57 const std::set<std::unique_ptr<SymbolsFile>, CCompareSymbolsFile> &GetSymbolsFiles() 58 { 59 return symbolsFiles_; 60 } 61 62 const Symbol GetSymbol(uint64_t ip, pid_t pid, pid_t tid, 63 const perf_callchain_context &context = PERF_CONTEXT_MAX); 64 65 VirtualThread &GetThread(pid_t pid, pid_t tid); GetThreads()66 const std::map<pid_t, VirtualThread> &GetThreads() const 67 { 68 return userSpaceThreadMap_; 69 } 70 71 void UnwindStack(std::vector<u64> regs, 72 const u8* stack_addr, 73 int stack_size, 74 pid_t pid, 75 pid_t tid, 76 std::vector<CallFrame>& callsFrames, 77 size_t maxStackLevel); 78 void GetSymbolName(pid_t pid, pid_t tid, std::vector<CallFrame>& callsFrames); 79 void ClearMaps(); 80 // debug time 81 #ifdef HIPERF_DEBUG_TIME 82 std::chrono::microseconds updateSymbolsTimes_ = std::chrono::microseconds::zero(); 83 std::chrono::microseconds unwindFromRecordTimes_ = std::chrono::microseconds::zero(); 84 std::chrono::microseconds unwindCallStackTimes_ = std::chrono::microseconds::zero(); 85 std::chrono::microseconds symbolicRecordTimes_ = std::chrono::microseconds::zero(); 86 std::chrono::microseconds updateThreadTimes_ = std::chrono::microseconds::zero(); 87 #endif 88 const bool loadSymboleWhenNeeded_ = true; // thie is a feature config 89 void UpdateSymbols(std::string filename); 90 private: 91 CallStack callstack_; 92 // pid map with user space thread 93 pthread_mutex_t threadMapsLock_; 94 std::map<pid_t, VirtualThread> userSpaceThreadMap_; 95 // not pid , just memmap 96 std::vector<MemMapItem> kernelSpaceMemMaps_; 97 pthread_mutex_t processSymbolsFileLock_; 98 std::set<std::unique_ptr<SymbolsFile>, CCompareSymbolsFile> symbolsFiles_; 99 // review maybe need change to lru cache? 100 std::map<pid_t, HashList<uint64_t, Symbol>> threadSymbolCache_; 101 HashList<uint64_t, Symbol> kernelSymbolCache_; 102 bool GetSymbolCache(uint64_t ip, pid_t pid, pid_t tid, Symbol &symbol, 103 const perf_callchain_context &context); 104 void UpdateSymbolCache(uint64_t ip, Symbol &symbol, HashList<uint64_t, Symbol> &cache); 105 106 // find synbols function name 107 void MakeCallFrame(Symbol &symbol, CallFrame &callFrame); 108 109 // threads 110 VirtualThread &UpdateThread(pid_t pid, pid_t tid, const std::string name = ""); 111 std::string ReadThreadName(pid_t tid); 112 VirtualThread &CreateThread(pid_t pid, pid_t tid); 113 114 const Symbol GetKernelSymbol(uint64_t ip, const std::vector<MemMapItem> &memMaps); 115 const Symbol GetUserSymbol(uint64_t ip, const VirtualThread &thread); 116 117 std::vector<std::string> symbolsPaths_; 118 119 friend class VirtualRuntimeTest; 120 friend class VirtualThread; 121 pthread_mutex_t threadMemMapsLock_; 122 std::vector<MemMapItem> processMemMaps_; 123 }; 124 } // namespace NativeDaemon 125 } // namespace Developtools 126 } // namespace OHOS 127 #endif