Dino on FreeBSD

Posted on

Tags: FreeBSD dino XMPP

This post is about trying out Dino XMPP client on FreeBSD. After seeing its screenshots, I was very tempted to try it on FreeBSD. Unfortunately, build was broken on FreeBSD, such that it’s crashing on FreeBSD during startup 😦:

(dino:6934): Gtk-ERROR **: 15:48:19.270: failed to add UI: .:9:1 Invalid object type 'DinoUiConversationSelectorView'

So today, I decided to investigate the problem. I’m not super familiar with Gtk+ ecosystem these days, having not worked with it in a long while. My first suspect was that the .ui template file is not getting included in the build or something, but it turns out it’s getting compiled into the binary:

λ strings /usr/local/bin/dino |fgrep -B3 -A12 DinoUiConversationSelectorView
title
with:
string_index_of
DinoUiConversationSelectorView
are typing
display_name != NULL
dino_ui_conversation_summary_file_item_widget_generator_getDefaultWidget
dino_ui_conversation_summary_content_provider_construct
dino_ui_conversation_summary_conversation_view_do_insert_item
dino_ui_conversation_summary_conversation_view_split_at_time
system-users-symbolic
DinoUiConversationTitlebar
/im/dino/Dino/manage_accounts/account_row.ui
server
register_form_continue
dino_ui_manage_accounts_dialog_construct
--
        <property name="orientation">horizontal</property>
        <property name="visible">True</property>
        <child>
            <object class="DinoUiConversationSelectorView" id="conversation_list">
                <property name="visible">True</property>
            </object>
            <packing>
                <property name="resize">False</property>
                <property name="shrink">False</property>
            </packing>
        </child>
        <child>
            <object class="GtkOverlay">
                <property name="visible">True</property>
                <child>
                    <object class="GtkOverlay">
--
view.ui
<?xml version="1.0" encoding="UTF-8"?>
<interface>
    <template class="DinoUiConversationSelectorView">
        <property name="can_focus">True</property>
        <property name="expand">True</property>
        <property name="orientation">vertical</property>
        <child>
            <object class="GtkScrolledWindow" id="scrolled">
                <property name="expand">True</property>
                <property name="hscrollbar_policy">never</property>
                <property name="visible">True</property>
            </object>
        </child>
    </template>
</interface>

Next suspect was something being broken with GLib resource loading, but that also was bad guess when gdb confirmed that the g_static_resource_init() is also getting hit.

(gdb) bt
#0  0x00000008014d07f8 in g_static_resource_init (static_resource=0x3072a0 <static_resource>) at gresource.c:1341
#1  0x00000000003032a3 in resource_constructor () at main/resources/resources.c:25403
#2  0x00000008003120fb in objlist_call_init (list=<optimized out>, lockstate=<optimized out>) at /usr/src/libexec/rtld-elf/rtld.c:2678
#3  0x0000000800310f4c in _rtld (sp=<optimized out>, exit_proc=0x7fffffffe000, objp=0x7fffffffe008) at /usr/src/libexec/rtld-elf/rtld.c:745
#4  0x000000080030f019 in .rtld_start () at /usr/src/libexec/rtld-elf/amd64/rtld_start.S:39
#5  0x0000000000000000 in  ()

After some further debugging I figured it that resources are embedded fine, and that it’s the type’s function symbol dino_ui_conversation_selector_view_get_type() that was failing to load via _g_module_symbol() which itself relies on dlsym() for loading the actual symbol from ELF file.

I wrote a minimal test case to see if I can reproduce the problem:

#include <dlfcn.h>
#include <stdio.h>

void*
dino_ui_conversation_selector_view_get_type (void)
{
        printf("Hello, world!\n");
        return ((void*)(42*42));
}

int
main()
{
        void* sym;

        sym = dlsym( RTLD_DEFAULT, "dino_ui_conversation_selector_view_get_type" );
        fprintf( stderr, "Output: %p\n", sym);
        fprintf( stderr, "Error (if any): %s\n", dlerror());
}

And turns out I can:

λ cc -g -o rtld-test{,.c}
λ ./rtld-test
Output: 0x0
Error (if any): Undefined symbol "dino_ui_conversation_selector_view_get_type"

After RTFM-ing ld(1) to see if I’m missing some compiler/linker flag, I spotted:

 --export-dynamic
     Put symbols in the dynamic symbol table.

And then:

λ cc -Wl,--export-dynamic -g -o ./rtld-test{,.c}
chateau.d.if!abbe:~/progs/c λ ./rtld-test
Output: 0x201350
Error (if any): (null)

w00t! 😅

Turns out what I was missing --export-dynamic linker option. After adding that dino works just fine. 😊

Thanks to availablity of debug symbols in base system (by default, from FreeBSD 12.0-RELEASE), and my decision to always keep debug builds for Glib2, and Gtk+ libraries (from few days ago) really helped with this debugging:

# make.conf(5)
WITH_DEBUG_PORTS+=      net-im/dino
WITH_DEBUG_PORTS+=      x11-toolkits/gtk20
WITH_DEBUG_PORTS+=      x11-toolkits/gtk30