programas - instalar wine 3.0 en android
EjecuciĆ³n de una biblioteca nativa en Android L. error: solo se admiten ejecutables independientes de posiciĆ³n(PIE) (3)
Construí dos archivos ejecutables: uno con APP_PLATFORM := android-9
y el otro con APP_PLATFORM := android-16
. Para ejecutar el código nativo en Java, necesito esto:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
// Run the file which was created using APP_PLATFORM := android-16
} else {
// Run the file which was created using APP_PLATFORM := android-9
}
Cuando ejecuto el código nativo en Android L (Nexus 5), obtengo el error.
error: solo se admiten ejecutables independientes de posición (PIE).
El mismo código se ejecuta correctamente en mi Samsung Galaxy S3 (Android 4.3).
Aquí está mi Application.mk
APP_PROJECT_PATH := $(call my-dir)/..
APP_ABI := armeabi
NDK_TOOLCHAIN_VERSION := 4.7
APP_PLATFORM := android-9
APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti
Sin embargo cuando reemplazo APP_PLATFORM := android-9
con APP_PLATFORM := android-16
(Como he leído here , el soporte de PIE apareció en Jelly Been (nivel de API 16)), el mismo archivo ejecutable funciona bien en Android L.
¿Hay alguna forma de compilar código nativo usando APP_PLATFORM := android-9
y ejecutarlo en Android L?
El proyecto Chromium lanzó un wrapper que permite que los binarios PIE se ejecuten en versiones anteriores a JB Android. Tenga en cuenta que su ejecutable PIE requiere algunas banderas adicionales para que esto funcione:
CFLAGS += -fvisibility=default -fPIE
LDFLAGS += -rdynamic -fPIE -pie
En mi caso, estaba enviando ~ 2MB binarios para 3 arquitecturas y no quería agregar 6MB de datos sin comprimir al APK solo para continuar con el soporte de ICS. run_pie
es extremadamente pequeño (6-7kB) por lo que se ajusta a la ley.
run_pie
no se debe construir con los indicadores PIE, y no se debe ejecutar en Android 5.0+ (porque, por supuesto, los binarios que no son PIE están prohibidos). Desafortunadamente no se puede construir estáticamente porque necesita estar vinculado con -ldl
y NDK solo proporciona una versión compartida de esa biblioteca.
El lado de Java podría ser algo así como:
String dir = mContext.getFilesDir().getPath();
String command = dir + "/busybox netstat";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
command = dir + "/run_pie " + command;
}
donde busybox
es un ejecutable de PIE y vive en el directorio de archivos privados de la aplicación.
Ver también: discusiones anteriores de este tema here y here .
Editar JFDee: en mi caso, seguí recibiendo el error "dlopen () failed: No se puede cargar la biblioteca" cuando se ejecuta run_pie con mi ejecutable PIE. Tuve que establecer explícitamente LD_LIBRARY_PATH en el directorio donde residía el ejecutable, es decir, la ruta actual.
En ese caso, la línea de código de ejemplo modificado de la llamada "run_pie" se vería así:
...
command = "LD_LIBRARY_PATH=. " + dir + "/run_pie " + command;
...
Si puedes vivir solo con Android 4.1 o superior, simplemente configura APP_PLATFORM := android-16
y estarás listo para continuar. Detrás de escena establece APP_PIE := true
. Su binario segfault en los SDK anteriores.
Si también necesita soportar niveles más bajos de SDK, necesitará crear dos binarios. Algunas otras respuestas que he visto recomiendan el mantenimiento de dos árboles fuente separados con diferentes APP_PLATFORMs, pero no es necesario que haga eso. Es posible hacer que un solo resultado de Android.mk sea un PIE y un binario que no sea PIE.
NDK 10c y posterior:
Asegúrese de que la PIE esté desactivada por defecto, ya que habilitarla manualmente es más fácil que deshabilitarla. PIE no se activa de manera predeterminada a menos que APP_PLATFORM sea> = 16. Asegúrese de que su APP_PLATFORM no esté configurado (predeterminado en android-3 o android-14 desde NDK 15), menor que android-16, o establezca APP_PIE := false
.
El siguiente Android.mk luego crea un PIE y un binario que no es PIE, pero tiene una advertencia (ver a continuación) :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Enable PIE manually. Will get reset on $(CLEAR_VARS). This
# is what enabling PIE translates to behind the scenes.
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie
LOCAL_MODULE := mymod
LOCAL_SRC_FILES := /
mymod.c
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := mymod-nopie
LOCAL_SRC_FILES := /
mymod.c
include $(BUILD_EXECUTABLE)
Luego deberá agregar algún tipo de lógica para invocar el código binario correcto.
Desafortunadamente, esto significa que tendrás que compilar el módulo ejecutable dos veces, lo que puede ser lento. También necesita especificar LOCAL_SRC_FILES y cualquier biblioteca dos veces, lo que puede ser frustrante y difícil de seguir. Lo que puede hacer es compilar el ejecutable principal como una biblioteca estática y compilar ejecutables desde nada más que esa biblioteca estática. Las bibliotecas estáticas no requieren PIE.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mymod-common
LOCAL_SRC_FILES := /
mymod.c
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
# Enable PIE manually. Will get reset on $(CLEAR_VARS). This
# is what enabling PIE translates to behind the scenes.
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie
LOCAL_MODULE := mymod
LOCAL_STATIC_LIBRARIES := mymod-common
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := mymod-nopie
LOCAL_STATIC_LIBRARIES := mymod-common
include $(BUILD_EXECUTABLE)
Esto parece funcionar muy bien, aunque todavía se requiere una cierta cantidad de repetición.
NDK 10b:
NDK 10b habilita PIE por defecto y no le permite desactivarlo, excepto con terribles hacks. Realmente, solo actualiza a 10c. Dejo mi respuesta anterior aquí como referencia, pero no se lo recomendaría a nadie.
LOCAL_PATH := $(call my-dir)
# Forcefully disable PIE globally. This makes it possible to
# build some binaries without PIE by adding the necessary flags
# manually. These will not get reset by $(CLEAR_VARS). PIE is
# force-enabled on NDK 10b so we''ll need this even if APP_PIE
# is set to false.
TARGET_PIE := false
NDK_APP_PIE := false
include $(CLEAR_VARS)
# Enable PIE manually. Will get reset on $(CLEAR_VARS). This
# is what enabling PIE translates to behind the scenes.
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie
LOCAL_MODULE := mymod
LOCAL_SRC_FILES := /
mymod.c
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := mymod-nopie
LOCAL_SRC_FILES := /
mymod.c
include $(BUILD_EXECUTABLE)