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_process.h"
17
18 #include <climits>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 #include <dirent.h>
23 #include <securec.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <vector>
27 #include "dfx_config.h"
28 #include "dfx_define.h"
29 #include "dfx_logger.h"
30 #include "dfx_ring_buffer_wrapper.h"
31 #include "dfx_signal.h"
32 #include "dfx_util.h"
33 #include "procinfo.h"
34
35 namespace OHOS {
36 namespace HiviewDFX {
Create(pid_t pid,pid_t nsPid)37 std::shared_ptr<DfxProcess> DfxProcess::Create(pid_t pid, pid_t nsPid)
38 {
39 auto process = std::make_shared<DfxProcess>(pid, nsPid);
40 return process;
41 }
42
DfxProcess(pid_t pid,pid_t nsPid)43 DfxProcess::DfxProcess(pid_t pid, pid_t nsPid)
44 {
45 InitProcessInfo(pid, nsPid);
46 }
47
InitProcessInfo(pid_t pid,pid_t nsPid)48 void DfxProcess::InitProcessInfo(pid_t pid, pid_t nsPid)
49 {
50 processInfo_.pid = pid;
51 processInfo_.nsPid = nsPid;
52 ReadProcessName(processInfo_.pid, processInfo_.processName);
53 }
54
InitOtherThreads(bool attach)55 bool DfxProcess::InitOtherThreads(bool attach)
56 {
57 std::vector<int> tids;
58 std::vector<int> nstids;
59 if (!GetTidsByPid(processInfo_.pid, tids, nstids)) {
60 return false;
61 }
62
63 for (size_t i = 0; i < nstids.size(); ++i) {
64 if ((recycleTid_ > 0) && (nstids[i] == static_cast<int>(recycleTid_))) {
65 DFXLOG_DEBUG("skip recycle thread:%d.", nstids[i]);
66 continue;
67 }
68
69 if ((keyThread_ != nullptr) && nstids[i] == keyThread_->threadInfo_.nsTid) {
70 DFXLOG_DEBUG("skip key thread:%d.", nstids[i]);
71 continue;
72 }
73
74 auto thread = DfxThread::Create(processInfo_.pid, tids[i], nstids[i]);
75 if (attach) {
76 thread->Attach();
77 }
78 otherThreads_.push_back(thread);
79 }
80 return true;
81 }
82
ChangeTid(pid_t tid,bool ns)83 pid_t DfxProcess::ChangeTid(pid_t tid, bool ns)
84 {
85 if (processInfo_.pid == processInfo_.nsPid) {
86 return tid;
87 }
88
89 if (kvThreads_.empty()) {
90 std::vector<int> tids;
91 std::vector<int> nstids;
92 if (!GetTidsByPid(processInfo_.pid, tids, nstids)) {
93 return tid;
94 }
95 for (size_t i = 0; i < nstids.size(); ++i) {
96 kvThreads_[nstids[i]] = tids[i];
97 }
98 }
99
100 for (auto iter = kvThreads_.begin(); iter != kvThreads_.end(); iter++) {
101 if (ns && (iter->first == tid)) {
102 return iter->second;
103 }
104 if (!ns && (iter->second == tid)) {
105 return iter->first;
106 }
107 }
108 return tid;
109 }
110
GetOtherThreads() const111 std::vector<std::shared_ptr<DfxThread>> DfxProcess::GetOtherThreads() const
112 {
113 return otherThreads_;
114 }
115
ClearOtherThreads()116 void DfxProcess::ClearOtherThreads()
117 {
118 otherThreads_.clear();
119 }
120
Attach(bool hasKey)121 void DfxProcess::Attach(bool hasKey)
122 {
123 if (hasKey && keyThread_) {
124 keyThread_->Attach();
125 }
126
127 if (otherThreads_.empty()) {
128 return;
129 }
130 for (auto thread : otherThreads_) {
131 thread->Attach();
132 }
133 }
134
Detach()135 void DfxProcess::Detach()
136 {
137 if (otherThreads_.empty()) {
138 return;
139 }
140
141 for (auto thread : otherThreads_) {
142 thread->Detach();
143 }
144 }
145
SetFatalMessage(const std::string & msg)146 void DfxProcess::SetFatalMessage(const std::string &msg)
147 {
148 fatalMsg_ = msg;
149 }
150
GetFatalMessage() const151 std::string DfxProcess::GetFatalMessage() const
152 {
153 return fatalMsg_;
154 }
155
SetMaps(std::shared_ptr<DfxElfMaps> maps)156 void DfxProcess::SetMaps(std::shared_ptr<DfxElfMaps> maps)
157 {
158 maps_ = maps;
159 }
160
InitProcessMaps()161 void DfxProcess::InitProcessMaps()
162 {
163 if (maps_ == nullptr) {
164 if (processInfo_.pid <= 0) {
165 return;
166 }
167 maps_ = DfxElfMaps::Create(processInfo_.pid);
168 }
169 }
170
GetMaps() const171 std::shared_ptr<DfxElfMaps> DfxProcess::GetMaps() const
172 {
173 return maps_;
174 }
175 } // namespace HiviewDFX
176 } // namespace OHOS
177