Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*.so is too small to be an ELF executable #234

Closed
trivedigaurav opened this issue May 10, 2014 · 17 comments · Fixed by #251
Closed

*.so is too small to be an ELF executable #234

trivedigaurav opened this issue May 10, 2014 · 17 comments · Fixed by #251

Comments

@trivedigaurav
Copy link
Member

Running a packaged kivy app on Android causes: "ImportError: dlopen failed: "/data/data/org.test.sms/files/lib/python2.7/site-packages/kivy/properties.so" is too small to be an ELF executable.

Run Log (using logcat): https://gist.github.com/trivedigaurav/74197a06807c4abdb485
Build Log (using P4A): https://gist.github.com/trivedigaurav/8203502e17bd1cf52e31

Related:

@trivedigaurav
Copy link
Member Author

Since I was able to build APKs successfully before (it has recently stopped working), I had the helloworld example of an APK (built on my same system) that worked fine. I have uploaded them in case it helps.

Working fine - http://ge.tt/1CwVwah1/v/0
ELF Problem - http://ge.tt/8lmHwah1/v/0

And here's the folder diff output between these two packages: https://gist.github.com/trivedigaurav/2e657dc5f995be6a5729

@trivedigaurav
Copy link
Member Author

I tried to build a distribution using the Ubuntu VM provided in the downloads section on the kivy website as well. I get a very similar error there as well:

I/python  (18650):    File "/home/kivy/code/test/hello/main.py", line 1, in <module>
I/python  (18650):    File "/home/kivy/android/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/app.py", line 321, in <module>
I/python  (18650):    File "/home/kivy/android/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/base.py", line 29, in <module>
I/python  (18650):    File "/home/kivy/android/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/event.py", line 8, in <module>
I/python  (18650):  ImportError: dlopen failed: "/data/data/org.hello.world/files/lib/python2.7/site-packages/kivy/_event.so" has unexpected e_machine: 3
I/python  (18650): Python for android ended.
I/ActivityManager(  815): Process org.hello.world:python (pid 18650) (adj 0) has died.

This confirms that this is not a mac specific issue.

Also, here's the log while creating a distribution using disitribute.sh: http://pastebin.com/LgfZPE1s; It looks like that it may be due an error in the kivy code.

@trivedigaurav
Copy link
Member Author

I am to confirm that I see these errors when I use the local copy of the Kivy code by setting $P4A_kivy_DIR variable. The APKs run just fine when using the default kivy version in P4A (by not setting the variable). This probably suggests this issue may be moved to kivy/kivy.

Thanks to @brousch for helping me confirm these.

@brousch
Copy link
Contributor

brousch commented May 20, 2014

I am able to replicate this problem by using the P4A_kivy_DIR environment variable. When using a local kivy clone and that environment setting, the APK is built, but crashes on Android with the "too small to be an ELF error". Additionally, the APKs generated using a local Kivy clone and barebones Hello World program are about 5.6MB. APKs created using the normal python-for-android downloaded Kivy end up around 6.3MB.

My best guess is that python-for-android is doing something different when downloading and extracting Kivy compared to when it's using a local clone.

Here is an APK generated using P4A_kivy_DIR with a local Kivy clone with the 1.8.0 branch checked out: https://www.dropbox.com/s/zugkjaydvtk9t4e/HelloWorld-1.0-debug-local.apk

Here is an APK generated using the normal python-for-android Kivy download of the stable branch: https://www.dropbox.com/s/uc6dgxiekmbvmj3/HelloWorld-1.0-debug-normal.apk

@kived
Copy link
Contributor

kived commented May 20, 2014

FYI - this usually happens for me when there is a C extension conflict. C module names (NOT including namespace!) must be unique. So, for example, if you have package1.module and package2.module as C extensions, this conflict will happen (both are called module, containing functions init_module() and generate module.so). This is because all .so files are packed into a single libpymodules.so. The .so files in the Python folders are fakes (0 bytes) to trick the interpreter into loading modules which are already loaded via libpymodules.so.

Things get even trickier with pure C (non-Cython) extensions, like cdecimal. Here we have to worry about ALL function name collisions, because nothing is guaranteed to have a unique name, whereas Cython generates names like __pyx_gb_4kivy_6_event_2generator(). The module init function will still be init_event() for kivy._event whether it's pure C or Cython.

FWIW we always use P4A_kivy_DIR, as we have our own modifications to Kivy.

@brousch
Copy link
Contributor

brousch commented May 21, 2014

I can now reliably reproduce and fix this bug using plain python-for-android and buildozer.

Buildozer:

  1. Set the P4A_kivy_DIR to a local clone of Kivy
  2. Run buildozer android debug - this will produce a working APK
  3. Delete the app's .buildozer dir
  4. Run buildozer android debug - this will produce an APK with the small ELF problem
  5. Delete the Kivy clone and the app's .buildozer dir
  6. Run buildozer android debug - this will produce a working APK

python-for-android

  1. Set the P4A_kivy_DIR to a local clone of Kivy
  2. Run ./distribute.sh -m "kivy" - this will produce a working distribution
  3. Delete the build and dist dirs
  4. Run ./distribute.sh -m "kivy" - this will produce a non-working distribution
  5. Delete the Kivy clone and the build and dist dirs
  6. Run ./distribute.sh -m "kivy" - this will produce a working distribution

@brousch
Copy link
Contributor

brousch commented May 21, 2014

I've narrowed the problem further. You only need to delete the dist directory to trigger it. In buildozer, that's .buildozer/android/platform/python-for-android/dist and in python-for-android that's dist.

@trivedigaurav
Copy link
Member Author

@brousch I am able to reproduce this issue (ie. create a distribution that makes an apk with ELF errors) with the following steps using python-for-android:

  1. set p4a variable in ~/.bashrc:

    export P4A_kivy_DIR = /home/code/kivy

  2. go to P4A directory

  3. clean builds
    rm -rf build/

  4. also remove the previous dist (you may skip this step if you'd be creating another distribution with a new name using distribute.sh -d option)

    rm -rf dist/default

  5. now create the distribution

    distribute.sh -m "kivy"

  6. Run build.sh from the new dist

In order to create, a working distribution you need to follow all of the above steps but without the P4A variable set. Remember to source bashrc again or open a new terminal.

My guess is that we may have introduced the problem mentioned by @kived between the stable version of kivy and now.

@trivedigaurav
Copy link
Member Author

@akshayaurora has further narrowed this issue. You can work around this issue by deleting the build/ directory from your P4A_kivy_DIR before you create a distribution. Make sure you clean your P4A directory (builds and dists) as well before you do this the first time.

@inclement
Copy link
Member

The problem seems to definitely be that the object files in an existing build directory are not packed properly into libpymodules.so - you can see by comparison of apk sizes, a working apk is about 0.7MB larger, and unpacking reveals this difference is all in libpymodules.so. Checking that with objdump, sure enough the not working one doesn't include everything from kivy.

I still don't know why (looking into it still), but adding that here in case it helps anyone.

@inclement
Copy link
Member

I think I tracked this down to being related to the most recent change in the kivy recipe, replacing 'cython' with '$CYTHON' which is really 'cython -t'. Does anyone else find that reverting that change makes things work again?

I asked tito about it (copied below to not forget...), and he gave directions to investigate further so I'll keep going - the correct fix is probably not to revert the above change (it should work) but to fix something else that causes the problem.

00:25 <+tito> what symbol are missing?
00:27 <+tito> that should give an hint about what's failing
00:28 <+tito> and the issue is now either on the strip, biglink, or deduplicate
00:28 -!- jwinterm [[email protected]] has quit [Ping timeout: 252 seconds]
00:28 <+tito> strip -> in recipe/XX.sh usually, done manually
00:28 <+tito> biglink -> the python script
00:28 <+tito> deduplicate -> the tiny sh function (uber uber hackish)
00:29 <+tito> i bet deduplicating twice, maybe.

Of these, I think biglink is fine - the kivy files are already missing from the argument directory passed to it. I pasted the files it sees at http://inclem.net/files/kivy/biglink_sofiles.txt .

@inclement
Copy link
Member

I did a pr for a fix, but it needs some discussion and confirmation about what's really going on - I wrote my semi-speculation there, but I don't follow all the technical details and it might be the wrong way to change things.

@thegrymek
Copy link

Hi,

I have the same error when I set P4A_pyjinius_DIR.

@cbenhagen
Copy link
Contributor

I am running into the same error with NO P4A_kivy_DIR set. #251 did not fix it.

@cbenhagen
Copy link
Contributor

I finally found what triggered this error in my case: pyyaml. Actually the pyyaml recipe. After removing it from p4a (rm -f .buildozer/android/platform/python-for-android/recipes/pyyaml) my app worked again. While this is only a workaround it might help narrow down the actual bug. Or at least it would help someone who got bitten by it.

I tested on Ubuntu 14.04 and OSX 10.10.2 with a minimal hello world example: https://gist.github.com/cbenhagen/e16da236c3aa821d0a81

@tito tito closed this as completed in #251 May 16, 2015
@tito tito reopened this May 16, 2015
@dl1ksv
Copy link
Contributor

dl1ksv commented Jun 28, 2015

I get the same problem when building ( and running ) the compass example of kivy from a fresh git checkout
distribute.sh -m "kivy"
The only adaptation I made was setting the toolchain version to 4.6 instead of 4.4.3 in distribute.sh
The file jnius.so is empty ( 0 byte).
Looking into the build messages I got

creating build/lib.linux-x86_64-2.7/jnius
/home/schroer/python-for-android/src/tools/liblink -lm -L/home/schroer/python-for-android/build/libs -DANDROID -mandroid -fomit-frame-pointer --sysroot /opt/android-ndk/platforms/android-14/arch-arm build/temp.linux-x86_64-2.7/jnius/jnius.o -Llibs/armeabi -L/home/schroer/python-for-android/build/python-install/lib -lsdl -llog -lpython2.7 -o build/lib.linux-x86_64-2.7/jnius/jnius.so
/home/schroer/python-for-android/build/python-install/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'install_requires'
warnings.warn(msg)
running install

To avoid The UserWarning I patched pyjnius/setup.py by

--- pyjnius/master/setup.orig.py 2015-06-27 17:53:45.939286150 +0200
+++ pyjnius/master/setup.py 2015-06-27 17:54:21.783483210 +0200
@@ -1,4 +1,7 @@
-from distutils.core import setup, Extension
+try:

  • from setuptools import setup, Extension
    +except ImportError:
  • from distutils.core import setup, Extension
    from os import environ
    from os.path import dirname, join, exists
    import sys

and run

distribute.sh -m "setuptools kivy"

Now I get the build error
creating build/lib.linux-x86_64-2.7/jnius
/home/schroer/python-for-android/src/tools/liblink -lm -L/home/schroer/python-for-android/build/libs -DANDROID -mandroid -fomit-frame-pointer --sysroot /opt/android-ndk/platforms/android-14/arch-arm build/temp.linux-x86_64-2.7/jnius/jnius.o -Llibs/armeabi -L/home/schroer/python-for-android/build/python-install/lib -lsdl -llog -lpython2.7 -o build/lib.linux-x86_64-2.7/jnius/jnius.so
running install
Traceback (most recent call last):
File "setup.py", line 142, in
'Topic :: Software Development :: Libraries :: Application Frameworks'])
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/distutils/core.py", line 152, in setup
dist.run_commands()
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/distutils/dist.py", line 953, in run_commands
self.run_command(cmd)
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/site-packages/setuptools/command/install.py", line 76, in run
self.do_egg_install()
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/site-packages/setuptools/command/install.py", line 85, in do_egg_install
easy_install = self.distribution.get_command_class('easy_install')
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/site-packages/setuptools/dist.py", line 395, in get_command_class
self.cmdclass[command] = cmdclass = ep.load()
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/site-packages/pkg_resources.py", line 1954, in load
entry = import(self.module_name, globals(),globals(), ['name'])
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 12, in
import sys, os.path, zipimport, shutil, tempfile, zipfile, re, stat, random
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/zipfile.py", line 6, in
import io
File "/home/schroer/python-for-android/build/python-install/lib/python2.7/io.py", line 60, in
import _io
ImportError: /home/schroer/python-for-android/build/python-install/lib/python2.7/lib-dynload/_io.so: wrong ELF class: ELFCLASS32

I tested on gentoo with these settings

Check environment
SDK located at /opt/android-sdk-update-manager/
NDK located at /opt/android-ndk
NDK version is r8c
API level set to 14

The touchtracer example works.

@akshayaurora
Copy link
Member

@dl1ksv yours is a different error than the original one in this issue the original issue happens on device when the build is not recompiled which should not happen anymore cause we force recompilation.

Your issue which is raised while compiling is most probably cause of issues with python installation being broken, @ecdsa found out that this was the cause of a similar error as yours. He solved the issue with installing python using apt-get.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants