Author xdegaye
Recipients Alex.Willmer, python-dev, skrah, xdegaye, yan12125
Date 2017-02-06.19:41:22
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1486410083.77.0.920876740816.issue29439@psf.upfronthosting.co.za>
In-reply-to
Content
With the following module named dlsym.py, the command 'python dlsym.py log10' produces the same successful output on linux and on Android API 21 (when _decimal is not explicitly linked with libm.so, i.e.without changeset b60b46ad8751):
  'The symbol "log10" is resolved.'

----------------------     dlsym.py     ---------------------------
import sys, os
from ctypes import *

if len(sys.argv) != 2:
    sys.exit('Error: the symbol name is required.')
symbol = sys.argv[1]
libdl = CDLL('libdl.so')
libdl.dlopen.restype = c_void_p
libdl.dlsym.restype = c_void_p
hdle = libdl.dlopen(None, os.RTLD_NOW | RTLD_GLOBAL)
if hdle is None:
    print('Cannot get a handle on the global symbol object.')
else:
    v = libdl.dlsym(c_void_p(hdle), symbol.encode())
    _not = 'not ' if v is None else ''
    print('The symbol "%s" is %sresolved.' % (symbol, _not))
-------------------------------------------------------------------

This is as expected since the python executable is linked with the math library. However on Android API 21 importing _decimal fails with the error message reported earlier:
  'dlopen failed: cannot locate symbol "log10"'.

So this seems to be a bug with Android dlopen() at API 21 since the 'log10' symbol does exist in the process image relocation tables as shown by dlsym.py. This is confirmed by the fact that the import does not fail anymore at API 24 (still without changeset b60b46ad8751). This change of behavior may be a side effect of the changes reported in this bionic (Android libc) changelog entry:
    https://android.googlesource.com/platform/bionic/+show/refs/heads/master/android-changes-for-ndk-developers.md#36

For completness, my (possibly wrong) interpretation of why changeset b60b46ad8751 fixes the problem at API 21:
Changeset b60b46ad8751 adds the '-lm' command line option to the linker and this adds [1] a new DT_NEEDED entry to the .dynamic section of the shared library ELF file as shown by the command 'readelf -d build/lib.linux-x86_64-3.7-pydebug/_decimal.cpython-37dm-x86_64-linux-gnu.so':

Dynamic section at offset 0x54d30 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 ...

The Android loader lookup for 'log10' is now successful at API 21 and the symbol is found in the libm.so.6 library listed in the DT_NEEDED lists of needed libraries.

[1] See option '--as-needed' in the 'ld' man pages or see the ELF specification. Note that the Android toolchains use the clang compiler but continue to use the GNU binutils tools including the linker 'ld'.
History
Date User Action Args
2017-02-06 19:41:23xdegayesetrecipients: + xdegaye, skrah, python-dev, Alex.Willmer, yan12125
2017-02-06 19:41:23xdegayesetmessageid: <1486410083.77.0.920876740816.issue29439@psf.upfronthosting.co.za>
2017-02-06 19:41:23xdegayelinkissue29439 messages
2017-02-06 19:41:22xdegayecreate