[Android] NDK issues (found)

* common

+ '-rdynamic' is not supported.
  android dynamic linker allows 'undefined symbol' only for weak symbol.(See (*1))
+ 'tmpfile()' function always returns NULL. "No such file or directory!"
+ 'strtod()' doesn't support '0xXXXX' format.

* NDK 8

'regex.h' exists in 'include'. But function bodies are not in library.

* NDK 9

'pthread_rwlock_xxxx' is declared in 'pthread.h'. But body is missing in library.
'pthread_exit' is declared without 'noreturn' attribute.
'regex' functions doesn't work as it should be. (bug? or not-implemented yet?? I have no idea.)

to be continued…

===== Details =====

(*1) : ‘-rdynamic’ and ‘weak’ symbol (Updated at 2011-Aug-29)

Here is sample code to for testing ‘weak’ symbol at Android.

[ main.c ]
#include <dlfcn.h>
#include <stdio.h>

int g_d;

void
main() {
    void* handle;
    void  (*prf)(void);

    g_d = 369;

    handle = dlopen("/data/libgtst.so", RTLD_LAZY);
    if (!handle) {
        printf("Fail to load library\n");
        return;
    }

    prf = dlsym(handle, "print_g");
    if (NULL != dlerror()) {
        printf("Fail to get symbol print_g\n");
        return;
    }

    (*prf)();
    printf("=== DONE! ===\n");
}

[ lib.c ]
#include <stdio.h>

extern int g_d __attribute__((weak));

void
print_g(void) {
    printf("==> %d\n", g_d);
}

[ Android.mk ]
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libgtst
LOCAL_SRC_FILES := lib.c

LOCAL_CFLAGS :=
LOCAL_C_INCLUDES += $(NDK_PROJECT_PATH)
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := main.c
LOCAL_CFLAGS :=
LOCAL_LDFLAGS :=
LOCAL_C_INCLUDES += $(NDK_PROJECT_PATH)
include $(BUILD_EXECUTABLE)

----- Test Steps -----
* build above codes at Android NDK
adb push libgtst.so /data/libgtst.so
adb push test /data/test
adb shell /data/test
==> 369
=== DONE! ===

to be continued…

Advertisements

4 thoughts on “[Android] NDK issues (found)

  1. As you mentioned that ‘-rdynamic’ is not supported on android.

    My main program needs link to a shared lib and this lib “extern” declare a global variable which defined in the main program.
    First the program will fail to run and get the msg “link_image[1995]: failed to link ./hello CANNOT LINK EXECUTABLE”.

    After read your post, I change the global declaration by adding __attribute__((weak)). The program can be executed but will crash when the code in the shared lib tries to access the global var.

    Can you give any advice? Thanks.

    • Which android version do you use?
      Patch for handling weak symbol at Android Dynamic Linker, is already introduced.
      So, this should works well.
      Here is steps for you.
      – Declare global variable at your main executable.
      – At library, extern global variable with ‘weak’ attribute.
      – At main executable, call your function of library by using ‘dlopen’ and ‘dlsym’.
      This should work.

      • Thanks for your replay.

        Android version is 2.2.
        ndk version is r6(also test with r5b)

        Here is my program:
        – Declare global var in main
        – At lib, extern global var with/without weak
        – At lib, function to print the global var
        – At main, call the function with/without ‘dlopen’ & ‘dlsym’
        – Set LD_LIBRARY_PATH on android

        Here is the result:
        1. At lib, extern global with or without weak; At main call with ‘dlopen’ & ‘dlsym’:
        Both work. It seems the weak attribute is not necessary. Nothing weird in this case.

        2. At lib(say libtest.so), extern global with or without weak; At main, call function directly:
        – with weak, the main program crash with ‘Segmentation fault’, I enabled the linker debug output, and the weak symbol is NULL
        – without weak, the main program cannot startup with ‘link_image[1995]: failed to link ./main CANNOT LINK EXECUTABLE’. The debug output indicates that when loading the libtest.so, the externed global var symbol cannot be resolved.

        Compile cmd for libtest.so:
        arm-linux-androideabi-gcc -fPIC -c ./hello_shared.c -I /home/deepsky/android-ndk-r6/platforms/android-8/arch-arm/usr/include/
        arm-linux-androideabi-gcc -shared -o libtest.so hello_shared.o -L /home/deepsky/android-ndk-r6/platforms/android-8/arch-arm/usr/lib

        Compile cmd for main:
        arm-linux-androideabi-gcc -o main ./main.c -I /home/deepsky/android-ndk-r6/platforms/android-8/arch-arm/usr/include/ -L /home/deepsky/android-ndk-r6/platforms/android-8/arch-arm/usr/lib -nostdlib -lc -ldl -L. -ltest /home/deepsky/android-ndk-r6/platforms/android-8/arch-arm/usr/lib/crtbegin_dynamic.o (also test with -rdynamic)

        But case2 with almost the same compilation flags(exclude the cross-compile flags) will work on Linux on PC.
        I read the linker debug output in logcat and it shows that when starting main program, without using dlopen/dlsym, Android will first to resolve all symbols in the needed libraries. When searching the extern global var the dynamic linker (/system/bin/linker) will not search it in main program, so the lib cannot be loaded. As a result, the main program fails to run.

        Anything wrong with the dynamic linker on android?
        I also checked the source code of the dynamic linker. A comment shows that the dynamic linker doesn’t support ‘Lazy binding’ currently?

      • I didn’t check your command line in detail.
        But, as you may know, NDK support it’s own build tool – ‘ndk-build’.
        My testing by using ndk-build gives totally different result from yours (on NDK-9).
        I don’t have any idea about your situation. So, I can’t give you any idea about this issue.
        The only idea in my mind is,
        *check with give ndk-build tool
        *compare your own build command line with ndk-build-tool’s one.
        I’m sorry for humble idea.
        God bless you :-)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s