1 /*
2     Copyright (c) 2014-2016 Intel Corporation.  All Rights Reserved.
3 
4     Redistribution and use in source and binary forms, with or without
5     modification, are permitted provided that the following conditions
6     are met:
7 
8       * Redistributions of source code must retain the above copyright
9         notice, this list of conditions and the following disclaimer.
10       * Redistributions in binary form must reproduce the above copyright
11         notice, this list of conditions and the following disclaimer in the
12         documentation and/or other materials provided with the distribution.
13       * Neither the name of Intel Corporation nor the names of its
14         contributors may be used to endorse or promote products derived
15         from this software without specific prior written permission.
16 
17     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 
31 #include "offload_util.h"
32 #include <errno.h>
33 #include "liboffload_error_codes.h"
34 
35 #ifdef TARGET_WINNT
thread_getspecific(pthread_key_t key)36 void *thread_getspecific(pthread_key_t key)
37 {
38     if (key == 0) {
39         return NULL;
40     }
41     else {
42         return TlsGetValue(key);
43     }
44 }
45 
thread_setspecific(pthread_key_t key,const void * value)46 int thread_setspecific(pthread_key_t key, const void *value)
47 {
48     return (TlsSetValue(key, (LPVOID)value)) ? 0 : GetLastError();
49 }
50 #endif // TARGET_WINNT
51 
__offload_parse_size_string(const char * str,uint64_t & new_size)52 bool __offload_parse_size_string(const char *str, uint64_t &new_size)
53 {
54     uint64_t val;
55     char *suffix;
56 
57     errno = 0;
58 #ifdef TARGET_WINNT
59     val = strtoul(str, &suffix, 10);
60 #else // TARGET_WINNT
61     val = strtoull(str, &suffix, 10);
62 #endif // TARGET_WINNT
63     if (errno != 0 || suffix == str) {
64         return false;
65     }
66 
67     if (suffix[0] == '\0') {
68         // default is Kilobytes
69         new_size = val * 1024;
70         return true;
71     }
72     else if (suffix[1] == '\0') {
73         // Optional suffixes: B (bytes), K (Kilobytes), M (Megabytes),
74         // G (Gigabytes), or T (Terabytes) specify the units.
75         switch (suffix[0]) {
76             case 'b':
77             case 'B':
78                 new_size = val;
79                 break;
80 
81             case 'k':
82             case 'K':
83                 new_size = val * 1024;
84                 break;
85 
86             case 'm':
87             case 'M':
88                 new_size = val * 1024 * 1024;
89                 break;
90 
91             case 'g':
92             case 'G':
93                 new_size = val * 1024 * 1024 * 1024;
94                 break;
95 
96             case 't':
97             case 'T':
98                 new_size = val * 1024 * 1024 * 1024 * 1024;
99                 break;
100 
101             default:
102                 return false;
103         }
104         return true;
105     }
106 
107     return false;
108 }
109 
__offload_parse_int_string(const char * str,int64_t & value)110 bool __offload_parse_int_string(const char *str, int64_t &value)
111 {
112     int64_t val;
113     char *suffix;
114 
115     errno = 0;
116 #ifdef TARGET_WINNT
117     val = strtol(str, &suffix, 0);
118 #else
119     val = strtoll(str, &suffix, 0);
120 #endif
121     if (errno == 0 && suffix != str && *suffix == '\0') {
122         value = val;
123         return true;
124     }
125     return false;
126 }
127 
128 #ifdef TARGET_WINNT
DL_open(const char * path)129 extern void* DL_open(const char *path)
130 {
131     void *handle;
132     int error_mode;
133 
134     /*
135      * do not display message box with error if it the call below fails to
136      * load dynamic library.
137      */
138     error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
139 
140     /* load dynamic library */
141     handle = (void*) LoadLibrary(path);
142 
143     /* restore error mode */
144     SetErrorMode(error_mode);
145 
146     return handle;
147 }
148 
DL_addr(const void * addr,Dl_info * dl_info)149 extern int DL_addr(const void *addr, Dl_info *dl_info)
150 {
151     MEMORY_BASIC_INFORMATION mem_info;
152     char mod_name[MAX_PATH];
153     HMODULE mod_handle;
154 
155     /* Fill MEMORY_BASIC_INFORMATION struct */
156     if (!VirtualQuery(addr, &mem_info, sizeof(mem_info))) {
157         return 0;
158     }
159     mod_handle = (HMODULE)mem_info.AllocationBase;
160 
161     /* ANSI file name for module */
162     if (!GetModuleFileNameA(mod_handle, (char*) mod_name, sizeof(mod_name))) {
163         return 0;
164     }
165     strcpy(dl_info->dli_fname, mod_name);
166     dl_info->dli_fbase = mem_info.BaseAddress;
167     dl_info->dli_saddr = addr;
168     strcpy(dl_info->dli_sname, mod_name);
169     return 1;
170 }
171 
172 // Run once
__offload_run_once_wrapper(PINIT_ONCE initOnce,PVOID parameter,PVOID * context)173 static BOOL CALLBACK __offload_run_once_wrapper(
174     PINIT_ONCE initOnce,
175     PVOID parameter,
176     PVOID *context
177 )
178 {
179     void (*init_routine)(void) = (void(*)(void)) parameter;
180     init_routine();
181     return true;
182 }
183 
__offload_run_once(OffloadOnceControl * ctrl,void (* func)(void))184 void __offload_run_once(OffloadOnceControl *ctrl, void (*func)(void))
185 {
186     InitOnceExecuteOnce(ctrl, __offload_run_once_wrapper, (void*) func, 0);
187 }
188 #endif // TARGET_WINNT
189 
190 /* ARGSUSED */ // version is not used on windows
DL_sym(void * handle,const char * name,const char * version)191 void* DL_sym(void *handle, const char *name, const char *version)
192 {
193 #ifdef TARGET_WINNT
194     return GetProcAddress((HMODULE) handle, name);
195 #else // TARGET_WINNT
196     if (version == 0) {
197         return dlsym(handle, name);
198     }
199     else {
200         return dlvsym(handle, name, version);
201     }
202 #endif // TARGET_WINNT
203 }
204 
get_el_value(char * base,int64_t offset,int64_t size)205 int64_t get_el_value(
206                      char *base,
207                      int64_t offset,
208                      int64_t size)
209 {
210     int64_t val = 0;
211     switch (size) {
212         case 1:
213             val = static_cast<int64_t>(*((char *)(base + offset)));
214             break;
215         case 2:
216             val = static_cast<int64_t>(*((short *)(base + offset)));
217             break;
218         case 4:
219             val = static_cast<int64_t>(*((int *)(base + offset)));
220             break;
221         default:
222             val = *((int64_t *)(base + offset));
223             break;
224     }
225     return val;
226 }
227