/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "faultloggerdunwinder_fuzzer.h" #include #include #include "dfx_ark.h" #include "dfx_config.h" #include "dfx_hap.h" #include "dfx_regs.h" #include "dfx_xz_utils.h" #include "dwarf_op.h" #include "faultloggerd_fuzzertest_common.h" #include "thread_context.h" #include "unwinder.h" namespace OHOS { namespace HiviewDFX { const int FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH = 50; void TestDfxConfig() { DfxConfig::GetConfig(); } void TestGetArkNativeFrameInfo(const uint8_t* data, size_t size) { int pid; uintptr_t pc; uintptr_t fp; uintptr_t sp; int offsetTotalLength = sizeof(pid) + sizeof(pc) + sizeof(fp) + sizeof(sp); if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, pid); STREAM_TO_VALUEINFO(data, pc); STREAM_TO_VALUEINFO(data, fp); STREAM_TO_VALUEINFO(data, sp); const size_t jSFRAME_MAX = 64; JsFrame jsFrames[jSFRAME_MAX]; DfxArk::GetArkNativeFrameInfo(pid, pc, fp, sp, jsFrames, size); } void TestStepArkFrame(const uint8_t* data, size_t size) { uintptr_t pc; uintptr_t fp; uintptr_t sp; uintptr_t methodid; int offsetTotalLength = sizeof(pc) + sizeof(fp) + sizeof(sp) + sizeof(methodid); if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, pc); STREAM_TO_VALUEINFO(data, fp); STREAM_TO_VALUEINFO(data, sp); STREAM_TO_VALUEINFO(data, methodid); bool isJsFrame = methodid % 2; DfxMemory dfxMemory; DfxArk::StepArkFrame(&dfxMemory, &(Unwinder::AccessMem), &fp, &sp, &pc, &methodid, &isJsFrame); } void TestStepArkFrameWithJit(const uint8_t* data, size_t size) { uintptr_t fp; uintptr_t pc; uintptr_t sp; uintptr_t methodid; int offsetTotalLength = sizeof(pc) + sizeof(fp) + sizeof(sp) + sizeof(methodid); if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, pc); STREAM_TO_VALUEINFO(data, fp); STREAM_TO_VALUEINFO(data, sp); STREAM_TO_VALUEINFO(data, methodid); bool isJsFrame = methodid % 2; std::vector jitCache_ = {}; DfxMemory dfxMemory; ArkUnwindParam arkParam(&dfxMemory, &(Unwinder::AccessMem), &fp, &sp, &pc, &methodid, &isJsFrame, jitCache_); DfxArk::StepArkFrameWithJit(&arkParam); } void TestJitCodeWriteFile(const uint8_t* data, size_t size) { int fd; uintptr_t jitCacheData; int offsetTotalLength = sizeof(fd) + sizeof(jitCacheData); if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, fd); STREAM_TO_VALUEINFO(data, jitCacheData); std::vector jitCache = {}; jitCache.push_back(jitCacheData); DfxMemory dfxMemory; DfxArk::JitCodeWriteFile(&dfxMemory, &(Unwinder::AccessMem), fd, jitCache.data(), jitCache.size()); } void TestParseArkFrameInfoLocal(const uint8_t* data, size_t size) { uintptr_t pc; uintptr_t funcOffset; uintptr_t mapBegin; uintptr_t offset; int offsetTotalLength = sizeof(pc) + sizeof(funcOffset) + sizeof(mapBegin) + sizeof(offset); if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, pc); STREAM_TO_VALUEINFO(data, funcOffset); STREAM_TO_VALUEINFO(data, mapBegin); STREAM_TO_VALUEINFO(data, offset); JsFunction jsFunction; DfxArk::ParseArkFrameInfoLocal(static_cast(pc), static_cast(funcOffset), static_cast(mapBegin), static_cast(offset), &jsFunction); } void TestArkCreateJsSymbolExtractor(const uint8_t* data, size_t size) { uintptr_t extractorPtr; if (size < sizeof(extractorPtr)) { return; } STREAM_TO_VALUEINFO(data, extractorPtr); DfxArk::ArkCreateJsSymbolExtractor(&extractorPtr); } void TestArkDestoryJsSymbolExtractor(const uint8_t* data, size_t size) { uintptr_t extractorPtr; if (size < sizeof(extractorPtr)) { return; } STREAM_TO_VALUEINFO(data, extractorPtr); DfxArk::ArkDestoryJsSymbolExtractor(extractorPtr); } void TestDfxArk(const uint8_t* data, size_t size) { TestGetArkNativeFrameInfo(data, size); TestStepArkFrame(data, size); TestStepArkFrameWithJit(data, size); TestJitCodeWriteFile(data, size); TestParseArkFrameInfoLocal(data, size); TestArkCreateJsSymbolExtractor(data, size); } void TestDfxHap(const uint8_t* data, size_t size) { pid_t pid; uint64_t pc; uintptr_t methodid; uintptr_t offset; unsigned int offsetTotalLength = sizeof(pid) + sizeof(pc) + sizeof(methodid) + sizeof(offset); if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, pid); STREAM_TO_VALUEINFO(data, pc); STREAM_TO_VALUEINFO(data, methodid); STREAM_TO_VALUEINFO(data, offset); auto map = std::make_shared(); JsFunction jsFunction; DfxHap dfxHap; dfxHap.ParseHapInfo(pid, pc, methodid, map, &jsFunction); } #if defined(__aarch64__) void TestSetFromFpMiniRegs(const uint8_t* data, size_t size) { uintptr_t regs; if (size < sizeof(regs)) { return; } STREAM_TO_VALUEINFO(data, regs); auto dfxregs = std::make_shared(); dfxregs->SetFromFpMiniRegs(®s, size); } #endif #if defined(__aarch64__) void TestSetFromQutMiniRegs(const uint8_t* data, size_t size) { uintptr_t regs; if (size < sizeof(regs)) { return; } STREAM_TO_VALUEINFO(data, regs); auto dfxregs = std::make_shared(); dfxregs->SetFromQutMiniRegs(®s, size); } #endif #if defined(__aarch64__) void TestDfxRegsArm64(const uint8_t* data, size_t size) { TestSetFromFpMiniRegs(data, size); TestSetFromQutMiniRegs(data, size); } #endif void TestThreadContext(const uint8_t* data, size_t size) { int32_t tid; uintptr_t stackBottom; uintptr_t stackTop; unsigned int offsetTotalLength = sizeof(tid) + sizeof(stackBottom) + sizeof(stackTop); if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, tid); STREAM_TO_VALUEINFO(data, stackBottom); STREAM_TO_VALUEINFO(data, stackTop); LocalThreadContext& context = LocalThreadContext::GetInstance(); context.GetStackRange(tid, stackBottom, stackTop); context.CollectThreadContext(tid); context.GetThreadContext(tid); context.ReleaseThread(tid); } void TestDfxInstrStatistic(const uint8_t* data, size_t size) { uint32_t type; uint64_t val; uint64_t errInfo; unsigned int offsetTotalLength = sizeof(type) + sizeof(val) + sizeof(errInfo) + FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH; if (offsetTotalLength > size) { return; } STREAM_TO_VALUEINFO(data, type); type = type % 10; // 10 : get the last digit of the number STREAM_TO_VALUEINFO(data, val); STREAM_TO_VALUEINFO(data, errInfo); std::string soName(reinterpret_cast(data), FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH); data += FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH; InstrStatisticType statisticType; if (type == 0) { statisticType = InstrStatisticType::InstructionEntriesArmExidx; } else { statisticType = InstrStatisticType::UnsupportedArmExidx; } DfxInstrStatistic& statistic = DfxInstrStatistic::GetInstance(); statistic.SetCurrentStatLib(soName); statistic.AddInstrStatistic(statisticType, val, errInfo); std::vector> result; statistic.DumpInstrStatResult(result); } void TestDfxXzUtils(const uint8_t* data, size_t size) { uint8_t src; if (size < sizeof(src)) { return; } STREAM_TO_VALUEINFO(data, src); std::shared_ptr> out; XzDecompress(&src, size, out); } void FaultloggerdUnwinderTest(const uint8_t* data, size_t size) { TestDfxConfig(); TestDfxArk(data, size); TestDfxHap(data, size); #if defined(__aarch64__) TestDfxRegsArm64(data, size); #endif TestThreadContext(data, size); TestDfxInstrStatistic(data, size); TestDfxXzUtils(data, size); sleep(1); } } // namespace HiviewDFX } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (data == nullptr || size == 0) { return 0; } /* Run your code on data */ OHOS::HiviewDFX::FaultloggerdUnwinderTest(data, size); return 0; }