9
9
#include < CL/sycl/detail/os_util.hpp>
10
10
#include < CL/sycl/exception.hpp>
11
11
12
+ #include < cassert>
13
+
12
14
#ifdef SYCL_RT_OS_POSIX_SUPPORT
13
15
#include < cstdlib>
14
16
#endif
20
22
#endif // _GNU_SOURCE
21
23
22
24
#include < cstdio>
25
+ #include < cstring>
26
+ #include < dlfcn.h>
27
+ #include < fstream>
28
+ #include < libgen.h> // for dirname
23
29
#include < link.h>
30
+ #include < linux/limits.h> // for PATH_MAX
24
31
#include < sys/sysinfo.h>
25
32
26
33
#elif defined(SYCL_RT_OS_WINDOWS)
27
34
28
35
#include < Windows.h>
29
36
#include < malloc.h>
37
+ #include < shlwapi.h>
30
38
31
39
#elif defined(SYCL_RT_OS_DARWIN)
32
40
@@ -77,6 +85,97 @@ OSModuleHandle OSUtil::getOSModuleHandle(const void *VirtAddr) {
77
85
return reinterpret_cast <OSModuleHandle>(Res.Handle );
78
86
}
79
87
88
+ bool procMapsAddressInRange (std::istream &Stream, uintptr_t Addr) {
89
+ uintptr_t Start = 0 , End = 0 ;
90
+ Stream >> Start;
91
+ assert (!Stream.fail () && Stream.peek () == ' -' &&
92
+ " Couldn't read /proc/self/maps correctly" );
93
+ Stream.ignore (1 );
94
+
95
+ Stream >> End;
96
+ assert (!Stream.fail () && Stream.peek () == ' ' &&
97
+ " Couldn't read /proc/self/maps correctly" );
98
+ Stream.ignore (1 );
99
+
100
+ return Addr >= Start && Addr < End;
101
+ }
102
+
103
+ // / Returns an absolute path to a directory where the object was found.
104
+ std::string OSUtil::getCurrentDSODir () {
105
+ // Examine /proc/self/maps and find where this function (getCurrendDSODir)
106
+ // comes from - this is supposed to be an absolute path to libsycl.so.
107
+ //
108
+ // File structure is the following:
109
+ // address perms offset dev inode pathname
110
+ // 00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/foo
111
+ // 007c2000-007c8000 r--p 001c2000 fc:05 52567930 /usr/bin/bar
112
+ //
113
+ // We need to:
114
+ //
115
+ // 1) Iterate over lines and find the line which have an address of the
116
+ // current function in an `address' range.
117
+ //
118
+ // 2) Check that perms have read and executable flags (since we do execute
119
+ // this function).
120
+ //
121
+ // 3) Skip offset, dev, inode
122
+ //
123
+ // 4) Extract an absolute path to a filename and get a dirname from it.
124
+ //
125
+ uintptr_t CurrentFunc = (uintptr_t ) &getCurrentDSODir;
126
+ std::ifstream Stream (" /proc/self/maps" );
127
+ Stream >> std::hex;
128
+ while (!Stream.eof ()) {
129
+ if (!procMapsAddressInRange (Stream, CurrentFunc)) {
130
+ // Skip the rest until an EOL and check the next line
131
+ Stream.ignore (std::numeric_limits<std::streamsize>::max (), ' \n ' );
132
+ continue ;
133
+ }
134
+
135
+ char Perm[4 ];
136
+ Stream.readsome (Perm, sizeof (Perm));
137
+ assert (Perm[0 ] == ' r' && Perm[2 ] == ' x' &&
138
+ " Invalid flags in /proc/self/maps" );
139
+ assert (Stream.peek () == ' ' );
140
+ Stream.ignore (1 );
141
+
142
+ // Read and ignore the following:
143
+ // offset
144
+ Stream.ignore (std::numeric_limits<std::streamsize>::max (), ' ' );
145
+ Stream.ignore (1 );
146
+ // dev major
147
+ Stream.ignore (std::numeric_limits<std::streamsize>::max (), ' :' );
148
+ Stream.ignore (1 );
149
+ // dev minor
150
+ Stream.ignore (std::numeric_limits<std::streamsize>::max (), ' ' );
151
+ Stream.ignore (1 );
152
+ // inode
153
+ Stream.ignore (std::numeric_limits<std::streamsize>::max (), ' ' );
154
+ Stream.ignore (1 );
155
+
156
+ // Now read the path: it is padded with whitespaces, so we skip them
157
+ // first.
158
+ while (Stream.peek () == ' ' ) {
159
+ Stream.ignore (1 );
160
+ }
161
+ char Path[PATH_MAX];
162
+ Stream.getline (Path, PATH_MAX - 1 );
163
+ Path[PATH_MAX - 1 ] = ' \0 ' ;
164
+ return OSUtil::getDirName (Path);
165
+ }
166
+ assert (false && " Unable to find the current function in /proc/self/maps" );
167
+ return " " ;
168
+ }
169
+
170
+ std::string OSUtil::getDirName (const char * Path) {
171
+ std::string Tmp (Path);
172
+ // dirname(3) needs a writable C string: a null-terminator is written where a
173
+ // path should split.
174
+ size_t TruncatedSize = strlen (dirname (const_cast <char *>(Tmp.c_str ())));
175
+ Tmp.resize (TruncatedSize);
176
+ return Tmp;
177
+ }
178
+
80
179
#elif defined(SYCL_RT_OS_WINDOWS)
81
180
OSModuleHandle OSUtil::getOSModuleHandle (const void *VirtAddr) {
82
181
HMODULE PhModule;
@@ -93,6 +192,25 @@ OSModuleHandle OSUtil::getOSModuleHandle(const void *VirtAddr) {
93
192
return reinterpret_cast <OSModuleHandle>(PhModule);
94
193
}
95
194
195
+ // / Returns an absolute path where the object was found.
196
+ std::string OSUtil::getCurrentDSODir () {
197
+ char Path[MAX_PATH];
198
+ Path[0 ] = ' \0 ' ;
199
+ Path[sizeof (Path) - 1 ] = ' \0 ' ;
200
+ DWORD Ret = GetModuleFileNameA (
201
+ reinterpret_cast <HMODULE>(getOSModuleHandle (&getCurrentDSODir)),
202
+ reinterpret_cast <LPSTR>(&Path),
203
+ sizeof (Path));
204
+ assert (Ret < sizeof (Path) && " Path is longer than PATH_MAX?" );
205
+ assert (Ret > 0 && " GetModuleFileNameA failed" );
206
+
207
+ BOOL RetCode = PathRemoveFileSpecA (reinterpret_cast <LPSTR>(&Path));
208
+ assert (RetCode && " PathRemoveFileSpecA failed" );
209
+ (void )RetCode;
210
+
211
+ return Path;
212
+ };
213
+
96
214
#elif defined(SYCL_RT_OS_DARWIN)
97
215
OSModuleHandle OSUtil::getOSModuleHandle (const void *VirtAddr) {
98
216
Dl_info Res;
0 commit comments