Skip to content
Dynamic creation and update of ELF files, or: an allocator for JIT compilers
C Makefile
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
include
lib
src
test
.hgignore
Makefile
README

README

This is libdlbind, an extension to System V-style dynamic loaders to
allow dynamic allocation of objects and dynamic binding of symbols.

Its main use-case is in JIT compilers, or other run-time code
generators. Rather than allocating code memory yourself, allocating it
with dlbind keeps the dynamic loader informed -- along with any debugger
that might be attached. This means that your JITted code and data are
debuggable "by default" just like any other dynamically loaded content.
It also means that the usual dlsym() and dladdr() interfaces will work
against your JITted output.

Currently, the implementation is very minimal and naive. It does work,
with some caveats:

- you must have a writable /run/shm directory;

- no deallocation or unbinding yet;

- when defining a new symbol, the dlreload() call, necessary for
introducing the new symbols, requires some instrumentation of the
dynamic linker or and/or modifications to the debugger. To do this
introduction, the linker looks for a "change in the link map". To signal
this, we have two options.

 (1) really unload (unmap) and reload (re-open/mmap) the file;

 (2) don't really close the file (hence keeping the mappings in memory),
     but make the debugger re-read the symbols anyway.

To make (2) work, we need to make the debugger think that the link map
has changed even when it hasn't, i.e. to be more conservative and
(correctly) avoid assuming that an unchanged link map means unchanged
symbol tables. This is probably the "right way" but means extending the
protocol between dynamic linker and debugger. This is not done yet.

Fortunately we can make (1) work already. The main caveat is that we
rely on getting the same object base address when we do the re-load...
currently this seems to work on glibc's ld.so. To ensure data written to
the file persists across close/reopen, we also require (logically) a
modified dynamic linker, so that the mmap() calls it makes for libdlbind
objects request MAP_SHARED rather than MAP_PRIVATE semantics. As a
quick-and-dirty solution, we can trap these syscalls and tweak the
flags. This is what our gdb-script <test/elfproto-simple/gdb-script>
does, as a minimal demo of correct operation. In liballocs
<https://github.com/stephenrkell/liballocs/>, the same idea is used but
the syscall trapping is automated and happens online. Medium-term, a
modified dynamic linker created with libgerald
<https://github.com/stephenrkell/libgerald/> will be a more robust
solution... most readily for tweaking the mmap flags, but also allowing
us to implement the RTLD_RELOADABLE extension mentioned above.
You can’t perform that action at this time.