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