• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2021 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef MINDSPORE_LITE_SRC_EXTENDRT_CXX_API_DLUTILS_H_
17 #define MINDSPORE_LITE_SRC_EXTENDRT_CXX_API_DLUTILS_H_
18 #include <string>
19 #include <vector>
20 #include "include/api/status.h"
21 #include "src/common/file_utils.h"
22 #if !defined(_WIN32) && !defined(_WIN64)
23 #include <dlfcn.h>
24 #include <string.h>
25 #include <dirent.h>
26 #include <memory>
27 #include <fstream>
28 
29 namespace mindspore {
30 inline std::string FindFileWithRecursion(const std::string &parent_dir, const std::string &target_so, int depth = 0) {
31   constexpr int MAX_RECURSION_DEPTH = 5;
32   if (depth == MAX_RECURSION_DEPTH) {
33     MS_LOG(DEBUG) << "Recursion depth exceeds MAX_RECURSION_DEPTH(5).";
34     return "";
35   }
36   DIR *dir = opendir(parent_dir.c_str());
37   if (dir == nullptr) {
38     MS_LOG(ERROR) << "Can't open dir " << parent_dir;
39     return "";
40   }
41   dirent *ent = readdir(dir);
42   std::vector<std::string> child_dirs;
43   while (ent != nullptr) {
44     if (ent->d_type == DT_DIR && strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) {
45       std::string dir_path = parent_dir + std::string(ent->d_name);
46       child_dirs.push_back(lite::RealPath(dir_path.c_str()) + "/");
47       ent = readdir(dir);
48       continue;
49     }
50     if (std::string(ent->d_name).find(target_so) != std::string::npos) {
51       std::string found_path = parent_dir + std::string(ent->d_name);
52       (void)closedir(dir);
53       return found_path;
54     }
55     ent = readdir(dir);
56   }
57   for (auto const &child_dir : child_dirs) {
58     if (!child_dir.empty()) {
59       std::string found_path = FindFileWithRecursion(child_dir, target_so, depth + 1);
60       if (!found_path.empty()) {
61         (void)closedir(dir);
62         return found_path;
63       }
64     }
65   }
66   (void)closedir(dir);
67   return "";
68 }
69 
FindSoPath(const std::string & parent_dir,const std::string & target_so,std::string * target_so_path)70 inline Status FindSoPath(const std::string &parent_dir, const std::string &target_so, std::string *target_so_path) {
71   if (target_so_path == nullptr) {
72     return Status(kMEFailed, "Input target_so_path is nullptr.");
73   }
74   std::string found_target_so = FindFileWithRecursion(parent_dir, target_so);
75   if (found_target_so.empty()) {
76     return Status(kMEFailed, "Could not find target so " + target_so + " in " + parent_dir);
77   }
78   auto realpath = lite::RealPath(found_target_so.c_str());
79   if (realpath.empty()) {
80     return Status(kMEFailed, "Get target so " + target_so + " real path failed, path: " + found_target_so);
81   }
82   *target_so_path = realpath;
83   return kSuccess;
84 }
85 
DLSoPath(const std::vector<std::string> & so_names,const std::string & target_so,std::string * target_so_path)86 inline Status DLSoPath(const std::vector<std::string> &so_names, const std::string &target_so,
87                        std::string *target_so_path) {
88   if (target_so_path == nullptr) {
89     return Status(kMEFailed, "Input so_path can not be nullptr.");
90   }
91   Dl_info dl_info;
92   dladdr(reinterpret_cast<void *>(DLSoPath), &dl_info);
93   std::string cur_so_path = dl_info.dli_fname;
94   std::string::size_type pos = std::string::npos;
95   for (auto &item : so_names) {
96     pos = cur_so_path.find(item);
97     if (pos != std::string::npos) {
98       break;
99     }
100   }
101   if (pos == std::string::npos) {
102     return Status(kMEFailed, "Could not find target so " + target_so + " in check path " + cur_so_path);
103   }
104   std::string parent_dir = cur_so_path.substr(0, pos);
105   return FindSoPath(parent_dir, target_so, target_so_path);
106 }
107 
108 inline Status DLSoOpen(const std::string &dl_path, const std::string &func_name, void **handle, void **function,
109                        bool runtime_convert = false) {
110   // do dlopen and export functions from c_dataengine
111   if (handle == nullptr) {
112     MS_LOG(WARNING) << "Input parameter handle cannot be nullptr";
113     return Status(kMEFailed, "Input parameter handle cannot be nullptr");
114   }
115   int mode = runtime_convert ? RTLD_GLOBAL : RTLD_LOCAL;
116   *handle = dlopen(dl_path.c_str(), RTLD_LAZY | mode);
117 
118   auto get_dl_error = []() -> std::string {
119     auto error = dlerror();
120     return error == nullptr ? "" : error;
121   };
122   if (*handle == nullptr) {
123     auto error = get_dl_error();
124     MS_LOG(WARNING) << "dlopen " << dl_path << " failed, error: " << error;
125     return Status(kMEFailed, "dlopen " + dl_path + " failed, error: " + error);
126   }
127   if (!func_name.empty()) {
128     if (function == nullptr) {
129       MS_LOG(WARNING) << "Input parameter function cannot be nullptr";
130       return Status(kMEFailed, "Input parameter function cannot be nullptr");
131     }
132     *function = dlsym(*handle, func_name.c_str());
133     if (*function == nullptr) {
134       auto error = get_dl_error();
135       MS_LOG(WARNING) << "Could not find " + func_name + " in " + dl_path + ", error: " << error;
136       return Status(kMEFailed, "Could not find " + func_name + " in " + dl_path + ", error: " + error);
137     }
138   }
139   return kSuccess;
140 }
141 
DLSoSym(const std::string & dl_path,void * handle,const std::string & func_name,void ** function)142 inline Status DLSoSym(const std::string &dl_path, void *handle, const std::string &func_name, void **function) {
143   if (handle == nullptr) {
144     MS_LOG(WARNING) << "Input parameter handle cannot be nullptr";
145     return Status(kMEFailed, "Input parameter handle cannot be nullptr");
146   }
147   if (func_name.empty()) {
148     MS_LOG(WARNING) << "Input parameter func_name cannot be empty";
149     return Status(kMEFailed, "Input parameter func_name cannot be empty");
150   }
151   if (function == nullptr) {
152     MS_LOG(WARNING) << "Input parameter function cannot be nullptr";
153     return Status(kMEFailed, "Input parameter function cannot be nullptr");
154   }
155   auto get_dl_error = []() -> std::string {
156     auto error = dlerror();
157     return error == nullptr ? "" : error;
158   };
159   *function = dlsym(handle, func_name.c_str());
160   if (*function == nullptr) {
161     auto error = get_dl_error();
162     MS_LOG(WARNING) << "Could not find " + func_name + " in " + dl_path + ", error: " << error;
163     return Status(kMEFailed, "Could not find " + func_name + " in " + dl_path + ", error: " + error);
164   }
165   return kSuccess;
166 }
167 
DLSoClose(void * handle)168 inline void DLSoClose(void *handle) {
169   if (handle != nullptr) {
170     (void)dlclose(handle);
171   }
172 }
173 
174 #define CHECK_FAIL_AND_RELEASE(_s, _handle, _e) \
175   do {                                          \
176     Status __rc = (_s);                         \
177     if (__rc.IsError()) {                       \
178       MS_LOG(ERROR) << (_e);                    \
179       DLSoClose((_handle));                     \
180       return __rc;                              \
181     }                                           \
182   } while (false)
183 }  // namespace mindspore
184 #else
FindSoPath(const std::string & benchmark_so_path,const std::string & target_so,std::string * target_so_path)185 inline mindspore::Status FindSoPath(const std::string &benchmark_so_path, const std::string &target_so,
186                                     std::string *target_so_path) {
187   MS_LOG(ERROR) << "Not support FindSoPath";
188   return mindspore::kMEFailed;
189 }
190 
DLSoPath(const std::string & benchmark_so,const std::string & target_so,std::string * target_so_path)191 inline mindspore::Status DLSoPath(const std::string &benchmark_so, const std::string &target_so,
192                                   std::string *target_so_path) {
193   MS_LOG(ERROR) << "Not support dlopen so";
194   return mindspore::kMEFailed;
195 }
196 
197 inline mindspore::Status DLSoOpen(const std::string &dl_path, const std::string &func_name, void **handle,
198                                   void **function, bool runtime_convert = false) {
199   MS_LOG(ERROR) << "Not support dlopen so";
200   return mindspore::kMEFailed;
201 }
202 #endif
203 #endif  // MINDSPORE_LITE_SRC_EXTENDRT_CXX_API_DLUTILS_H_
204