Wandering Thoughts archives

2013-01-12

Runtime loading of general code usually requires general dynamic linking

Let me set the stage. You have a system that supports dynamic linking and dynamic code loading in general, with a low-level interface for this; for example, modern Unixes have dlopen(), dlsym(), and so on. You also have a language runtime that's entirely statically linked, and you want to have a program in this language environment dynamically load some of its code at runtime, for example to implement some sort of plugin system. One hypothetical approach to doing this is to directly use the low-level system interface for dynamic loading; you build the plugin code into a single object file, use system tools to transmogrify it into a dynamically loadable one, and then dlopen() it in your program, fish entry points out with dlsym(), and call them.

(Depending on what sort of FFI your language has, you might need some sort of low level shim to sit between your plugin's code and your main program's code.)

All of this sounds nice, but is it likely to actually work if you tried to implement it? My answer is 'probably not'. The problem is pretty simple to state: how does the plugin code get access to the runtime environment and other outside code?

Unless the plugin code does pure computation (without even memory allocation), it needs access to the runtime code that does things like memory allocation, operating system calls, DNS lookups, general IO routines, and so on. Plus, it may also want access to other higher level library code or the like. The plugin can't safely statically link all of this code into itself unless all of the runtime environment is carefully designed so that you can run two (or more) independent copies of it inside the same process, one in your main program and one in the plugin (this is often a big problem for things like memory allocators and garbage collection). Using the runtime environment from your main program requires connecting the plugin to it; you need to either somehow build the plugin so that it knows all of the right addresses in your main program (which binds it to a particular build of your main program) or do your own relocation at dlopen() time. You also need to insure that your main program actually includes all of the code that plugins will need, whether or not that code is used by your main program.

What makes runtime code loading work without hassle is general support for dynamic linking. When the plugin code is dynamically linked, it's already set up to do runtime lookups of outside addresses (and possibly runtime relocation). When you dlopen() it in a dynamically linked program the dynamic loader code only has to connect it to the existing symbol tables in your program (plus any new shared libraries that it requires). And of course a chunk of code that's built to be statically linked doesn't have any of this infrastructure built into it since such infrastructure isn't necessary and in fact is usually undesirable (partly because of the added complexity).

tech/RuntimeLoadingAndDynamicLinking written at 01:28:35;


Page tools: See As Normal.
Search:
Login: Password:

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.