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 "async_stack.h" 17 18#include <pthread.h> 19#include <threads.h> 20#include "dfx_param.h" 21#include "unique_stack_table.h" 22#include "fp_unwinder.h" 23 24#include "dfx_log.h" 25 26#if defined(__aarch64__) 27static pthread_key_t g_stackidKey; 28static bool g_init = false; 29 30extern "C" void SetAsyncStackCallbackFunc(void* func) __attribute__((weak)); 31static void InitAsyncStackInner(void) 32{ 33 if (SetAsyncStackCallbackFunc == nullptr) { 34 DFXLOGE("failed to init async stack, could not find SetAsyncStackCallbackFunc."); 35 return; 36 } 37 38 // init unique stack table 39 if (!OHOS::HiviewDFX::UniqueStackTable::Instance()->Init()) { 40 DFXLOGE("failed to init unique stack table?."); 41 return; 42 } 43 44 if (pthread_key_create(&g_stackidKey, nullptr) == 0) { 45 g_init = true; 46 } else { 47 DFXLOGE("failed to create key for stackId."); 48 return; 49 } 50 51 // set callback for DfxSignalHandler to read stackId 52 SetAsyncStackCallbackFunc((void*)(&GetStackId)); 53} 54 55static bool InitAsyncStack(void) 56{ 57 static once_flag onceFlag = ONCE_FLAG_INIT; 58 call_once(&onceFlag, InitAsyncStackInner); 59 return g_init; 60} 61#endif 62 63extern "C" uint64_t CollectAsyncStack(void) 64{ 65#if defined(__aarch64__) 66 if (!InitAsyncStack()) { 67 return 0; 68 } 69 const int32_t maxSize = 16; 70 uintptr_t pcs[maxSize] = {0}; 71 int32_t skipFrameNum = 2; 72 size_t sz = static_cast<size_t>(OHOS::HiviewDFX::FpUnwinder::Unwind(pcs, maxSize, skipFrameNum)); 73 uint64_t stackId = 0; 74 auto stackIdPtr = reinterpret_cast<OHOS::HiviewDFX::StackId*>(&stackId); 75 OHOS::HiviewDFX::UniqueStackTable::Instance()->PutPcsInTable(stackIdPtr, pcs, sz); 76 return stackId; 77#else 78 return 0; 79#endif 80} 81 82extern "C" void SetStackId(uint64_t stackId) 83{ 84#if defined(__aarch64__) 85 if (!InitAsyncStack()) { 86 return; 87 } 88 pthread_setspecific(g_stackidKey, reinterpret_cast<void *>(stackId)); 89#else 90 return; 91#endif 92} 93 94extern "C" uint64_t GetStackId() 95{ 96#if defined(__aarch64__) 97 if (!InitAsyncStack()) { 98 return 0; 99 } 100 return reinterpret_cast<uint64_t>(pthread_getspecific(g_stackidKey)); 101#else 102 return 0; 103#endif 104}