1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include "faultloggerdunwinder_fuzzer.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <cstddef>
19800b99b8Sopenharmony_ci#include <cstdint>
20800b99b8Sopenharmony_ci
21800b99b8Sopenharmony_ci#include "dfx_ark.h"
22800b99b8Sopenharmony_ci#include "dfx_config.h"
23800b99b8Sopenharmony_ci#include "dfx_hap.h"
24800b99b8Sopenharmony_ci#include "dfx_regs.h"
25800b99b8Sopenharmony_ci#include "dfx_xz_utils.h"
26800b99b8Sopenharmony_ci#include "dwarf_op.h"
27800b99b8Sopenharmony_ci#include "faultloggerd_fuzzertest_common.h"
28800b99b8Sopenharmony_ci#include "thread_context.h"
29800b99b8Sopenharmony_ci#include "unwinder.h"
30800b99b8Sopenharmony_ci
31800b99b8Sopenharmony_cinamespace OHOS {
32800b99b8Sopenharmony_cinamespace HiviewDFX {
33800b99b8Sopenharmony_ciconst int FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH = 50;
34800b99b8Sopenharmony_ci
35800b99b8Sopenharmony_civoid TestDfxConfig()
36800b99b8Sopenharmony_ci{
37800b99b8Sopenharmony_ci    DfxConfig::GetConfig();
38800b99b8Sopenharmony_ci}
39800b99b8Sopenharmony_ci
40800b99b8Sopenharmony_civoid TestGetArkNativeFrameInfo(const uint8_t* data, size_t size)
41800b99b8Sopenharmony_ci{
42800b99b8Sopenharmony_ci    int pid;
43800b99b8Sopenharmony_ci    uintptr_t pc;
44800b99b8Sopenharmony_ci    uintptr_t fp;
45800b99b8Sopenharmony_ci    uintptr_t sp;
46800b99b8Sopenharmony_ci    int offsetTotalLength = sizeof(pid) + sizeof(pc) + sizeof(fp) + sizeof(sp);
47800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
48800b99b8Sopenharmony_ci        return;
49800b99b8Sopenharmony_ci    }
50800b99b8Sopenharmony_ci
51800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, pid);
52800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, pc);
53800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, fp);
54800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, sp);
55800b99b8Sopenharmony_ci
56800b99b8Sopenharmony_ci    const size_t jSFRAME_MAX = 64;
57800b99b8Sopenharmony_ci    JsFrame jsFrames[jSFRAME_MAX];
58800b99b8Sopenharmony_ci
59800b99b8Sopenharmony_ci    DfxArk::GetArkNativeFrameInfo(pid, pc, fp, sp, jsFrames, size);
60800b99b8Sopenharmony_ci}
61800b99b8Sopenharmony_ci
62800b99b8Sopenharmony_civoid TestStepArkFrame(const uint8_t* data, size_t size)
63800b99b8Sopenharmony_ci{
64800b99b8Sopenharmony_ci    uintptr_t pc;
65800b99b8Sopenharmony_ci    uintptr_t fp;
66800b99b8Sopenharmony_ci    uintptr_t sp;
67800b99b8Sopenharmony_ci    uintptr_t methodid;
68800b99b8Sopenharmony_ci    int offsetTotalLength = sizeof(pc) + sizeof(fp) + sizeof(sp) + sizeof(methodid);
69800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
70800b99b8Sopenharmony_ci        return;
71800b99b8Sopenharmony_ci    }
72800b99b8Sopenharmony_ci
73800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, pc);
74800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, fp);
75800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, sp);
76800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, methodid);
77800b99b8Sopenharmony_ci    bool isJsFrame = methodid % 2;
78800b99b8Sopenharmony_ci
79800b99b8Sopenharmony_ci    DfxMemory dfxMemory;
80800b99b8Sopenharmony_ci    DfxArk::StepArkFrame(&dfxMemory, &(Unwinder::AccessMem), &fp, &sp, &pc, &methodid, &isJsFrame);
81800b99b8Sopenharmony_ci}
82800b99b8Sopenharmony_ci
83800b99b8Sopenharmony_civoid TestStepArkFrameWithJit(const uint8_t* data, size_t size)
84800b99b8Sopenharmony_ci{
85800b99b8Sopenharmony_ci    uintptr_t fp;
86800b99b8Sopenharmony_ci    uintptr_t pc;
87800b99b8Sopenharmony_ci    uintptr_t sp;
88800b99b8Sopenharmony_ci    uintptr_t methodid;
89800b99b8Sopenharmony_ci    int offsetTotalLength = sizeof(pc) + sizeof(fp) + sizeof(sp) + sizeof(methodid);
90800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
91800b99b8Sopenharmony_ci        return;
92800b99b8Sopenharmony_ci    }
93800b99b8Sopenharmony_ci
94800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, pc);
95800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, fp);
96800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, sp);
97800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, methodid);
98800b99b8Sopenharmony_ci    bool isJsFrame = methodid % 2;
99800b99b8Sopenharmony_ci
100800b99b8Sopenharmony_ci    std::vector<uintptr_t> jitCache_ = {};
101800b99b8Sopenharmony_ci    DfxMemory dfxMemory;
102800b99b8Sopenharmony_ci    ArkUnwindParam arkParam(&dfxMemory, &(Unwinder::AccessMem), &fp, &sp, &pc, &methodid, &isJsFrame, jitCache_);
103800b99b8Sopenharmony_ci    DfxArk::StepArkFrameWithJit(&arkParam);
104800b99b8Sopenharmony_ci}
105800b99b8Sopenharmony_ci
106800b99b8Sopenharmony_civoid TestJitCodeWriteFile(const uint8_t* data, size_t size)
107800b99b8Sopenharmony_ci{
108800b99b8Sopenharmony_ci    int fd;
109800b99b8Sopenharmony_ci    uintptr_t jitCacheData;
110800b99b8Sopenharmony_ci    int offsetTotalLength = sizeof(fd) + sizeof(jitCacheData);
111800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
112800b99b8Sopenharmony_ci        return;
113800b99b8Sopenharmony_ci    }
114800b99b8Sopenharmony_ci
115800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, fd);
116800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, jitCacheData);
117800b99b8Sopenharmony_ci
118800b99b8Sopenharmony_ci    std::vector<uintptr_t> jitCache = {};
119800b99b8Sopenharmony_ci    jitCache.push_back(jitCacheData);
120800b99b8Sopenharmony_ci    DfxMemory dfxMemory;
121800b99b8Sopenharmony_ci    DfxArk::JitCodeWriteFile(&dfxMemory, &(Unwinder::AccessMem), fd, jitCache.data(), jitCache.size());
122800b99b8Sopenharmony_ci}
123800b99b8Sopenharmony_ci
124800b99b8Sopenharmony_civoid TestParseArkFrameInfoLocal(const uint8_t* data, size_t size)
125800b99b8Sopenharmony_ci{
126800b99b8Sopenharmony_ci    uintptr_t pc;
127800b99b8Sopenharmony_ci    uintptr_t funcOffset;
128800b99b8Sopenharmony_ci    uintptr_t mapBegin;
129800b99b8Sopenharmony_ci    uintptr_t offset;
130800b99b8Sopenharmony_ci    int offsetTotalLength = sizeof(pc) + sizeof(funcOffset) + sizeof(mapBegin) + sizeof(offset);
131800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
132800b99b8Sopenharmony_ci        return;
133800b99b8Sopenharmony_ci    }
134800b99b8Sopenharmony_ci
135800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, pc);
136800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, funcOffset);
137800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, mapBegin);
138800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, offset);
139800b99b8Sopenharmony_ci
140800b99b8Sopenharmony_ci    JsFunction jsFunction;
141800b99b8Sopenharmony_ci    DfxArk::ParseArkFrameInfoLocal(static_cast<uintptr_t>(pc), static_cast<uintptr_t>(funcOffset),
142800b99b8Sopenharmony_ci                                   static_cast<uintptr_t>(mapBegin), static_cast<uintptr_t>(offset), &jsFunction);
143800b99b8Sopenharmony_ci}
144800b99b8Sopenharmony_ci
145800b99b8Sopenharmony_civoid TestArkCreateJsSymbolExtractor(const uint8_t* data, size_t size)
146800b99b8Sopenharmony_ci{
147800b99b8Sopenharmony_ci    uintptr_t extractorPtr;
148800b99b8Sopenharmony_ci    if (size < sizeof(extractorPtr)) {
149800b99b8Sopenharmony_ci        return;
150800b99b8Sopenharmony_ci    }
151800b99b8Sopenharmony_ci
152800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, extractorPtr);
153800b99b8Sopenharmony_ci
154800b99b8Sopenharmony_ci    DfxArk::ArkCreateJsSymbolExtractor(&extractorPtr);
155800b99b8Sopenharmony_ci}
156800b99b8Sopenharmony_ci
157800b99b8Sopenharmony_civoid TestArkDestoryJsSymbolExtractor(const uint8_t* data, size_t size)
158800b99b8Sopenharmony_ci{
159800b99b8Sopenharmony_ci    uintptr_t extractorPtr;
160800b99b8Sopenharmony_ci    if (size < sizeof(extractorPtr)) {
161800b99b8Sopenharmony_ci        return;
162800b99b8Sopenharmony_ci    }
163800b99b8Sopenharmony_ci
164800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, extractorPtr);
165800b99b8Sopenharmony_ci
166800b99b8Sopenharmony_ci    DfxArk::ArkDestoryJsSymbolExtractor(extractorPtr);
167800b99b8Sopenharmony_ci}
168800b99b8Sopenharmony_ci
169800b99b8Sopenharmony_civoid TestDfxArk(const uint8_t* data, size_t size)
170800b99b8Sopenharmony_ci{
171800b99b8Sopenharmony_ci    TestGetArkNativeFrameInfo(data, size);
172800b99b8Sopenharmony_ci    TestStepArkFrame(data, size);
173800b99b8Sopenharmony_ci    TestStepArkFrameWithJit(data, size);
174800b99b8Sopenharmony_ci    TestJitCodeWriteFile(data, size);
175800b99b8Sopenharmony_ci    TestParseArkFrameInfoLocal(data, size);
176800b99b8Sopenharmony_ci    TestArkCreateJsSymbolExtractor(data, size);
177800b99b8Sopenharmony_ci}
178800b99b8Sopenharmony_ci
179800b99b8Sopenharmony_civoid TestDfxHap(const uint8_t* data, size_t size)
180800b99b8Sopenharmony_ci{
181800b99b8Sopenharmony_ci    pid_t pid;
182800b99b8Sopenharmony_ci    uint64_t pc;
183800b99b8Sopenharmony_ci    uintptr_t methodid;
184800b99b8Sopenharmony_ci    uintptr_t offset;
185800b99b8Sopenharmony_ci    unsigned int offsetTotalLength = sizeof(pid) + sizeof(pc) + sizeof(methodid) + sizeof(offset);
186800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
187800b99b8Sopenharmony_ci        return;
188800b99b8Sopenharmony_ci    }
189800b99b8Sopenharmony_ci
190800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, pid);
191800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, pc);
192800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, methodid);
193800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, offset);
194800b99b8Sopenharmony_ci
195800b99b8Sopenharmony_ci    auto map = std::make_shared<DfxMap>();
196800b99b8Sopenharmony_ci    JsFunction jsFunction;
197800b99b8Sopenharmony_ci    DfxHap dfxHap;
198800b99b8Sopenharmony_ci    dfxHap.ParseHapInfo(pid, pc, methodid, map, &jsFunction);
199800b99b8Sopenharmony_ci}
200800b99b8Sopenharmony_ci
201800b99b8Sopenharmony_ci#if defined(__aarch64__)
202800b99b8Sopenharmony_civoid TestSetFromFpMiniRegs(const uint8_t* data, size_t size)
203800b99b8Sopenharmony_ci{
204800b99b8Sopenharmony_ci    uintptr_t regs;
205800b99b8Sopenharmony_ci    if (size < sizeof(regs)) {
206800b99b8Sopenharmony_ci        return;
207800b99b8Sopenharmony_ci    }
208800b99b8Sopenharmony_ci
209800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, regs);
210800b99b8Sopenharmony_ci
211800b99b8Sopenharmony_ci    auto dfxregs = std::make_shared<DfxRegsArm64>();
212800b99b8Sopenharmony_ci    dfxregs->SetFromFpMiniRegs(&regs, size);
213800b99b8Sopenharmony_ci}
214800b99b8Sopenharmony_ci#endif
215800b99b8Sopenharmony_ci
216800b99b8Sopenharmony_ci#if defined(__aarch64__)
217800b99b8Sopenharmony_civoid TestSetFromQutMiniRegs(const uint8_t* data, size_t size)
218800b99b8Sopenharmony_ci{
219800b99b8Sopenharmony_ci    uintptr_t regs;
220800b99b8Sopenharmony_ci    if (size < sizeof(regs)) {
221800b99b8Sopenharmony_ci        return;
222800b99b8Sopenharmony_ci    }
223800b99b8Sopenharmony_ci
224800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, regs);
225800b99b8Sopenharmony_ci
226800b99b8Sopenharmony_ci    auto dfxregs = std::make_shared<DfxRegsArm64>();
227800b99b8Sopenharmony_ci    dfxregs->SetFromQutMiniRegs(&regs, size);
228800b99b8Sopenharmony_ci}
229800b99b8Sopenharmony_ci#endif
230800b99b8Sopenharmony_ci
231800b99b8Sopenharmony_ci#if defined(__aarch64__)
232800b99b8Sopenharmony_civoid TestDfxRegsArm64(const uint8_t* data, size_t size)
233800b99b8Sopenharmony_ci{
234800b99b8Sopenharmony_ci    TestSetFromFpMiniRegs(data, size);
235800b99b8Sopenharmony_ci    TestSetFromQutMiniRegs(data, size);
236800b99b8Sopenharmony_ci}
237800b99b8Sopenharmony_ci#endif
238800b99b8Sopenharmony_ci
239800b99b8Sopenharmony_civoid TestThreadContext(const uint8_t* data, size_t size)
240800b99b8Sopenharmony_ci{
241800b99b8Sopenharmony_ci    int32_t tid;
242800b99b8Sopenharmony_ci    uintptr_t stackBottom;
243800b99b8Sopenharmony_ci    uintptr_t stackTop;
244800b99b8Sopenharmony_ci    unsigned int offsetTotalLength = sizeof(tid) + sizeof(stackBottom) + sizeof(stackTop);
245800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
246800b99b8Sopenharmony_ci        return;
247800b99b8Sopenharmony_ci    }
248800b99b8Sopenharmony_ci
249800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, tid);
250800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, stackBottom);
251800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, stackTop);
252800b99b8Sopenharmony_ci
253800b99b8Sopenharmony_ci    LocalThreadContext& context = LocalThreadContext::GetInstance();
254800b99b8Sopenharmony_ci    context.GetStackRange(tid, stackBottom, stackTop);
255800b99b8Sopenharmony_ci    context.CollectThreadContext(tid);
256800b99b8Sopenharmony_ci    context.GetThreadContext(tid);
257800b99b8Sopenharmony_ci    context.ReleaseThread(tid);
258800b99b8Sopenharmony_ci}
259800b99b8Sopenharmony_ci
260800b99b8Sopenharmony_civoid TestDfxInstrStatistic(const uint8_t* data, size_t size)
261800b99b8Sopenharmony_ci{
262800b99b8Sopenharmony_ci    uint32_t type;
263800b99b8Sopenharmony_ci    uint64_t val;
264800b99b8Sopenharmony_ci    uint64_t errInfo;
265800b99b8Sopenharmony_ci    unsigned int offsetTotalLength = sizeof(type) + sizeof(val) + sizeof(errInfo) +
266800b99b8Sopenharmony_ci                                     FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH;
267800b99b8Sopenharmony_ci    if (offsetTotalLength > size) {
268800b99b8Sopenharmony_ci        return;
269800b99b8Sopenharmony_ci    }
270800b99b8Sopenharmony_ci
271800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, type);
272800b99b8Sopenharmony_ci    type = type % 10; // 10 : get the last digit of the number
273800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, val);
274800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, errInfo);
275800b99b8Sopenharmony_ci
276800b99b8Sopenharmony_ci    std::string soName(reinterpret_cast<const char*>(data), FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH);
277800b99b8Sopenharmony_ci    data += FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH;
278800b99b8Sopenharmony_ci
279800b99b8Sopenharmony_ci    InstrStatisticType statisticType;
280800b99b8Sopenharmony_ci    if (type == 0) {
281800b99b8Sopenharmony_ci        statisticType = InstrStatisticType::InstructionEntriesArmExidx;
282800b99b8Sopenharmony_ci    } else {
283800b99b8Sopenharmony_ci        statisticType = InstrStatisticType::UnsupportedArmExidx;
284800b99b8Sopenharmony_ci    }
285800b99b8Sopenharmony_ci    DfxInstrStatistic& statistic = DfxInstrStatistic::GetInstance();
286800b99b8Sopenharmony_ci    statistic.SetCurrentStatLib(soName);
287800b99b8Sopenharmony_ci    statistic.AddInstrStatistic(statisticType, val, errInfo);
288800b99b8Sopenharmony_ci    std::vector<std::pair<uint32_t, uint32_t>> result;
289800b99b8Sopenharmony_ci    statistic.DumpInstrStatResult(result);
290800b99b8Sopenharmony_ci}
291800b99b8Sopenharmony_ci
292800b99b8Sopenharmony_civoid TestDfxXzUtils(const uint8_t* data, size_t size)
293800b99b8Sopenharmony_ci{
294800b99b8Sopenharmony_ci    uint8_t src;
295800b99b8Sopenharmony_ci    if (size < sizeof(src)) {
296800b99b8Sopenharmony_ci        return;
297800b99b8Sopenharmony_ci    }
298800b99b8Sopenharmony_ci
299800b99b8Sopenharmony_ci    STREAM_TO_VALUEINFO(data, src);
300800b99b8Sopenharmony_ci
301800b99b8Sopenharmony_ci    std::shared_ptr<std::vector<uint8_t>> out;
302800b99b8Sopenharmony_ci    XzDecompress(&src, size, out);
303800b99b8Sopenharmony_ci}
304800b99b8Sopenharmony_ci
305800b99b8Sopenharmony_civoid FaultloggerdUnwinderTest(const uint8_t* data, size_t size)
306800b99b8Sopenharmony_ci{
307800b99b8Sopenharmony_ci    TestDfxConfig();
308800b99b8Sopenharmony_ci    TestDfxArk(data, size);
309800b99b8Sopenharmony_ci    TestDfxHap(data, size);
310800b99b8Sopenharmony_ci#if defined(__aarch64__)
311800b99b8Sopenharmony_ci    TestDfxRegsArm64(data, size);
312800b99b8Sopenharmony_ci#endif
313800b99b8Sopenharmony_ci    TestThreadContext(data, size);
314800b99b8Sopenharmony_ci    TestDfxInstrStatistic(data, size);
315800b99b8Sopenharmony_ci    TestDfxXzUtils(data, size);
316800b99b8Sopenharmony_ci    sleep(1);
317800b99b8Sopenharmony_ci}
318800b99b8Sopenharmony_ci} // namespace HiviewDFX
319800b99b8Sopenharmony_ci} // namespace OHOS
320800b99b8Sopenharmony_ci
321800b99b8Sopenharmony_ci/* Fuzzer entry point */
322800b99b8Sopenharmony_ciextern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
323800b99b8Sopenharmony_ci{
324800b99b8Sopenharmony_ci    if (data == nullptr || size == 0) {
325800b99b8Sopenharmony_ci        return 0;
326800b99b8Sopenharmony_ci    }
327800b99b8Sopenharmony_ci
328800b99b8Sopenharmony_ci    /* Run your code on data */
329800b99b8Sopenharmony_ci    OHOS::HiviewDFX::FaultloggerdUnwinderTest(data, size);
330800b99b8Sopenharmony_ci    return 0;
331800b99b8Sopenharmony_ci}
332