Subject: [alpine-user] ld-musl not resolving symbols

From: Andrew Bell <[email-masked]>
Date: Wed, 7 Feb 2018 13:49:14 -0500

Hi,

I'm trying to run a program I've written that opens a library with
dlopen("libname", RTLD_NOW).   dlopen() succeeds without error and I can
use dlsym() to get a good address of an entry point in the .so, but global
symbols in the dlopen'ed library seem not to be resolved (they're null).

The really strange thing is that this only happens if I run my code as a
python extension through the python2.7 binary.  If I invoke my code through
my own driver, things work fine.

Is there anything that python could be doing that would tell ld-musl not to
resolve all the symbols when dlopen'ing a library?  The documentation I've
seen says that ld-musl always resolves all the symbols in a library when
dlopen() is called.  Are there exceptions to this?  Is there some way I can
trace the behavior of ld-musl?

Thanks,

-- 
Andrew Bell
[email-masked]

---

From: Andrew Bell <[email-masked]>
Date: Thu, 8 Feb 2018 17:38:43 -0500

Replying to my own note here in case it helps someone else.

> symbols in the dlopen'ed library seem not to be resolved (they're null).

The symbols weren't null, but they weren't resolved to the previously
resolved global symbols of the same name - they were given addresses known
only to the dlopen'ed library and dependencies.

> my own driver, things work fine.

In my own driver, the library wasn't dlopen'ed as a python extension is, it
was simply linked.

> Is there anything that python could be doing that would tell ld-musl not
> to resolve all the symbols when dlopen'ing a library?  The documentation
> I've seen says that ld-musl always resolves all the symbols in a library
> when dlopen() is called.  Are there exceptions to this?  Is there some way
> I can trace the behavior of ld-musl?
>

When python dlopen's an extension, by default it uses the flag RTLD_NOW,
but not RTLD_GLOBAL.  This means that the symbols defined in the library
that were linked to the extension module weren't available to be resolved
by subsequent dlopen() calls that were made by code invoked by the
extension module.  In python, this can be changed by setting the dlopen
flags prior to importing the extension module:

import sys
import ctypes
flags = sys.getdlopenflags()
sys.setdlopenflags(flags | ctypes.RTLD_GLOBAL)
from whatever import extentionmodule
sys.setdlopenflags(flags)

Alternatively, you can force the symbols you need exposed to be made global
by calling from C/C++ after the library is loaded:

dlopen("library.so", RTLD_NOLOAD | RTLD_GLOBAL);

The bit I don't understand is why this behavior was different on Ubuntu.  I
read that ld-musl doesn't do lazy symbol resolution, but the documentation
says that only applies to functions, not objects/data anyway.  Is this
perhaps a bug in GNU ld.so that I didn't notice because it worked as I
hoped rather than as documented?

-- 
Andrew Bell
[email-masked]