provides versioned backends for program units symbol tables #1037
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
TL;DR; follow mainstream OCaml and make dynamic loading sound and safe
(not again, as it never was before).
The Problem
The long story. Before OCaml 4.08 the dynlink module was
unsound. Linking the same module resulted in GC roots table corruption
and segmentation faults. To prevent this behavior, we were tracking
loaded units. However, we weren't able to reliably track units that
were linked into the program directly with the OCaml linker. We were
using
findlib.dynload
and a corresponding functionality in dunethat provide us the information about the units that were used to link
the host program. Unfortunately,
findlib.dynload
was recording thisinformation in terms of the findlib packages, not in compilation
units. Therefore, in order to resolve a package name to corresponding
compilation unit names, we needed a working findlib system, i.e., the
META files for all packages that are statically linked in the binary
should be present in the hard-coded locations. In normal mode of
operation, when packages that were used to build bap are present in
the file system it didn't pose any problems. However, when bap
together with its plugins was packed into a Debian package and
distributed to other machines no meta files were available. To enable
binary distributions we developed an ocamlbuild plugin that was
resolving package names to compilation unit names during the
compilation time so that bap (and other tools built from our main
source repository) wasn't dependent on the runtime presence of META
files. However, when a host program is compiled with dune or any
other build system that doesn't reflect package names to unit names
and store them in the host file predicates (read it anywhere outside
of bap), then when packaged and distributed to other hosts the program
will fail in runtime.
The Solution
Since the bug is fixed in 4.08 there is no longer problem. The solution
is trivial, just use Dynlink and the newly provided
all_units
function, that enumerates unit names as we always needed.
The only problem with this solution is that it is probably to early
for us to drop the support for OCaml 4.07. Therefore, we decided to
provide two backends. The fallback solution still uses the old findlib
approach, but we decided to make it a little bit more robust, to
minimize the debugging time in case it will fail. We now check if we
have the static information about the compilation units that comprise
the host program, and if we don't then we ensure that we have working
ocamlfind and META files. If not then we terminate the program with
a more or less comprehensible message. If we have a modern compiler,
then we just use the Dynlink module (which is guarded with
ppx_optcomp).