Mir driver example compatible with musl or cosmo libc in statically linked mode #390
Replies: 3 comments 9 replies
-
Hi, The symbols can be solved through dlopen (as they are now), but to be included statically in the driver the linker of the driver needs to include all of libc in the final binary, which I think is just hard to do (I wouldn't even know how to try), Anyway, as I said, this is just for external symbol resolution, you may not even need to load any libraries if they are not to be used. Not much of a solution here, just to give more context |
Beta Was this translation helpful? Give feedback.
-
alpine does use musl, yet it rarely if at all uses static linking. even its busybox binary is dynamically linked.
musl supports dlopen() just fine, unless you statically link. |
Beta Was this translation helpful? Give feedback.
-
So I adapted the I also added the Here is the #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mir-gen.h"
#define MIR_TYPE_INTERP 1
#define MIR_TYPE_INTERP_NAME "interp"
#define MIR_TYPE_JIT 2
#define MIR_TYPE_JIT_NAME "jit"
#define MIR_TYPE_LAZY 3
#define MIR_TYPE_LAZY_NAME "lazy"
#define MIR_TYPE_DEFAULT MIR_TYPE_INTERP
#define MIR_ENV_VAR_TYPE "MIR_TYPE"
int _mir_printi(int i) {
return printf("%d\n", i);
}
static void *import_resolver (const char *name) {
if (!strcmp(name, "printf")) return printf;
fprintf(stderr, "can not load symbol %s\n", name);
exit (1);
}
static int get_mir_type(void) {
const char *type_value = getenv(MIR_ENV_VAR_TYPE);
if (type_value == NULL || type_value[0] == '\0')
return MIR_TYPE_DEFAULT;
if (strcmp(type_value, MIR_TYPE_INTERP_NAME) == 0)
return MIR_TYPE_INTERP;
if (strcmp(type_value, MIR_TYPE_JIT_NAME) == 0)
return MIR_TYPE_JIT;
if (strcmp(type_value, MIR_TYPE_LAZY_NAME) == 0)
return MIR_TYPE_LAZY;
fprintf(stderr, "warning: unknown MIR_TYPE '%s', using default one\n", type_value);
return MIR_TYPE_DEFAULT;
}
int main (int argc, char **argv, char **envp) {
#ifdef _WITH_BINFMT_MISC
if (argc < 3) {
fprintf(stderr, "usage: %s <full-path> <name> [<arg>...]\n", argv[0]);
return 1;
}
#else
if (argc < 2) {
fprintf(stderr, "usage: %s <bmir-file> [<arg>...]\n", argv[0]);
return 1;
}
#endif
int mir_type = get_mir_type();
MIR_val_t val;
int exit_code;
MIR_item_t main_func = NULL;
MIR_context_t mctx = MIR_init();
FILE *mir_file = fopen(argv[1], "r");
if (!mir_file) {
fprintf(stderr, "failed to open file '%s'\n", argv[1]);
return 1;
}
MIR_read(mctx, mir_file);
for (MIR_module_t module = DLIST_HEAD (MIR_module_t, *MIR_get_module_list (mctx)); module; module = DLIST_NEXT (MIR_module_t, module)) {
for (MIR_item_t func = DLIST_HEAD (MIR_item_t, module->items); func; func = DLIST_NEXT (MIR_item_t, func)) {
if (func ->item_type != MIR_func_item) continue;
if (strcmp (func->u.func->name, "main") == 0) main_func = func;
}
MIR_load_module (mctx, module);
}
if (main_func == NULL) {
fprintf(stderr, "cannot execute program w/o main function\n");
return 1;
}
#ifdef _WITH_BINFMT_MISC
#define _SKIP_ARGS 2
#else
#define _SKIP_ARGS 1
#endif
if (mir_type == MIR_TYPE_INTERP) {
MIR_link (mctx, MIR_set_interp_interface, import_resolver);
MIR_interp (
mctx, main_func, &val, 3,
(MIR_val_t){.i = (argc-_SKIP_ARGS)},
(MIR_val_t){.a = (void*)(argv+_SKIP_ARGS)},
(MIR_val_t){.a = (void*)envp}
);
exit_code = val.i;
} else {
MIR_gen_init (mctx, 1);
MIR_link (mctx,
mir_type == MIR_TYPE_JIT
? MIR_set_gen_interface
: MIR_set_lazy_gen_interface,
import_resolver);
uint64_t (*fun_addr)(int, char**, char**) = MIR_gen(mctx, 0, main_func);
exit_code = fun_addr(argc-_SKIP_ARGS, argv+_SKIP_ARGS, envp);
MIR_gen_finish (mctx);
}
MIR_finish (mctx);
return exit_code;
} I'm testing with the following C file, using the int printf(char *fmt, ...);
int main() {
printf("hello\n");
printf("world\n");
return 0;
} |
Beta Was this translation helpful? Give feedback.
-
The standard Linux libc is glibc, which only supports dynamic linking nowadays. cf https://developers.redhat.com/articles/2023/08/31/how-we-ensure-statically-linked-applications-stay-way
Static linking is still popular among people who like lightweight software like mir. Musl and cosmo libc are designed for static linking only on the contrary. https://www.alpinelinux.org is one of the most famous Linux distro using static linking and musl libc for example.
Would it be difficult to provide a mir driver example compatible with such a statically linked libc ? This means removing calls to dlopen in practice as this is not implemented by musl and only through hacks by cosmo.
Beta Was this translation helpful? Give feedback.
All reactions