1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2022-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 "backtrace_local.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <cstring> 19800b99b8Sopenharmony_ci#include <dirent.h> 20800b99b8Sopenharmony_ci#include <mutex> 21800b99b8Sopenharmony_ci#include <unistd.h> 22800b99b8Sopenharmony_ci#include <vector> 23800b99b8Sopenharmony_ci 24800b99b8Sopenharmony_ci#include "backtrace_local_thread.h" 25800b99b8Sopenharmony_ci#include "elapsed_time.h" 26800b99b8Sopenharmony_ci#include "dfx_frame_formatter.h" 27800b99b8Sopenharmony_ci#include "dfx_kernel_stack.h" 28800b99b8Sopenharmony_ci#include "dfx_log.h" 29800b99b8Sopenharmony_ci#include "dfx_util.h" 30800b99b8Sopenharmony_ci#include "directory_ex.h" 31800b99b8Sopenharmony_ci#include "procinfo.h" 32800b99b8Sopenharmony_ci#include "unwinder.h" 33800b99b8Sopenharmony_ci 34800b99b8Sopenharmony_cinamespace OHOS { 35800b99b8Sopenharmony_cinamespace HiviewDFX { 36800b99b8Sopenharmony_cinamespace { 37800b99b8Sopenharmony_ci#undef LOG_DOMAIN 38800b99b8Sopenharmony_ci#undef LOG_TAG 39800b99b8Sopenharmony_ci#define LOG_TAG "DfxBacktrace" 40800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 41800b99b8Sopenharmony_ci 42800b99b8Sopenharmony_cistd::string GetThreadHead(int32_t tid) 43800b99b8Sopenharmony_ci{ 44800b99b8Sopenharmony_ci std::string threadName; 45800b99b8Sopenharmony_ci if (tid == BACKTRACE_CURRENT_THREAD) { 46800b99b8Sopenharmony_ci tid = gettid(); 47800b99b8Sopenharmony_ci } 48800b99b8Sopenharmony_ci ReadThreadName(tid, threadName); 49800b99b8Sopenharmony_ci std::string threadHead = "Tid:" + std::to_string(tid) + ", Name:" + threadName + "\n"; 50800b99b8Sopenharmony_ci return threadHead; 51800b99b8Sopenharmony_ci} 52800b99b8Sopenharmony_ci} 53800b99b8Sopenharmony_ci 54800b99b8Sopenharmony_cibool GetBacktraceFramesByTid(std::vector<DfxFrame>& frames, int32_t tid, size_t skipFrameNum, bool fast, 55800b99b8Sopenharmony_ci size_t maxFrameNums) 56800b99b8Sopenharmony_ci{ 57800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder = nullptr; 58800b99b8Sopenharmony_ci#ifdef __aarch64__ 59800b99b8Sopenharmony_ci if (fast || (tid != BACKTRACE_CURRENT_THREAD)) { 60800b99b8Sopenharmony_ci unwinder = std::make_shared<Unwinder>(false); 61800b99b8Sopenharmony_ci } 62800b99b8Sopenharmony_ci#endif 63800b99b8Sopenharmony_ci if (unwinder == nullptr) { 64800b99b8Sopenharmony_ci unwinder = std::make_shared<Unwinder>(); 65800b99b8Sopenharmony_ci } 66800b99b8Sopenharmony_ci BacktraceLocalThread thread(tid, unwinder); 67800b99b8Sopenharmony_ci bool ret = thread.Unwind(fast, maxFrameNums, skipFrameNum + 1); 68800b99b8Sopenharmony_ci frames = thread.GetFrames(); 69800b99b8Sopenharmony_ci return ret; 70800b99b8Sopenharmony_ci} 71800b99b8Sopenharmony_ci 72800b99b8Sopenharmony_cibool GetBacktraceStringByTid(std::string& out, int32_t tid, size_t skipFrameNum, bool fast, 73800b99b8Sopenharmony_ci size_t maxFrameNums, bool enableKernelStack) 74800b99b8Sopenharmony_ci{ 75800b99b8Sopenharmony_ci std::vector<DfxFrame> frames; 76800b99b8Sopenharmony_ci bool ret = GetBacktraceFramesByTid(frames, tid, skipFrameNum + 1, fast, maxFrameNums); 77800b99b8Sopenharmony_ci if (!ret && enableKernelStack) { 78800b99b8Sopenharmony_ci std::string msg = ""; 79800b99b8Sopenharmony_ci DfxThreadStack threadStack; 80800b99b8Sopenharmony_ci if (DfxGetKernelStack(tid, msg) == 0 && FormatThreadKernelStack(msg, threadStack)) { 81800b99b8Sopenharmony_ci frames = threadStack.frames; 82800b99b8Sopenharmony_ci ret = true; 83800b99b8Sopenharmony_ci DFXLOGI("Failed to get tid(%{public}d) user stack, try kernel", tid); 84800b99b8Sopenharmony_ci } 85800b99b8Sopenharmony_ci } 86800b99b8Sopenharmony_ci if (ret) { 87800b99b8Sopenharmony_ci out.clear(); 88800b99b8Sopenharmony_ci std::string threadHead = GetThreadHead(tid); 89800b99b8Sopenharmony_ci out = threadHead + Unwinder::GetFramesStr(frames); 90800b99b8Sopenharmony_ci } 91800b99b8Sopenharmony_ci return ret; 92800b99b8Sopenharmony_ci} 93800b99b8Sopenharmony_ci 94800b99b8Sopenharmony_cibool PrintBacktrace(int32_t fd, bool fast, size_t maxFrameNums) 95800b99b8Sopenharmony_ci{ 96800b99b8Sopenharmony_ci DFXLOGI("Receive PrintBacktrace request."); 97800b99b8Sopenharmony_ci std::vector<DfxFrame> frames; 98800b99b8Sopenharmony_ci bool ret = GetBacktraceFramesByTid(frames, 99800b99b8Sopenharmony_ci BACKTRACE_CURRENT_THREAD, 1, fast, maxFrameNums); // 1: skip current frame 100800b99b8Sopenharmony_ci if (!ret) { 101800b99b8Sopenharmony_ci return false; 102800b99b8Sopenharmony_ci } 103800b99b8Sopenharmony_ci 104800b99b8Sopenharmony_ci for (auto const& frame : frames) { 105800b99b8Sopenharmony_ci auto line = DfxFrameFormatter::GetFrameStr(frame); 106800b99b8Sopenharmony_ci if (fd >= 0) { 107800b99b8Sopenharmony_ci dprintf(fd, " %s", line.c_str()); 108800b99b8Sopenharmony_ci } 109800b99b8Sopenharmony_ci DFXLOGI(" %{public}s", line.c_str()); 110800b99b8Sopenharmony_ci } 111800b99b8Sopenharmony_ci return ret; 112800b99b8Sopenharmony_ci} 113800b99b8Sopenharmony_ci 114800b99b8Sopenharmony_cibool GetBacktrace(std::string& out, bool fast, size_t maxFrameNums) 115800b99b8Sopenharmony_ci{ 116800b99b8Sopenharmony_ci ElapsedTime et; 117800b99b8Sopenharmony_ci bool ret = GetBacktraceStringByTid(out, BACKTRACE_CURRENT_THREAD, 1, 118800b99b8Sopenharmony_ci fast, maxFrameNums, false); // 1: skip current frame 119800b99b8Sopenharmony_ci DFXLOGI("GetBacktrace elapsed time: %{public}" PRId64 " ms", et.Elapsed<std::chrono::milliseconds>()); 120800b99b8Sopenharmony_ci return ret; 121800b99b8Sopenharmony_ci} 122800b99b8Sopenharmony_ci 123800b99b8Sopenharmony_cibool GetBacktrace(std::string& out, size_t skipFrameNum, bool fast, size_t maxFrameNums) 124800b99b8Sopenharmony_ci{ 125800b99b8Sopenharmony_ci ElapsedTime et; 126800b99b8Sopenharmony_ci bool ret = GetBacktraceStringByTid(out, BACKTRACE_CURRENT_THREAD, skipFrameNum + 1, fast, maxFrameNums, false); 127800b99b8Sopenharmony_ci DFXLOGI("GetBacktrace with skip, elapsed time: %{public}" PRId64 " ms", et.Elapsed<std::chrono::milliseconds>()); 128800b99b8Sopenharmony_ci return ret; 129800b99b8Sopenharmony_ci} 130800b99b8Sopenharmony_ci 131800b99b8Sopenharmony_cibool PrintTrace(int32_t fd, size_t maxFrameNums) 132800b99b8Sopenharmony_ci{ 133800b99b8Sopenharmony_ci return PrintBacktrace(fd, false, maxFrameNums); 134800b99b8Sopenharmony_ci} 135800b99b8Sopenharmony_ci 136800b99b8Sopenharmony_ciconst char* GetTrace(size_t skipFrameNum, size_t maxFrameNums) 137800b99b8Sopenharmony_ci{ 138800b99b8Sopenharmony_ci static std::string trace; 139800b99b8Sopenharmony_ci trace.clear(); 140800b99b8Sopenharmony_ci if (!GetBacktrace(trace, skipFrameNum, false, maxFrameNums)) { 141800b99b8Sopenharmony_ci DFXLOGE("Failed to get trace string"); 142800b99b8Sopenharmony_ci } 143800b99b8Sopenharmony_ci return trace.c_str(); 144800b99b8Sopenharmony_ci} 145800b99b8Sopenharmony_ci 146800b99b8Sopenharmony_cistd::string GetProcessStacktrace(size_t maxFrameNums, bool enableKernelStack) 147800b99b8Sopenharmony_ci{ 148800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 149800b99b8Sopenharmony_ci std::string ss = "\n" + GetStacktraceHeader(); 150800b99b8Sopenharmony_ci std::function<bool(int)> func = [&](int tid) { 151800b99b8Sopenharmony_ci if (tid <= 0 || tid == gettid()) { 152800b99b8Sopenharmony_ci return false; 153800b99b8Sopenharmony_ci } 154800b99b8Sopenharmony_ci BacktraceLocalThread thread(tid, unwinder); 155800b99b8Sopenharmony_ci if (thread.Unwind(false, maxFrameNums, 0)) { 156800b99b8Sopenharmony_ci ss += thread.GetFormattedStr(true) + "\n"; 157800b99b8Sopenharmony_ci } else if (enableKernelStack) { 158800b99b8Sopenharmony_ci std::string msg = ""; 159800b99b8Sopenharmony_ci DfxThreadStack threadStack; 160800b99b8Sopenharmony_ci if (DfxGetKernelStack(tid, msg) == 0 && FormatThreadKernelStack(msg, threadStack)) { 161800b99b8Sopenharmony_ci thread.SetFrames(threadStack.frames); 162800b99b8Sopenharmony_ci ss += thread.GetFormattedStr(true) + "\n"; 163800b99b8Sopenharmony_ci DFXLOGI("Failed to get tid(%{public}d) user stack, try kernel", tid); 164800b99b8Sopenharmony_ci } 165800b99b8Sopenharmony_ci } 166800b99b8Sopenharmony_ci return true; 167800b99b8Sopenharmony_ci }; 168800b99b8Sopenharmony_ci 169800b99b8Sopenharmony_ci std::vector<int> tids; 170800b99b8Sopenharmony_ci GetTidsByPidWithFunc(getpid(), tids, func); 171800b99b8Sopenharmony_ci 172800b99b8Sopenharmony_ci return ss; 173800b99b8Sopenharmony_ci} 174800b99b8Sopenharmony_ci} // namespace HiviewDFX 175800b99b8Sopenharmony_ci} // namespace OHOS 176