• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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_hap.h"
23 #include "dfx_regs.h"
24 #include "dwarf_op.h"
25 #include "thread_context.h"
26 #include "unwinder.h"
27 #include "unwind_define.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 
32 struct TestArkFrameData {
33     uintptr_t pc;
34     uintptr_t fp;
35     uintptr_t sp;
36     uintptr_t methodid;
37 };
38 
TestStepArkFrame(const uint8_t * data,size_t size)39 void TestStepArkFrame(const uint8_t* data, size_t size)
40 {
41     if (data == nullptr || size < sizeof(TestArkFrameData)) {
42         return;
43     }
44     auto testData = *reinterpret_cast<const TestArkFrameData *>(data);
45     bool isJsFrame = testData.methodid % 2;
46 
47     DfxMemory dfxMemory;
48     ArkStepParam arkParam(&testData.fp, &testData.sp, &testData.pc, &isJsFrame);
49     DfxArk::Instance().StepArkFrame(&dfxMemory, &(Unwinder::AccessMem), &arkParam);
50 }
51 
TestStepArkFrameWithJit(const uint8_t * data,size_t size)52 void TestStepArkFrameWithJit(const uint8_t* data, size_t size)
53 {
54     if (data == nullptr || size < sizeof(TestArkFrameData)) {
55         return;
56     }
57     auto testData = *reinterpret_cast<const TestArkFrameData*>(data);
58     bool isJsFrame = testData.methodid % 2;
59     std::vector<uintptr_t> jitCache_ = {};
60     DfxMemory dfxMemory;
61     ArkUnwindParam arkParam(&dfxMemory, &(Unwinder::AccessMem), &testData.fp,
62         &testData.sp, &testData.pc, &testData.methodid, &isJsFrame, jitCache_);
63     DfxArk::Instance().StepArkFrameWithJit(&arkParam);
64 }
65 
TestJitCodeWriteFile(const uint8_t * data,size_t size)66 void TestJitCodeWriteFile(const uint8_t* data, size_t size)
67 {
68     struct TestData {
69         int fd;
70         uintptr_t jitCacheData;
71     };
72     if (data == nullptr || size < sizeof(TestData)) {
73         return;
74     }
75     const auto testData = reinterpret_cast<const TestData*>(data);
76     std::vector<uintptr_t> jitCache = {};
77     jitCache.push_back(testData->jitCacheData);
78     DfxMemory dfxMemory;
79     DfxArk::Instance().JitCodeWriteFile(&dfxMemory, &(Unwinder::AccessMem),
80         testData->fd, jitCache.data(), jitCache.size());
81 }
82 
TestParseArkFrameInfoLocal(const uint8_t * data,size_t size)83 void TestParseArkFrameInfoLocal(const uint8_t* data, size_t size)
84 {
85     struct TestData {
86         uintptr_t pc;
87         uintptr_t mapBegin;
88         uintptr_t offset;
89     };
90     if (data == nullptr || size < sizeof(TestData)) {
91         return;
92     }
93     const auto testData = reinterpret_cast<const TestData*>(data);
94 
95     JsFunction jsFunction;
96     DfxArk::Instance().ParseArkFrameInfoLocal(testData->pc, testData->mapBegin, testData->offset, &jsFunction);
97 }
98 
TestArkCreateJsSymbolExtractor(const uint8_t * data,size_t size)99 void TestArkCreateJsSymbolExtractor(const uint8_t* data, size_t size)
100 {
101     if (data == nullptr || size < sizeof(uintptr_t)) {
102         return;
103     }
104     auto extractorPtr = *reinterpret_cast<const uintptr_t*>(data);
105     DfxArk::Instance().ArkCreateJsSymbolExtractor(&extractorPtr);
106 }
107 
TestArkDestoryJsSymbolExtractor(const uint8_t * data,size_t size)108 void TestArkDestoryJsSymbolExtractor(const uint8_t* data, size_t size)
109 {
110     if (data == nullptr || size < sizeof(uintptr_t)) {
111         return;
112     }
113     DfxArk::Instance().ArkDestoryJsSymbolExtractor(*reinterpret_cast<const uintptr_t*>(data));
114 }
115 
TestDfxArk(const uint8_t * data,size_t size)116 void TestDfxArk(const uint8_t* data, size_t size)
117 {
118     TestStepArkFrame(data, size);
119     TestStepArkFrameWithJit(data, size);
120     TestJitCodeWriteFile(data, size);
121     TestParseArkFrameInfoLocal(data, size);
122     TestArkCreateJsSymbolExtractor(data, size);
123 }
124 
TestDfxHap(const uint8_t * data,size_t size)125 void TestDfxHap(const uint8_t* data, size_t size)
126 {
127     struct TestData {
128         pid_t pid;
129         uint64_t pc;
130     };
131     if (data == nullptr || size < sizeof(TestData)) {
132         return;
133     }
134     const auto testData = reinterpret_cast<const TestData*>(data);
135 
136     auto map = std::make_shared<DfxMap>();
137     JsFunction jsFunction;
138     DfxHap dfxHap;
139     dfxHap.ParseHapInfo(testData->pid, testData->pc, map, &jsFunction);
140 }
141 
142 #if defined(__aarch64__)
TestSetFromFpMiniRegs(const uint8_t * data,size_t size)143 void TestSetFromFpMiniRegs(const uint8_t* data, size_t size)
144 {
145     struct TestData {
146         uintptr_t regs[FP_MINI_REGS_SIZE];
147     };
148     if (data == nullptr || size < sizeof(TestData)) {
149         return;
150     }
151     const auto testData = reinterpret_cast<const TestData*>(data);
152 
153     auto dfxregs = std::make_shared<DfxRegsArm64>();
154     dfxregs->SetFromFpMiniRegs(testData->regs, FP_MINI_REGS_SIZE);
155 }
156 #endif
157 
158 #if defined(__aarch64__)
TestSetFromQutMiniRegs(const uint8_t * data,size_t size)159 void TestSetFromQutMiniRegs(const uint8_t* data, size_t size)
160 {
161     struct TestData {
162         uintptr_t regs[QUT_MINI_REGS_SIZE];
163     };
164     if (data == nullptr || size < sizeof(TestData)) {
165         return;
166     }
167     const auto testData = reinterpret_cast<const TestData*>(data);
168     auto dfxregs = std::make_shared<DfxRegsArm64>();
169     dfxregs->SetFromQutMiniRegs(testData->regs, QUT_MINI_REGS_SIZE);
170 }
171 #endif
172 
173 #if defined(__aarch64__)
TestDfxRegsArm64(const uint8_t * data,size_t size)174 void TestDfxRegsArm64(const uint8_t* data, size_t size)
175 {
176     TestSetFromFpMiniRegs(data, size);
177     TestSetFromQutMiniRegs(data, size);
178 }
179 #endif
180 
TestThreadContext(const uint8_t * data,size_t size)181 void TestThreadContext(const uint8_t* data, size_t size)
182 {
183     if (data || size < sizeof(int32_t)) {
184         return;
185     }
186     auto tid = *reinterpret_cast<const int32_t*>(data);
187     LocalThreadContext& context = LocalThreadContext::GetInstance();
188     uintptr_t stackBottom;
189     uintptr_t stackTop;
190     context.GetStackRange(tid, stackBottom, stackTop);
191     context.CollectThreadContext(tid);
192     context.GetThreadContext(tid);
193     context.ReleaseThread(tid);
194 }
195 
TestDfxInstrStatistic(const uint8_t * data,size_t size)196 void TestDfxInstrStatistic(const uint8_t* data, size_t size)
197 {
198     constexpr int maxStringLength = 50;
199     struct TestData {
200         uint32_t type;
201         uint64_t val;
202         uint64_t errInfo;
203         char soName[maxStringLength];
204     };
205     if (data == nullptr || size < sizeof(TestData)) {
206         return;
207     }
208     auto testData = reinterpret_cast<const TestData*>(data);
209     InstrStatisticType statisticType = (testData->type % 10) ? InstructionEntriesArmExidx : UnsupportedArmExidx;
210     DfxInstrStatistic& statistic = DfxInstrStatistic::GetInstance();
211     std::string testSoName(testData->soName, maxStringLength);
212     statistic.SetCurrentStatLib(testSoName);
213     statistic.AddInstrStatistic(statisticType, testData->val, testData->errInfo);
214     std::vector<std::pair<uint32_t, uint32_t>> result;
215     statistic.DumpInstrStatResult(result);
216 }
217 
FaultloggerdUnwinderTest(const uint8_t * data,size_t size)218 void FaultloggerdUnwinderTest(const uint8_t* data, size_t size)
219 {
220     TestDfxArk(data, size);
221     TestDfxHap(data, size);
222 #if defined(__aarch64__)
223     TestDfxRegsArm64(data, size);
224 #endif
225     TestThreadContext(data, size);
226     TestDfxInstrStatistic(data, size);
227     sleep(1);
228 }
229 } // namespace HiviewDFX
230 } // namespace OHOS
231 
232 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)233 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
234 {
235     if (data == nullptr || size == 0) {
236         return 0;
237     }
238 
239     /* Run your code on data */
240     OHOS::HiviewDFX::FaultloggerdUnwinderTest(data, size);
241     return 0;
242 }
243