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 
16 #ifndef HOOK_COMMON_H
17 #define HOOK_COMMON_H
18 
19 #if defined(HAVE_LIBUNWIND) && HAVE_LIBUNWIND
20 // for libunwind.h empty struct has size 0 in c, size 1 in c++
21 #define UNW_EMPTY_STRUCT uint8_t unused;
22 #include <libunwind.h>
23 #endif
24 
25 #include "register.h"
26 #include "utilities.h"
27 
28 #define MAX_THREAD_NAME (32)
29 #define MAX_UNWIND_DEPTH (100)
30 
31 namespace OHOS {
32 namespace Developtools {
33 namespace NativeDaemon {
34 const int STACK_DATA_SIZE = 40000;
35 const int SPEED_UP_THRESHOLD = STACK_DATA_SIZE / 2;
36 const int SLOW_DOWN_THRESHOLD = STACK_DATA_SIZE / 4;
37 const int32_t MIN_STACK_DEPTH = 6;
38 // filter two layers of dwarf stack in libnative_hook.z.so
39 const size_t FILTER_STACK_DEPTH = 2;
40 const size_t MAX_CALL_FRAME_UNWIND_SIZE = MAX_UNWIND_DEPTH + FILTER_STACK_DEPTH;
41 // dlopen function minimum stack depth
42 const int32_t DLOPEN_MIN_UNWIND_DEPTH = 5;
43 const uint32_t  MMAP_FILE_TYPE = (1u << 8);
44 // default max js stack depth
45 const int32_t DEFAULT_MAX_JS_STACK_DEPTH = 10;
46 }
47 }
48 }
49 
50 constexpr size_t MAX_REG_SIZE = sizeof(uint64_t)
51     * OHOS::Developtools::NativeDaemon::PERF_REG_ARM64_MAX;
52 
53 enum {
54     MALLOCDISABLE = (1u << 0),
55     MMAPDISABLE = (1u << 1),
56     FREEMSGSTACK = (1u << 2),
57     MUNMAPMSGSTACK = (1u << 3),
58     FPUNWIND = (1u << 4),
59     BLOCKED = (1u << 5),
60     MEMTRACE_ENABLE = (1u << 6),
61 };
62 
63 enum {
64     MALLOC_MSG = 0,
65     FREE_MSG,
66     MMAP_MSG,
67     MMAP_FILE_PAGE_MSG,
68     MUNMAP_MSG,
69     MEMORY_USING_MSG,
70     MEMORY_UNUSING_MSG,
71     MEMORY_TAG,
72     THREAD_NAME_MSG,
73     PR_SET_VMA_MSG,
74     JS_STACK_MSG,
75     NMD_MSG,
76     END_MSG,
77 };
78 
79 struct alignas(8) MmapFileRawData { // 8 is 8 bit
80     off_t offset;
81     uint32_t flags;
82 };
83 
84 struct alignas(8) BaseStackRawData { // 8 is 8 bit
85     union {
86         struct timespec ts;
87         MmapFileRawData mmapArgs;
88     };
89     void* addr;
90     size_t mallocSize;
91     uint64_t jsChainId;
92     uint32_t pid;
93     uint32_t tid;
94     uint16_t type;
95     uint16_t tagId;
96 };
97 
98 struct alignas(8) StackRawData: public BaseStackRawData { // 8 is 8 bit
99     union {
100         char regs[MAX_REG_SIZE];
101         uint64_t ip[MAX_UNWIND_DEPTH];
102         char name[PATH_MAX + 1] {0};
103     };
104 };
105 
106 struct alignas(8) ReportEventBaseData { // 8 is 8 bit
ReportEventBaseData(const BaseStackRawData* baseData, uint32_t id = 0)107     ReportEventBaseData(const BaseStackRawData* baseData, uint32_t id = 0)
108     {
109         ts = baseData->ts;
110         addr = reinterpret_cast<uint64_t>(baseData->addr);
111         type = baseData->type;
112         tagId = baseData->tagId;
113         mallocSize = baseData->mallocSize;
114         tid = baseData->tid;
115         stackMapId = id;
116     }
117     struct timespec ts;
118     uint64_t addr : 40;
119     uint64_t type : 8;
120     uint64_t tagId : 16;
121     uint32_t mallocSize;
122     uint32_t tid;
123     uint32_t stackMapId;
124 };
125 
126 struct alignas(8) ArkTsClientConfig { // 8 is 8 bit
127         int32_t jsStackReport = 0;
128         uint8_t maxJsStackDepth = 0;
129         bool jsFpunwind = false;
130         char filterNapiName[64] = {""};
131 };
132 
133 struct alignas(8) ClientConfig { // 8 is 8 bit
Reset()134     void Reset()
135     {
136         filterSize = -1;
137         shareMemorySize = 0;
138         clockId = CLOCK_REALTIME;
139         maxStackDepth = 0;
140         statisticsInterval = 0;
141         sampleInterval = 0;
142         mallocDisable = false;
143         mmapDisable = false;
144         freeStackData = false;
145         munmapStackData = false;
146         fpunwind = false;
147         isBlocked = false;
148         memtraceEnable = false;
149         responseLibraryMode = false;
150         freeEventOnlyAddrEnable = false;
151         printNmd = false;
152         nmdType = -1;
153         arktsConfig.jsStackReport = 0;
154         arktsConfig.maxJsStackDepth = 0;
155         arktsConfig.jsFpunwind = false;
156         arktsConfig.filterNapiName[0] = '\0';
157     }
158 
ToString()159     std::string ToString()
160     {
161         std::stringstream ss;
162         ss << "filterSize:" << filterSize << ", shareMemorySize:" << shareMemorySize
163             << ", clockId:" << clockId << ", maxStackDepth:" << std::to_string(maxStackDepth)
164             << ", mallocDisable:" << mallocDisable << ", mmapDisable:" << mmapDisable
165             << ", freeStackData:" << freeStackData << ", munmapStackData:" << munmapStackData
166             << ", fpunwind:" << fpunwind << ", isBlocked:" << isBlocked << ", memtraceEnable:" << memtraceEnable
167             << ", sampleInterval: " << sampleInterval << ", responseLibraryMode: " << responseLibraryMode
168             << ", freeEventOnlyAddrEnable: " << freeEventOnlyAddrEnable << ", jsStackReport: "
169             << arktsConfig.jsStackReport << ", maxJsStackDepth: "
170             << std::to_string(arktsConfig.maxJsStackDepth) << ", filterNapiName: "
171             << arktsConfig.filterNapiName << ", jsFpunwind: " << arktsConfig.jsFpunwind;
172         return ss.str();
173     }
174 
175     int32_t filterSize = -1;
176     uint32_t shareMemorySize = 0;
177     uint32_t sampleInterval = 0;
178     uint32_t statisticsInterval = 0;
179     clockid_t clockId = CLOCK_REALTIME;
180     uint8_t maxStackDepth = 0;
181     bool mallocDisable = false;
182     bool mmapDisable = false;
183     bool freeStackData = false;
184     bool munmapStackData = false;
185     bool fpunwind = false;
186     bool isBlocked = false;
187     bool memtraceEnable = false;
188     bool responseLibraryMode = false;
189     bool freeEventOnlyAddrEnable = false;
190     bool printNmd = false;
191     int nmdType = -1;
192     ArkTsClientConfig arktsConfig = {0};
193 };
194 #endif // HOOK_COMMON_H