LoongsonNBL – heterogeneous library loader. More...
#include <dlfcn.h>#include <elf.h>#include <fcntl.h>#include <signal.h>#include <stdbool.h>#include <stdint.h>#include <unistd.h>
Go to the source code of this file.
Data Structures | |
| struct | Nbl |
| Dispatch table of NBL runtime functions. More... | |
Macros | |
| #define | NBL_MAXPATHLEN 2048 |
Enumerations | |
| enum | NblVaargsPolicy { NBL_VAARGS_NONE = 0, NBL_VAARGS_NULL_TERMINATED = 1 } |
| Variadic-argument handling policy for host function registration. More... | |
Functions | |
| Nbl * | nbl_load (int tr_mode, const char *nbl_lib_base, bool host_dispatch_signal) |
| Create and initialise an Nbl instance. More... | |
| void | nbl_unload (Nbl *nbl) |
| Destroy an Nbl instance previously created by nbl_load() and release all associated resources. | |
| void | set_host_sighandle (int(*host_sig_handler)(int signo, void *siginfo, void *ucontext, int abort_if_unrecognized)) |
| Register a host (LoongArch) signal handler with the current NBL instance so that the translator can delegate signal dispatch to it. More... | |
LoongsonNBL – heterogeneous library loader.
NBL is a userspace runtime that lets a LoongArch (la64 / la32) process load x86_64 ELF shared objects and invoke functions inside them, by routing cross-architecture calls through a binary translator.
The public C API mirrors a subset of libdl.so (dlopen / dlclose / dlsym / ...) so that callers familiar with POSIX dynamic loading can use it with minimal friction, while extending it with the extra entry points required for cross-architecture bridging – signature-aware symbol lookup, host function registration, wrapper-stub generation, and so on.
Several entry points of Nbl – dlsym_with_signature(), method_stub() and the register_hostfunc*() family – take a nbl_signature string. It is the only description of a function's parameter list and return type that NBL receives, so it must match the real prototype exactly.
<signature> ::= <ret_type> "F" <arg_type>*
Primitive type letters:
v : void
B : uint8_t (unsigned byte)
b : int8_t (signed byte)
S : uint16_t (unsigned half-word)
s : int16_t (signed half-word)
I : uint32_t (unsigned word)
i : int32_t (signed word)
L : uint64_t (unsigned double-word) -- 64-bit on LA64, 32-bit on LA32
l : int64_t (signed double-word) -- 64-bit on LA64, 32-bit on LA32
p : pointer (sizeof(void*) on the host arch: 8 on LA64, 4 on LA32)
f : float (IEEE-754 single precision, 32-bit)
d : double (IEEE-754 double precision, 64-bit)
D : long double
H : struct -- followed by a brace-delimited layout, e.g. "H{ii}"
Structures may nest, e.g. "H{iH{i}}" for
struct { int a; struct { int b; } inner; }
and repeated members may use an array count, e.g. "H{i2}".
The members of a nested structure are laid out with their real
alignment and tail padding, exactly like the C compiler does.
U : union
V : variadic arguments (vaargs)
A : va_list
C : complex number. "C1" for float _Complex, "C2" for double
_Complex, "C3" for long double _Complex. (TODO)
Platform-dependent sizing (applies to L, l and p):
- LA64 (64-bit LoongArch): 64-bit wide.
- LA32 (32-bit LoongArch): 32-bit wide.
Conceptual call path:
.............................................
| wrapper_stub (la64 args -> x86_64 args) |
.............................................
| x86_64 function |
.............................................
| wrapper_stub (x86_64 ret -> la64 ret) |
.............................................
The helper convert_to_nbl_signature(raw_sig, nbl_sig) is available to translate JNI-style ("(ILjava/lang/String;[I)J") or other raw signatures into nbl_signature form.
Examples:
JNI example:
| #define NBL_MAXPATHLEN 2048 |
Maximum length (including the trailing NUL) of an NBL path string.
| enum NblVaargsPolicy |
Variadic-argument handling policy for host function registration.
| Nbl* nbl_load | ( | int | tr_mode, |
| const char * | nbl_lib_base, | ||
| bool | host_dispatch_signal | ||
| ) |
Create and initialise an Nbl instance.
The returned dispatch table must be released with nbl_unload() when no longer needed.
| tr_mode | Selects the underlying translator backend: 1 for the default backend, 2 is under development. |
| nbl_lib_base | Directory from which to load libnbl.so and its translator dependencies. |
| host_dispatch_signal |
|
| void set_host_sighandle | ( | int(*)(int signo, void *siginfo, void *ucontext, int abort_if_unrecognized) | host_sig_handler | ) |
Register a host (LoongArch) signal handler with the current NBL instance so that the translator can delegate signal dispatch to it.
Only one host handler is active at a time; passing NULL restores the translator's default behaviour.
| host_sig_handler | Pointer to the host signal handler. Receives signo, siginfo, ucontext and an abort_if_unrecognized flag, and returns 0 when the signal has been fully handled, non-zero to fall back to the translator's own handling. Pass NULL to restore the translator's default behaviour. |
1.8.5