unicorn-engine / unicorn

Unicorn CPU emulator framework (ARM, AArch64, M68K, Mips, Sparc, PowerPC, RiscV, S390x, TriCore, X86)
http://www.unicorn-engine.org
GNU General Public License v2.0
7.33k stars 1.31k forks source link

glib_compat breaks Qt Widgets with glib backend #1943

Closed vlasta-labsky closed 2 months ago

vlasta-labsky commented 2 months ago

When unicorn is linked in program that uses Qt Widgets (that uses glib internally), the glib_compat inside breaks resulting binary (Qt wrongly uses glib_compat and crashes).

I removed glib_compat from unicorn completely and pointed it to system glib, everythinks works OK now (Qt works and unicorn works).

Is it possible to prevent such library incompatibilities? Maybe rename glib_compat functions to not collide with glib, or remove glib_compat completely (as I did).

Why is it there at all?

wtdcode commented 2 months ago

We don’t expose any glibs symbols so please check your own build scripts.

vlasta-labsky commented 2 months ago

I experience this bug on upstream packages in Ubuntu 23.10 amd64 (Qt and libunicorn).

I tried to create a minimal example of this bug. Started new empty Qt Widgets project in Qt Creator. Tested that binary is ok, GUI window shows up. Added find_package(PkgConfig REQUIRED) pkg_check_modules(UNICORN REQUIRED unicorn) include_directories(${UNICORN_INCLUDE_DIRS}) and changed the link cmake command target_link_libraries(test3 PRIVATE Qt${QT_VERSION_MAJOR}::Widgets ${UNICORN_LIBRARIES})

once i force compiler to include libunicorn by putting uc_engine* m_uc; uc_err err = uc_open(UC_ARCH_X86, UC_MODE_32, &m_uc); in main function, the resulting binary is crashing.

Backtrace of the crash #0 0x0000000000000000 in ??? () #1 0x00007ffff5301857 in g_hash_table_add () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #2 0x00007ffff0dfe028 in g_param_spec_pool_insert () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0 #3 0x00007ffff0dfad8e in ??? () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0 #4 0x00007ffff0e1b8be in g_type_class_ref () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0 #5 0x00007ffff0e03892 in g_object_new_with_properties () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0 #6 0x00007ffff0e045f1 in g_object_new () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0 #7 0x00007ffff0ee133d in gdk_display_manager_get () at /lib/x86_64-linux-gnu/libgdk-3.so.0 #8 0x00007ffff0a000c0 in ??? () at /lib/x86_64-linux-gnu/libgtk-3.so.0 #9 0x00007ffff07f5577 in ??? () at /lib/x86_64-linux-gnu/libgtk-3.so.0 #10 0x00007ffff53241da in g_option_context_parse () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #11 0x00007ffff07edc28 in gtk_parse_args () at /lib/x86_64-linux-gnu/libgtk-3.so.0 #12 0x00007ffff07f537a in gtk_init_check () at /lib/x86_64-linux-gnu/libgtk-3.so.0 #13 0x00007ffff07f6a6d in gtk_init () at /lib/x86_64-linux-gnu/libgtk-3.so.0 #14 0x00007ffff0fc048a in ??? () at /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/libqgtk3.so #15 0x00007ffff0fba5a0 in ??? () at /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/libqgtk3.so #16 0x00007ffff492c894 in QPlatformThemeFactory::create(QString const&, QString const&) () at /lib/x86_64-linux-gnu/libQt5Gui.so.5 #17 0x00007ffff4939e48 in QGuiApplicationPrivate::createPlatformIntegration() () at /lib/x86_64-linux-gnu/libQt5Gui.so.5 #18 0x00007ffff493b228 in QGuiApplicationPrivate::createEventDispatcher() () at /lib/x86_64-linux-gnu/libQt5Gui.so.5 #19 0x00007ffff5ad3525 in QCoreApplicationPrivate::init() () at /lib/x86_64-linux-gnu/libQt5Core.so.5 #20 0x00007ffff493e150 in QGuiApplicationPrivate::init() () at /lib/x86_64-linux-gnu/libQt5Gui.so.5 #21 0x00007ffff797135d in QApplicationPrivate::init() () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5 #22 0x0000555555557631 in main (argc=1, argv=0x7fffffffdc08) at /home/vlastik/Projekty/test3/main.cpp:10

This issue happens even if no libunicorn code is ever run, is linker-related only.

I confirmed this issue is affecting unicorn git master and dev, Qt5 and Qt6 both crashes. Glib is used on my system because of GTK theme used in Qt, what can be seen in the backtrace. But I don't understand why glib_compat breaks upstream glib even if symbols are not exposed.

Remove glib_compat solves this for opensource world, where bundling code is not a good way to go. I don't know how to properly solve this issue for windows.

wtdcode commented 2 months ago

I got the point. Please check if you are linking against unicorn statically. If so, could you try to target_link_library with unicorn_static?

vlasta-labsky commented 2 months ago

I dont use static libraries. Checked the ldd output and indeed it is full dynamic binary. I will try static linking of the unicorn.

Ldd output: linux-vdso.so.1 (0x00007fff919a7000) libQt5Widgets.so.5 => /lib/x86_64-linux-gnu/libQt5Widgets.so.5 (0x00007f42f9c00000) libunicorn.so.2 => /lib/x86_64-linux-gnu/libunicorn.so.2 (0x00007f42f8200000) libQt5Core.so.5 => /lib/x86_64-linux-gnu/libQt5Core.so.5 (0x00007f42f7c00000) libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f42f7800000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f42fa3e8000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f42f7400000) libQt5Gui.so.5 => /lib/x86_64-linux-gnu/libQt5Gui.so.5 (0x00007f42f6c00000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f42fa2fb000) /lib64/ld-linux-x86-64.so.2 (0x00007f42fa44e000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f42fa2dc000) libdouble-conversion.so.3 => /lib/x86_64-linux-gnu/libdouble-conversion.so.3 (0x00007f42fa2c8000) libicui18n.so.72 => /lib/x86_64-linux-gnu/libicui18n.so.72 (0x00007f42f6800000) libicuuc.so.72 => /lib/x86_64-linux-gnu/libicuuc.so.72 (0x00007f42f6400000) libpcre2-16.so.0 => /lib/x86_64-linux-gnu/libpcre2-16.so.0 (0x00007f42f9b72000) libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x00007f42f7b49000) libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f42f76b9000) libGL.so.1 => /lib/x86_64-linux-gnu/libGL.so.1 (0x00007f42f8179000) libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f42f9b3a000) libharfbuzz.so.0 => /lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007f42f72f9000) libmd4c.so.0 => /lib/x86_64-linux-gnu/libmd4c.so.0 (0x00007f42f9b28000) libicudata.so.72 => /lib/x86_64-linux-gnu/libicudata.so.72 (0x00007f42f4600000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f42f7aae000) libGLdispatch.so.0 => /lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007f42f6b48000) libGLX.so.0 => /lib/x86_64-linux-gnu/libGLX.so.0 (0x00007f42f7a7c000) libfreetype.so.6 => /lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f42f6734000) libgraphite2.so.3 => /lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007f42f7692000) libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f42f44c2000) libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f42f9b15000) libbrotlidec.so.1 => /lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007f42f9b08000) libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f42f7668000) libbrotlicommon.so.1 => /lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007f42f7645000) libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f42f7a76000) libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f42f7a6e000) libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f42f7630000) libmd.so.0 => /lib/x86_64-linux-gnu/libmd.so.0 (0x00007f42f7621000)

wtdcode commented 2 months ago

If you are using dynamic library, I think it's really not our fault. There are many users using dynamic library via our bindings, especially python and libglib2 is so ubiquitous.

Could you try to reproduce this without Qt? Meaning, just using glib2 and libunicorn.

vlasta-labsky commented 2 months ago

I managed to reproduce it closer to glib, I made GTK3 only minimal window example (without Qt) and it crashes the same way. I am trying to get even closer and have just glib2 and libunicorn, but first I must get understanding of what GTK3 do with glib to make it crash like this.

vlasta-labsky commented 2 months ago

I have got an idea how to test if symbols are leaking out. Made a simple test program in c: #include <glib.h> int main(void) { gpointer ptr = g_malloc(4); return 0; }

I compile this test with gcc -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -o linktest test.c -lunicorn This should fail with "undefined reference" as glib library is not linked and unicorn should not present glib symbols. But it compiles without errors.

Ldd output on this simple binary is: linux-vdso.so.1 (0x00007ffdf190c000) libunicorn.so.2 => /lib/x86_64-linux-gnu/libunicorn.so.2 (0x00007e55a0a00000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007e55a0600000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007e55a241c000) /lib64/ld-linux-x86-64.so.2 (0x00007e55a2545000)

I digged deeper and listed all exported symbols of "libunicorn.so" with nm -D libunicorn.so | grep g_malloc and it shows that symbols are there 00000000003e3993 T g_malloc 00000000003e39ce T g_malloc_n 00000000003e3a04 T g_malloc0 00000000003e3a44 T g_malloc0_n

aquynh commented 2 months ago

Please send in a PR to make those glibc API private, that will solve the problem.

wtdcode commented 2 months ago

I see. It's our fault. All glib functions lacks a __attribute__ ((visibility ("hidden"))).

wtdcode commented 2 months ago

I checked in a minimum patch to dev, could you have a try?

vlasta-labsky commented 2 months ago

I confirm that commit da84208 fixes the bug for me. Thank you for developing this great software :-)