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