eld
is a minimal dynamic loader for ELF shared objects.
mkdir eld
cd eld
git clone ... src
mkdir build
cd build
cmake ../src/ -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE="Debug" \
-DCMAKE_C_COMPILER="$INSTALL_PATH/bin/clang" \
-DCMAKE_C_FLAGS="-target or1k-elf" \
-DOR1K_SIM_PATH="$INSTALL_PATH/bin/or32-elf-sim" \
-DCMAKE_INSTALL_PREFIX="$INSTALL_PATH/or1k-elf"
make
This is the core dynamic loading library. It exposes the classical dlopen
,
dlclose
and dlsym
functions. They work pretty much as expected, except for
the fact that the file name provided to dlopen
must be a pointer to the buffer
of memory where the ELF to load is located.
To try it out, create a C file, name it libyour.c
and make it a shared
library:
int your() {
return 99;
}
$ clang -target or1k-elf libyour.c -shared -o libyour.so
Convert the ELF shell object (.so
file) in a C array with xxd
:
$ xxd -i libyour.so > libyour.so.h
$ cat libyour.so.h
unsigned char libmy_so[] = {
0x7f, 0x45, 0x4c, 0x46, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
...
Then include it in your main C file (main.c
) and call dlopen
on the
generated array:
#include <stdlib.h>
#include <stdio.h>
#include "dl.h"
#include "libyour.so.h"
typedef int (*myfunc_ptr)();
int main() {
void *handle = NULL;
handle = dlopen((char *) libyour_so, 0);
if (!handle) {
printf("Couldn't load the dynamic library\n");
return EXIT_FAILURE;
}
myfunc_ptr your = dlsym(handle, "your");
if (!your) {
printf("Couldn't find the symbol \"your\"\n");
return EXIT_FAILURE;
}
printf("your() == %d\n", your());
return EXIT_SUCCESS;
}
Supposing you are working the eld
build directory:
$ clang -target or1k-elf -I. main.c -L. -leld -o main -Wl,--export-dynamic
$ or32-elf-sim -f sim.cfg main
...
your() == 99
...
The project provides some example libraries and a simple application to test the loader.
loader
(test.c
): reads from standard input a series of libraries, loads them and performs some simple operations usingeld
; libraries are fed into the loader once at a time, first sending an integer (4-byte, little endian) representing the size of the library, and then the library itself; repeat until a 0-sized library is fed in input. This process is facilitated byfeed-so.py
script.libyour.so
(libyour.c
): contains just a single function and a global variable;libmy.so
(libmy.c
): depends onlibyour.so
and uses its function, has a constructor and a destructor, and expects to have some functions from the libc.
There is a target to build and test with or1ksim
the loader:
make loader_sim
Or if you want to launch or1ksim
in debug mode:
make loader_sim_debug
eld
primary aim is currently supporting bare-metal OpenRISC targets. eld
has
been tested with both clang and GCC and works fine with both or1k-elf
and
or1kle-elf
targets.
When applying resolving symbols in shared object or calling dlsym
, the symbols
are not searched in the proper order. Currently we first search in the shared
object currently being relocated (or the handle passed to dlsym
) and then all
the previously loaded shared objects are searched in load order.
- Isolate platform specific parts
- Move examples to a dedicated directory
- Add CMake target to generate documentation
- Import
sys/queue.h
- Add support for PID objects
- Add support for TLS relocations