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 #if defined(__x86_64__)
29 #include "dfx_frame_format.h"
30 #else
31 #include "dfx_frame_formatter.h"
32 #endif
33 #include "dfx_log.h"
34 #include "dfx_ptrace.h"
35 #include "dfx_util.h"
36 #include "procinfo.h"
37
38 namespace OHOS {
39 namespace HiviewDFX {
Create(pid_t pid,pid_t tid,pid_t nsTid)40 std::shared_ptr<DfxThread> DfxThread::Create(pid_t pid, pid_t tid, pid_t nsTid)
41 {
42 auto thread = std::make_shared<DfxThread>(pid, tid, nsTid);
43 return thread;
44 }
45
DfxThread(pid_t pid,pid_t tid,pid_t nsTid)46 DfxThread::DfxThread(pid_t pid, pid_t tid, pid_t nsTid) : regs_(nullptr)
47 {
48 InitThreadInfo(pid, tid, nsTid);
49 }
50
InitThreadInfo(pid_t pid,pid_t tid,pid_t nsTid)51 void DfxThread::InitThreadInfo(pid_t pid, pid_t tid, pid_t nsTid)
52 {
53 threadInfo_.pid = pid;
54 threadInfo_.tid = tid;
55 threadInfo_.nsTid = nsTid;
56 ReadThreadName(threadInfo_.tid, threadInfo_.threadName);
57 threadStatus = ThreadStatus::THREAD_STATUS_INIT;
58 }
59
~DfxThread()60 DfxThread::~DfxThread()
61 {
62 threadStatus = ThreadStatus::THREAD_STATUS_INVALID;
63 }
64
GetThreadRegs() const65 std::shared_ptr<DfxRegs> DfxThread::GetThreadRegs() const
66 {
67 return regs_;
68 }
69
SetThreadRegs(const std::shared_ptr<DfxRegs> & regs)70 void DfxThread::SetThreadRegs(const std::shared_ptr<DfxRegs> ®s)
71 {
72 regs_ = regs;
73 }
74
AddFrame(DfxFrame & frame)75 void DfxThread::AddFrame(DfxFrame& frame)
76 {
77 frames_.emplace_back(frame);
78 }
79
GetFrames() const80 const std::vector<DfxFrame>& DfxThread::GetFrames() const
81 {
82 return frames_;
83 }
84
ToString() const85 std::string DfxThread::ToString() const
86 {
87 if (frames_.size() == 0) {
88 return "No frame info";
89 }
90
91 std::stringstream ss;
92 ss << "Thread name:" << threadInfo_.threadName << "" << std::endl;
93 for (size_t i = 0; i < frames_.size(); i++) {
94 #if defined(__x86_64__)
95 ss << DfxFrameFormat::GetFrameStr(frames_[i]);
96 #else
97 ss << DfxFrameFormatter::GetFrameStr(frames_[i]);
98 #endif
99 }
100 return ss.str();
101 }
102
Detach()103 void DfxThread::Detach()
104 {
105 if (threadStatus == ThreadStatus::THREAD_STATUS_ATTACHED) {
106 DfxPtrace::Detach(threadInfo_.nsTid);
107 threadStatus = ThreadStatus::THREAD_STATUS_INIT;
108 }
109 }
110
Attach()111 bool DfxThread::Attach()
112 {
113 if (threadStatus == ThreadStatus::THREAD_STATUS_ATTACHED) {
114 return true;
115 }
116
117 if (!DfxPtrace::Attach(threadInfo_.nsTid)) {
118 return false;
119 }
120
121 threadStatus = ThreadStatus::THREAD_STATUS_ATTACHED;
122 return true;
123 }
124
InitFaultStack(bool needParseStack)125 void DfxThread::InitFaultStack(bool needParseStack)
126 {
127 if (faultStack_ != nullptr) {
128 return;
129 }
130 faultStack_ = std::make_shared<FaultStack>(threadInfo_.nsTid);
131 faultStack_->CollectStackInfo(frames_, needParseStack);
132 }
133
134
SetFrames(const std::vector<DfxFrame> & frames)135 void DfxThread::SetFrames(const std::vector<DfxFrame>& frames)
136 {
137 frames_ = frames;
138 }
139
GetFaultStack() const140 std::shared_ptr<FaultStack> DfxThread::GetFaultStack() const
141 {
142 return faultStack_;
143 }
144 } // namespace HiviewDFX
145 } // nampespace OHOS
146