diff --git a/README.en.rst b/README.en.rst index e4c52a5da58..8d06bea529a 100644 --- a/README.en.rst +++ b/README.en.rst @@ -232,9 +232,10 @@ x86 instruction set coverage: Runtime behavior notes: -- Library pass-through (``LATX_KZT``) is available only in 64-bit builds and - is enabled subject to compatibility checks by default. 32-bit builds do - not provide this option. +- KZT wrappers (``LATX_KZT``) are available only in 64-bit builds. Run + ``latx-x86_64 --kzt-libs`` to list the library groups, stability status, and + dependencies provided by the installed version. 32-bit builds do not + provide this option. - Multi-threaded guests use the QEMU user-mode threading model; atomic instructions select an optimized path according to host kernel capabilities. @@ -254,6 +255,22 @@ command-line options. The `LATX configuration reference `_ describes precedence and common settings. This reference is currently available in Chinese. +Common KZT library-group controls: + +.. code-block:: bash + + # List the groups provided by this version + latx-x86_64 --kzt-libs + + # Enable the current stable set + LATX_KZT=1 latx-x86_64 /path/to/program + + # Remove one group and its dependents from the stable set + LATX_KZT=1 LATX_KZT_LIBS=-x11 latx-x86_64 /path/to/program + + # Select one group and its required dependencies + LATX_KZT=1 LATX_KZT_LIBS=x11 latx-x86_64 /path/to/program + AVX Instruction Support ======================= diff --git a/README.rst b/README.rst index 0b71415edbc..116f0213453 100644 --- a/README.rst +++ b/README.rst @@ -211,7 +211,8 @@ x86 指令集覆盖: 运行行为说明: -- 库直通( ``LATX_KZT`` )仅在 64 位构建中提供,默认按兼容性检查启用; +- KZT wrapper( ``LATX_KZT`` )仅在 64 位构建中提供。可以运行 + ``latx-x86_64 --kzt-libs`` 查询当前版本提供的库族、稳定状态和依赖关系; 32 位构建没有该选项。 - 多线程 guest 程序沿用 QEMU 用户态多线程模型,原子指令根据宿主内核能力 选择优化路径。 @@ -227,6 +228,22 @@ x86 指令集覆盖: LATX 支持系统配置文件、用户配置文件、环境变量和命令行参数。优先级、常用配置 及示例见 `LATX 配置信息 `_。 +KZT 库族控制的常用方式: + +.. code-block:: bash + + # 查询当前版本提供的库族 + latx-x86_64 --kzt-libs + + # 启用当前稳定库族 + LATX_KZT=1 latx-x86_64 /path/to/program + + # 从稳定集合关闭一个库族及其依赖者 + LATX_KZT=1 LATX_KZT_LIBS=-x11 latx-x86_64 /path/to/program + + # 只启用一个库族及其必要依赖 + LATX_KZT=1 LATX_KZT_LIBS=x11 latx-x86_64 /path/to/program + AVX 指令支持 ============ diff --git a/configs/latx-x86_64.conf b/configs/latx-x86_64.conf index 936c8c387a7..41f68884379 100644 --- a/configs/latx-x86_64.conf +++ b/configs/latx-x86_64.conf @@ -12,6 +12,12 @@ # Notes: # - Section names are case-sensitive. # - Keys represent environment variables. +# - KZT library groups select wrapper eligibility. Custom wrappers may still +# re-enter guest code when required. +# - LATX_KZT_LIBS=-name removes a group; LATX_KZT_LIBS=name selects one group +# and its dependencies. # #[devcpp.exe] #LATX_SOFTFPU = 1 +#LATX_KZT = 1 +#LATX_KZT_LIBS = -x11 diff --git a/docs/user/latx-environment.rst b/docs/user/latx-environment.rst index 1acbf3df47a..97fe62cded5 100644 --- a/docs/user/latx-environment.rst +++ b/docs/user/latx-environment.rst @@ -117,11 +117,15 @@ Meson 安装目标会把模板安装到 configure 指定的 ``sysconfdir``。默 - ``0`` - 控制 64 位构建中的库直通。``1`` 表示按兼容性检查启用,``2`` 是供测试 使用的强制模式。32 位构建不提供该选项。 + * - ``LATX_KZT_LIBS`` + - ``stable`` + - 可选的 KZT 库族选择。``-x11`` 从稳定集合关闭 X11,``x11`` 表示只启用 + X11 及其依赖,``+name`` 用于在稳定集合上增加已知的实验库族。 * - ``LATX_KZT_LOG`` - ``0`` - 控制 KZT 关键降级日志。设为 ``1`` 时,release 构建也会在某个装载对象 - 无法安全完成直通绑定时向标准错误输出原因;默认不输出,也不会改变 - KZT 的启用状态或安全降级行为。仅 64 位 KZT 构建提供该选项。 + 无法安全完成直通绑定时向标准错误输出原因,并记录最终库族集合和每个库 + 是否启用 KZT wrapper 的决策;默认不输出,也不会改变安全降级行为。 * - ``LATX_SOFTFPU`` - ``0`` - 浮点结果异常时可尝试 ``1``;``2`` 是另一种软浮点模式。非零值会自动 @@ -144,6 +148,82 @@ Meson 安装目标会把模板安装到 configure 指定的 ``sysconfdir``。默 ``-runtime-info`` 确认当前选择,避免掩盖运行时安装问题。 +KZT 库族控制 +============ + +``LATX_KZT`` 仍然是 KZT(库直通)总开关。这里的库族选择控制 guest 动态库 +是否可以使用对应的 KZT wrapper,并不表示该库的所有函数都无条件调用 host +实现。为了保持 guest 可见状态,loader 协调、回调等自定义 wrapper 仍可能有意 +回到 guest 翻译执行。 + +普通用户只需设置 +``LATX_KZT=1``,此时启用当前版本的稳定库族。只有兼容性排查、二分和实验性 +wrapper 测试需要设置 ``LATX_KZT_LIBS``。总开关为 ``0`` 时忽略库族选择。 + +库族名称、稳定状态和依赖关系由当前 LATX 构建定义,不在文档中维护一份容易 +过期的静态清单。下面的 ``x11``、``gl`` 等名称只用于说明选择语法。 + +运行以下命令可以查询当前安装版本提供的清单,无需指定 guest 程序: + +.. code-block:: bash + + latx-x86_64 --kzt-libs + +``LATX_KZT_LIBS`` 只有两种写法,不能混用: + +* 不带符号的名称表示“只启用这些库族”,例如 ``x11`` 或 ``x11,gl``; +* 全部带 ``+`` 或 ``-`` 时,以稳定集合为起点增加或关闭库族,例如 + ``-x11`` 或 ``+x11,-vulkan``。 + +未设置、空值和 ``stable`` 都表示稳定集合。``stable`` 必须单独使用。库族名 +大小写不敏感,逗号两侧允许空白。这里不提供 ``all``:未来新增实验库族时, +旧配置不应在升级后自动启用尚未验证的 wrapper。 + +依赖由 LATX 自动处理。例如 ``LATX_KZT_LIBS=gl`` 实际启用 +``core,x11,gl``;``LATX_KZT_LIBS=-x11`` 会保留 ``core``,并同时关闭依赖 +X11 的 ``gl``、``vulkan`` 和 ``vaapi``。这样不会把 host 库创建的对象交给已经 +回退 guest 翻译的依赖库。 + +以 ``libdl`` 为例,guest ``dlopen`` 会先进入 LAT 的自定义 wrapper。目标库有 +安全 KZT wrapper 时,LAT 才装载对应的 host 库;目标库没有 wrapper 时,LAT +会重新进入 guest ``dlopen``,由 ``cpu_loop`` 翻译执行 guest loader。因而 +``core`` 是 KZT 的基础 wrapper 和 loader 协调库族,不是“完整原生 libdl”开关。 + +未知库族、空项、混合两种写法,或者同时写 ``+x11`` 和 ``-x11`` 都属于配置 +错误。LATX 会报告原因、关闭本次运行的全部 KZT,并继续完整翻译 guest 库, +不会忽略错误后继续走非预期的 native 路径。``LATX_KZT`` 只接受 ``0``、``1``、 +``2``,``LATX_KZT_LOG`` 只接受 ``0``、``1``;其他值同样按配置错误处理。 + +常见用法: + +.. code-block:: bash + + # 关闭全部 KZT + LATX_KZT=0 latx-x86_64 /path/to/program + + # 启用当前稳定库族 + LATX_KZT=1 latx-x86_64 /path/to/program + + # 从稳定集合临时关闭 X11 及其依赖者 + LATX_KZT=1 LATX_KZT_LIBS=-x11 \ + latx-x86_64 /path/to/program + + # 只启用 X11 及其必要依赖,便于调试和二分 + LATX_KZT=1 LATX_KZT_LIBS=x11 LATX_KZT_LOG=1 \ + latx-x86_64 /path/to/program + +所有选项都可以写入应用 section。例如只对 ``gtkperf`` 关闭 X11: + +.. code-block:: ini + + [gtkperf] + LATX_KZT = 1 + LATX_KZT_LIBS = -x11 + +高优先级配置会完整替换低优先级的 ``LATX_KZT_LIBS`` 字符串,不会跨配置来源 +拼接集合,因此环境变量覆盖应用配置后的结果仍可直接复现。 + + 指定 guest 运行时 ================== diff --git a/linux-user/elfload.c b/linux-user/elfload.c index cdb9b714dd1..3aa16df9bd4 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -3484,23 +3484,14 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) } #if defined(CONFIG_LATX_KZT) if (!elf_interpreter) { - if(option_kzt && getenv("LATX_KZT")) { - char * arg_kzt = getenv("LATX_KZT"); - option_kzt = strtol(arg_kzt, NULL, 0); - - /* option_kzt == 1 is normal kzt, - disable kzt for static or direct exec ld.so - option_kzt == 2 is forced kzt, used for test */ - if (option_kzt == 1) { - if (latx_wine) { - wine_option_kzt = option_kzt; - } - option_kzt = 0; - } - } else { - if (latx_wine) { - wine_option_kzt = option_kzt; - } + /* Wine maps its real main image later, so defer either KZT mode + * until that image is available. For other static/direct-ld.so + * guests, normal mode is disabled while forced mode remains a test + * override. option_kzt already reflects config and CLI precedence. */ + if (latx_wine && option_kzt) { + wine_option_kzt = option_kzt; + option_kzt = 0; + } else if (option_kzt == 1) { option_kzt = 0; } } diff --git a/linux-user/main.c b/linux-user/main.c index 47281e85906..5023a23807b 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -74,6 +74,7 @@ int mydebug = 1; #include "librarian.h" #include "wrapper.h" #if defined(CONFIG_LATX_KZT) +#include "kzt-groups.h" #include "wrappertbbridge.h" box64context_t* my_context = NULL; elfheader_t* elf_header = NULL; @@ -183,9 +184,7 @@ static int last_log_mask; unsigned long reserved_va; -#if defined(CONFIG_LATX_DEBUG) || defined(CONFIG_DEBUG_TCG) static void usage(int exitcode); -#endif const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; const char *qemu_uname_release; @@ -422,11 +421,6 @@ static void handle_arg_latx_disassemble_trace_cmp(const char *arg) #endif -static void handle_arg_help(const char *arg) -{ - usage(EXIT_SUCCESS); -} - static void handle_arg_imm_skip_pc(const char *arg) { imm_skip_pc = strtol(arg, NULL, 16); } @@ -604,6 +598,12 @@ static void handle_arg_plugin(const char *arg) #endif #endif +static void handle_arg_help(const char *arg) +{ + (void)arg; + usage(EXIT_SUCCESS); +} + #ifdef CONFIG_LATX static void handle_arg_version(const char *arg) { @@ -668,12 +668,43 @@ static void handle_arg_latx_avx_cpuid(const char *arg) #if defined(CONFIG_LATX_KZT) static void handle_arg_latx_kzt(const char *arg) { - option_kzt = strtol(arg, NULL, 0); + int value; + + g_clear_pointer(&option_kzt_error, g_free); + if (qemu_strtoi(arg, NULL, 0, &value) || value < 0 || value > 2) { + option_kzt = 0; + option_kzt_error = g_strdup_printf( + "LATX_KZT must be exactly 0, 1, or 2 (got '%s')", arg); + return; + } + option_kzt = value; +} + +static void handle_arg_latx_kzt_libs(const char *arg) +{ + g_free(option_kzt_libs); + option_kzt_libs = g_strdup(arg); } static void handle_arg_latx_kzt_log(const char *arg) { - option_kzt_log = strtol(arg, NULL, 0) != 0; + int value; + + g_clear_pointer(&option_kzt_log_error, g_free); + if (qemu_strtoi(arg, NULL, 0, &value) || value < 0 || value > 1) { + option_kzt_log = 1; + option_kzt_log_error = g_strdup_printf( + "LATX_KZT_LOG must be exactly 0 or 1 (got '%s')", arg); + return; + } + option_kzt_log = value; +} + +static void handle_arg_kzt_libs_info(const char *arg) +{ + (void)arg; + kzt_groups_print_available(); + exit(EXIT_SUCCESS); } #endif @@ -889,8 +920,12 @@ static const struct qemu_argument arg_table[] = { #if defined(CONFIG_LATX_KZT) {"latx-kzt", "LATX_KZT", true, handle_arg_latx_kzt, "", "enable kuzhitong"}, + {"latx-kzt-libs", "LATX_KZT_LIBS", true, handle_arg_latx_kzt_libs, + "group,...", "select KZT library groups"}, {"latx-kzt-log", "LATX_KZT_LOG", true, handle_arg_latx_kzt_log, "0|1", "log important KZT binding and fallback decisions"}, + {"kzt-libs", NULL, false, handle_arg_kzt_libs_info, + "", "list available KZT library groups and exit"}, #endif {"latx-fputag", "LATX_FPUTAG", true, handle_arg_latx_fputag, "", "enable fputag"}, @@ -965,10 +1000,6 @@ static const struct qemu_argument arg_table[] = { true, handle_arg_latx_disassemble_trace_cmp, "", "LATX Compare different disassemble."}, #endif - {"h", "", false, handle_arg_help, - "", "print this help"}, - {"help", "", false, handle_arg_help, - "", ""}, {"g", "LAT_GDB", true, handle_arg_gdb, "port", "wait gdb connection to 'port'"}, {"s", "LAT_STACK_SIZE", true, handle_arg_stack_size, @@ -1013,6 +1044,10 @@ static const struct qemu_argument arg_table[] = { "", "[file=][,arg=]"}, #endif #endif + {"h", NULL, false, handle_arg_help, + "", "print this help"}, + {"help", NULL, false, handle_arg_help, + "", "print this help"}, {"L", "LAT_LD_PREFIX", true, handle_arg_ld_prefix, "path", "set the elf interpreter prefix to 'path'"}, {"runtime-info", NULL, false, handle_arg_runtime_info, @@ -1022,7 +1057,6 @@ static const struct qemu_argument arg_table[] = { {NULL, NULL, false, NULL, NULL, NULL} }; -#if defined(CONFIG_LATX_DEBUG) || defined(CONFIG_DEBUG_TCG) static void usage(int exitcode) { const struct qemu_argument *arginfo; @@ -1046,8 +1080,10 @@ static void usage(int exitcode) if (arginfo->has_arg) { arglen += strlen(arginfo->example) + 1; } - if (strlen(arginfo->env) > maxenvlen) { - maxenvlen = strlen(arginfo->env); + const char *env = arginfo->env ? arginfo->env : ""; + + if (strlen(env) > maxenvlen) { + maxenvlen = strlen(env); } if (arglen > maxarglen) { maxarglen = arglen; @@ -1058,13 +1094,15 @@ static void usage(int exitcode) maxenvlen, "Env-variable"); for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { + const char *env = arginfo->env ? arginfo->env : ""; + if (arginfo->has_arg) { printf("-%s %-*s %-*s %s\n", arginfo->argv, (int)(maxarglen - strlen(arginfo->argv) - 1), - arginfo->example, maxenvlen, arginfo->env, arginfo->help); + arginfo->example, maxenvlen, env, arginfo->help); } else { printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv, - maxenvlen, arginfo->env, + maxenvlen, env, arginfo->help); } } @@ -1089,11 +1127,11 @@ static void usage(int exitcode) " LAT_SET_ENV=var1=val2,var2=val2 LAT_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" "Note that if you provide several changes to a single variable\n" "the last change will stay in effect.\n" + "Both -option and --option spellings are accepted.\n" "\n"); exit(exitcode); } -#endif struct ParseOption { const char *opt_name; @@ -1228,12 +1266,13 @@ static int parse_args(int argc, char **argv) } else { if (!strcmp(r, "version") || !strcmp(r, "h") || !strcmp(r, "help") - || !strcmp(r, "runtime-info")) { + || !strcmp(r, "runtime-info") + || !strcmp(r, "kzt-libs")) { /* - * runtime-info must take effect here so it can be used - * without a guest. options_set() intentionally - * replays its idempotent handler with the other - * command-line options. + * Query options must take effect here so they can be + * used without a guest. options_set() intentionally + * replays the idempotent runtime-info handler with the + * other command-line options. */ arginfo->handle_opt(NULL); } @@ -1396,6 +1435,13 @@ int main(int argc, char **argv, char **envp) /* set environment variables */ options_set(target_argv); + if (!latx_options_finalize()) { +#if defined(CONFIG_LATX_KZT) + error_report("invalid KZT configuration: %s; KZT disabled", + kzt_groups_last_error()); +#endif + } + if (runtime_info_requested) { print_runtime_info(); return EXIT_SUCCESS; diff --git a/target/i386/latx/context/elfloader.c b/target/i386/latx/context/elfloader.c index 6b08dc2234e..e959bb9a895 100755 --- a/target/i386/latx/context/elfloader.c +++ b/target/i386/latx/context/elfloader.c @@ -32,6 +32,7 @@ #include "symbols.h" #include "lsenv.h" #include "qemu.h" +#include "kzt-groups.h" #include "kzt_relocation_transaction.h" static int kzt_relocation_slot_fits_page(uintptr_t slot_addr) @@ -402,8 +403,8 @@ void FreeElfHeader(elfheader_t** head) *head = NULL; } #include "fileutils.h" -#define GO(P, N) P, -#define GOALIAS(P, N) P, +#define GO(P, N, G) P, +#define GOALIAS(P, N, G) P, const char * wrappedlibs_name[] = { #include "library_list.h" }; @@ -692,6 +693,9 @@ int CheckEnableKZT(elfheader_t* h, char** target_argv, int target_argc) /* check KZT libs in paths */ int nb = sizeof(wrappedlibs_name) / sizeof(char*); for (int i=0; istr); + g_string_free(valid, true); +} + +static const char *kzt_skip_space(const char *cursor) +{ + while (*cursor && g_ascii_isspace(*cursor)) { + cursor++; + } + return cursor; +} + +static bool kzt_parse_group_spec(const char *spec, KztGroupSpecMode *mode, + uint32_t *selected, uint32_t *added, + uint32_t *removed, bool *use_stable) +{ + const char *cursor; + bool saw_token = false; + + if (!spec || !*kzt_skip_space(spec)) { + return true; + } + + cursor = spec; + while (true) { + char token[32]; + const char *start; + const char *end; + char operation = '\0'; + size_t length; + KztLibraryGroup group; + + cursor = kzt_skip_space(cursor); + if (!*cursor || *cursor == ',') { + snprintf(group_error, sizeof(group_error), + "contains an empty library group"); + return false; + } + if (*cursor == '+' || *cursor == '-') { + operation = *cursor++; + } + start = cursor; + while (*cursor && *cursor != ',') { + cursor++; + } + end = cursor; + while (end > start && g_ascii_isspace(end[-1])) { + end--; + } + length = end - start; + if (!length) { + snprintf(group_error, sizeof(group_error), + "contains a sign without a library group"); + return false; + } + if (length >= sizeof(token)) { + snprintf(group_error, sizeof(group_error), + "contains a group name longer than %zu bytes", + sizeof(token) - 1); + return false; + } + memcpy(token, start, length); + token[length] = '\0'; + + if (!strcasecmp(token, "stable")) { + if (operation || saw_token || *cursor == ',') { + snprintf(group_error, sizeof(group_error), + "'stable' must be used by itself"); + return false; + } + *mode = KZT_GROUP_SPEC_EXACT; + *use_stable = true; + saw_token = true; + } else { + group = kzt_group_from_name(token); + if (group == KZT_GROUP_NONE) { + kzt_set_unknown_group_error(token); + return false; + } + + if (operation) { + if (*mode == KZT_GROUP_SPEC_EXACT) { + snprintf(group_error, sizeof(group_error), + "cannot mix exact groups with + or - modifiers"); + return false; + } + *mode = KZT_GROUP_SPEC_MODIFY; + if (operation == '+') { + if (*removed & group) { + snprintf(group_error, sizeof(group_error), + "configures group '%s' as both enabled " + "and disabled", token); + return false; + } + *added |= group; + } else { + if (*added & group) { + snprintf(group_error, sizeof(group_error), + "configures group '%s' as both enabled " + "and disabled", token); + return false; + } + *removed |= group; + } + } else { + if (*mode == KZT_GROUP_SPEC_MODIFY) { + snprintf(group_error, sizeof(group_error), + "cannot mix exact groups with + or - modifiers"); + return false; + } + *mode = KZT_GROUP_SPEC_EXACT; + *selected |= group; + } + saw_token = true; + } + + if (!*cursor) { + break; + } + cursor++; + if (!*kzt_skip_space(cursor)) { + snprintf(group_error, sizeof(group_error), + "contains a trailing comma"); + return false; + } + } + return true; +} + +static uint32_t kzt_add_dependencies(uint32_t groups) +{ + uint32_t previous; + + do { + previous = groups; + for (size_t i = 0; i < ARRAY_SIZE(kzt_group_definitions); i++) { + if (groups & kzt_group_definitions[i].group) { + groups |= kzt_group_definitions[i].dependencies; + } + } + } while (groups != previous); + return groups; +} + +static uint32_t kzt_prune_missing_dependencies(uint32_t groups) +{ + uint32_t previous; + + do { + previous = groups; + for (size_t i = 0; i < ARRAY_SIZE(kzt_group_definitions); i++) { + const KztGroupDefinition *definition = + &kzt_group_definitions[i]; + + if ((groups & definition->group) && + (groups & definition->dependencies) != + definition->dependencies) { + groups &= ~definition->group; + } + } + } while (groups != previous); + return groups; +} + +static void kzt_groups_log_mask(const char *label, uint32_t groups) +{ + bool first = true; + + fprintf(stderr, "KZT: %s: ", label); + for (size_t i = 0; i < ARRAY_SIZE(kzt_group_definitions); i++) { + if (!(groups & kzt_group_definitions[i].group)) { + continue; + } + fprintf(stderr, "%s%s", first ? "" : ",", + kzt_group_definitions[i].name); + first = false; + } + fprintf(stderr, "%s\n", first ? "none" : ""); +} + +static void kzt_groups_log_effective(const char *spec, uint32_t dependencies, + uint32_t removed, uint32_t pruned) +{ + if (!group_log_enabled) { + return; + } + fprintf(stderr, "KZT: requested library groups: %s\n", + spec && *kzt_skip_space(spec) ? spec : "stable"); + if (dependencies) { + kzt_groups_log_mask("added required library groups", dependencies); + } + if (removed) { + kzt_groups_log_mask("explicitly disabled library groups", removed); + } + if (pruned) { + kzt_groups_log_mask("disabled dependent library groups", pruned); + } + kzt_groups_log_mask("enabled library groups", enabled_groups); +} + +KztLibraryGroup kzt_group_for_library(const char *soname) +{ + if (!soname) { + return KZT_GROUP_NONE; + } + + for (size_t i = 0; i < ARRAY_SIZE(kzt_library_groups); i++) { + if (!strcmp(soname, kzt_library_groups[i].soname)) { + return kzt_library_groups[i].group; + } + } + + return KZT_GROUP_NONE; +} + +const char *kzt_group_name(KztLibraryGroup group) +{ + for (size_t i = 0; i < ARRAY_SIZE(kzt_group_definitions); i++) { + if (group == kzt_group_definitions[i].group) { + return kzt_group_definitions[i].name; + } + } + return "none"; +} + +void kzt_groups_print_available(void) +{ + puts("Available KZT library groups:"); + for (size_t i = 0; i < ARRAY_SIZE(kzt_group_definitions); i++) { + const KztGroupDefinition *definition = &kzt_group_definitions[i]; + uint32_t dependencies = + kzt_add_dependencies(definition->group) & ~definition->group; + bool first = true; + + printf(" %-8s status=%s requires=", definition->name, + definition->stable ? "stable" : "experimental"); + for (size_t j = 0; j < ARRAY_SIZE(kzt_group_definitions); j++) { + if (!(dependencies & kzt_group_definitions[j].group)) { + continue; + } + printf("%s%s", first ? "" : ",", + kzt_group_definitions[j].name); + first = false; + } + puts(first ? "none" : ""); + } + puts("Selection syntax:"); + puts(" LATX_KZT_LIBS=stable use the current stable set"); + puts(" LATX_KZT_LIBS=name,... use only the named groups and " + "dependencies"); + puts(" LATX_KZT_LIBS=+name,-name modify the current stable set"); +} + +void kzt_groups_reset(void) +{ + enabled_groups = KZT_GROUP_STABLE; + group_log_enabled = false; + group_error[0] = '\0'; + memset(library_decision_logged, 0, sizeof(library_decision_logged)); +} + +bool kzt_groups_configure(const char *spec, bool log_enabled) +{ + KztGroupSpecMode mode = KZT_GROUP_SPEC_UNSET; + uint32_t selected = KZT_GROUP_NONE; + uint32_t added = KZT_GROUP_NONE; + uint32_t removed = KZT_GROUP_NONE; + uint32_t groups; + uint32_t before_dependencies; + uint32_t before_prune; + uint32_t dependencies; + uint32_t pruned; + bool use_stable = false; + + group_error[0] = '\0'; + memset(library_decision_logged, 0, sizeof(library_decision_logged)); + if (!kzt_parse_group_spec(spec, &mode, &selected, &added, &removed, + &use_stable)) { + enabled_groups = KZT_GROUP_NONE; + group_log_enabled = log_enabled; + return false; + } + + if (mode == KZT_GROUP_SPEC_EXACT && !use_stable) { + groups = selected; + } else { + groups = KZT_GROUP_STABLE; + } + if (mode == KZT_GROUP_SPEC_MODIFY) { + groups |= added; + } + before_dependencies = groups; + groups = kzt_add_dependencies(groups); + dependencies = groups & ~before_dependencies; + groups &= ~removed; + before_prune = groups; + enabled_groups = kzt_prune_missing_dependencies(groups); + pruned = before_prune & ~enabled_groups; + group_log_enabled = log_enabled; + kzt_groups_log_effective(spec, dependencies, removed, pruned); + return true; +} + +void kzt_groups_reject_configuration(const char *reason, bool log_enabled) +{ + enabled_groups = KZT_GROUP_NONE; + group_log_enabled = log_enabled; + snprintf(group_error, sizeof(group_error), "%s", reason); +} + +uint32_t kzt_groups_enabled_mask(void) +{ + return enabled_groups; +} + +bool kzt_group_is_enabled(KztLibraryGroup group) +{ + return group != KZT_GROUP_NONE && (enabled_groups & group) == group; +} + +bool kzt_library_is_enabled(const char *soname) +{ + return kzt_group_is_enabled(kzt_group_for_library(soname)); +} + +const char *kzt_groups_last_error(void) +{ + return group_error; +} + +void kzt_groups_log_library(const char *soname, bool enabled) +{ + if (!group_log_enabled) { + return; + } + + for (size_t i = 0; i < ARRAY_SIZE(kzt_library_groups); i++) { + if (strcmp(soname, kzt_library_groups[i].soname)) { + continue; + } + + g_mutex_lock(&group_log_lock); + if (!library_decision_logged[i]) { + library_decision_logged[i] = true; + fprintf(stderr, "KZT: %s KZT wrapper for %s (group %s)\n", + enabled ? "using" : "skipping", soname, + kzt_group_name(kzt_library_groups[i].group)); + } + g_mutex_unlock(&group_log_lock); + return; + } +} diff --git a/target/i386/latx/context/library.c b/target/i386/latx/context/library.c index 90b8264ea61..af2ae878fea 100755 --- a/target/i386/latx/context/library.c +++ b/target/i386/latx/context/library.c @@ -29,18 +29,19 @@ #include "librarian.h" #include "librarian_private.h" #include "pathcoll.h" +#include "kzt-groups.h" -#define GO(P, N) int wrapped##N##_init(library_t* lib, box64context_t *box64); \ +#define GO(P, N, G) int wrapped##N##_init(library_t* lib, box64context_t *box64); \ void wrapped##N##_fini(library_t* lib); \ int wrapped##N##_get(library_t* lib, const char* name, khint_t pre_k, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local); \ int wrapped##N##_getnoweak(library_t* lib, const char* name, khint_t pre_k, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local); -#define GOALIAS(P, N) +#define GOALIAS(P, N, G) #include "library_list.h" #undef GO #undef GOALIAS -#define GO(P, N) {P, wrapped##N##_init, wrapped##N##_fini, wrapped##N##_get, wrapped##N##_getnoweak}, -#define GOALIAS(P, N) {P, wrapped##N##_init, wrapped##N##_fini, wrapped##N##_get, wrapped##N##_getnoweak}, +#define GO(P, N, G) {P, wrapped##N##_init, wrapped##N##_fini, wrapped##N##_get, wrapped##N##_getnoweak}, +#define GOALIAS(P, N, G) {P, wrapped##N##_init, wrapped##N##_fini, wrapped##N##_get, wrapped##N##_getnoweak}, wrappedlib_t wrappedlibs[] = { #include "library_list.h" }; @@ -201,7 +202,11 @@ int FindLibIsWrapped(char * name) int nb = sizeof(wrappedlibs) / sizeof(wrappedlib_t); for (int i=0; iname, wrappedlibs[i].name)==0) { + if (!kzt_library_is_enabled(lib->name)) { + kzt_groups_log_library(lib->name, false); + return; + } if(wrappedlibs[i].init(lib, context)) { // error! const char* error_str = dlerror(); @@ -244,6 +253,7 @@ static void initNativeLib(library_t *lib, box64context_t* context) { lm->l_addr = real_lm.l_addr; lm->l_name = real_lm.l_name; lm->l_ld = real_lm.l_ld; + kzt_groups_log_library(lib->name, true); break; } } diff --git a/target/i386/latx/context/meson.build b/target/i386/latx/context/meson.build index fbf30369509..60db56cbea2 100644 --- a/target/i386/latx/context/meson.build +++ b/target/i386/latx/context/meson.build @@ -59,6 +59,7 @@ my_file = files( 'dictionnary.c', 'symbols.c', 'library.c', + 'kzt-groups.c', 'pathcoll.c', 'fileutils.c', 'elfparser.c', diff --git a/target/i386/latx/include/kzt-group-list.h b/target/i386/latx/include/kzt-group-list.h new file mode 100644 index 00000000000..6c7caab659b --- /dev/null +++ b/target/i386/latx/include/kzt-group-list.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 LAT Project Authors + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef LATX_KZT_GROUP_LIST_H +#define LATX_KZT_GROUP_LIST_H + +/* + * KZT library-group registry. + * + * This is the single source of truth for group names, bit positions, + * stability, and dependencies. Keep concrete shared-library assignments in + * library_list.h. + * + * KZT_GROUP_LIST(X) entries are: + * + * X(identifier, name, bit, STABLE|EXPERIMENTAL, dependencies) + */ +#define KZT_GROUP_LIST(X) \ + X(CORE, "core", 0, STABLE, KZT_GROUP_NONE) \ + X(X11, "x11", 1, STABLE, KZT_GROUP_CORE) \ + X(GL, "gl", 2, STABLE, KZT_GROUP_CORE | KZT_GROUP_X11) \ + X(VULKAN, "vulkan", 3, STABLE, KZT_GROUP_CORE | KZT_GROUP_X11) \ + X(VAAPI, "vaapi", 4, STABLE, KZT_GROUP_CORE | KZT_GROUP_X11) + +#endif /* LATX_KZT_GROUP_LIST_H */ diff --git a/target/i386/latx/include/kzt-groups.h b/target/i386/latx/include/kzt-groups.h new file mode 100644 index 00000000000..0986c548e73 --- /dev/null +++ b/target/i386/latx/include/kzt-groups.h @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2026 LAT Project Authors + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef LATX_KZT_GROUPS_H +#define LATX_KZT_GROUPS_H + +#include +#include + +#include "kzt-group-list.h" + +typedef enum KztLibraryGroup { + KZT_GROUP_NONE = 0, +#define KZT_GROUP_ENUM(identifier, name, bit, stability, dependencies) \ + KZT_GROUP_##identifier = 1U << bit, + KZT_GROUP_LIST(KZT_GROUP_ENUM) +#undef KZT_GROUP_ENUM +} KztLibraryGroup; + +/* + * Group selection controls whether a guest library is eligible for its KZT + * wrapper. It does not imply that every custom wrapper function executes + * only host code: loader coordination and callback wrappers may deliberately + * re-enter guest execution to preserve guest-visible state. + */ + +#define KZT_GROUP_STABLE_MASK_STABLE(group) | (group) +#define KZT_GROUP_STABLE_MASK_EXPERIMENTAL(group) +#define KZT_GROUP_STABLE_MASK(identifier, name, bit, stability, dependencies) \ + KZT_GROUP_STABLE_MASK_##stability(KZT_GROUP_##identifier) +enum { + KZT_GROUP_STABLE = KZT_GROUP_NONE + KZT_GROUP_LIST(KZT_GROUP_STABLE_MASK), +}; +#undef KZT_GROUP_STABLE_MASK +#undef KZT_GROUP_STABLE_MASK_EXPERIMENTAL +#undef KZT_GROUP_STABLE_MASK_STABLE + +KztLibraryGroup kzt_group_for_library(const char *soname); +const char *kzt_group_name(KztLibraryGroup group); +void kzt_groups_print_available(void); +void kzt_groups_reset(void); +bool kzt_groups_configure(const char *spec, bool log_enabled); +void kzt_groups_reject_configuration(const char *reason, bool log_enabled); +uint32_t kzt_groups_enabled_mask(void); +bool kzt_group_is_enabled(KztLibraryGroup group); +bool kzt_library_is_enabled(const char *soname); +const char *kzt_groups_last_error(void); +void kzt_groups_log_library(const char *soname, bool enabled); + +#endif /* LATX_KZT_GROUPS_H */ diff --git a/target/i386/latx/include/latx-options.h b/target/i386/latx/include/latx-options.h index 98814baddbe..bb396086e45 100644 --- a/target/i386/latx/include/latx-options.h +++ b/target/i386/latx/include/latx-options.h @@ -33,6 +33,9 @@ extern int option_tu_link; #ifdef CONFIG_LATX_KZT extern int option_kzt_log; +extern char *option_kzt_libs; +extern char *option_kzt_error; +extern char *option_kzt_log_error; #endif #ifdef CONFIG_LATX_AVX_OPT @@ -152,6 +155,7 @@ extern unsigned long long counter_mips_tr; #if defined(CONFIG_LATX) && defined(CONFIG_LATX_KZT) #define ENVSUP_KZT \ ENVFUN(LATX_KZT, handle_arg_latx_kzt) \ + ENVFUN(LATX_KZT_LIBS, handle_arg_latx_kzt_libs) \ ENVFUN(LATX_KZT_LOG, handle_arg_latx_kzt_log) #else #define ENVSUP_KZT @@ -230,6 +234,7 @@ extern unsigned long long counter_mips_tr; ENVSUP_PLUGIN void options_init(void); +bool latx_options_finalize(void); void options_parse_opt(const char *opt); void options_parse_imm_reg(const char *bits); void options_parse_dump(const char *bits); diff --git a/target/i386/latx/include/library_list.h b/target/i386/latx/include/library_list.h index 01638dd688b..35a1ed3e784 100755 --- a/target/i386/latx/include/library_list.h +++ b/target/i386/latx/include/library_list.h @@ -4,121 +4,121 @@ #include "config-host.h" -GO("libEGL.so.1", libegl) +GO("libEGL.so.1", libegl, KZT_GROUP_GL) #ifndef CONFIG_LOONGARCH_NEW_WORLD -GO("libdl.so.2", libdl) +GO("libdl.so.2", libdl, KZT_GROUP_CORE) #endif -//GO("libgtk-3.so", gtk3) -//GO("libgio-2.0.so", gio2) -GO("libc.so.6", libc) -GO("libGL.so.1", libgl) -GO("libX11.so.6", libx11) -GO("libGLU.so.1", libglu) -GO("libGLX.so.0", libglx) -GO("libXxf86vm.so.1", libxxf86vm) -GO("libXext.so.6", libxext) -GO("libXau.so.6", libxau) -GO("libXi.so.6", libxi) -GO("libXdmcp.so.6", libxdmcp) -GO("libxshmfence.so.1", xshmfence) -GO("libXfixes.so.3", libxfixes) -GO("libXcursor.so.1", libxcursor) -GO("libXinerama.so.1", xinerama) -GO("libXrandr.so.2", libxrandr) -GO("libXss.so.1", libxss) -GO("libXft.so.2", libxft) -GO("libXtst.so.6", libxtst) -GO("libXt.so.6", libxt) -GO("libXrender.so.1", libxrender) -GO("libXpm.so.4", libxpm) -GO("libXdamage.so.1", libxdamage) -GO("libXmu.so.6", libxmu) -GO("libXcomposite.so.1", libxcomposite) -GO("libva-x11.so.2", libvax11) -GO("libva-drm.so.2", libvadrm) -GO("libva.so.2", libva) -GO("libxcb.so.1", libxcb) -GO("libxcb-xkb.so.1", libxcbxkb) -//GO("libxkbcommon-x11.so.0", xkbcommonx11) -//GO("libxkbcommon.so.0", xkbcommon) -GO("libX11-xcb.so.1", libx11xcb) -GO("libxcb-randr.so.0", libxcbrandr) -GO("libxcb-shm.so.0", libxcbshm) -GO("libxcb-xfixes.so.0", libxcbxfixes) -GO("libxcb-shape.so.0", libxcbshape) -GO("libxcb-image.so.0", libxcbimage) -GO("libxcb-keysyms.so.1", libxcbkeysyms) -GO("libxcb-xtest.so.0", libxcbxtest) -GO("libxcb-glx.so.0", libxcbglx) -GO("libxcb-dri2.so.0", libxcbdri2) -GO("libxcb-dri3.so.0", libxcbdri3) -GO("libvulkan.so.1", vulkan) -GO("libxcb-cursor.so.0", libxcbcursor) -GO("libxcb-icccm.so.4", libxcbicccm) -GO("libxcb-util.so.1", libxcbutil) -GO("libxcb-render-util.so.0", libxcbrenderutil) -GO("libxcb-render.so.0", libxcbrender) -GO("libxcb-sync.so.1", libxcbsync) -GO("libxcb-xinerama.so.0", libxcbxinerama) -GO("libxcb-xinput.so.0", libxcbxinput) -GO("libxcb-present.so.0", libxcbpresent) +//GO("libgtk-3.so", gtk3, KZT_GROUP_X11) +//GO("libgio-2.0.so", gio2, KZT_GROUP_CORE) +GO("libc.so.6", libc, KZT_GROUP_CORE) +GO("libGL.so.1", libgl, KZT_GROUP_GL) +GO("libX11.so.6", libx11, KZT_GROUP_X11) +GO("libGLU.so.1", libglu, KZT_GROUP_GL) +GO("libGLX.so.0", libglx, KZT_GROUP_GL) +GO("libXxf86vm.so.1", libxxf86vm, KZT_GROUP_X11) +GO("libXext.so.6", libxext, KZT_GROUP_X11) +GO("libXau.so.6", libxau, KZT_GROUP_X11) +GO("libXi.so.6", libxi, KZT_GROUP_X11) +GO("libXdmcp.so.6", libxdmcp, KZT_GROUP_X11) +GO("libxshmfence.so.1", xshmfence, KZT_GROUP_X11) +GO("libXfixes.so.3", libxfixes, KZT_GROUP_X11) +GO("libXcursor.so.1", libxcursor, KZT_GROUP_X11) +GO("libXinerama.so.1", xinerama, KZT_GROUP_X11) +GO("libXrandr.so.2", libxrandr, KZT_GROUP_X11) +GO("libXss.so.1", libxss, KZT_GROUP_X11) +GO("libXft.so.2", libxft, KZT_GROUP_X11) +GO("libXtst.so.6", libxtst, KZT_GROUP_X11) +GO("libXt.so.6", libxt, KZT_GROUP_X11) +GO("libXrender.so.1", libxrender, KZT_GROUP_X11) +GO("libXpm.so.4", libxpm, KZT_GROUP_X11) +GO("libXdamage.so.1", libxdamage, KZT_GROUP_X11) +GO("libXmu.so.6", libxmu, KZT_GROUP_X11) +GO("libXcomposite.so.1", libxcomposite, KZT_GROUP_X11) +GO("libva-x11.so.2", libvax11, KZT_GROUP_VAAPI) +GO("libva-drm.so.2", libvadrm, KZT_GROUP_VAAPI) +GO("libva.so.2", libva, KZT_GROUP_VAAPI) +GO("libxcb.so.1", libxcb, KZT_GROUP_X11) +GO("libxcb-xkb.so.1", libxcbxkb, KZT_GROUP_X11) +//GO("libxkbcommon-x11.so.0", xkbcommonx11, KZT_GROUP_X11) +//GO("libxkbcommon.so.0", xkbcommon, KZT_GROUP_X11) +GO("libX11-xcb.so.1", libx11xcb, KZT_GROUP_X11) +GO("libxcb-randr.so.0", libxcbrandr, KZT_GROUP_X11) +GO("libxcb-shm.so.0", libxcbshm, KZT_GROUP_X11) +GO("libxcb-xfixes.so.0", libxcbxfixes, KZT_GROUP_X11) +GO("libxcb-shape.so.0", libxcbshape, KZT_GROUP_X11) +GO("libxcb-image.so.0", libxcbimage, KZT_GROUP_X11) +GO("libxcb-keysyms.so.1", libxcbkeysyms, KZT_GROUP_X11) +GO("libxcb-xtest.so.0", libxcbxtest, KZT_GROUP_X11) +GO("libxcb-glx.so.0", libxcbglx, KZT_GROUP_X11) +GO("libxcb-dri2.so.0", libxcbdri2, KZT_GROUP_X11) +GO("libxcb-dri3.so.0", libxcbdri3, KZT_GROUP_X11) +GO("libvulkan.so.1", vulkan, KZT_GROUP_VULKAN) +GO("libxcb-cursor.so.0", libxcbcursor, KZT_GROUP_X11) +GO("libxcb-icccm.so.4", libxcbicccm, KZT_GROUP_X11) +GO("libxcb-util.so.1", libxcbutil, KZT_GROUP_X11) +GO("libxcb-render-util.so.0", libxcbrenderutil, KZT_GROUP_X11) +GO("libxcb-render.so.0", libxcbrender, KZT_GROUP_X11) +GO("libxcb-sync.so.1", libxcbsync, KZT_GROUP_X11) +GO("libxcb-xinerama.so.0", libxcbxinerama, KZT_GROUP_X11) +GO("libxcb-xinput.so.0", libxcbxinput, KZT_GROUP_X11) +GO("libxcb-present.so.0", libxcbpresent, KZT_GROUP_X11) -GOALIAS("libxcb-cursor.so", libxcbcursor) -GOALIAS("libxcb-icccm.so", libxcbicccm) -GOALIAS("libxcb-util.so", libxcbutil) -GOALIAS("libxcb-render-util.so", libxcbrenderutil) -GOALIAS("libxcb-render.so", libxcbrender) -GOALIAS("libxcb-sync.so", libxcbsync) -GOALIAS("libxcb-xinerama.so", libxcbxinerama) -GOALIAS("libxcb-xinput.so", libxcbxinput) -GOALIAS("libxcb-present.so", libxcbpresent) -GOALIAS("libvulkan.so", vulkan) -GOALIAS("libEGL.so", libegl) +GOALIAS("libxcb-cursor.so", libxcbcursor, KZT_GROUP_X11) +GOALIAS("libxcb-icccm.so", libxcbicccm, KZT_GROUP_X11) +GOALIAS("libxcb-util.so", libxcbutil, KZT_GROUP_X11) +GOALIAS("libxcb-render-util.so", libxcbrenderutil, KZT_GROUP_X11) +GOALIAS("libxcb-render.so", libxcbrender, KZT_GROUP_X11) +GOALIAS("libxcb-sync.so", libxcbsync, KZT_GROUP_X11) +GOALIAS("libxcb-xinerama.so", libxcbxinerama, KZT_GROUP_X11) +GOALIAS("libxcb-xinput.so", libxcbxinput, KZT_GROUP_X11) +GOALIAS("libxcb-present.so", libxcbpresent, KZT_GROUP_X11) +GOALIAS("libvulkan.so", vulkan, KZT_GROUP_VULKAN) +GOALIAS("libEGL.so", libegl, KZT_GROUP_GL) #ifndef CONFIG_LOONGARCH_NEW_WORLD -GOALIAS("libdl.so", libdl) +GOALIAS("libdl.so", libdl, KZT_GROUP_CORE) #endif -//GOALIAS("libgtk-3.so", gtk3) -//GOALIAS("libgio-2.0.so", gio2) -GOALIAS("libc.so", libc) -GOALIAS("libGL.so", libgl) -GOALIAS("libX11.so", libx11) -GOALIAS("libGLU.so", libglu) -GOALIAS("libGLX.so", libglx) -GOALIAS("libXxf86vm.so", libxxf86vm) -GOALIAS("libXext.so", libxext) -GOALIAS("libXau.so", libxau) -GOALIAS("libXi.so", libxi) -GOALIAS("libXdmcp.so", libxdmcp) -GOALIAS("libxshmfence.so", xshmfence) -GOALIAS("libXfixes.so", libxfixes) -GOALIAS("libXcursor.so", libxcursor) -GOALIAS("libXinerama.so", xinerama) -GOALIAS("libXrandr.so", libxrandr) -GOALIAS("libXss.so", libxss) -GOALIAS("libXft.so", libxft) -GOALIAS("libXtst.so", libxtst) -GOALIAS("libXt.so", libxt) -GOALIAS("libXrender.so", libxrender) -GOALIAS("libXpm.so", libxpm) -GOALIAS("libXdamage.so", libxdamage) -GOALIAS("libXmu.so", libxmu) -GOALIAS("libXcomposite.so", libxcomposite) -GOALIAS("libva-x11.so", libvax11) -GOALIAS("libva-drm.so", libvadrm) -GOALIAS("libva.so", libva) -GOALIAS("libxcb.so", libxcb) -GOALIAS("libxcb-xkb.so", libxcbxkb) -//GOALIAS("libxkbcommon-x11.so", xkbcommonx11) -//GOALIAS("libxkbcommon.so", xkbcommon) -GOALIAS("libX11-xcb.so", libx11xcb) -GOALIAS("libxcb-randr.so", libxcbrandr) -GOALIAS("libxcb-shm.so", libxcbshm) -GOALIAS("libxcb-xfixes.so", libxcbxfixes) -GOALIAS("libxcb-shape.so", libxcbshape) -GOALIAS("libxcb-image.so", libxcbimage) -GOALIAS("libxcb-keysyms.so", libxcbkeysyms) -GOALIAS("libxcb-xtest.so", libxcbxtest) -GOALIAS("libxcb-glx.so", libxcbglx) -GOALIAS("libxcb-dri2.so", libxcbdri2) -GOALIAS("libxcb-dri3.so", libxcbdri3) +//GOALIAS("libgtk-3.so", gtk3, KZT_GROUP_X11) +//GOALIAS("libgio-2.0.so", gio2, KZT_GROUP_CORE) +GOALIAS("libc.so", libc, KZT_GROUP_CORE) +GOALIAS("libGL.so", libgl, KZT_GROUP_GL) +GOALIAS("libX11.so", libx11, KZT_GROUP_X11) +GOALIAS("libGLU.so", libglu, KZT_GROUP_GL) +GOALIAS("libGLX.so", libglx, KZT_GROUP_GL) +GOALIAS("libXxf86vm.so", libxxf86vm, KZT_GROUP_X11) +GOALIAS("libXext.so", libxext, KZT_GROUP_X11) +GOALIAS("libXau.so", libxau, KZT_GROUP_X11) +GOALIAS("libXi.so", libxi, KZT_GROUP_X11) +GOALIAS("libXdmcp.so", libxdmcp, KZT_GROUP_X11) +GOALIAS("libxshmfence.so", xshmfence, KZT_GROUP_X11) +GOALIAS("libXfixes.so", libxfixes, KZT_GROUP_X11) +GOALIAS("libXcursor.so", libxcursor, KZT_GROUP_X11) +GOALIAS("libXinerama.so", xinerama, KZT_GROUP_X11) +GOALIAS("libXrandr.so", libxrandr, KZT_GROUP_X11) +GOALIAS("libXss.so", libxss, KZT_GROUP_X11) +GOALIAS("libXft.so", libxft, KZT_GROUP_X11) +GOALIAS("libXtst.so", libxtst, KZT_GROUP_X11) +GOALIAS("libXt.so", libxt, KZT_GROUP_X11) +GOALIAS("libXrender.so", libxrender, KZT_GROUP_X11) +GOALIAS("libXpm.so", libxpm, KZT_GROUP_X11) +GOALIAS("libXdamage.so", libxdamage, KZT_GROUP_X11) +GOALIAS("libXmu.so", libxmu, KZT_GROUP_X11) +GOALIAS("libXcomposite.so", libxcomposite, KZT_GROUP_X11) +GOALIAS("libva-x11.so", libvax11, KZT_GROUP_VAAPI) +GOALIAS("libva-drm.so", libvadrm, KZT_GROUP_VAAPI) +GOALIAS("libva.so", libva, KZT_GROUP_VAAPI) +GOALIAS("libxcb.so", libxcb, KZT_GROUP_X11) +GOALIAS("libxcb-xkb.so", libxcbxkb, KZT_GROUP_X11) +//GOALIAS("libxkbcommon-x11.so", xkbcommonx11, KZT_GROUP_X11) +//GOALIAS("libxkbcommon.so", xkbcommon, KZT_GROUP_X11) +GOALIAS("libX11-xcb.so", libx11xcb, KZT_GROUP_X11) +GOALIAS("libxcb-randr.so", libxcbrandr, KZT_GROUP_X11) +GOALIAS("libxcb-shm.so", libxcbshm, KZT_GROUP_X11) +GOALIAS("libxcb-xfixes.so", libxcbxfixes, KZT_GROUP_X11) +GOALIAS("libxcb-shape.so", libxcbshape, KZT_GROUP_X11) +GOALIAS("libxcb-image.so", libxcbimage, KZT_GROUP_X11) +GOALIAS("libxcb-keysyms.so", libxcbkeysyms, KZT_GROUP_X11) +GOALIAS("libxcb-xtest.so", libxcbxtest, KZT_GROUP_X11) +GOALIAS("libxcb-glx.so", libxcbglx, KZT_GROUP_X11) +GOALIAS("libxcb-dri2.so", libxcbdri2, KZT_GROUP_X11) +GOALIAS("libxcb-dri3.so", libxcbdri3, KZT_GROUP_X11) diff --git a/target/i386/latx/latx-options.c b/target/i386/latx/latx-options.c index 08c920392b5..df1feab32ce 100644 --- a/target/i386/latx/latx-options.c +++ b/target/i386/latx/latx-options.c @@ -12,10 +12,16 @@ #include "latx-runtime.h" #include "latx-string-utils.h" #include "translate.h" +#if defined(CONFIG_LATX_KZT) +#include "kzt-groups.h" +#endif #if defined(CONFIG_LATX_KZT) int option_kzt = 0; int option_kzt_log = 0; +char *option_kzt_libs; +char *option_kzt_error; +char *option_kzt_log_error; #endif #ifdef CONFIG_LATX_AVX_OPT @@ -210,6 +216,14 @@ void conf_init(char **argv) void options_init(void) { latx_runtime_reset(); +#if defined(CONFIG_LATX_KZT) + option_kzt = 0; + option_kzt_log = 0; + g_clear_pointer(&option_kzt_libs, g_free); + g_clear_pointer(&option_kzt_error, g_free); + g_clear_pointer(&option_kzt_log_error, g_free); + kzt_groups_reset(); +#endif option_debug_lative = 0; option_save_xmm = 0xff; option_dump_host = 0; @@ -271,6 +285,33 @@ void options_init(void) option_fast_atomic = 0; } +bool latx_options_finalize(void) +{ +#if defined(CONFIG_LATX_KZT) + if (option_kzt_log_error) { + kzt_groups_reject_configuration(option_kzt_log_error, true); + option_kzt = 0; + return false; + } + if (option_kzt_error) { + kzt_groups_reject_configuration(option_kzt_error, + option_kzt_log != 0); + option_kzt = 0; + return false; + } + if (option_kzt == 0) { + kzt_groups_reset(); + return true; + } + if (!kzt_groups_configure(option_kzt_libs, + option_kzt_log != 0 && option_kzt != 0)) { + option_kzt = 0; + return false; + } +#endif + return true; +} + #define OPTIONS_IMM_REG 0 #define OPTIONS_IMM_RIP 1 #define OPTIONS_IMM_COMPLEX 2