Hello all, The current Parrot interface to dlopen on UNIX systems is incomplete; it does not allow passing control parameters, one of which is needed for the correct operation of Blizkost (the Perl 5 to Parrot adaptor which I am working on for Rakudo *). I beleive the best place to add this functionality is in Parrot itself, as this avoids any duplication of the configuration logic required to bind to the dynamic linker portably. This patch implements a portable and extensible interface for Parrot extensions to pass data to the Parrot dynamic linking mechanism. Is this acceptable for Parrot?
This is my first Parrot patch and so I especially welcome all feedback, especially as regarding the PIR-level interface. Thank you. -Stefan (sorear on #parrot)
Index: src/ops/core.ops
===================================================================
--- src/ops/core.ops (revision 45050)
+++ src/ops/core.ops (working copy)
@@ -1209,8 +1209,22 @@
=item B<loadlib>(out PMC, in STR)
-Load a dynamic link library named $2 and store it in $1.
+=item B<loadlib>(out PMC, in STR, in PMC)
+Load a dynamic link library named $2 and store it in $1. $3, if
+provided, controls library loading and initialization; currently,
+we expect a bitmask accessible as an integer. Bit definitions are
+accessible from PASM if F<dlopenflags.pasm> is included. The current
+bits are:
+
+=over 4
+
+=item PARROT_DLOPEN_GLOBAL
+
+Make any symbols in the library accessible to other libraries loaded.
+
+=back
+
=item B<dlfunc>(out PMC, invar PMC, in STR, in STR)
Look up symbol $3 in library $2 with signature $4, and put the
@@ -1250,6 +1264,10 @@
$1 = Parrot_load_lib(interp, $2, NULL);
}
+inline op loadlib(out PMC, in STR, in PMC) {
+ $1 = Parrot_load_lib(interp, $2, $3);
+}
+
op dlfunc(out PMC, invar PMC, in STR, in STR) {
char * const name = Parrot_str_to_cstring(interp, ($3));
void *dl_handle = NULL;
Index: src/ops/ops.num
===================================================================
--- src/ops/ops.num (revision 45050)
+++ src/ops/ops.num (working copy)
@@ -1271,3 +1271,7 @@
find_name_p_sc 1247
find_sub_not_null_p_s 1248
find_sub_not_null_p_sc 1249
+loadlib_p_s_p 1250
+loadlib_p_sc_p 1251
+loadlib_p_s_pc 1252
+loadlib_p_sc_pc 1253
Index: src/dynext.c
===================================================================
--- src/dynext.c (revision 45050)
+++ src/dynext.c (working copy)
@@ -42,20 +42,23 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
-static void * dlopen_string(PARROT_INTERP, ARGIN(STRING *path))
+static void * dlopen_string(PARROT_INTERP,
+ Parrot_dlopen_flags flags,
+ ARGIN(STRING *path))
__attribute__nonnull__(1)
- __attribute__nonnull__(2);
+ __attribute__nonnull__(3);
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
static STRING * get_path(PARROT_INTERP,
ARGMOD_NULLOK(STRING *lib),
+ Parrot_dlopen_flags flags,
ARGOUT(void **handle),
ARGIN(STRING *wo_ext),
ARGIN_NULLOK(STRING *ext))
__attribute__nonnull__(1)
- __attribute__nonnull__(3)
__attribute__nonnull__(4)
+ __attribute__nonnull__(5)
FUNC_MODIFIES(*lib)
FUNC_MODIFIES(*handle);
@@ -218,9 +221,11 @@
/*
-=item C<static void * dlopen_string(PARROT_INTERP, STRING *path)>
+=item C<static void * dlopen_string(PARROT_INTERP, Parrot_dlopen_flags flags,
+STRING *path)>
-Call Parrot_dlopen with the Parrot String argument converted to C string.
+Call Parrot_dlopen with the Parrot String argument converted to C string. The
+flags argument will be converted into native form and used if applicable.
=cut
@@ -229,20 +234,20 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
static void *
-dlopen_string(PARROT_INTERP, ARGIN(STRING *path))
+dlopen_string(PARROT_INTERP, Parrot_dlopen_flags flags, ARGIN(STRING *path))
{
ASSERT_ARGS(dlopen_string)
char * const pathstr = Parrot_str_to_cstring(interp, path);
- void * handle = Parrot_dlopen(pathstr);
+ void * handle = Parrot_dlopen(pathstr, flags);
Parrot_str_free_cstring(pathstr);
return handle;
}
/*
-=item C<static STRING * get_path(PARROT_INTERP, STRING *lib, void **handle,
-STRING *wo_ext, STRING *ext)>
+=item C<static STRING * get_path(PARROT_INTERP, STRING *lib, Parrot_dlopen_flags
+flags, void **handle, STRING *wo_ext, STRING *ext)>
Return path and handle of a dynamic lib, setting lib_name to just the filestem
(i.e. without path or extension) as a freshly-allocated C string.
@@ -254,8 +259,9 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
static STRING *
-get_path(PARROT_INTERP, ARGMOD_NULLOK(STRING *lib), ARGOUT(void **handle),
- ARGIN(STRING *wo_ext), ARGIN_NULLOK(STRING *ext))
+get_path(PARROT_INTERP, ARGMOD_NULLOK(STRING *lib), Parrot_dlopen_flags flags,
+ ARGOUT(void **handle), ARGIN(STRING *wo_ext),
+ ARGIN_NULLOK(STRING *ext))
{
ASSERT_ARGS(get_path)
STRING *path, *full_name;
@@ -268,7 +274,7 @@
PARROT_LIB_DYN_EXTS);
if (lib == NULL) {
- *handle = Parrot_dlopen((char *)NULL);
+ *handle = Parrot_dlopen((char *)NULL, flags);
if (*handle) {
return string_from_literal(interp, "");
}
@@ -292,7 +298,7 @@
path = Parrot_locate_runtime_file_str(interp, full_name,
PARROT_RUNTIME_FT_DYNEXT);
if (path) {
- *handle = dlopen_string(interp, path);
+ *handle = dlopen_string(interp, flags, path);
if (*handle) {
return path;
}
@@ -307,7 +313,7 @@
* File with extension and prefix was not found,
* so try file.extension w/o prefix
*/
- *handle = dlopen_string(interp, full_name);
+ *handle = dlopen_string(interp, flags, full_name);
if (*handle) {
return full_name;
}
@@ -322,7 +328,7 @@
full_name = Parrot_locate_runtime_file_str(interp, lib,
PARROT_RUNTIME_FT_DYNEXT);
if (full_name) {
- *handle = dlopen_string(interp, full_name);
+ *handle = dlopen_string(interp, flags, full_name);
if (*handle) {
return full_name;
}
@@ -333,7 +339,7 @@
*/
#ifdef WIN32
if (!STRING_IS_EMPTY(lib) && memcmp(lib->strstart, "lib", 3) == 0) {
- *handle = Parrot_dlopen((char *)lib->strstart + 3);
+ *handle = Parrot_dlopen((char *)lib->strstart + 3, 0);
if (*handle) {
path = Parrot_str_substr(interp, lib, 3, lib->strlen - 3, NULL, 0);
return path;
@@ -347,7 +353,7 @@
path = Parrot_str_append(interp, CONST_STRING(interp, "cyg"),
Parrot_str_substr(interp, lib, 3, lib->strlen - 3, NULL, 0));
- *handle = dlopen_string(interp, path);
+ *handle = dlopen_string(interp, flags, path);
if (*handle)
return path;
@@ -356,7 +362,7 @@
/* And after-finally, let the OS use his own search */
if (!STRING_IS_EMPTY(lib)) {
- *handle = dlopen_string(interp, lib);
+ *handle = dlopen_string(interp, flags, lib);
if (*handle)
return lib;
}
@@ -606,11 +612,13 @@
/*
-=item C<PMC * Parrot_load_lib(PARROT_INTERP, STRING *lib, PMC *initializer)>
+=item C<PMC * Parrot_load_lib(PARROT_INTERP, STRING *lib, PMC *parameters)>
Dynamic library loader.
-C<initializer> is currently unused.
+C<parameters>, if not null, points to something which controls library
+loading and initialization. Currently just its integer value is used,
+interpreted as C<PDLOpen_flags>.
Calls C<Parrot_lib_%s_load()> which performs the registration of the lib
once C<Parrot_lib_%s_init()> gets called (if exists) to perform thread
@@ -633,7 +641,7 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC *
-Parrot_load_lib(PARROT_INTERP, ARGIN_NULLOK(STRING *lib), SHIM(PMC *initializer))
+Parrot_load_lib(PARROT_INTERP, ARGIN_NULLOK(STRING *lib), PMC *parameters)
{
ASSERT_ARGS(Parrot_load_lib)
void *handle;
@@ -641,6 +649,7 @@
STRING *path;
STRING *lib_name, *wo_ext, *ext; /* library stem without path
* or extension. */
+ Parrot_dlopen_flags flags;
/* Find the pure library name, without path or extension. */
/*
* TODO move the class_count_mutex here
@@ -662,7 +671,12 @@
return lib_pmc;
}
- path = get_path(interp, lib, &handle, wo_ext, ext);
+ flags = 0;
+ if (!PMC_IS_NULL(parameters)) {
+ flags = VTABLE_get_integer(interp, parameters);
+ }
+
+ path = get_path(interp, lib, flags, &handle, wo_ext, ext);
if (!path || !handle) {
/*
* XXX Parrot_ex_throw_from_c_args? return PMCNULL?
Index: include/parrot/dynext.h
===================================================================
--- include/parrot/dynext.h (revision 45050)
+++ include/parrot/dynext.h (working copy)
@@ -41,7 +41,7 @@
PARROT_CANNOT_RETURN_NULL
PMC * Parrot_load_lib(PARROT_INTERP,
ARGIN_NULLOK(STRING *lib),
- SHIM(PMC *initializer))
+ PMC *initializer)
__attribute__nonnull__(1);
#define ASSERT_ARGS_Parrot_clone_lib_into __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
Index: MANIFEST.generated
===================================================================
--- MANIFEST.generated (revision 45050)
+++ MANIFEST.generated (working copy)
@@ -118,6 +118,7 @@
runtime/parrot/include/cclass.pasm [main]
runtime/parrot/include/config.fpmc []
runtime/parrot/include/datatypes.pasm [main]
+runtime/parrot/include/dlopenflags.pasm [main]
runtime/parrot/include/errors.pasm [main]
runtime/parrot/include/except_severity.pasm [main]
runtime/parrot/include/except_types.pasm [main]
Index: config/gen/makefiles/root.in
===================================================================
--- config/gen/makefiles/root.in (revision 45050)
+++ config/gen/makefiles/root.in (working copy)
@@ -209,6 +209,7 @@
runtime/parrot/include/stdio.pasm \
runtime/parrot/include/socket.pasm \
runtime/parrot/include/libpaths.pasm \
+ runtime/parrot/include/dlopenflags.pasm \
runtime/parrot/include/longopt.pasm \
runtime/parrot/include/packfile_segments.pasm \
runtime/parrot/include/packfile_constants.pasm \
@@ -1088,6 +1089,9 @@
runtime/parrot/include/libpaths.pasm : $(INC_DIR)/library.h $(H2INC)
$(PERL) $(H2INC) $(INC_DIR)/library.h $@
+runtime/parrot/include/dlopenflags.pasm : $(INC_DIR)/platform_interface.h $(H2INC)
+ $(PERL) $(H2INC) $(INC_DIR)/platform_interface.h $@
+
runtime/parrot/include/datatypes.pasm : $(INC_DIR)/datatypes.h $(H2INC)
$(PERL) $(H2INC) $(INC_DIR)/datatypes.h $@
Index: config/gen/platform/win32/dl.c
===================================================================
--- config/gen/platform/win32/dl.c (revision 45050)
+++ config/gen/platform/win32/dl.c (working copy)
@@ -23,7 +23,8 @@
/*
-=item C<void * Parrot_dlopen(const char *filename)>
+=item C<void * Parrot_dlopen(const char *filename, SHIM(Parrot_dlopen_flags
+flags))>
Opens a dynamic library, and returns a system handle to that library.
Returns Parrot_dlerror() on failure.
@@ -33,7 +34,7 @@
*/
void *
-Parrot_dlopen(const char *filename)
+Parrot_dlopen(const char *filename, SHIM(Parrot_dlopen_flags flags))
{
return LoadLibrary(filename);
}
Index: config/gen/platform/ansi/dl.c
===================================================================
--- config/gen/platform/ansi/dl.c (revision 45050)
+++ config/gen/platform/ansi/dl.c (working copy)
@@ -23,14 +23,15 @@
/*
-=item C<void * Parrot_dlopen(const char *filename)>
+=item C<void * Parrot_dlopen(const char *filename, SHIM(Parrot_dlopen_flags
+flags)>
=cut
*/
void *
-Parrot_dlopen(const char *filename)
+Parrot_dlopen(const char *filename, SHIM(Parrot_dlopen_flags flags))
{
Parrot_warn(NULL, PARROT_WARNINGS_PLATFORM_FLAG, "Parrot_dlopen not implemented");
return NULL;
Index: config/gen/platform/platform_interface.h
===================================================================
--- config/gen/platform/platform_interface.h (revision 45050)
+++ config/gen/platform/platform_interface.h (working copy)
@@ -73,7 +73,25 @@
** Dynamic Loading:
*/
-void *Parrot_dlopen(const char *filename);
+/*
+ * We need to at least provide access to global loading, because two kinds
+ * of extension need it. First, if you are providing a C-level API to your
+ * extension, it needs to be possible for other extensions to resolve your
+ * symbols. Second, if your extension loads a library which itself has
+ * extensions, and those extensions are not linked against the main library
+ * but use symbols from it, this flag is needed to prevent dynamic linker
+ * errors - notably, this is the case with Perl 5.
+ *
+ * All flags will be ignored on platforms for which they are inapplicable.
+ */
+
+/* &gen_from_enum(dlopenflags.pasm) */
+typedef enum Parrot_dlopen_enum {
+ Parrot_dlopen_global_FLAG = 0x01,
+} Parrot_dlopen_flags;
+/* &end_gen */
+
+void *Parrot_dlopen(const char *filename, Parrot_dlopen_flags flags);
const char *Parrot_dlerror(void);
void *Parrot_dlsym(void *handle, const char *symbol);
int Parrot_dlclose(void *handle);
Index: config/gen/platform/generic/dl.c
===================================================================
--- config/gen/platform/generic/dl.c (revision 45050)
+++ config/gen/platform/generic/dl.c (working copy)
@@ -29,17 +29,18 @@
/*
-=item C<void * Parrot_dlopen(const char *filename)>
+=item C<void * Parrot_dlopen(const char *filename, Parrot_dlopen_flags flags)>
=cut
*/
void *
-Parrot_dlopen(const char *filename)
+Parrot_dlopen(const char *filename, Parrot_dlopen_flags flags)
{
#ifdef PARROT_HAS_HEADER_DLFCN
- return dlopen(filename, PARROT_DLOPEN_FLAGS);
+ return dlopen(filename, PARROT_DLOPEN_FLAGS
+ | ((flags & Parrot_dlopen_global_FLAG) ? RTLD_GLOBAL : 0));
#else
return 0;
#endif
signature.asc
Description: Digital signature
_______________________________________________ http://lists.parrot.org/mailman/listinfo/parrot-dev
