summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bytecomp/bytelink.ml2
-rw-r--r--bytecomp/dll.ml18
-rw-r--r--bytecomp/dll.mli12
-rw-r--r--byterun/dynlink.c6
-rw-r--r--byterun/osdeps.h7
-rw-r--r--byterun/unix.c9
-rw-r--r--byterun/win32.c10
-rw-r--r--debugger/dynlink.ml3
-rw-r--r--otherlibs/dynlink/dynlink.ml3
-rw-r--r--toplevel/topdirs.ml2
10 files changed, 49 insertions, 23 deletions
diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml
index 7d72038a7..b9aa3dd23 100644
--- a/bytecomp/bytelink.ml
+++ b/bytecomp/bytelink.ml
@@ -296,7 +296,7 @@ let link_bytecode tolink exec_name standalone =
(* Initialize the DLL machinery *)
Dll.init_compile !Clflags.no_std_include;
Dll.add_path !load_path;
- try Dll.open_dlls sharedobjs
+ try Dll.open_dlls Dll.For_checking sharedobjs
with Failure reason -> raise(Error(Cannot_open_dll reason))
end;
let output_fun = output_string outchan
diff --git a/bytecomp/dll.ml b/bytecomp/dll.ml
index aa79a173b..4463d5b98 100644
--- a/bytecomp/dll.ml
+++ b/bytecomp/dll.ml
@@ -16,8 +16,9 @@
type dll_handle
type dll_address
+type dll_mode = For_checking | For_execution
-external dll_open: string -> dll_handle = "caml_dynlink_open_lib"
+external dll_open: dll_mode -> string -> dll_handle = "caml_dynlink_open_lib"
external dll_close: dll_handle -> unit = "caml_dynlink_close_lib"
external dll_sym: dll_handle -> string -> dll_address
= "caml_dynlink_lookup_symbol"
@@ -52,7 +53,7 @@ let extract_dll_name file =
(* Open a list of DLLs, adding them to opened_dlls.
Raise [Failure msg] in case of error. *)
-let open_dll name =
+let open_dll mode name =
let name = name ^ Config.ext_dll in
let fullname =
try
@@ -62,13 +63,16 @@ let open_dll name =
else fullname
with Not_found -> name in
if not (List.mem fullname !names_of_opened_dlls) then begin
- let dll = dll_open fullname in
- names_of_opened_dlls := fullname :: !names_of_opened_dlls;
- opened_dlls := dll :: !opened_dlls
+ try
+ let dll = dll_open mode fullname in
+ names_of_opened_dlls := fullname :: !names_of_opened_dlls;
+ opened_dlls := dll :: !opened_dlls
+ with Failure msg ->
+ failwith (fullname ^ ": " ^ msg)
end
-let open_dlls names =
- List.iter open_dll names
+let open_dlls mode names =
+ List.iter (open_dll mode) names
(* Close all DLLs *)
diff --git a/bytecomp/dll.mli b/bytecomp/dll.mli
index 8eb81794d..4f57571de 100644
--- a/bytecomp/dll.mli
+++ b/bytecomp/dll.mli
@@ -17,9 +17,15 @@
(* Extract the name of a DLLs from its external name (xxx.so or -lxxx) *)
val extract_dll_name: string -> string
-(* Open a list of DLLs, adding them to opened_dlls.
- Raise [Failure msg] in case of error. *)
-val open_dlls: string list -> unit
+type dll_mode =
+ | For_checking (* will just check existence of symbols;
+ no need to do full symbol resolution *)
+ | For_execution (* will call functions from this DLL;
+ must resolve symbols completely *)
+
+(* Open a list of DLLs. First argument indicates whether to perform
+ full symbol resolution. Raise [Failure msg] in case of error. *)
+val open_dlls: dll_mode -> string list -> unit
(* Close all DLLs *)
val close_all_dlls: unit -> unit
diff --git a/byterun/dynlink.c b/byterun/dynlink.c
index 251206cc6..aea47d8f1 100644
--- a/byterun/dynlink.c
+++ b/byterun/dynlink.c
@@ -123,7 +123,7 @@ static void open_shared_lib(char * name)
realname = caml_search_dll_in_path(&caml_shared_libs_path, name);
caml_gc_message(0x100, "Loading shared library %s\n",
(uintnat) realname);
- handle = caml_dlopen(realname);
+ handle = caml_dlopen(realname, 1);
if (handle == NULL)
caml_fatal_error_arg2("Fatal error: cannot load shared library %s\n", name,
"Reason: %s\n", caml_dlerror());
@@ -194,12 +194,12 @@ void caml_build_primitive_table_builtin(void)
#define Handle_val(v) (*((void **) (v)))
-CAMLprim value caml_dynlink_open_lib(value filename)
+CAMLprim value caml_dynlink_open_lib(value mode, value filename)
{
void * handle;
value result;
- handle = caml_dlopen(String_val(filename));
+ handle = caml_dlopen(String_val(filename), Int_val(mode));
if (handle == NULL) caml_failwith(caml_dlerror());
result = caml_alloc_small(1, Abstract_tag);
Handle_val(result) = handle;
diff --git a/byterun/osdeps.h b/byterun/osdeps.h
index beddd9b77..2dababedf 100644
--- a/byterun/osdeps.h
+++ b/byterun/osdeps.h
@@ -36,8 +36,13 @@ CAMLextern char * caml_search_exe_in_path(char * name);
extern char * caml_search_dll_in_path(struct ext_table * path, char * name);
/* Open a shared library and return a handle on it.
+ If [for_execution] is true, perform full symbol resolution and
+ execute initialization code so that functions from the shared library
+ can be called. If [for_execution] is false, functions from this
+ shared library will not be called, but just checked for presence,
+ so symbol resolution can be skipped.
Return [NULL] on error. */
-extern void * caml_dlopen(char * libname);
+extern void * caml_dlopen(char * libname, int for_execution);
/* Close a shared library handle */
extern void caml_dlclose(void * handle);
diff --git a/byterun/unix.c b/byterun/unix.c
index 7bb986008..def4f152c 100644
--- a/byterun/unix.c
+++ b/byterun/unix.c
@@ -199,7 +199,7 @@ entry_t *caml_lookup_bundle(const char *name)
return current;
}
-void * caml_dlopen(char * libname)
+void * caml_dlopen(char * libname, int for_execution)
{
NSObjectFileImage image;
entry_t *bentry = caml_lookup_bundle(libname);
@@ -283,9 +283,12 @@ char * caml_dlerror(void)
#define RTLD_NODELETE 0
#endif
-void * caml_dlopen(char * libname)
+void * caml_dlopen(char * libname, int for_execution)
{
- return dlopen(libname, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+ return dlopen(libname,
+ for_execution
+ ? RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE
+ : RTLD_LAZY);
}
void caml_dlclose(void * handle)
diff --git a/byterun/win32.c b/byterun/win32.c
index 229a07d63..427093a1d 100644
--- a/byterun/win32.c
+++ b/byterun/win32.c
@@ -120,9 +120,15 @@ char * caml_search_dll_in_path(struct ext_table * path, char * name)
return res;
}
-void * caml_dlopen(char * libname)
+void * caml_dlopen(char * libname, int for_execution)
{
- return (void *) LoadLibrary(libname);
+ HMODULE m;
+ m = LoadLibraryEx(libname, NULL,
+ for_execution ? 0 : DONT_RESOLVE_DLL_REFERENCES);
+ /* LoadLibraryEx can fail under Win 95/98/ME in cases where LoadLibrary
+ would succeed. Just try again with LoadLibrary for good measure. */
+ if (m == NULL) m = LoadLibrary(libname);
+ return (void *) m;
}
void caml_dlclose(void * handle)
diff --git a/debugger/dynlink.ml b/debugger/dynlink.ml
index 068015f8c..6f4fe5af7 100644
--- a/debugger/dynlink.ml
+++ b/debugger/dynlink.ml
@@ -200,7 +200,8 @@ let loadfile file_name =
seek_in ic toc_pos;
let lib = (input_value ic : library) in
begin try
- Dll.open_dlls (List.map Dll.extract_dll_name lib.lib_dllibs)
+ Dll.open_dlls Dll.For_execution
+ (List.map Dll.extract_dll_name lib.lib_dllibs)
with Failure reason ->
raise(Error(Cannot_open_dll reason))
end;
diff --git a/otherlibs/dynlink/dynlink.ml b/otherlibs/dynlink/dynlink.ml
index 0cc849b71..6fb154bd7 100644
--- a/otherlibs/dynlink/dynlink.ml
+++ b/otherlibs/dynlink/dynlink.ml
@@ -198,7 +198,8 @@ let loadfile file_name =
seek_in ic toc_pos;
let lib = (input_value ic : library) in
begin try
- Dll.open_dlls (List.map Dll.extract_dll_name lib.lib_dllibs)
+ Dll.open_dlls Dll.For_execution
+ (List.map Dll.extract_dll_name lib.lib_dllibs)
with Failure reason ->
raise(Error(Cannot_open_dll reason))
end;
diff --git a/toplevel/topdirs.ml b/toplevel/topdirs.ml
index 5e8c73675..d8a776505 100644
--- a/toplevel/topdirs.ml
+++ b/toplevel/topdirs.ml
@@ -105,7 +105,7 @@ let load_file ppf name =
List.iter
(fun dllib ->
let name = Dll.extract_dll_name dllib in
- try Dll.open_dlls [name]
+ try Dll.open_dlls Dll.For_execution [name]
with Failure reason ->
fprintf ppf
"Cannot load required shared library %s.@.Reason: %s.@."