tech-x11 archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: alacritty: possible inputmethod issue?
tnn reports that this works when built with X from pkgsrc, so I wonder
if we're doing something wrong in base X11 to break this.
Does anyone have an idea?
This is caused by:
1. alacritty -> dlopen(libX11.so)
2. libX11.so -> dlopen(/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so)
3. xlcUTF8Load.so referencing _XlcGenericMethods back inside libX11.so
---
$ LD_LIBRARY_PATH=/usr/src/external/mit/xorg/lib/libX11/dynamic/ ./xim-dl
Trying to open XIM without RTLD_GLOBAL
path=/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2
/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2: Undefined symbol "_XlcGenericMethods" (symnum = 7)
path=/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2
/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2: Undefined symbol "_XlcGenericMethods" (symnum = 7)
path=/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2
/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2: Undefined symbol "_XlcGenericMethods" (symnum = 7)
path=/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2
/usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so.2: Undefined symbol "_XlcGenericMethods" (symnum = 7)
XSetLocaleModifiers() failed
[...]
$ nm -D /usr/X11R7/lib/libX11.so | fgrep _XlcGenericMethods
0000000000305040 D _XlcGenericMethods
$ nm -D /usr/X11R7/lib/X11/locale/lib/common/xlcDef.so | fgrep _XlcGenericMethods
U _XlcGenericMethods
$ nm -D /usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so | fgrep _XlcGenericMethods
U _XlcGenericMethods
$ nm -D /usr/X11R7/lib/X11/locale/lib/common/xlibi18n.so | fgrep _XlcGenericMethods
U _XlcGenericMethods
---
None of the runtime linkers that I tried (NetBSD 9.99.86, FreeBSD
13-RELEASE, Ubuntu 19.04) allow this sort of "back-reference" without
RTLD_GLOBAL (possibly to preclude reference-loops).
The solution is to either
a) fold these locale modules back into libX11.so like in pkgsrc:
---
# pkgsrc
$ nm -D lib/libX11.so.6.4.0 | fgrep _XlcUtf8Loader
000000000006efe0 T _XlcUtf8Loader
$
# system xorg
$ nm -D /usr/X11R7/lib/libX11.so | fgrep _XlcUtf8Loader
$ nm -D /usr/X11R7/lib/X11/locale/lib/common/xlcUTF8Load.so |
fgrep _XlcUtf8Loader
0000000000000760 T _XlcUtf8Loader
$
---
or,
b) Explicitly link the locale modules with -lX11: after all they
are using stuff from there. Right now, they only depend on
libc.so
Test programs (many thanks to iquiw--I wouldn't have bothered to
look into this without xim-dl.c):
---
==> Makefile <==
CC = gcc
CFLAGS = -Wall -Wextra -O2 -pipe
LFLAGS = -fpic -shared
run: dltest
env LD_LIBRARY_PATH=$$(pwd) ./dltest
dltest: main.c a.so b.so
${CC} ${CFLAGS} -o $@ main.c
a.so: a.c
${CC} ${CFLAGS} ${LFLAGS} -o $@ $>
b.so: b.c
${CC} ${CFLAGS} ${LFLAGS} -o $@ $>
clean:
rm -f dltest *.so
==> a.c <==
#include <dlfcn.h>
#include <stdbool.h>
#include <stdio.h>
int a;
bool
a_fn(void)
{
bool (*b_fn)(void);
void* h;
printf("Inside: %s\n", __func__);
a = 42; /* no access from dlopen()ed b.so */
if ((h = dlopen("b.so", RTLD_NOW)) == NULL) {
fprintf(stderr, "%s\n", dlerror());
return false;
}
if ((b_fn = (bool (*)(void))dlsym(h, "b_fn")) == NULL) {
fprintf(stderr, "%s\n", dlerror());
dlclose(h);
return false;
}
dlclose(h);
return true;
}
==> b.c <==
#include <stdbool.h>
#include <stdio.h>
extern int a;
bool
b_fn(void)
{
printf("Inside: %s\n", __func__);
printf("Extern: a=%d\n", a);
return true;
}
==> main.c <==
/**
* https://mail-index.netbsd.org/tech-x11/2021/06/19/msg002208.html
*
* main() loads a.so; calls a_fn() within
* a_fn() defines global int a; tries to load b.so
* Without RTLD_GLOBAL this load will fail because of back-referenced
* symbol `a' in b.so. Only forward-references are OK for the runtime
* linker.
*
* alacritty, written in Rust, fails to start on NetBSD because of this
* behaviour. alacritty -> libX11.so -> xlcUTF8load.so -> which needs
* _XlcGenericMethods defined in libX11.so.
*/
#include <dlfcn.h>
#include <stdbool.h>
#include <stdio.h>
static void
my_dl(int flags)
{
bool (*a_fn)(void);
void* h;
if ((h = dlopen("a.so", flags)) == NULL)
fprintf(stderr, "%s\n", dlerror());
else {
if ((a_fn = (bool (*)(void))dlsym(h, "a_fn")) == NULL)
fprintf(stderr, "%s\n", dlerror());
else
printf("a_fn loading b.so = %s\n", a_fn() ?
"OK" : "ERR");
dlclose(h);
}
}
int
main(void)
{
printf("loading a.so with RTLD_NOW\n");
my_dl(RTLD_NOW);
printf("loading a.so with RTLD_NOW | RTLD_GLOBAL\n");
my_dl(RTLD_NOW | RTLD_GLOBAL);
return 0;
}
---
-RVP
Home |
Main Index |
Thread Index |
Old Index