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