]> icculus.org git repositories - divverent/darkplaces.git/blob - sys_shared.c
win32 specific code start (not done)
[divverent/darkplaces.git] / sys_shared.c
1 #include "quakedef.h"
2
3 #define SUPPORTDLL
4
5 # include <time.h>
6 #ifndef WIN32
7 # include <unistd.h>
8 # include <fcntl.h>
9 #ifdef SUPPORTDLL
10 # include <dlfcn.h>
11 #endif
12 #endif
13
14 static char sys_timestring[128];
15 char *Sys_TimeString(const char *timeformat)
16 {
17         time_t mytime = time(NULL);
18 #if _MSC_VER >= 1400
19         struct tm mytm;
20         localtime_s(&mytm, &mytime);
21         strftime(sys_timestring, sizeof(sys_timestring), timeformat, &mytm);
22 #else
23         strftime(sys_timestring, sizeof(sys_timestring), timeformat, localtime(&mytime));
24 #endif
25         return sys_timestring;
26 }
27
28 #if defined(__linux__) || defined(MACOSX)
29
30 #include <execinfo.h>
31 static void Sys_Backtrace(void)
32 {
33         void *tracebuf[64];
34         int n = backtrace(tracebuf, sizeof(tracebuf) / sizeof(*tracebuf));
35         char **trace = backtrace_symbols(tracebuf, n);
36         int i;
37         Con_Printf("Backtrace:\n");
38         for(i = 0; i < n; ++i)
39                 Con_Printf("%2d: %s\n", i, trace[i]);
40 }
41
42 #elif defined(WIN32)
43
44 // http://gcc.gnu.org/ml/java/2002-04/msg00331.html
45 int backtrace (void **__array, int __size)
46 {
47         register void *_ebp __asm__ ("ebp");
48         register void *_esp __asm__ ("esp");
49         unsigned int *rfp;
50         int i=0;
51         for (rfp = *(unsigned int**)_ebp; rfp && i < __size; rfp = *(unsigned int **)rfp)
52         {
53                 int diff = *rfp - (unsigned int)rfp;
54                 if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0)
55                         break;
56                 __array[i++] = (void*)(rfp[1]-4);
57         }
58         return i;
59 }
60
61 static void Sys_Backtrace(void)
62 {
63         void *tracebuf[64];
64         int n = backtrace(tracebuf, sizeof(tracebuf) / sizeof(*tracebuf));
65         char **trace = backtrace_symbols(tracebuf, n);
66         int i;
67         Con_Printf("Backtrace:\n");
68         for(i = 0; i < n; ++i)
69                 Con_Printf("%2d: %s\n", i, trace[i]);
70 }
71
72 #elif 0
73
74 #define _GNU_SOURCE
75 #include <dlfcn.h>
76 static qboolean Sys_PrintSymbol(void *addr)
77 {
78         Dl_info da;
79         if(dladdr(addr, &da))
80         {
81                 Con_Printf("%p: File %s Function %s Offset 0x%x\n", addr, da.dli_fname ? da.dli_fname : "(unknown)", da.dli_sname ? da.dli_sname : "(unknown)", (unsigned int)(addr - da.dli_saddr));
82                 if(da.dli_sname && (!strcmp(da.dli_sname, "main") || !strcmp(da.dli_sname, "Sys_Backtrace")))
83                         return true;
84         }
85         return false;
86 }
87 void Sys_Backtrace(void) // this function must not be static so gcc can export it
88 {
89         // this way of backtracing may potentially crash, but seems reliable enough for me
90         void *a[1];
91         int i;
92         a[0] = 0;
93         Con_Printf("Backtrace:\n");
94         if(Sys_PrintSymbol((void *) Sys_Backtrace)) // this detects whether dladdr works, and is also nice output
95                 for(i = 1; i < 2047; ++i)
96                         if(Sys_PrintSymbol(a[i]))
97                                 return;
98 }
99
100 #else
101
102 void Sys_Backtrace()
103 {
104 }
105
106 #endif
107
108 extern qboolean host_shuttingdown;
109 void Sys_Quit (int returnvalue)
110 {
111         if (COM_CheckParm("-profilegameonly"))
112                 Sys_AllowProfiling(false);
113         host_shuttingdown = true;
114         Host_Shutdown();
115         if(returnvalue > 1)
116                 Sys_Backtrace();
117         exit(returnvalue);
118 }
119
120 #if defined(__linux__) || defined(__FreeBSD__)
121 #ifdef __cplusplus
122 extern "C"
123 #endif
124 int moncontrol(int);
125 #endif
126
127 void Sys_AllowProfiling(qboolean enable)
128 {
129 #if defined(__linux__) || defined(__FreeBSD__)
130         moncontrol(enable);
131 #endif
132 }
133
134
135 /*
136 ===============================================================================
137
138 DLL MANAGEMENT
139
140 ===============================================================================
141 */
142
143 qboolean Sys_LoadLibrary (const char** dllnames, dllhandle_t* handle, const dllfunction_t *fcts)
144 {
145 #ifdef SUPPORTDLL
146         const dllfunction_t *func;
147         dllhandle_t dllhandle = 0;
148         unsigned int i;
149
150         if (handle == NULL)
151                 return false;
152
153 #ifndef WIN32
154 #ifdef PREFER_PRELOAD
155         dllhandle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
156         if(dllhandle)
157         {
158                 for (func = fcts; func && func->name != NULL; func++)
159                         if (!(*func->funcvariable = (void *) Sys_GetProcAddress (dllhandle, func->name)))
160                         {
161                                 dlclose(dllhandle);
162                                 goto notfound;
163                         }
164                 Con_DPrintf ("All of %s's functions were already linked in! Not loading dynamically...\n", dllnames[0]);
165                 *handle = dllhandle;
166                 return true;
167         }
168 notfound:
169 #endif
170 #endif
171
172         // Initializations
173         for (func = fcts; func && func->name != NULL; func++)
174                 *func->funcvariable = NULL;
175
176         // Try every possible name
177         Con_DPrintf ("Trying to load library...");
178         for (i = 0; dllnames[i] != NULL; i++)
179         {
180                 Con_DPrintf (" \"%s\"", dllnames[i]);
181 #ifdef WIN32
182                 dllhandle = LoadLibrary (dllnames[i]);
183 #else
184                 dllhandle = dlopen (dllnames[i], RTLD_LAZY | RTLD_GLOBAL);
185 #endif
186                 if (dllhandle)
187                         break;
188         }
189
190         // see if the names can be loaded relative to the executable path
191         // (this is for Mac OSX which does not check next to the executable)
192         if (!dllhandle && strrchr(com_argv[0], '/'))
193         {
194                 char path[MAX_OSPATH];
195                 strlcpy(path, com_argv[0], sizeof(path));
196                 strrchr(path, '/')[1] = 0;
197                 for (i = 0; dllnames[i] != NULL; i++)
198                 {
199                         char temp[MAX_OSPATH];
200                         strlcpy(temp, path, sizeof(temp));
201                         strlcat(temp, dllnames[i], sizeof(temp));
202                         Con_DPrintf (" \"%s\"", temp);
203 #ifdef WIN32
204                         dllhandle = LoadLibrary (temp);
205 #else
206                         dllhandle = dlopen (temp, RTLD_LAZY | RTLD_GLOBAL);
207 #endif
208                         if (dllhandle)
209                                 break;
210                 }
211         }
212
213         // No DLL found
214         if (! dllhandle)
215         {
216                 Con_DPrintf(" - failed.\n");
217                 return false;
218         }
219
220         Con_DPrintf(" - loaded.\n");
221
222         // Get the function adresses
223         for (func = fcts; func && func->name != NULL; func++)
224                 if (!(*func->funcvariable = (void *) Sys_GetProcAddress (dllhandle, func->name)))
225                 {
226                         Con_DPrintf ("Missing function \"%s\" - broken library!\n", func->name);
227                         Sys_UnloadLibrary (&dllhandle);
228                         return false;
229                 }
230
231         *handle = dllhandle;
232         return true;
233 #else
234         return false;
235 #endif
236 }
237
238 void Sys_UnloadLibrary (dllhandle_t* handle)
239 {
240 #ifdef SUPPORTDLL
241         if (handle == NULL || *handle == NULL)
242                 return;
243
244 #ifdef WIN32
245         FreeLibrary (*handle);
246 #else
247         dlclose (*handle);
248 #endif
249
250         *handle = NULL;
251 #endif
252 }
253
254 void* Sys_GetProcAddress (dllhandle_t handle, const char* name)
255 {
256 #ifdef SUPPORTDLL
257 #ifdef WIN32
258         return (void *)GetProcAddress (handle, name);
259 #else
260         return (void *)dlsym (handle, name);
261 #endif
262 #else
263         return NULL;
264 #endif
265 }
266