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> &parameter, 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