• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "call_stack.h"
23 #include "perf_event_record.h"
24 #include "symbols_file.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(bool onDevice = true);
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() const
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     bool 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     bool GetSymbolName(pid_t pid, pid_t tid, std::vector<CallFrame>& callsFrames, int offset, bool first);
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     bool IsSymbolExist(std::string fileName);
91     void UpdateMaps(pid_t pid, pid_t tid);
92 private:
93     CallStack callstack_;
94     // pid map with user space thread
95     pthread_mutex_t threadMapsLock_;
96     std::map<pid_t, VirtualThread> userSpaceThreadMap_;
97     // not pid , just memmap
98     std::vector<MemMapItem> kernelSpaceMemMaps_;
99     pthread_mutex_t processSymbolsFileLock_;
100     std::set<std::unique_ptr<SymbolsFile>, CCompareSymbolsFile> symbolsFiles_;
101     enum SymbolCacheLimit : std::size_t {
102         KERNEL_SYMBOL_CACHE_LIMIT = 4000,
103         THREAD_SYMBOL_CACHE_LIMIT = 2000,
104     };
105     std::unordered_map<pid_t, HashList<uint64_t, Symbol>> threadSymbolCache_;
106     HashList<uint64_t, Symbol> kernelSymbolCache_ {KERNEL_SYMBOL_CACHE_LIMIT};
107     bool GetSymbolCache(uint64_t ip, pid_t pid, pid_t tid, Symbol &symbol,
108                         const perf_callchain_context &context);
109     void UpdateSymbolCache(uint64_t ip, Symbol &symbol, HashList<uint64_t, Symbol> &cache);
110 
111     // find synbols function name
112     void MakeCallFrame(Symbol &symbol, CallFrame &callFrame);
113 
114     // threads
115     VirtualThread &UpdateThread(pid_t pid, pid_t tid, const std::string name = "");
116     std::string ReadThreadName(pid_t tid);
117     VirtualThread &CreateThread(pid_t pid, pid_t tid);
118 
119     const Symbol GetKernelSymbol(uint64_t ip, const std::vector<MemMapItem> &memMaps,
120                                  const VirtualThread &thread);
121     const Symbol GetUserSymbol(uint64_t ip, const VirtualThread &thread);
122 
123     std::vector<std::string> symbolsPaths_;
124 
125     friend class VirtualRuntimeTest;
126     friend class VirtualThread;
127     pthread_mutex_t threadMemMapsLock_;
128     std::vector<MemMapItem> processMemMaps_;
129     std::unordered_set<uint64_t> failedIPs_;
130 };
131 } // namespace NativeDaemon
132 } // namespace Developtools
133 } // namespace OHOS
134 #endif