Two years ago, I experimented with collectable dynamically loaded code.
You can find the main patches here: https://github.com/def-lkb/ocaml/compare/4.00.1...dyn-unload

This is just a proof-of-concept and applies only to bytecode. A table keep track of some pages allocated outside of ocaml heap, pointers pointing to the middle of the page are allowed.
Reacheable pages are marked during major scan, unmarked pages are released during major collection.

I tested with Dynlink and toplevel, but I don't remember the details.