From 0ca1005669c8fdfd0d6e9ece6d7798344c30bd41 Mon Sep 17 00:00:00 2001 From: ivg Date: Tue, 30 Aug 2022 15:04:53 -0400 Subject: [PATCH] prevents double-loading of the bap packages in the toplevel This is a hotfix that prevents double-loading of certain bap core libraries (e.g., bap-knowledge, bap-core-theory, bap-main, etc) when using the baptop executable or bap.top library. It is not 100% bulletproof against all double-loads but the problem only affects the toplevel environment and builds that use opam-repository and oasis, which we will eventually sunset after a full move to the dune build system. Problem Description ------------------- The BAP plugin system is designed to be self-contained so that all dependencies could be loaded directly from the plugins. This let us deploy BAP in a standalone form, i.e., on systems that lack OCaml installation. This feature, of course, leads to bloated plugins. To partially alleviate this issue, we defined a set of compilation units that are presumed to be present in the executable that loads bap plugins. This set includes the transitive closure of three packages `bap`, `core-kernel`, and `ppx_bap`. So that any compilation unit on which one of these packages depends will not be packed into a plugin, since it is expected to be linked into the host exectuable. This worked perfectly under assumption that all plugins depend on bap or, at least, that the bap library is installed when a plugin is built. This assumption stopped to be true after #1419 when we started to use plugins that do not depend on bap. Since bap is not installed when such a plugin is built (which is only possible when building each package independently from the opam-repository) we can no longer build the transitive closure of bap dependencies that includes bap-core-theory, bap-knowledge, etc, therefore we store them in the plugin. When this plugin is loaded from a toplevel, we can't prevent units that comprise these packages from loading since in the toplevel mode they have been loaded to the host executable with the `require` directive and there's no mechanism in the toplevel system that allows us to know what units were loaded (dynlink doesn't work in toplevel). In the end, it leads to double-loading of bap-knowledge, and if some of the previously loaded plugins already used bap-knowledge, the information that they have stored in it will be erased. --- lib/bap_build/bap_build.ml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/bap_build/bap_build.ml b/lib/bap_build/bap_build.ml index de28d8b81..a6ece6c17 100644 --- a/lib/bap_build/bap_build.ml +++ b/lib/bap_build/bap_build.ml @@ -15,7 +15,13 @@ module Plugin_rules = struct with Fl.No_such_package _ -> false let default_packages = List.filter ~f:is_installed [ - "bap"; "core_kernel"; "ppx_bap" + "bap"; + "bap-main"; + "bap-core-theory"; + "bap-knowledge"; + "core_kernel"; + "ppx_bap"; + "regular" ] let default_predicates = [ ]