Elements  6.0.1
A C++ base framework for the Euclid Software.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ModuleInfo.cpp
Go to the documentation of this file.
1 
23 
24 #include <dlfcn.h>
25 #include <libgen.h>
26 #include <sys/param.h>
27 #include <sys/times.h>
28 #include <unistd.h>
29 
30 #ifdef __APPLE__
31 #include <mach-o/dyld.h> // for _NSGetExecutablePath
32 #endif
33 
34 #include <array>
35 #include <cerrno>
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
39 #include <fstream> // for ifstream
40 #include <iostream>
41 #include <sstream> // for stringstream
42 #include <string> // for string
43 #include <vector>
44 
45 #ifdef __APPLE__
46 #include <climits> // for PATH_MAX
47 #endif
48 
49 #include <boost/filesystem/operations.hpp> // for filesystem::exists, canonical
50 
52 #include "ElementsKernel/Path.h" // for Path::Item
53 
54 using std::string;
55 using std::vector;
56 
57 namespace {
58 vector<string> s_linkedModules;
59 }
60 
61 namespace Elements {
62 namespace System {
63 
64 ModuleInfo::ModuleInfo() : m_dlinfo{nullptr} {}
65 
66 ModuleInfo::ModuleInfo(void* funct) {
67  m_dlinfo.reset(new Dl_info);
68  ::dladdr(FuncPtrCast<void*>(funct), m_dlinfo.get());
69 }
70 
71 const string ModuleInfo::name() const {
72  return ::basename(const_cast<char*>(m_dlinfo->dli_fname));
73 }
74 
75 const string ModuleInfo::libraryName() const {
76  return const_cast<char*>(m_dlinfo->dli_fname);
77 }
78 
79 const void* ModuleInfo::addresse() const {
80  return m_dlinfo->dli_saddr;
81 }
82 
83 bool ModuleInfo::isEmpty() const {
84  return (m_dlinfo == nullptr);
85 }
86 
87 ModuleInfo::operator const Dl_info&() const {
88  return *m_dlinfo;
89 }
90 
91 namespace {
92 ImageHandle s_module_handle = nullptr;
93 }
95 const string& moduleName() {
96  static string module{};
97  if (module.empty()) {
98  if ((processHandle() != nullptr) and (moduleHandle() != nullptr)) {
99  string mod = ::basename(const_cast<char*>((reinterpret_cast<Dl_info*>(moduleHandle()))->dli_fname));
100  module = mod.substr(static_cast<string::size_type>(0), mod.find('.'));
101  }
102  }
103  return module;
104 }
105 
107 const string& moduleNameFull() {
108  static string module{};
109  if (module.empty()) {
110  if (processHandle() and moduleHandle()) {
111  std::array<char, PATH_MAX> name{"Unknown.module"};
112  name[0] = 0;
113  const char* path = (reinterpret_cast<Dl_info*>(moduleHandle())->dli_fname);
114  if (::realpath(path, name.data())) {
115  module = name.data();
116  }
117  }
118  }
119  return module;
120 }
121 
124  static ModuleType type = ModuleType::UNKNOWN;
125  if (type == ModuleType::UNKNOWN) {
126  const string& module = moduleNameFull();
127  std::size_t loc = module.rfind('.') + 1;
128  if (loc == 0) {
129  type = ModuleType::EXECUTABLE;
130  } else if (module[loc] == 'e' or module[loc] == 'E') {
131  type = ModuleType::EXECUTABLE;
132  } else if (module[loc] == 's' and module[loc + 1] == 'o') {
133  type = ModuleType::SHAREDLIB;
134  } else {
135  type = ModuleType::UNKNOWN;
136  }
137  }
138  return type;
139 }
140 
142 void* processHandle() {
143  static std::int64_t pid = ::getpid();
144  static void* hP = reinterpret_cast<void*>(pid);
145  return hP;
146 }
147 
149  s_module_handle = handle;
150 }
151 
153  if (nullptr == s_module_handle) {
154  if (processHandle() != nullptr) {
155  static Dl_info info;
156  if (0 != ::dladdr(FuncPtrCast<void*>(moduleHandle), &info)) {
157  return &info;
158  }
159  }
160  }
161  return s_module_handle;
162 }
163 
165  // This does NOT work!
166  static Dl_info infoBuf;
167  static Dl_info* info;
168 
169  if (nullptr == info) {
170  void* handle = ::dlopen(nullptr, RTLD_LAZY);
171  if (nullptr != handle) {
172  void* func = ::dlsym(handle, "main");
173  if (nullptr != func) {
174  if (0 != ::dladdr(func, &infoBuf)) {
175  info = &infoBuf;
176  }
177  }
178  }
179  }
180  return info;
181 }
182 
183 const string& exeName() {
184  static string module{""};
185  if (module.empty()) {
186  module = getExecutablePath().string();
187  }
188  return module;
189 }
190 
192 
193  Path::Item self_proc{"/proc/self"};
194 
195  Path::Item exe = self_proc / "exe";
196 
197  if (not boost::filesystem::exists(exe)) {
198  std::stringstream self_str{};
199  self_str << "/proc/" << ::getpid();
200  self_proc = Path::Item(self_str.str());
201  }
202 
203  return self_proc;
204 }
205 
207 
208  vector<Path::Item> linked_modules;
209 
210  Path::Item self_maps = getSelfProc() / "maps";
211  std::ifstream maps_str(self_maps.string());
212 
213  string line;
214  while (std::getline(maps_str, line)) {
215  string address, perms, offset, dev, pathname;
216  unsigned inode;
217  std::istringstream iss(line);
218  if (not(iss >> address >> perms >> offset >> dev >> inode >> pathname)) {
219  continue;
220  }
221  if (perms == "r-xp" and boost::filesystem::exists(pathname)) {
222  linked_modules.emplace_back(Path::Item(pathname));
223  }
224  }
225 
226  maps_str.close();
227 
228  return linked_modules;
229 }
230 
232 
233  if (s_linkedModules.size() == 0) {
234 
235  for (auto m : linkedModulePaths()) {
236  s_linkedModules.emplace_back(m.string());
237  }
238  }
239  return s_linkedModules;
240 }
241 
243 
244 #ifdef __APPLE__
245  path self_proc{};
246  char pathbuf[PATH_MAX + 1];
247  unsigned int bufsize = sizeof(pathbuf);
248  _NSGetExecutablePath(pathbuf, &bufsize);
249  path self_exe = path(string(pathbuf));
250 #else
251 
252  Path::Item self_exe = getSelfProc() / "exe";
253 
254 #endif
255 
256  return boost::filesystem::canonical(self_exe);
257 }
258 
259 } // namespace System
260 } // namespace Elements
ELEMENTS_API ModuleType moduleType()
Get type of the module.
Definition: ModuleInfo.cpp:123
ELEMENTS_API std::vector< Path::Item > linkedModulePaths()
Definition: ModuleInfo.cpp:206
OS specific details to access at run-time the module configuration of the process.
T rfind(T...args)
T getline(T...args)
std::unique_ptr< Dl_info > m_dlinfo
Definition: ModuleInfo.h:55
defines a Small helper function that allows the cast from void * to function pointer ...
ELEMENTS_API void setModuleHandle(ImageHandle handle)
Attach module handle.
Definition: ModuleInfo.cpp:148
ELEMENTS_API const std::vector< std::string > linkedModules()
Vector of names of linked modules.
Definition: ModuleInfo.cpp:231
STL class.
ELEMENTS_API const std::string & moduleNameFull()
Get the full name of the (executable/DLL) file.
Definition: ModuleInfo.cpp:107
void * ImageHandle
Definition of an image handle.
Definition: System.h:109
ELEMENTS_API ProcessHandle processHandle()
Handle to running process.
Definition: ModuleInfo.cpp:142
boost::filesystem::path Item
Definition: Path.h:56
const std::string name() const
Definition: ModuleInfo.cpp:71
T reset(T...args)
ELEMENTS_API const std::string & exeName()
Name of the executable file running.
Definition: ModuleInfo.cpp:183
const std::string libraryName() const
Definition: ModuleInfo.cpp:75
ELEMENTS_API ImageHandle moduleHandle()
Handle to currently executed module.
Definition: ModuleInfo.cpp:152
T get(T...args)
T find(T...args)
ELEMENTS_API const std::string & moduleName()
Get the name of the (executable/DLL) file without file-type.
Definition: ModuleInfo.cpp:95
STL class.
ELEMENTS_API ImageHandle exeHandle()
Handle to the executable file running.
Definition: ModuleInfo.cpp:164
provide functions to retrieve resources pointed by environment variables
STL class.
T substr(T...args)
constexpr double m
Definition: SystemOfUnits.h:79
ELEMENTS_API Path::Item getExecutablePath()
Get the full executable path.
Definition: ModuleInfo.cpp:242
const void * addresse() const
Definition: ModuleInfo.cpp:79
ELEMENTS_API Path::Item getSelfProc()
Get the path to the /proc directory of the process.
Definition: ModuleInfo.cpp:191
Path::Item path
importing the path item from ElementsKernel
Definition: DataSyncUtils.h:41
STL class.
T emplace_back(T...args)