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