Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Dynamic creation and update of ELF files, or: an allocator for JIT compilers
Fetching latest commit…
Cannot retrieve the latest commit at this time.
|Type||Name||Latest commit message||Commit time|
|Failed to load latest commit information.|
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.