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 isShowMaps_ = parameter->GetOpts().isShowSmaps_;
36 isShowSmapsInfo_ = parameter->GetOpts().isShowSmapsInfo_;
37 dumpDatas_ = dumpDatas;
38
39 bool isZip = parameter->GetOpts().IsDumpZip();
40 auto callback = parameter->getClientCallback();
41 if (callback == nullptr) {
42 DUMPER_HILOGE(MODULE_SERVICE, "PreExecute error|callback is nullptr");
43 return DumpStatus::DUMP_FAIL;
44 }
45 std::string logDefaultPath_ = callback->GetFolder() + "log.txt";
46 if (isZip) {
47 rawParamFd_ = DumpUtils::FdToWrite(logDefaultPath_);
48 } else {
49 rawParamFd_ = parameter->getClientCallback()->GetOutputFd();
50 }
51 return DumpStatus::DUMP_OK;
52 }
53
Execute()54 DumpStatus MemoryDumper::Execute()
55 {
56 DUMPER_HILOGI(MODULE_SERVICE, "info|MemoryDumper Execute enter");
57 if (dumpDatas_ != nullptr) {
58 if (pid_ >= 0) {
59 if (isShowMaps_) {
60 GetMemSmapsByPid();
61 DUMPER_HILOGI(MODULE_SERVICE, "get mem smaps end,pid:%{public}d", pid_);
62 return status_;
63 }
64 GetMemByPid();
65 } else {
66 GetMemNoPid();
67 }
68 }
69 DUMPER_HILOGI(MODULE_SERVICE, "info|MemoryDumper Execute end");
70 return status_;
71 }
72
GetMemByPid()73 void MemoryDumper::GetMemByPid()
74 {
75 void *handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
76 if (handle == nullptr) {
77 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
78 return;
79 }
80 GetMemByPidFunc pfn = reinterpret_cast<GetMemByPidFunc>(dlsym(handle, "GetMemoryInfoByPid"));
81 if (pfn == nullptr) {
82 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym GetMemoryInfoByPid. errno:%{public}s", dlerror());
83 dlclose(handle);
84 return;
85 }
86 if (!pfn(pid_, dumpDatas_)) {
87 status_ = DumpStatus::DUMP_OK;
88 } else {
89 DUMPER_HILOGE(MODULE_SERVICE, "MemoryDumper Execute failed, pid:%{public}d", pid_);
90 status_ = DumpStatus::DUMP_FAIL;
91 }
92 dlclose(handle);
93 }
94
GetMemNoPid()95 void MemoryDumper::GetMemNoPid()
96 {
97 void* handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
98 if (handle == nullptr) {
99 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
100 return;
101 }
102 GetMemNoPidFunc getMemNoPidFunc = reinterpret_cast<GetMemNoPidFunc>(dlsym(handle, "GetMemoryInfoNoPid"));
103 if (getMemNoPidFunc == nullptr) {
104 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym GetMemoryInfoNoPid. errno:%{public}s", dlerror());
105 dlclose(handle);
106 status_ = DUMP_FAIL;
107 return;
108 }
109 status_ = (DumpStatus)(getMemNoPidFunc(rawParamFd_, dumpDatas_));
110 dlclose(handle);
111 }
112
GetMemSmapsByPid()113 void MemoryDumper::GetMemSmapsByPid()
114 {
115 void *handle = dlopen(MEM_LIB.c_str(), RTLD_LAZY | RTLD_NODELETE);
116 if (handle == nullptr) {
117 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s. errno:%{public}s", MEM_LIB.c_str(), dlerror());
118 return;
119 }
120 GetMemSmapsByPidFunc pfn = reinterpret_cast<GetMemSmapsByPidFunc>(dlsym(handle, "ShowMemorySmapsByPid"));
121 if (pfn == nullptr) {
122 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym ShowMemorySmapsByPid. errno:%{public}s", dlerror());
123 dlclose(handle);
124 return;
125 }
126 if (!pfn(pid_, dumpDatas_, isShowSmapsInfo_)) {
127 status_ = DumpStatus::DUMP_OK;
128 } else {
129 DUMPER_HILOGE(MODULE_SERVICE, "GetMemSmapsByPid failed, pid:%{public}d", pid_);
130 status_ = DumpStatus::DUMP_FAIL;
131 }
132 dlclose(handle);
133 }
134
AfterExecute()135 DumpStatus MemoryDumper::AfterExecute()
136 {
137 return status_;
138 }
139 } // namespace HiviewDFX
140 } // namespace OHOS