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 31namespace OHOS { 32namespace HiviewDFX { 33const int FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH = 50; 34 35void TestDfxConfig() 36{ 37 DfxConfig::GetConfig(); 38} 39 40void 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 62void 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 83void 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 106void 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 124void 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 145void 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 157void 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 169void 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 179void 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__) 202void 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__) 217void 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__) 232void TestDfxRegsArm64(const uint8_t* data, size_t size) 233{ 234 TestSetFromFpMiniRegs(data, size); 235 TestSetFromQutMiniRegs(data, size); 236} 237#endif 238 239void 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 260void 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 292void 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 305void 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 */ 322extern "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