source: git/libpolys/polys/mod_raw.cc @ 6909cfb

spielwiese
Last change on this file since 6909cfb was c899161, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Fixed dynamic loading under Mac OS X
  • Property mode set to 100644
File size: 9.2 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5 * ABSTRACT: machine depend code for dynamic modules
6 *
7 * Provides: dynl_check_opened()
8 *           dynl_open()
9 *           dynl_sym()
10 *           dynl_error()
11 *           dynl_close()
12*/
13
14#include <stdio.h>
15#include <string.h>
16#include <ctype.h>
17#include <sys/stat.h>
18
19
20#include "config.h"
21#include <misc/auxiliary.h>
22
23#include <omalloc/omalloc.h>
24
25#include <reporter/reporter.h>
26
27#include <findexec/feResource.h>
28
29#include "mod_raw.h"
30
31#ifdef HAVE_STATIC
32#undef HAVE_DL
33#endif
34/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
35#define BYTES_TO_CHECK 7
36
37#define SI_BUILTIN_LIBSTR(name) (char*) #name ".so",
38
39char* si_bultin_libs[]={ SI_FOREACH_BUILTIN(SI_BUILTIN_LIBSTR)  NULL };
40
41#undef SI_BUILTIN_LIBSTR
42
43lib_types type_of_LIB(char *newlib, char *libnamebuf)
44{
45  const unsigned char mach_o[]={0xfe,0xed,0xfa,0xce,0};
46  const unsigned char mach_O[]={0xce,0xfa,0xed,0xfe,0};
47   
48  const unsigned char mach_o64[]={0xfe,0xed,0xfa,0xcf,0};
49  const unsigned char mach_O64[]={0xcf,0xfa,0xed,0xfe,0};
50   
51  int i=0;
52  while(si_bultin_libs[i]!=NULL)
53  {
54    if (strcmp(newlib,si_bultin_libs[i])==0)
55    {
56      if(libnamebuf!=NULL) strcpy(libnamebuf,newlib);
57      return LT_BUILTIN;
58    }
59    i++;
60  }
61  char        buf[BYTES_TO_CHECK+1];        /* one extra for terminating '\0' */
62  struct stat sb;
63  int nbytes = 0;
64  int ret;
65  lib_types LT=LT_NONE;
66
67  FILE * fp = feFopen( newlib, "r", libnamebuf, FALSE );
68  ret = stat(libnamebuf, &sb);
69
70  if (fp==NULL)
71  {
72    return LT_NOTFOUND;
73  }
74  if((sb.st_mode & S_IFMT) != S_IFREG)
75  {
76    goto lib_type_end;
77  }
78  if ((nbytes = fread((char *)buf, sizeof(char), BYTES_TO_CHECK, fp)) == -1)
79  {
80    goto lib_type_end;
81    /*NOTREACHED*/
82  }
83  if (nbytes == 0)
84    goto lib_type_end;
85  else
86  {
87    buf[nbytes++] = '\0';        /* null-terminate it */
88  }
89  if( (strncmp(buf, "\177ELF", 4)==0)) /* generic ELF */
90  {
91    LT = LT_ELF;
92    //omFree(newlib);
93    //newlib = omStrDup(libnamebuf);
94    goto lib_type_end;
95  }
96
97  if( (strncmp(buf, (const char *)mach_o, 4)==0) || (strncmp(buf, (const char *)mach_O, 4)==0)) /* generic Mach-O module */
98  {
99    LT = LT_MACH_O;
100    //omFree(newlib);
101    //newlib = omStrDup(libnamebuf);
102    goto lib_type_end;
103  }
104
105  if( (strncmp(buf, (const char *)mach_o64, 4)==0) || (strncmp(buf, (const char *)mach_O64, 4)==0)) /* generic Mach-O 64-bit module */
106  {
107    LT = LT_MACH_O;
108    //omFree(newlib);
109    //newlib = omStrDup(libnamebuf);
110    goto lib_type_end;
111  }
112
113
114  if( (strncmp(buf, "\02\020\01\016\05\022@", 7)==0))
115  {
116    LT = LT_HPUX;
117    //omFree(newlib);
118    //newlib = omStrDup(libnamebuf);
119    goto lib_type_end;
120  }
121  if(isprint(buf[0]) || buf[0]=='\n')
122  { LT = LT_SINGULAR; goto lib_type_end; }
123
124  lib_type_end:
125  fclose(fp);
126  return LT;
127}
128/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
129#if defined(HAVE_DL)
130
131/*****************************************************************************
132 *
133 * General section
134 * These are just wrappers around the repsective dynl_* calls
135 * which look for the binary in the bin_dir of Singular and ommit warnings if
136 * somethings goes wrong
137 *
138 *****************************************************************************/
139static BOOLEAN warn_handle = FALSE;
140static BOOLEAN warn_proc = FALSE;
141#ifndef DL_TAIL
142#ifdef NDEBUG
143#define DL_TAIL ".so"
144#else
145#define DL_TAIL "_g.so"
146#endif
147#endif
148
149void* dynl_open_binary_warn(const char* binary_name, const char* msg)
150{
151  void* handle = NULL;
152  const char* bin_dir = feGetResource('b');
153  if (bin_dir != NULL)
154  {
155    const int binary_name_so_length = 3 + strlen(DL_TAIL) + strlen(binary_name) + strlen(DIR_SEPP) + strlen(bin_dir);
156    char* binary_name_so = (char *)omAlloc0( binary_name_so_length * sizeof(char) );
157    snprintf(binary_name_so, binary_name_so_length, "%s%s%s%s", bin_dir, DIR_SEPP, binary_name, DL_TAIL);
158    handle = dynl_open(binary_name_so);
159    omFreeSize((ADDRESS)binary_name_so, binary_name_so_length * sizeof(char) );
160  }
161
162  if (handle == NULL )
163  {
164    const int binary_name_so_length = 3 + strlen(DL_TAIL) + strlen(binary_name);
165    char* binary_name_so = (char *)omAlloc0( binary_name_so_length * sizeof(char) );
166    snprintf(binary_name_so, binary_name_so_length, "%s%s", binary_name, DL_TAIL);
167
168    char* pp = (char *)omAlloc0( MAXPATHLEN * sizeof(char) );
169    lib_types type = type_of_LIB( binary_name_so, pp );
170    omFreeSize((ADDRESS)binary_name_so, binary_name_so_length * sizeof(char) );
171
172    if( type != LT_SINGULAR && type != LT_NONE && type != LT_NOTFOUND )
173      handle = dynl_open(pp);
174
175    omFreeSize((ADDRESS)pp, MAXPATHLEN * sizeof(char) );
176  }
177
178  if (handle == NULL && ! warn_handle)
179  {
180      Warn("Could not find dynamic library: %s%s", binary_name, DL_TAIL);
181      Warn("Error message from system: %s", dynl_error());
182      if (msg != NULL) Warn("%s", msg);
183      Warn("See the INSTALL section in the Singular manual for details.");
184      warn_handle = TRUE;
185  }
186
187  return  handle;
188}
189
190void* dynl_sym_warn(void* handle, const char* proc, const char* msg)
191{
192  void *proc_ptr = NULL;
193  if (handle != NULL)
194  {
195    proc_ptr = dynl_sym(handle, proc);
196    if (proc_ptr == NULL && ! warn_proc)
197    {
198      Warn("Could load a procedure from a dynamic library");
199      Warn("Error message from system: %s", dynl_error());
200      if (msg != NULL) Warn("%s", msg);
201      Warn("See the INSTALL section in the Singular manual for details.");
202      warn_proc = TRUE;
203    }
204  }
205  return proc_ptr;
206}
207
208#ifdef __cplusplus
209extern "C" {
210#endif
211
212/*****************************************************************************
213 * SECTION generic ELF: ix86-linux / alpha-linux / IA64-linux /x86_64_Linux  *
214 *                      SunOS-5 / IRIX-6 / ppcMac-Darwin / FreeeBSD          *
215 *****************************************************************************/
216// relying on gcc to define __ELF__, check with cpp -dM /dev/null
217// Mac OsX is an ELF system, but does not define __ELF__
218// Solaris is an ELF system, but does not define __ELF__
219#if defined(__ELF__)
220#define HAVE_ELF_SYSTEM
221#endif
222
223#if defined(ppcMac_darwin)
224#define HAVE_ELF_SYSTEM
225#endif
226
227#if defined(ix86Mac_darwin)
228#define HAVE_ELF_SYSTEM
229#endif
230
231#if defined(x86_64Mac_darwin)
232#define HAVE_ELF_SYSTEM
233#endif
234
235#if (defined(__APPLE__) && defined(__MACH__)) && (!defined(HAVE_ELF_SYSTEM))
236#define HAVE_ELF_SYSTEM
237#endif
238
239#if defined(SunOS_5)
240#define HAVE_ELF_SYSTEM
241#endif
242
243#if defined(HAVE_ELF_SYSTEM)
244#include <dlfcn.h>
245#define DL_IMPLEMENTED
246
247static void* kernel_handle = NULL;
248int dynl_check_opened(
249  char *filename    /* I: filename to check */
250  )
251{
252  return dlopen(filename,RTLD_NOW|RTLD_NOLOAD) != NULL;
253}
254
255void *dynl_open(
256  char *filename    /* I: filename to load */
257  )
258{
259// glibc 2.2:
260  if ((filename==NULL) || (dlopen(filename,RTLD_NOW|RTLD_NOLOAD)==NULL))
261    return(dlopen(filename, RTLD_NOW|RTLD_GLOBAL));
262  else
263    Werror("module %s already loaded",filename);
264  return NULL;
265// alternative
266//    return(dlopen(filename, RTLD_NOW|RTLD_GLOBAL));
267}
268
269void *dynl_sym(void *handle, const char *symbol)
270{
271  if (handle == DYNL_KERNEL_HANDLE)
272  {
273    if (kernel_handle == NULL)
274      kernel_handle = dynl_open(NULL);
275    handle = kernel_handle;
276  }
277  return(dlsym(handle, symbol));
278}
279
280int dynl_close (void *handle)
281{
282  return(dlclose (handle));
283}
284
285const char *dynl_error()
286{
287  return(dlerror());
288}
289#endif /* ELF_SYSTEM */
290
291/*****************************************************************************
292 * SECTION HPUX-9/10                                                         *
293 *****************************************************************************/
294#if defined(HPUX_9) || defined(HPUX_10)
295#define DL_IMPLEMENTED
296#include <dl.h>
297
298typedef char *((*func_ptr) ());
299
300int dynl_check_opened(    /* NOTE: untested */
301  char *filename    /* I: filename to check */
302  )
303{
304  struct shl_descriptor *desc;
305  for (int idx = 0; shl_get(idx, &desc) != -1; ++idx)
306  {
307    if (strcmp(filename, desc->filename) == 0) return TRUE;
308  }
309  return FALSE;
310}
311
312void *dynl_open(char *filename)
313{
314  shl_t           handle = shl_load(filename, BIND_DEFERRED, 0);
315
316  return ((void *) handle);
317}
318
319void *dynl_sym(void *handle, const char *symbol)
320{
321  func_ptr        f;
322
323  if (handle == DYNL_KERNEL_HANDLE)
324    handle = PROG_HANDLE;
325
326  if (shl_findsym((shl_t *) & handle, symbol, TYPE_PROCEDURE, &f) == -1)
327  {
328    if (shl_findsym((shl_t *) & handle, symbol, TYPE_UNDEFINED, &f) == -1)
329    {
330      f = (func_ptr) NULL;
331    }
332  }
333  return ((void *)f);
334}
335
336int dynl_close (void *handle)
337{
338  shl_unload((shl_t) handle);
339  return(0);
340}
341
342const char *dynl_error()
343{
344  static char errmsg[] = "shl_load failed";
345
346  return errmsg;
347}
348#endif /* HPUX_9  or HPUX_10 */
349
350/*****************************************************************************
351 * SECTION generic: dynamic madules not available
352 *****************************************************************************/
353#ifndef DL_IMPLEMENTED
354
355int dynl_check_opened(char *filename)
356{
357  return FALSE;
358}
359
360void *dynl_open(char *filename)
361{
362  return(NULL);
363}
364
365void *dynl_sym(void *handle, const char *symbol)
366{
367  return(NULL);
368}
369
370int dynl_close (void *handle)
371{
372  return(0);
373}
374
375const char *dynl_error()
376{
377  static char errmsg[] = "support for dynamic loading not implemented";
378  return errmsg;
379}
380#endif
381
382#ifdef __cplusplus
383}
384#endif
385
386#endif /* HAVE_DL */
Note: See TracBrowser for help on using the repository browser.