1 /*
2 * Copyright (c) 2021-2025 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 "dump_utils.h"
32 #include "procinfo.h"
33 namespace OHOS {
34 namespace HiviewDFX {
Create(pid_t pid,pid_t tid,pid_t nsTid)35 std::shared_ptr<DfxThread> DfxThread::Create(pid_t pid, pid_t tid, pid_t nsTid)
36 {
37 auto thread = std::make_shared<DfxThread>(pid, tid, nsTid);
38 return thread;
39 }
40
DfxThread(pid_t pid,pid_t tid,pid_t nsTid)41 DfxThread::DfxThread(pid_t pid, pid_t tid, pid_t nsTid) : regs_(nullptr)
42 {
43 InitThreadInfo(pid, tid, nsTid);
44 }
45
InitThreadInfo(pid_t pid,pid_t tid,pid_t nsTid)46 void DfxThread::InitThreadInfo(pid_t pid, pid_t tid, pid_t nsTid)
47 {
48 threadInfo_.pid = pid;
49 threadInfo_.tid = tid;
50 threadInfo_.nsTid = nsTid;
51 ReadThreadNameByPidAndTid(threadInfo_.pid, threadInfo_.tid, threadInfo_.threadName);
52 threadStatus = ThreadStatus::THREAD_STATUS_INIT;
53 }
54
~DfxThread()55 DfxThread::~DfxThread()
56 {
57 threadStatus = ThreadStatus::THREAD_STATUS_INVALID;
58 }
59
GetThreadRegs() const60 std::shared_ptr<DfxRegs> DfxThread::GetThreadRegs() const
61 {
62 return regs_;
63 }
64
SetThreadRegs(const std::shared_ptr<DfxRegs> & regs)65 void DfxThread::SetThreadRegs(const std::shared_ptr<DfxRegs> ®s)
66 {
67 regs_ = regs;
68 }
69
AddFrame(const DfxFrame & frame)70 void DfxThread::AddFrame(const DfxFrame& frame)
71 {
72 frames_.emplace_back(frame);
73 }
74
GetFrames() const75 const std::vector<DfxFrame>& DfxThread::GetFrames() const
76 {
77 return frames_;
78 }
79
ToString(bool needPrintTid) const80 std::string DfxThread::ToString(bool needPrintTid) const
81 {
82 std::string dumpThreadInfo;
83 if (needPrintTid) {
84 dumpThreadInfo += "Tid:" + std::to_string(threadInfo_.tid) +
85 ", Name:" + threadInfo_.threadName + "\n";
86 } else {
87 if (frames_.size() == 0) {
88 return "No frame info";
89 }
90 dumpThreadInfo += "Thread name:" + threadInfo_.threadName + "\n";
91 }
92
93 dumpThreadInfo += DumpUtils::GetStackTrace(frames_);
94
95 if (!submitterFrames_.empty()) {
96 dumpThreadInfo += "========SubmitterStacktrace========\n";
97 dumpThreadInfo += DumpUtils::GetStackTrace(submitterFrames_);
98 }
99 return dumpThreadInfo;
100 }
101
Detach()102 void DfxThread::Detach()
103 {
104 if (threadStatus == ThreadStatus::THREAD_STATUS_ATTACHED) {
105 DfxPtrace::Detach(threadInfo_.nsTid);
106 threadStatus = ThreadStatus::THREAD_STATUS_INIT;
107 }
108 }
109
Attach(int timeout)110 bool DfxThread::Attach(int timeout)
111 {
112 if (threadStatus == ThreadStatus::THREAD_STATUS_ATTACHED) {
113 return true;
114 }
115
116 if (!DfxPtrace::Attach(threadInfo_.nsTid, timeout)) {
117 return false;
118 }
119
120 threadStatus = ThreadStatus::THREAD_STATUS_ATTACHED;
121 return true;
122 }
123
SetFrames(const std::vector<DfxFrame> & frames)124 void DfxThread::SetFrames(const std::vector<DfxFrame>& frames)
125 {
126 frames_ = frames;
127 }
128
ParseSymbol(Unwinder & unwinder)129 void DfxThread::ParseSymbol(Unwinder& unwinder)
130 {
131 if (!needParseSymbol_) {
132 return;
133 }
134
135 for (auto& frame : frames_) {
136 if (frame.isJsFrame) { // js frame parse in unwinder
137 continue;
138 }
139 unwinder.ParseFrameSymbol(frame);
140 }
141 }
142
SetParseSymbolNecessity(bool needParseSymbol)143 void DfxThread::SetParseSymbolNecessity(bool needParseSymbol)
144 {
145 needParseSymbol_ = needParseSymbol;
146 }
147 } // namespace HiviewDFX
148 } // nampespace OHOS
149