This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Revert "$XS::APItest::VERSION = '0.34'"
[perl5.git] / ext / DynaLoader / dl_dlopen.xs
CommitLineData
a0d0e21e
LW
1/* dl_dlopen.xs
2 *
3 * Platform: SunOS/Solaris, possibly others which use dlopen.
0536e0eb 4 * Author: Paul Marquess (Paul.Marquess@btinternet.com)
a0d0e21e
LW
5 * Created: 10th July 1994
6 *
7 * Modified:
abb9e9dc
GS
8 * 15th July 1994 - Added code to explicitly save any error messages.
9 * 3rd August 1994 - Upgraded to v3 spec.
10 * 9th August 1994 - Changed to use IV
11 * 10th August 1994 - Tim Bunce: Added RTLD_LAZY, switchable debugging,
12 * basic FreeBSD support, removed ClearError
b7b1e41b 13 * 29th February 2000 - Alan Burlison: Added functionality to close dlopen'd
abb9e9dc 14 * files when the interpreter exits
a0d0e21e
LW
15 *
16 */
17
18/* Porting notes:
19
20
21 Definition of Sunos dynamic Linking functions
22 =============================================
23 In order to make this implementation easier to understand here is a
24 quick definition of the SunOS Dynamic Linking functions which are
25 used here.
26
27 dlopen
28 ------
29 void *
30 dlopen(path, mode)
31 char * path;
32 int mode;
33
34 This function takes the name of a dynamic object file and returns
35 a descriptor which can be used by dlsym later. It returns NULL on
36 error.
37
38 The mode parameter must be set to 1 for Solaris 1 and to
8e07c86e 39 RTLD_LAZY (==2) on Solaris 2.
a0d0e21e
LW
40
41
abb9e9dc
GS
42 dlclose
43 -------
44 int
45 dlclose(handle)
46 void * handle;
47
48 This function takes the handle returned by a previous invocation of
49 dlopen and closes the associated dynamic object file. It returns zero
50 on success, and non-zero on failure.
51
52
a0d0e21e
LW
53 dlsym
54 ------
55 void *
56 dlsym(handle, symbol)
57 void * handle;
58 char * symbol;
59
60 Takes the handle returned from dlopen and the name of a symbol to
61 get the address of. If the symbol was found a pointer is
62 returned. It returns NULL on error. If DL_PREPEND_UNDERSCORE is
63 defined an underscore will be added to the start of symbol. This
64 is required on some platforms (freebsd).
65
66 dlerror
67 ------
68 char * dlerror()
69
70 Returns a null-terminated string which describes the last error
71 that occurred with either dlopen or dlsym. After each call to
72 dlerror the error message will be reset to a null pointer. The
abb9e9dc 73 SaveError function is used to save the error as soon as it happens.
a0d0e21e
LW
74
75
76 Return Types
77 ============
78 In this implementation the two functions, dl_load_file &
79 dl_find_symbol, return void *. This is because the underlying SunOS
80 dynamic linker calls also return void *. This is not necessarily
81 the case for all architectures. For example, some implementation
82 will want to return a char * for dl_load_file.
83
84 If void * is not appropriate for your architecture, you will have to
85 change the void * to whatever you require. If you are not certain of
86 how Perl handles C data types, I suggest you start by consulting
87 Dean Roerich's Perl 5 API document. Also, have a look in the typemap
88 file (in the ext directory) for a fairly comprehensive list of types
89 that are already supported. If you are completely stuck, I suggest you
13934ef4 90 post a message to perl5-porters, comp.lang.perl.misc or if you are really
a0d0e21e
LW
91 desperate to me.
92
93 Remember when you are making any changes that the return value from
94 dl_load_file is used as a parameter in the dl_find_symbol
95 function. Also the return value from find_symbol is used as a parameter
96 to install_xsub.
97
98
99 Dealing with Error Messages
100 ============================
101 In order to make the handling of dynamic linking errors as generic as
102 possible you should store any error messages associated with your
103 implementation with the StoreError function.
104
105 In the case of SunOS the function dlerror returns the error message
106 associated with the last dynamic link error. As the SunOS dynamic
107 linker functions dlopen & dlsym both return NULL on error every call
108 to a SunOS dynamic link routine is coded like this
109
110 RETVAL = dlopen(filename, 1) ;
111 if (RETVAL == NULL)
112 SaveError("%s",dlerror()) ;
113
114 Note that SaveError() takes a printf format string. Use a "%s" as
42eb1a87 115 the first parameter if the error may contain any % characters.
a0d0e21e
LW
116
117*/
118
53ca1a61
NC
119#define PERL_NO_GET_CONTEXT
120
a0d0e21e
LW
121#include "EXTERN.h"
122#include "perl.h"
123#include "XSUB.h"
124
125#ifdef I_DLFCN
126#include <dlfcn.h> /* the dynamic linker include file for Sunos/Solaris */
127#else
128#include <nlist.h>
129#include <link.h>
130#endif
131
8e07c86e
AD
132#ifndef RTLD_LAZY
133# define RTLD_LAZY 1 /* Solaris 1 */
134#endif
135
a0d0e21e 136#ifndef HAS_DLERROR
5d94fbed
AD
137# ifdef __NetBSD__
138# define dlerror() strerror(errno)
139# else
140# define dlerror() "Unknown error - dlerror() not implemented"
141# endif
a0d0e21e
LW
142#endif
143
144
145#include "dlutils.c" /* SaveError() etc */
146
147
148static void
cea2e8a9 149dl_private_init(pTHX)
a0d0e21e 150{
cea2e8a9 151 (void)dl_generic_private_init(aTHX);
a0d0e21e
LW
152}
153
154MODULE = DynaLoader PACKAGE = DynaLoader
155
156BOOT:
cea2e8a9 157 (void)dl_private_init(aTHX);
a0d0e21e
LW
158
159
c6c619a9 160void
ff7f3c60
NIS
161dl_load_file(filename, flags=0)
162 char * filename
163 int flags
9d4ce9a5 164 PREINIT:
8e07c86e 165 int mode = RTLD_LAZY;
c6c619a9 166 void *handle;
9d4ce9a5
GS
167 CODE:
168{
169#if defined(DLOPEN_WONT_DO_RELATIVE_PATHS)
170 char pathbuf[PATH_MAX + 2];
171 if (*filename != '/' && strchr(filename, '/')) {
172 if (getcwd(pathbuf, PATH_MAX - strlen(filename))) {
173 strcat(pathbuf, "/");
174 strcat(pathbuf, filename);
175 filename = pathbuf;
176 }
177 }
178#endif
8e07c86e 179#ifdef RTLD_NOW
cdc73a10
JH
180 {
181 dMY_CXT;
182 if (dl_nonlazy)
183 mode = RTLD_NOW;
184 }
a0d0e21e 185#endif
ff7f3c60
NIS
186 if (flags & 0x01)
187#ifdef RTLD_GLOBAL
188 mode |= RTLD_GLOBAL;
189#else
cea2e8a9 190 Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename);
ff7f3c60 191#endif
bf49b057 192 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags));
c6c619a9
DM
193 handle = dlopen(filename, mode) ;
194 DLDEBUG(2,PerlIO_printf(Perl_debug_log, " libref=%lx\n", (unsigned long) handle));
a0d0e21e 195 ST(0) = sv_newmortal() ;
c6c619a9 196 if (handle == NULL)
cea2e8a9 197 SaveError(aTHX_ "%s",dlerror()) ;
a0d0e21e 198 else
c6c619a9 199 sv_setiv( ST(0), PTR2IV(handle));
9d4ce9a5 200}
a0d0e21e 201
abb9e9dc
GS
202
203int
204dl_unload_file(libref)
205 void * libref
206 CODE:
d2560b70 207 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_unload_file(%lx):\n", PTR2ul(libref)));
fa2bf5b6 208 RETVAL = (dlclose(libref) == 0 ? 1 : 0);
9c1391b6 209 if (!RETVAL)
fa2bf5b6 210 SaveError(aTHX_ "%s", dlerror()) ;
abb9e9dc
GS
211 DLDEBUG(2,PerlIO_printf(Perl_debug_log, " retval = %d\n", RETVAL));
212 OUTPUT:
213 RETVAL
214
215
c6c619a9 216void
a0d0e21e
LW
217dl_find_symbol(libhandle, symbolname)
218 void * libhandle
219 char * symbolname
c6c619a9
DM
220 PREINIT:
221 void *sym;
a0d0e21e
LW
222 CODE:
223#ifdef DLSYM_NEEDS_UNDERSCORE
7a3f2258 224 symbolname = Perl_form_nocontext("_%s", symbolname);
a0d0e21e 225#endif
bf49b057 226 DLDEBUG(2, PerlIO_printf(Perl_debug_log,
46fc3d4c 227 "dl_find_symbol(handle=%lx, symbol=%s)\n",
228 (unsigned long) libhandle, symbolname));
c6c619a9 229 sym = dlsym(libhandle, symbolname);
bf49b057 230 DLDEBUG(2, PerlIO_printf(Perl_debug_log,
c6c619a9 231 " symbolref = %lx\n", (unsigned long) sym));
a0d0e21e 232 ST(0) = sv_newmortal() ;
c6c619a9 233 if (sym == NULL)
cea2e8a9 234 SaveError(aTHX_ "%s",dlerror()) ;
a0d0e21e 235 else
c6c619a9 236 sv_setiv( ST(0), PTR2IV(sym));
a0d0e21e
LW
237
238
239void
240dl_undef_symbols()
c6c619a9 241 CODE:
a0d0e21e
LW
242
243
244
245# These functions should not need changing on any platform:
246
247void
248dl_install_xsub(perl_name, symref, filename="$Package")
249 char * perl_name
250 void * symref
d3f5e399 251 const char * filename
a0d0e21e 252 CODE:
8141890a
JH
253 DLDEBUG(2,PerlIO_printf(Perl_debug_log, "dl_install_xsub(name=%s, symref=%"UVxf")\n",
254 perl_name, PTR2UV(symref)));
77004dee
NC
255 ST(0) = sv_2mortal(newRV((SV*)newXS_flags(perl_name,
256 DPTR2FPTR(XSUBADDR_t, symref),
257 filename, NULL,
258 XS_DYNAMIC_FILENAME)));
a0d0e21e
LW
259
260
261char *
262dl_error()
263 CODE:
cdc73a10
JH
264 dMY_CXT;
265 RETVAL = dl_last_error ;
a0d0e21e
LW
266 OUTPUT:
267 RETVAL
268
8c472fc1
CB
269#if defined(USE_ITHREADS)
270
271void
272CLONE(...)
273 CODE:
274 MY_CXT_CLONE;
275
276 /* MY_CXT_CLONE just does a memcpy on the whole structure, so to avoid
277 * using Perl variables that belong to another thread, we create our
278 * own for this thread.
279 */
280 MY_CXT.x_dl_last_error = newSVpvn("", 0);
281
282#endif
283
a0d0e21e 284# end.