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
35 namespace OHOS {
36 namespace HiviewDFX {
Create(pid_t pid, pid_t tid, pid_t nsTid)37 std::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
DfxThread(pid_t pid, pid_t tid, pid_t nsTid)43 DfxThread::DfxThread(pid_t pid, pid_t tid, pid_t nsTid) : regs_(nullptr)
44 {
45 InitThreadInfo(pid, tid, nsTid);
46 }
47
InitThreadInfo(pid_t pid, pid_t tid, pid_t nsTid)48 void 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
~DfxThread()57 DfxThread::~DfxThread()
58 {
59 threadStatus = ThreadStatus::THREAD_STATUS_INVALID;
60 }
61
GetThreadRegs() const62 std::shared_ptr<DfxRegs> DfxThread::GetThreadRegs() const
63 {
64 return regs_;
65 }
66
SetThreadRegs(const std::shared_ptr<DfxRegs> ®s)67 void DfxThread::SetThreadRegs(const std::shared_ptr<DfxRegs> ®s)
68 {
69 regs_ = regs;
70 }
71
AddFrame(DfxFrame& frame)72 void DfxThread::AddFrame(DfxFrame& frame)
73 {
74 frames_.emplace_back(frame);
75 }
76
GetFrames() const77 const std::vector<DfxFrame>& DfxThread::GetFrames() const
78 {
79 return frames_;
80 }
81
ToString() const82 std::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
Detach()113 void DfxThread::Detach()
114 {
115 if (threadStatus == ThreadStatus::THREAD_STATUS_ATTACHED) {
116 DfxPtrace::Detach(threadInfo_.nsTid);
117 threadStatus = ThreadStatus::THREAD_STATUS_INIT;
118 }
119 }
120
Attach(int timeout)121 bool 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
InitFaultStack(bool needParseStack)135 void 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
SetFrames(const std::vector<DfxFrame>& frames)145 void DfxThread::SetFrames(const std::vector<DfxFrame>& frames)
146 {
147 frames_ = frames;
148 }
149
GetFaultStack() const150 std::shared_ptr<FaultStack> DfxThread::GetFaultStack() const
151 {
152 return faultStack_;
153 }
154 } // namespace HiviewDFX
155 } // nampespace OHOS
156