Skip to content

LATX, feat: Add experimental Cairo native wrapper - #396

Merged
LaurenIsACoder merged 6 commits into
lat-opensource:masterfrom
LaurenIsACoder:lauren/kzt-cairo-wrapper
Aug 13, 2026
Merged

LATX, feat: Add experimental Cairo native wrapper#396
LaurenIsACoder merged 6 commits into
lat-opensource:masterfrom
LaurenIsACoder:lauren/kzt-cairo-wrapper

Conversation

@LaurenIsACoder

Copy link
Copy Markdown
Contributor

English

Summary

This adds an experimental, opt-in KZT native wrapper for Cairo. Supported x86_64 guest Cairo calls can enter the LoongArch host Cairo library instead of translating the guest Cairo implementation.

The change:

  • adds the Cairo 1.18 public ABI catalog and the generic wrapper signatures it requires;
  • preflights the guest dynamic symbol table and corresponding host symbols before activating the wrapper;
  • treats Cairo as a whole-library boundary so host Cairo objects cannot fall back into uncovered guest Cairo code;
  • bridges destroy, PNG stream, user-font, observer, MIME-data, and raster-source callbacks back into guest x86 code;
  • adapts XCB connection objects at the Cairo/XCB boundary;
  • fixes the SSE argument indexing, int32 two-argument dispatch, and dynamic RELRO timing required by Cairo binding.

Safety and compatibility

Cairo remains an experimental KZT library family and is enabled explicitly with:

LATX_KZT=1 LATX_KZT_LIBS=+cairo

Native activation is rejected for the whole Cairo library when the guest ELF is unsupported, an exported Cairo function has no declared wrapper, or the host library lacks a required symbol. LAT then continues with the translated guest Cairo library.

The validated runtime combination is guest Cairo 1.18.0 and host Cairo 1.18.2. FreeType and Fontconfig opaque-object interoperation is not enabled; those entry points return an explicit Cairo font-type mismatch instead of mixing guest and host objects.

Validation

Validation was performed on a LoongArch system with a real local X11 display:

  • normal LAT product build completed;
  • all 420 Cairo wrapper declarations passed the static ABI class audit;
  • all 73 ordinary dispatch signatures passed register and stack mapping review;
  • external image, Xlib, XCB, threading, lifecycle, callback, and dlopen probes passed in KZT-off, stable-KZT, and Cairo-enabled modes;
  • GDB confirmed guest call -> LAT wrapper -> native bridge -> host Cairo -> guest return for cairo_create, cairo_set_source_rgba, cairo_rectangle, cairo_fill, cairo_show_text, cairo_surface_flush, and cairo_destroy;
  • GDB confirmed host Cairo -> LoongArch thunk -> LAT guest callback bridge -> guest x86 callback -> host return for PNG stream, user-data destroy, MIME destroy, and user-font callbacks;
  • gtkperf completed 3/3 runs with KZT disabled, 3/3 with the stable default groups, and 20/20 with Cairo enabled.

中文

概述

本 PR 为 Cairo 增加实验性质、需要显式开启的 KZT 原生 wrapper。受支持的 x86_64 guest Cairo 调用可以直接进入 LoongArch host Cairo,而不再翻译执行 guest Cairo 的实现代码。

本次修改:

  • 增加 Cairo 1.18 公开 ABI 清单及其需要的通用 wrapper 签名;
  • 在启用 wrapper 前检查 guest 动态符号表以及对应的 host 符号;
  • 将 Cairo 作为完整库边界处理,避免 host Cairo 对象回退到未覆盖的 guest Cairo 代码;
  • 将销毁、PNG stream、user font、observer、MIME data 和 raster source 回调桥接回 guest x86 代码;
  • 在 Cairo/XCB 边界转换 XCB connection 对象;
  • 修复 Cairo 绑定需要的 SSE 参数索引、两个 int32 参数的调用分派以及动态 RELRO 绑定时机。

安全性与兼容性

Cairo 仍属于实验 KZT 库族,需要显式启用:

LATX_KZT=1 LATX_KZT_LIBS=+cairo

如果 guest ELF 不受支持、某个导出的 Cairo 函数没有安全 wrapper,或者 host Cairo 缺少必要符号,LAT 会拒绝整个 Cairo 库的原生直通,并继续翻译执行 guest Cairo。

已验证的版本组合为 guest Cairo 1.18.0 和 host Cairo 1.18.2。当前不启用 FreeType 和 Fontconfig 不透明对象的跨库互操作;相关入口会明确返回 Cairo font type mismatch,避免混用 guest 与 host 对象。

验证

以下验证在 LoongArch 机器的真实本地 X11 显示环境完成:

  • 正常 LAT 产品构建完成;
  • 420 个 Cairo wrapper 声明全部通过静态 ABI 类型审查;
  • 73 个普通调用签名全部通过寄存器和栈参数映射审查;
  • 外部 image、Xlib、XCB、多线程、生命周期、回调和 dlopen 探针在关闭 KZT、稳定 KZT 和启用 Cairo 三种模式下均通过;
  • GDB 证明 cairo_createcairo_set_source_rgbacairo_rectanglecairo_fillcairo_show_textcairo_surface_flushcairo_destroy 完成 guest 调用 -> LAT wrapper -> native bridge -> host Cairo -> 返回 guest 的完整路径;
  • GDB 证明 PNG stream、user-data destroy、MIME destroy 和 user-font 回调完成 host Cairo -> LoongArch thunk -> LAT guest callback bridge -> guest x86 回调 -> 返回 host 的完整往返;
  • gtkperf 在关闭 KZT 时完成 3/3 次,在默认稳定库族下完成 3/3 次,在启用 Cairo 后完成 20/20 次。

A guest loader may publish RT_CONSISTENT before it has finished applying a dynamically loaded object's relocations. Marking a successful KZT pass complete at that point lets the loader overwrite native bridges and prevents the existing pre-RELRO retry.

For objects with PT_GNU_RELRO, wait for the intercepted writable RELRO boundary. Objects without RELRO still bind at RT_CONSISTENT because they have no later protection transition.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Read and write scalar wrapper values from lane zero of the selected guest XMM register. The old expression indexed lanes within XMM0, which misrouted XMM1 and later arguments and overlapped double values.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
The generic iFii signature was declared but had no callable wrapper, and its unused typedef used 64-bit integers. Cairo format-stride calculation is the first enabled native wrapper that requires this signature.

Implement the wrapper with two int32 arguments and an int32 return so the generated Cairo symbol map can link with the public Cairo ABI.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Add the Cairo 1.18 public symbol catalog together with the scalar, pointer, double, and XCB-aligned dispatch signatures it requires. Keep this mechanical ABI preparation separate from library activation, preflight policy, and callback behavior.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Inspect the guest Cairo dynamic symbol table before native activation. Require every exported Cairo function to have a declared safe wrapper and a matching host symbol, and expose rejection reasons through opt-in KZT diagnostics so unsupported backends fail as a whole library.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Register Cairo as an opt-in library family and cover the complete public symbol set exported by the supported guest Cairo 1.18 runtime. Bridge destroy, stream, user-font, observer, MIME, and raster-source callbacks with typed guest argument marshalling, bounded reusable slots, locking, and object-lifetime tracking.

Adapt XCB connection objects and reject native activation when whole-library preflight fails. Keep FreeType and Fontconfig interop memory-safe by returning an explicit font-type mismatch until those opaque object families have native wrappers.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
@LaurenIsACoder
LaurenIsACoder marked this pull request as ready for review August 13, 2026 12:25
@LaurenIsACoder
LaurenIsACoder merged commit 913710f into lat-opensource:master Aug 13, 2026
20 checks passed
@LaurenIsACoder
LaurenIsACoder deleted the lauren/kzt-cairo-wrapper branch August 13, 2026 12:55
@xiangzhai

Copy link
Copy Markdown
Contributor

Hi,

Loongnix Desktop ABI 1.0 gtkperf-for-gtk3 开启LATX_KZT_LIBS=cairo复现断言失败:

export LATX_KZT=1
export LATX_KZT_LIBS=cairo
export LATX_KZT_LOG=1
export BOX64_LOG=1

/your/path/lat/build64/latx-x86_64 ./src/gtkperf


KZT: requested library groups: cairo
KZT: added required library groups: core,x11
KZT: enabled library groups: core,x11,cairo
option avx cpuid 1
KZT: using KZT wrapper for libcairo.so.2 (group cairo)
KZT: using KZT wrapper for libc.so.6 (group core)
...
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
gtkperf: ../../src/xcb_io.c:263:poll_for_event: 假设 ‘!xcb_xlib_threads_sequence_lost’ 失败。

Thanks,
Leslie Zhai

@xiangzhai

xiangzhai commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

跑5次能复现2次。

gtkperf-for-gtk3 由于是libgtk-3.so被skip kzt了:

latx find libgtk or libXt, skip kzt 
DEBUG: kzt_init:2107 option_kzt=0
                     ^--- option_kzt等于0

请检查CheckEnableKZT

            case DT_NEEDED:
                if (strstr(h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val, "libgtk-3.so")||//skip gtk
                    strstr(h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val, "libXt.so")) {//skip mainexec needed libXt.so
                    printf_log(LOG_INFO, "latx find libgtk or libXt, skip kzt\n");
                    return 0;
                }

类似被option_kzt=0的场景还有:因为matlab R2016b的sys/opengl/lib/glnxa64/下有x86_64的libGL.so.1.6.0

所以CheckEnableKZT发现找到libGL的x86_64的so就return 0关闭了KZT:

...
    /* check KZT libs in paths */
    int nb = sizeof(wrappedlibs_name) / sizeof(char*);
    for (int i=0; i<nb; ++i) {
=>        char *p = box_strdup(wrappedlibs_name[i]);
        char *p2 = strchr(p, '.');
        if (++p2) {
            *p2 = '\0';
        }
        for (int j=0; j<lib_path.size; ++j) {
            DIR *dir = opendir(lib_path.paths[j]);
            if (dir == NULL) {
                printf_log(LOG_INFO, "dir %s not exist\n", lib_path.paths[j]);
                continue;
            }

            struct dirent *entry;
            while ((entry = readdir(dir)) != NULL) {
                if (entry->d_type == DT_REG) {  // Check if it's a regular file
=>                    if (!strncmp(entry->d_name, p, strlen(p))) {
                        printf_log(LOG_INFO, "File starting with '%s' found: %s at %s\n", p, entry->d_name, lib_path.paths[j]);
                        closedir(dir);
                        FreeCollection(&lib_path);
=>                        return 0;
                    }
                }
            }
            closedir(dir);
        }
    }    
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants