1 /*
2 * Copyright (C) 2021 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 #include "executor/memory_dumper.h"
16 #include "dump_utils.h"
17 #include <dlfcn.h>
18
19 using namespace std;
20 namespace OHOS {
21 namespace HiviewDFX {
22 static const std::string MEM_LIB = "libhidumpermemory.z.so";
23
MemoryDumper()24 MemoryDumper::MemoryDumper()
25 {
26 }
27
~MemoryDumper()28 MemoryDumper::~MemoryDumper()
29 {
30 }
31
PreExecute(const shared_ptr<DumperParameter> & parameter,StringMatrix dumpDatas)32 DumpStatus MemoryDumper::PreExecute(const shared_ptr<DumperParameter> ¶meter, StringMatrix dumpDatas)
33 {
34 pid_ = parameter->GetOpts().memPid_;
35 timeInterval_ = parameter->GetOpts().timeInterval_;
36 isShowMaps_ = parameter->GetOpts().isShowSmaps_;
37 isShowSmapsInfo_ = parameter->GetOpts().isShowSmapsInfo_;
38 isReceivedSigInt_ = parameter->GetOpts().isReceivedSigInt_;
39 dumpMemPrune_ = parameter->GetOpts().dumpMemPrune_;
40 showAshmem_ = parameter->GetOpts().showAshmem_;
41 showDmabuf_ = parameter->GetOpts().showDmaBuf_;
42 dumpDatas_ = dumpDatas;
43
44 bool isZip = parameter->GetOpts().IsDumpZip();
45 auto callback = parameter->getClientCallback();
46 if (callback == nullptr) {
47 DUMPER_HILOGE(MODULE_SERVICE, "PreExecute error|callback is nullptr");
48 return DumpStatus::DUMP_FAIL;
49 }
50 std::string logDefaultPath_ = callback->GetFolder() + "log.txt";
51 if (isZip) {
52 rawParamFd_ = DumpUtils::FdToWrite(logDefaultPath_);
53 } else {
54 rawParamFd_ = parameter->getClientCallback()->GetOutputFd();
55 }
56 return DumpStatus::DUMP_OK;
57 }
58
Execute()59 DumpStatus MemoryDumper::Execute()
60 {
61 DUMPER_HILOGI(MODULE_SERVICE, "info|MemoryDumper Execute enter");
62 if (isReceivedSigInt_) {
63 SetReceivedSigInt();
64 DUMPER_HILOGI(MODULE_SERVICE, "ctrl+c, pid:%{public}d", pid_);
65 return status_;
66 }
67 if (dumpDatas_ != nullptr) {
68 if (pid_ >= 0) {
69 if (isShowMaps_) {
70 GetMemSmapsByPid();
71 DUMPER_HILOGI(MODULE_SERVICE, "get mem smaps end,pid:%{public}d", pid_);
72 return status_;
73 }
74 if (timeInterval_ > 0) {
75 GetMemByTimeInterval();
76 DUMPER_HILOGI(MODULE_SERVICE, "GetMemByTimeInterval end,pid:%{public}d", pid_);
77 return status_;
78 }
79 GetMemByPid();
80 } else {
81 if (dumpMemPrune_) {
82 GetMemPruneNoPid();
83 } else {
84 GetMemNoPid();
85 }
86 }
87 }
88 DUMPER_HILOGI(MODULE_SERVICE, "info|MemoryDumper Execute end");
89 return status_;
90 }
91
GetMemByPid()92 void MemoryDumper::GetMemByPid()
93 {
94 void *handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
95 if (handle == nullptr) {
96 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
97 return;
98 }
99 GetMemByPidFunc pfn = reinterpret_cast<GetMemByPidFunc>(dlsym(handle, "GetMemoryInfoByPid"));
100 if (pfn == nullptr) {
101 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym GetMemoryInfoByPid. errno:%{public}s", dlerror());
102 dlclose(handle);
103 return;
104 }
105 if (!pfn(pid_, dumpDatas_, showAshmem_, showDmabuf_)) {
106 status_ = DumpStatus::DUMP_OK;
107 } else {
108 DUMPER_HILOGE(MODULE_SERVICE, "MemoryDumper Execute failed, pid:%{public}d", pid_);
109 status_ = DumpStatus::DUMP_FAIL;
110 }
111 dlclose(handle);
112 }
113
GetMemNoPid()114 void MemoryDumper::GetMemNoPid()
115 {
116 void* handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
117 if (handle == nullptr) {
118 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
119 return;
120 }
121 GetMemNoPidFunc getMemNoPidFunc = reinterpret_cast<GetMemNoPidFunc>(dlsym(handle, "GetMemoryInfoNoPid"));
122 if (getMemNoPidFunc == nullptr) {
123 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym GetMemoryInfoNoPid. errno:%{public}s", dlerror());
124 dlclose(handle);
125 status_ = DUMP_FAIL;
126 return;
127 }
128 status_ = (DumpStatus)(getMemNoPidFunc(rawParamFd_, dumpDatas_));
129 dlclose(handle);
130 }
131
GetMemPruneNoPid()132 void MemoryDumper::GetMemPruneNoPid()
133 {
134 void* handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
135 if (handle == nullptr) {
136 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
137 return;
138 }
139 GetMemPruneNoPidFunc getMemPruneNoPidFunc = reinterpret_cast<GetMemPruneNoPidFunc>(
140 dlsym(handle, "GetMemoryInfoPrune"));
141 if (getMemPruneNoPidFunc == nullptr) {
142 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym GetMemoryInfoPrune. errno:%{public}s", dlerror());
143 dlclose(handle);
144 status_ = DUMP_FAIL;
145 return;
146 }
147 status_ = (DumpStatus)(getMemPruneNoPidFunc(rawParamFd_, dumpDatas_));
148 dlclose(handle);
149 }
150
GetMemSmapsByPid()151 void MemoryDumper::GetMemSmapsByPid()
152 {
153 void *handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
154 if (handle == nullptr) {
155 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
156 return;
157 }
158 GetMemSmapsByPidFunc pfn = reinterpret_cast<GetMemSmapsByPidFunc>(dlsym(handle, "ShowMemorySmapsByPid"));
159 if (pfn == nullptr) {
160 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym ShowMemorySmapsByPid. errno:%{public}s", dlerror());
161 dlclose(handle);
162 return;
163 }
164 if (!pfn(pid_, dumpDatas_, isShowSmapsInfo_)) {
165 status_ = DumpStatus::DUMP_OK;
166 } else {
167 DUMPER_HILOGE(MODULE_SERVICE, "GetMemSmapsByPid failed, pid:%{public}d", pid_);
168 status_ = DumpStatus::DUMP_FAIL;
169 }
170 dlclose(handle);
171 }
172
GetMemByTimeInterval()173 void MemoryDumper::GetMemByTimeInterval()
174 {
175 void *handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
176 if (handle == nullptr) {
177 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
178 return;
179 }
180 GetMemByTimeIntervalFunc pfn = reinterpret_cast<GetMemByTimeIntervalFunc>(
181 dlsym(handle, "GetMemoryInfoByTimeInterval"));
182 if (pfn == nullptr) {
183 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym GetMemoryInfoByTimeInterval. errno:%{public}s", dlerror());
184 dlclose(handle);
185 return;
186 }
187 pfn(rawParamFd_, pid_, timeInterval_);
188 status_ = DumpStatus::DUMP_OK;
189 dlclose(handle);
190 }
191
SetReceivedSigInt()192 void MemoryDumper::SetReceivedSigInt()
193 {
194 void *handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
195 if (handle == nullptr) {
196 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
197 return;
198 }
199 SetReceivedSigIntFunc pfn = reinterpret_cast<SetReceivedSigIntFunc>(dlsym(handle, "SetReceivedSigInt"));
200 if (pfn == nullptr) {
201 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym SetReceivedSigInt. errno:%{public}s", dlerror());
202 dlclose(handle);
203 return;
204 }
205 pfn(isReceivedSigInt_);
206 status_ = DumpStatus::DUMP_OK;
207 dlclose(handle);
208 }
209
AfterExecute()210 DumpStatus MemoryDumper::AfterExecute()
211 {
212 return status_;
213 }
214 } // namespace HiviewDFX
215 } // namespace OHOS