1 /*
2  * Copyright (c) 2022 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_THREAD_H
16 #define HIPERF_VIRTUAL_THREAD_H
17 
18 #include <cinttypes>
19 #include <functional>
20 #include <unordered_set>
21 #include <unordered_map>
22 
23 #include "debug_logger.h"
24 #include "dfx_maps.h"
25 #include "perf_event_record.h"
26 #include "symbols_file.h"
27 
28 namespace OHOS {
29 namespace Developtools {
30 namespace HiPerf {
31 /*
32 03284000-03289000 r--p 00000000 b3:05 289        /system/bin/sh
33 032b7000-032b9000 rw-p 00000000 00:00 0
34 aff60000-aff96000 r--p 00000000 b3:05 923        /system/lib/libc++.so
35 affeb000-affed000 rw-p 00000000 00:00 0
36 b0023000-b0024000 r--p 00000000 b3:05 959        /system/lib/libdl.so
37 */
38 const std::string MMAP_NAME_HEAP = "[heap]";
39 const std::string MMAP_NAME_ANON = "[anon]";
40 
41 class VirtualThread {
42 public:
43     VirtualThread(const VirtualThread &) = delete;
44     VirtualThread &operator=(const VirtualThread &) = delete;
45 
VirtualThread(pid_t pid, const std::vector<std::unique_ptr<SymbolsFile>> &symbolsFiles)46     VirtualThread(pid_t pid, const std::vector<std::unique_ptr<SymbolsFile>> &symbolsFiles)
47         : pid_(pid),
48           tid_(pid),
49           symbolsFiles_(symbolsFiles),
50           processMemMaps_(),
51           memMaps_(processMemMaps_),
52           vaddr4kPageCache_(vaddr4kPageCacheOfProc_),
53           memMapsIndexs_(processMemMapsIndexs_),
54           parent_(*this) {}
55 
VirtualThread(pid_t pid, pid_t tid, VirtualThread &thread, const std::vector<std::unique_ptr<SymbolsFile>> &symbolsFiles)56     VirtualThread(pid_t pid, pid_t tid, VirtualThread &thread,
57                   const std::vector<std::unique_ptr<SymbolsFile>> &symbolsFiles)
58         : pid_(pid),
59           tid_(tid),
60           symbolsFiles_(symbolsFiles),
61           processMemMaps_(),
62           memMaps_(thread.processMemMaps_),
63           vaddr4kPageCache_(thread.vaddr4kPageCacheOfProc_),
64           memMapsIndexs_(thread.processMemMapsIndexs_),
65           parent_(thread)
66     {
67         HLOG_ASSERT(pid != tid);
68         HLOGV("%d %d map from parent size is %zu", pid, tid, memMaps_.size());
69     };
70 
71     pid_t pid_;
72     pid_t tid_;
73     std::string name_;
74 
GetMaps() const75     const std::vector<std::shared_ptr<DfxMap>> &GetMaps() const
76     {
77         return memMaps_;
78     }
79     void ParseMap();
80     void FixHMBundleMap();
81     void ParseServiceMap(const std::string &filename);
82     void ParseDevhostMap(pid_t devhost);
83     std::shared_ptr<DfxMap> CreateMapItem(const std::string filename, uint64_t begin,
84                                           uint64_t len, uint64_t offset, uint32_t prot = 0);
85     std::shared_ptr<DfxMap> FindMapByAddr(uint64_t addr) const;
86     std::shared_ptr<DfxMap> FindMapByFileInfo(const std::string name, uint64_t offset) const;
87     int64_t FindMapIndexByAddr(uint64_t addr) const;
88     SymbolsFile *FindSymbolsFileByMap(std::shared_ptr<DfxMap> map) const;
89     bool ReadRoMemory(uint64_t vaddr, uint8_t *data, size_t size) const;
90 #ifdef HIPERF_DEBUG
91     void ReportVaddrMapMiss(uint64_t vaddr) const;
92 #endif
93 
94 private:
95     void SortMemMaps();
96 #ifdef DEBUG_TIME
97     bool IsSorted() const;
98 #endif
99     const std::vector<std::unique_ptr<SymbolsFile>> &symbolsFiles_;
100 
101     // proc/xx/map
102     // use to put the parent thread's map
103     // only process have memmap
104     std::vector<std::shared_ptr<DfxMap>> processMemMaps_;
105     std::unordered_map<uint64_t, uint64_t> vaddr4kPageCacheOfProc_;
106     // thread must use ref from process
107     std::vector<std::shared_ptr<DfxMap>> &memMaps_;
108     std::unordered_map<uint64_t, uint64_t> &vaddr4kPageCache_;
109     std::vector<int> processMemMapsIndexs_;
110     std::vector<int> &memMapsIndexs_;
111     VirtualThread &parent_;
112 #ifdef HIPERF_DEBUG
113     mutable std::unordered_set<uint64_t> missedRuntimeVaddr_;
114 #endif
115 #ifdef DEBUG_MISS_SYMBOL
116     mutable std::vector<std::string> missedSymbolFile_;
117 #endif
118     FRIEND_TEST(VirtualThreadTest, ReadRoMemory);
119 };
120 } // namespace HiPerf
121 } // namespace Developtools
122 } // namespace OHOS
123 #endif // HIPERF_VIRTUAL_THREAD_H
124