• 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 "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