Package: ksh
Version: 93u+20120801-2
Severity: important
Tags: upstream

Dear Maintainer,

I have been attempting to build a loadable module (AKA "loadable built-in") for
ksh and I have been encountering a lot of undefined symbol errors when invoking
the module:


$ builtin -f ./recvmsg.so recvmsg
$ echo hi | recvmsg msgvar fdvar
ksh: symbol lookup error: ./recvmsg.so: undefined symbol: nv_open


After doing some digging I believe this is because symbols from the ksh
executable are not being exported to the loaded modules. (In this case,
nv_open() is one of the routines that modules may use to set shell variables.
It is implemented internally as part of ksh but used by loadable modules.)

Having looked through the code, I believe this to be a platform-specific build
issue. ksh uses this code to load the module:

dllopen(dle->path, (flags | RTLD_GLOBAL | RTLD_PARENT))
(src/lib/libdll/dllplug.c:54)
("dllopen" is defined in src/lib/libdll/dllopen.c: it performs some path
searches and then calls dlopen())

The flag RTLD_PARENT indicates that the loaded module should have access to the
host executable's symbols. However, RTLD_PARENT is not implemented on Linux.
ksh provides a fallback definition for the flag to allow compilation to
succeed:


#define RTLD_PARENT 0       // in ./arch/linux.i386-64/include/ast/dlldefs.h


To enable the equivalent functionality on Linux, the host executable must be
linked with the --export-dynamic flag. I have had some success by adding this
to debian/rules:


LDFLAGS += -Wl,--export-dynamic


With this set, I was able to build and invoke one of the example modules
included in the ksh source distribution (src/lib/libast/comp/open.c) with just
minor alteration:

Compiled as-is, the "open" module still failed to find the function tmfmt()
(defined in src/lib/libast/tm/tmform.c) - but, by disabling the calls to
tmfmt() in open.c I was able to get the rest of the module working:


gcc -c -fPIC -g -I ~/src/ksh-93u+20120801/arch/linux.i386-64/include/ast/ -I
~/src/ksh-93u+20120801/src/cmd/ksh93/include/ -I ~/src/ksh-
93u+20120801/arch/linux.i386-64/src/cmd/ksh93/ -c -o open.o open.c
gcc -shared -L ~/src/ksh-93u+20120801/arch/linux.i386-64/lib -last
-Wl,-soname,open.so -o open.so open.o

# Unaltered open.c:
$ builtin -f ./open.so open
$ open -r f Makefile
$ echo $f
/home/tetsujin/src/ksh-93u+20120801/arch/linux.i386-64/src/cmd/ksh93/ksh:
symbol lookup error: ./open.so: undefined symbol: tmfmt

# With call to tmfmt() replaced with "strcpy(buff, "{time}");" :
$ open -r f Makefile
$ echo $f
( atime='{time}' ctime='{time}' dev=2053 fd=4 gid=1000 ino=2744616
mode=u='rw,g=r,o=r' mtime='{time}' name=open.c nlink=1 size=12936 uid=1000 )
# Success!


Basically it appears as though functions from within ksh (nv_open(), etc.) are
being exported to my loadable modules correctly, but functions from within
libast (for instance, tmfmt() or fprintf()) are not. For my purposes that's a
distinct improvement - though it'd be much better to have ast calls working as
well.  (If I figure that one out, I'll let you know.)



-- System Information:
Debian Release: stretch/sid
  APT prefers testing
  APT policy: (500, 'testing'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.3.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages ksh depends on:
ii  binfmt-support  2.1.5-3
ii  libc6           2.21-7

ksh recommends no packages.

ksh suggests no packages.

-- no debconf information

Reply via email to