1 (**************************************************************************)
2 (* *)
3 (* OCaml *)
4 (* *)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
6 (* Mark Shinwell and Leo White, Jane Street Europe *)
7 (* *)
8 (* Copyright 1996 Institut National de Recherche en Informatique et *)
9 (* en Automatique. *)
10 (* Copyright 2017--2018 Jane Street Group LLC *)
11 (* *)
12 (* All rights reserved. This file is distributed under the terms of *)
13 (* the GNU Lesser General Public License version 2.1, with the *)
14 (* special exception on linking described in the file LICENSE. *)
15 (* *)
16 (**************************************************************************)
17
18 (** Dynamic loading of .cmo, .cma and .cmxs files. *)
19
20 [@@@ocaml.warning "+a-4-30-40-41-42"]
21
22 val is_native : bool
23 (** [true] if the program is native,
24 [false] if the program is bytecode. *)
25
26 (** {1 Dynamic loading of compiled files} *)
27
28 val loadfile : string -> unit
29 (** In bytecode: load the given bytecode object file ([.cmo] file) or
30 bytecode library file ([.cma] file), and link it with the running
31 program. In native code: load the given OCaml plugin file (usually
32 [.cmxs]), and link it with the running program.
33
34 All toplevel expressions in the loaded compilation units
35 are evaluated. No facilities are provided to
36 access value names defined by the unit. Therefore, the unit
37 must itself register its entry points with the main program (or a
38 previously-loaded library) e.g. by modifying tables of functions.
39
40 An exception will be raised if the given library defines toplevel
41 modules whose names clash with modules existing either in the main
42 program or a shared library previously loaded with [loadfile].
43 Modules from shared libraries previously loaded with
44 [loadfile_private] are not included in this restriction.
45
46 The compilation units loaded by this function are added to the
47 "allowed units" list (see {!set_allowed_units}). *)
48
49 val loadfile_private : string -> unit
50 (** Same as [loadfile], except that the compilation units just loaded
51 are hidden (cannot be referenced) from other modules dynamically
52 loaded afterwards.
53
54 An exception will be raised if the given library defines toplevel
55 modules whose names clash with modules existing in either the main
56 program or a shared library previously loaded with [loadfile].
57 Modules from shared libraries previously loaded with
58 [loadfile_private] are not included in this restriction.
59
60 An exception will also be raised if the given library defines
61 toplevel modules whose name matches that of an interface depended
62 on by a module existing in either the main program or a shared
63 library previously loaded with [loadfile]. This applies even if
64 such dependency is only a "module alias" dependency (i.e. just on
65 the name rather than the contents of the interface).
66
67 The compilation units loaded by this function are not added to the
68 "allowed units" list (see {!set_allowed_units}) since they cannot
69 be referenced from other compilation units. *)
70
71 val adapt_filename : string -> string
72 (** In bytecode, the identity function. In native code, replace the last
73 extension with [.cmxs]. *)
74
75 (** {1 Access control} *)
76
77 val set_allowed_units : string list -> unit
78 (** Set the list of compilation units that may be referenced from units that
79 are dynamically loaded in the future to be exactly the given value.
80
81 Initially all compilation units composing the program currently running
82 are available for reference from dynamically-linked units.
83 [set_allowed_units] can be used to restrict access to a subset of these
84 units, e.g. to the units that compose the API for
85 dynamically-linked code, and prevent access to all other units,
86 e.g. private, internal modules of the running program.
87
88 Note that {!loadfile} changes the allowed-units list. *)
89
90 val allow_only: string list -> unit
91 (** [allow_only units] sets the list of allowed units to be the intersection
92 of the existing allowed units and the given list of units. As such it
93 can never increase the set of allowed units. *)
94
95 val prohibit : string list -> unit
96 (** [prohibit units] prohibits dynamically-linked units from referencing
97 the units named in list [units] by removing such units from the allowed
98 units list. This can be used to prevent access to selected units,
99 e.g. private, internal modules of the running program. *)
100
101 val main_program_units : unit -> string list
102 (** Return the list of compilation units that form the main program (i.e.
103 are not dynamically linked). *)
104
105 val public_dynamically_loaded_units : unit -> string list
106 (** Return the list of compilation units that have been dynamically loaded via
107 [loadfile] (and not via [loadfile_private]). Note that compilation units
108 loaded dynamically cannot be unloaded. *)
109
110 val all_units : unit -> string list
111 (** Return the list of compilation units that form the main program together
112 with those that have been dynamically loaded via [loadfile] (and not via
113 [loadfile_private]). *)
114
115 val allow_unsafe_modules : bool -> unit
116 (** Govern whether unsafe object files are allowed to be
117 dynamically linked. A compilation unit is 'unsafe' if it contains
118 declarations of external functions, which can break type safety.
119 By default, dynamic linking of unsafe object files is
120 not allowed. In native code, this function does nothing; object files
121 with external functions are always allowed to be dynamically linked. *)
122
123 (** {1 Error reporting} *)
124
125 type linking_error = private
126 | Undefined_global of string
127 | Unavailable_primitive of string
128 | Uninitialized_global of string
129
130 type error = private
131 | Not_a_bytecode_file of string
132 | Inconsistent_import of string
133 | Unavailable_unit of string
134 | Unsafe_file
135 | Linking_error of string * linking_error
136 | Corrupted_interface of string
137 | Cannot_open_dynamic_library of exn
138 | Library's_module_initializers_failed of exn
139 | Inconsistent_implementation of string
140 | Module_already_loaded of string
141 | Private_library_cannot_implement_interface of string
142
143 exception Error of error
144 (** Errors in dynamic linking are reported by raising the [Error]
145 exception with a description of the error.
146 A common case is the dynamic library not being found on the system: this
147 is reported via [Cannot_open_dynamic_library] (the enclosed exception may
148 be platform-specific). *)
149
150 val error_message : error -> string
151 (** Convert an error description to a printable message. *)
152
153 (**/**)
154
155 val unsafe_get_global_value : bytecode_or_asm_symbol:string -> Obj.t option
156 (** Obtain the globally-visible value whose address is that of the given symbol.
157 The symbol name must be the mangled form as would occur in bytecode or
158 a native object file. [None] is returned if the value is inaccessible.
159 The accessible values are those in the main program and those provided by
160 previous calls to [loadfile].
161
162 This function is deemed "unsafe" as there is no type safety provided.
163
164 When executing in bytecode, this function uses [Symtable]. As a cautionary
165 note for programs such as the debugger: even though the linking of a packed
166 (subset of) compilerlibs into [Dynlink] hides the copy of [Symtable] that
167 [Dynlink] uses from its clients, there is still only one table of global
168 values in the bytecode VM. Changes to this table are NOT synchronized
169 between [Dynlink] and the functions that change the global value table
170 ([update_global_table] and [assign_global_value], accessed through a
171 client's version of [Symtable]). This is why we can't use [Dynlink] from the
172 toplevel interactive loop, in particular.
173 *)
174