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> &regs)
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