1 /*
2 * Copyright (c) 2024 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
16 #include "faultloggerdunwinder_fuzzer.h"
17
18 #include <cstddef>
19 #include <cstdint>
20
21 #include "dfx_ark.h"
22 #include "dfx_config.h"
23 #include "dfx_hap.h"
24 #include "dfx_regs.h"
25 #include "dfx_xz_utils.h"
26 #include "dwarf_op.h"
27 #include "faultloggerd_fuzzertest_common.h"
28 #include "thread_context.h"
29 #include "unwinder.h"
30
31 namespace OHOS {
32 namespace HiviewDFX {
33 const int FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH = 50;
34
TestDfxConfig()35 void TestDfxConfig()
36 {
37 DfxConfig::GetConfig();
38 }
39
TestGetArkNativeFrameInfo(const uint8_t * data,size_t size)40 void TestGetArkNativeFrameInfo(const uint8_t* data, size_t size)
41 {
42 int pid;
43 uintptr_t pc;
44 uintptr_t fp;
45 uintptr_t sp;
46 int offsetTotalLength = sizeof(pid) + sizeof(pc) + sizeof(fp) + sizeof(sp);
47 if (offsetTotalLength > size) {
48 return;
49 }
50
51 STREAM_TO_VALUEINFO(data, pid);
52 STREAM_TO_VALUEINFO(data, pc);
53 STREAM_TO_VALUEINFO(data, fp);
54 STREAM_TO_VALUEINFO(data, sp);
55
56 const size_t jSFRAME_MAX = 64;
57 JsFrame jsFrames[jSFRAME_MAX];
58
59 DfxArk::GetArkNativeFrameInfo(pid, pc, fp, sp, jsFrames, size);
60 }
61
TestStepArkFrame(const uint8_t * data,size_t size)62 void TestStepArkFrame(const uint8_t* data, size_t size)
63 {
64 uintptr_t pc;
65 uintptr_t fp;
66 uintptr_t sp;
67 uintptr_t methodid;
68 int offsetTotalLength = sizeof(pc) + sizeof(fp) + sizeof(sp) + sizeof(methodid);
69 if (offsetTotalLength > size) {
70 return;
71 }
72
73 STREAM_TO_VALUEINFO(data, pc);
74 STREAM_TO_VALUEINFO(data, fp);
75 STREAM_TO_VALUEINFO(data, sp);
76 STREAM_TO_VALUEINFO(data, methodid);
77 bool isJsFrame = methodid % 2;
78
79 DfxMemory dfxMemory;
80 DfxArk::StepArkFrame(&dfxMemory, &(Unwinder::AccessMem), &fp, &sp, &pc, &methodid, &isJsFrame);
81 }
82
TestStepArkFrameWithJit(const uint8_t * data,size_t size)83 void TestStepArkFrameWithJit(const uint8_t* data, size_t size)
84 {
85 uintptr_t fp;
86 uintptr_t pc;
87 uintptr_t sp;
88 uintptr_t methodid;
89 int offsetTotalLength = sizeof(pc) + sizeof(fp) + sizeof(sp) + sizeof(methodid);
90 if (offsetTotalLength > size) {
91 return;
92 }
93
94 STREAM_TO_VALUEINFO(data, pc);
95 STREAM_TO_VALUEINFO(data, fp);
96 STREAM_TO_VALUEINFO(data, sp);
97 STREAM_TO_VALUEINFO(data, methodid);
98 bool isJsFrame = methodid % 2;
99
100 std::vector<uintptr_t> jitCache_ = {};
101 DfxMemory dfxMemory;
102 ArkUnwindParam arkParam(&dfxMemory, &(Unwinder::AccessMem), &fp, &sp, &pc, &methodid, &isJsFrame, jitCache_);
103 DfxArk::StepArkFrameWithJit(&arkParam);
104 }
105
TestJitCodeWriteFile(const uint8_t * data,size_t size)106 void TestJitCodeWriteFile(const uint8_t* data, size_t size)
107 {
108 int fd;
109 uintptr_t jitCacheData;
110 int offsetTotalLength = sizeof(fd) + sizeof(jitCacheData);
111 if (offsetTotalLength > size) {
112 return;
113 }
114
115 STREAM_TO_VALUEINFO(data, fd);
116 STREAM_TO_VALUEINFO(data, jitCacheData);
117
118 std::vector<uintptr_t> jitCache = {};
119 jitCache.push_back(jitCacheData);
120 DfxMemory dfxMemory;
121 DfxArk::JitCodeWriteFile(&dfxMemory, &(Unwinder::AccessMem), fd, jitCache.data(), jitCache.size());
122 }
123
TestParseArkFrameInfoLocal(const uint8_t * data,size_t size)124 void TestParseArkFrameInfoLocal(const uint8_t* data, size_t size)
125 {
126 uintptr_t pc;
127 uintptr_t funcOffset;
128 uintptr_t mapBegin;
129 uintptr_t offset;
130 int offsetTotalLength = sizeof(pc) + sizeof(funcOffset) + sizeof(mapBegin) + sizeof(offset);
131 if (offsetTotalLength > size) {
132 return;
133 }
134
135 STREAM_TO_VALUEINFO(data, pc);
136 STREAM_TO_VALUEINFO(data, funcOffset);
137 STREAM_TO_VALUEINFO(data, mapBegin);
138 STREAM_TO_VALUEINFO(data, offset);
139
140 JsFunction jsFunction;
141 DfxArk::ParseArkFrameInfoLocal(static_cast<uintptr_t>(pc), static_cast<uintptr_t>(funcOffset),
142 static_cast<uintptr_t>(mapBegin), static_cast<uintptr_t>(offset), &jsFunction);
143 }
144
TestArkCreateJsSymbolExtractor(const uint8_t * data,size_t size)145 void TestArkCreateJsSymbolExtractor(const uint8_t* data, size_t size)
146 {
147 uintptr_t extractorPtr;
148 if (size < sizeof(extractorPtr)) {
149 return;
150 }
151
152 STREAM_TO_VALUEINFO(data, extractorPtr);
153
154 DfxArk::ArkCreateJsSymbolExtractor(&extractorPtr);
155 }
156
TestArkDestoryJsSymbolExtractor(const uint8_t * data,size_t size)157 void TestArkDestoryJsSymbolExtractor(const uint8_t* data, size_t size)
158 {
159 uintptr_t extractorPtr;
160 if (size < sizeof(extractorPtr)) {
161 return;
162 }
163
164 STREAM_TO_VALUEINFO(data, extractorPtr);
165
166 DfxArk::ArkDestoryJsSymbolExtractor(extractorPtr);
167 }
168
TestDfxArk(const uint8_t * data,size_t size)169 void TestDfxArk(const uint8_t* data, size_t size)
170 {
171 TestGetArkNativeFrameInfo(data, size);
172 TestStepArkFrame(data, size);
173 TestStepArkFrameWithJit(data, size);
174 TestJitCodeWriteFile(data, size);
175 TestParseArkFrameInfoLocal(data, size);
176 TestArkCreateJsSymbolExtractor(data, size);
177 }
178
TestDfxHap(const uint8_t * data,size_t size)179 void TestDfxHap(const uint8_t* data, size_t size)
180 {
181 pid_t pid;
182 uint64_t pc;
183 uintptr_t methodid;
184 uintptr_t offset;
185 unsigned int offsetTotalLength = sizeof(pid) + sizeof(pc) + sizeof(methodid) + sizeof(offset);
186 if (offsetTotalLength > size) {
187 return;
188 }
189
190 STREAM_TO_VALUEINFO(data, pid);
191 STREAM_TO_VALUEINFO(data, pc);
192 STREAM_TO_VALUEINFO(data, methodid);
193 STREAM_TO_VALUEINFO(data, offset);
194
195 auto map = std::make_shared<DfxMap>();
196 JsFunction jsFunction;
197 DfxHap dfxHap;
198 dfxHap.ParseHapInfo(pid, pc, methodid, map, &jsFunction);
199 }
200
201 #if defined(__aarch64__)
TestSetFromFpMiniRegs(const uint8_t * data,size_t size)202 void TestSetFromFpMiniRegs(const uint8_t* data, size_t size)
203 {
204 uintptr_t regs;
205 if (size < sizeof(regs)) {
206 return;
207 }
208
209 STREAM_TO_VALUEINFO(data, regs);
210
211 auto dfxregs = std::make_shared<DfxRegsArm64>();
212 dfxregs->SetFromFpMiniRegs(®s, size);
213 }
214 #endif
215
216 #if defined(__aarch64__)
TestSetFromQutMiniRegs(const uint8_t * data,size_t size)217 void TestSetFromQutMiniRegs(const uint8_t* data, size_t size)
218 {
219 uintptr_t regs;
220 if (size < sizeof(regs)) {
221 return;
222 }
223
224 STREAM_TO_VALUEINFO(data, regs);
225
226 auto dfxregs = std::make_shared<DfxRegsArm64>();
227 dfxregs->SetFromQutMiniRegs(®s, size);
228 }
229 #endif
230
231 #if defined(__aarch64__)
TestDfxRegsArm64(const uint8_t * data,size_t size)232 void TestDfxRegsArm64(const uint8_t* data, size_t size)
233 {
234 TestSetFromFpMiniRegs(data, size);
235 TestSetFromQutMiniRegs(data, size);
236 }
237 #endif
238
TestThreadContext(const uint8_t * data,size_t size)239 void TestThreadContext(const uint8_t* data, size_t size)
240 {
241 int32_t tid;
242 uintptr_t stackBottom;
243 uintptr_t stackTop;
244 unsigned int offsetTotalLength = sizeof(tid) + sizeof(stackBottom) + sizeof(stackTop);
245 if (offsetTotalLength > size) {
246 return;
247 }
248
249 STREAM_TO_VALUEINFO(data, tid);
250 STREAM_TO_VALUEINFO(data, stackBottom);
251 STREAM_TO_VALUEINFO(data, stackTop);
252
253 LocalThreadContext& context = LocalThreadContext::GetInstance();
254 context.GetStackRange(tid, stackBottom, stackTop);
255 context.CollectThreadContext(tid);
256 context.GetThreadContext(tid);
257 context.ReleaseThread(tid);
258 }
259
TestDfxInstrStatistic(const uint8_t * data,size_t size)260 void TestDfxInstrStatistic(const uint8_t* data, size_t size)
261 {
262 uint32_t type;
263 uint64_t val;
264 uint64_t errInfo;
265 unsigned int offsetTotalLength = sizeof(type) + sizeof(val) + sizeof(errInfo) +
266 FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH;
267 if (offsetTotalLength > size) {
268 return;
269 }
270
271 STREAM_TO_VALUEINFO(data, type);
272 type = type % 10; // 10 : get the last digit of the number
273 STREAM_TO_VALUEINFO(data, val);
274 STREAM_TO_VALUEINFO(data, errInfo);
275
276 std::string soName(reinterpret_cast<const char*>(data), FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH);
277 data += FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH;
278
279 InstrStatisticType statisticType;
280 if (type == 0) {
281 statisticType = InstrStatisticType::InstructionEntriesArmExidx;
282 } else {
283 statisticType = InstrStatisticType::UnsupportedArmExidx;
284 }
285 DfxInstrStatistic& statistic = DfxInstrStatistic::GetInstance();
286 statistic.SetCurrentStatLib(soName);
287 statistic.AddInstrStatistic(statisticType, val, errInfo);
288 std::vector<std::pair<uint32_t, uint32_t>> result;
289 statistic.DumpInstrStatResult(result);
290 }
291
TestDfxXzUtils(const uint8_t * data,size_t size)292 void TestDfxXzUtils(const uint8_t* data, size_t size)
293 {
294 uint8_t src;
295 if (size < sizeof(src)) {
296 return;
297 }
298
299 STREAM_TO_VALUEINFO(data, src);
300
301 std::shared_ptr<std::vector<uint8_t>> out;
302 XzDecompress(&src, size, out);
303 }
304
FaultloggerdUnwinderTest(const uint8_t * data,size_t size)305 void FaultloggerdUnwinderTest(const uint8_t* data, size_t size)
306 {
307 TestDfxConfig();
308 TestDfxArk(data, size);
309 TestDfxHap(data, size);
310 #if defined(__aarch64__)
311 TestDfxRegsArm64(data, size);
312 #endif
313 TestThreadContext(data, size);
314 TestDfxInstrStatistic(data, size);
315 TestDfxXzUtils(data, size);
316 sleep(1);
317 }
318 } // namespace HiviewDFX
319 } // namespace OHOS
320
321 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)322 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
323 {
324 if (data == nullptr || size == 0) {
325 return 0;
326 }
327
328 /* Run your code on data */
329 OHOS::HiviewDFX::FaultloggerdUnwinderTest(data, size);
330 return 0;
331 }
332