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