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
are typing
display_name != NULL
        <property name="orientation">horizontal</property>
        <property name="visible">True</property>
            <object class="DinoUiConversationSelectorView" id="conversation_list">
                <property name="visible">True</property>
                <property name="resize">False</property>
                <property name="shrink">False</property>
            <object class="GtkOverlay">
                <property name="visible">True</property>
                    <object class="GtkOverlay">
<?xml version="1.0" encoding="UTF-8"?>
    <template class="DinoUiConversationSelectorView">
        <property name="can_focus">True</property>
        <property name="expand">True</property>
        <property name="orientation">vertical</property>
            <object class="GtkScrolledWindow" id="scrolled">
                <property name="expand">True</property>
                <property name="hscrollbar_policy">never</property>
                <property name="visible">True</property>

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>

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

        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:

     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