1/* 2 * Copyright (c) 2021-2023 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 "dfx_thread.h" 17 18#include <cerrno> 19#include <chrono> 20#include <climits> 21#include <cstring> 22#include <securec.h> 23#include <sys/wait.h> 24#include <unistd.h> 25 26#include "dfx_define.h" 27#include "dfx_frame_formatter.h" 28#include "dfx_log.h" 29#include "dfx_ptrace.h" 30#include "dfx_util.h" 31#include "procinfo.h" 32#if defined(__aarch64__) 33#include "printer.h" 34#endif 35namespace OHOS { 36namespace HiviewDFX { 37std::shared_ptr<DfxThread> DfxThread::Create(pid_t pid, pid_t tid, pid_t nsTid) 38{ 39 auto thread = std::make_shared<DfxThread>(pid, tid, nsTid); 40 return thread; 41} 42 43DfxThread::DfxThread(pid_t pid, pid_t tid, pid_t nsTid) : regs_(nullptr) 44{ 45 InitThreadInfo(pid, tid, nsTid); 46} 47 48void DfxThread::InitThreadInfo(pid_t pid, pid_t tid, pid_t nsTid) 49{ 50 threadInfo_.pid = pid; 51 threadInfo_.tid = tid; 52 threadInfo_.nsTid = nsTid; 53 ReadThreadNameByPidAndTid(threadInfo_.pid, threadInfo_.tid, threadInfo_.threadName); 54 threadStatus = ThreadStatus::THREAD_STATUS_INIT; 55} 56 57DfxThread::~DfxThread() 58{ 59 threadStatus = ThreadStatus::THREAD_STATUS_INVALID; 60} 61 62std::shared_ptr<DfxRegs> DfxThread::GetThreadRegs() const 63{ 64 return regs_; 65} 66 67void DfxThread::SetThreadRegs(const std::shared_ptr<DfxRegs> ®s) 68{ 69 regs_ = regs; 70} 71 72void DfxThread::AddFrame(DfxFrame& frame) 73{ 74 frames_.emplace_back(frame); 75} 76 77const std::vector<DfxFrame>& DfxThread::GetFrames() const 78{ 79 return frames_; 80} 81 82std::string DfxThread::ToString() const 83{ 84 if (frames_.size() == 0) { 85 return "No frame info"; 86 } 87 88 std::string ss = "Thread name:" + threadInfo_.threadName + "\n"; 89 bool needSkip = false; 90 bool isSubmitter = true; 91 for (const auto& frame : frames_) { 92 if (frame.index == 0) { 93 isSubmitter = !isSubmitter; 94 } 95 if (isSubmitter) { 96 ss += "========SubmitterStacktrace========\n"; 97 isSubmitter = false; 98 needSkip = false; 99 } 100 if (needSkip) { 101 continue; 102 } 103 ss += DfxFrameFormatter::GetFrameStr(frame); 104#if defined(__aarch64__) 105 if (Printer::IsLastValidFrame(frame)) { 106 needSkip = true; 107 } 108#endif 109 } 110 return ss; 111} 112 113void DfxThread::Detach() 114{ 115 if (threadStatus == ThreadStatus::THREAD_STATUS_ATTACHED) { 116 DfxPtrace::Detach(threadInfo_.nsTid); 117 threadStatus = ThreadStatus::THREAD_STATUS_INIT; 118 } 119} 120 121bool DfxThread::Attach(int timeout) 122{ 123 if (threadStatus == ThreadStatus::THREAD_STATUS_ATTACHED) { 124 return true; 125 } 126 127 if (!DfxPtrace::Attach(threadInfo_.nsTid, timeout)) { 128 return false; 129 } 130 131 threadStatus = ThreadStatus::THREAD_STATUS_ATTACHED; 132 return true; 133} 134 135void DfxThread::InitFaultStack(bool needParseStack) 136{ 137 if (faultStack_ != nullptr) { 138 return; 139 } 140 faultStack_ = std::make_shared<FaultStack>(threadInfo_.nsTid); 141 faultStack_->CollectStackInfo(frames_, needParseStack); 142} 143 144 145void DfxThread::SetFrames(const std::vector<DfxFrame>& frames) 146{ 147 frames_ = frames; 148} 149 150std::shared_ptr<FaultStack> DfxThread::GetFaultStack() const 151{ 152 return faultStack_; 153} 154} // namespace HiviewDFX 155} // nampespace OHOS 156