Различное поведение переопределения слабой функции в разделяемой библиотеке между OS X и Android

Я сталкиваюсь с другим поведением между OS X и Android:

  • Есть слабая функция foo в моей общей библиотеке,
  • Я хочу переопределить его сильной функцией, определенной в моем исполняемом файле.
  • Я ожидаю, что переопределенные также влияют на вызов внутри библиотеки

Результат: я получил ожидаемый результат на OS X, но потерпел неудачу на Android.


Вот мой тестовый проект:

Файл: shared.h

void library_call_foo();
void __attribute__((weak)) foo();

Файл: shared.c

#include "shared.h"
#include <stdio.h>

void library_call_foo()
{
    printf("shared library call foo -> ");
    foo();
}

void foo()
{
    printf("weak foo in library\n");
}

Файл: main.c

#include <stdio.h>
#include <shared.h>

void foo()
{
    printf("strong foo in main\n");
}

int main()
{
    library_call_foo();
    printf("main call foo -> ");
    foo();
    return 0;
}

Я компилирую и запускаю его в OS X используя команды:

clang -shared -fPIC -o libshared.so shared.c
clang -I. -L. -lshared -o test main.c
./test

которые возвращают результаты, как я ожидал:

shared library call foo -> strong foo in main
main call foo -> strong foo in main

Но когда я компилирую его для Android с помощью цепочек инструментов NDK, использую те же команды:

arm-linux-androideabi-clang -shared -fPIC -o libshared.so shared.c
arm-linux-androideabi-clang -I. -L. -lshared -o test main.c

и запустить его на устройстве, я получил разные результаты:

shared library call foo -> weak foo in library
main call foo -> strong foo in main

Почему поведение отличается, и как я могу это исправить?

2 ответа

Динамический компоновщик Android на самом деле поддерживает слабые символы. Проблема в данном конкретном случае заключается в том, что библиотека компилируется с -Bsymbolic (чтобы проверить этот запуск "readelf -d libshared.so").

Обходной путь заключается в использовании "-Wl,-shared" вместо "-shared" при связывании библиотеки.

См. https://code.google.com/p/android/issues/detail?id=68956 подробности и способы их решения.

Android не поддерживает слабое переопределение символов.

В последнем выпуске android-5.0.2_r1 см. Комментарий в строке 539 в исходном коде linker.cpp.

/*
 *
 * Notes on weak symbols:
 * The ELF specs are ambigious about treatment of weak definitions in
 * dynamic linking.  Some systems return the first definition found
 * and some the first non-weak definition.   This is system dependent.
 * Here we return the first definition found for simplicity.
 */

Этот комментарий существует с версии 2.2_r1 (которая находится в linker.c) до новейшей версии 5.0.2_r1

Другие вопросы по тегам