Ausführen einer nativen Bibliothek auf Android L. Fehler: Nur positionsunabhängige ausführbare Dateien (PIE) werden unterstützt

Lesezeit: 6 Minuten

Ausfuhren einer nativen Bibliothek auf Android L Fehler Nur positionsunabhangige
Maksim Dmitrijew

Wenn ich nativen Code auf Android L (Nexus 5) ausführe, erhalte ich den Fehler.

Fehler: Nur positionsunabhängige ausführbare Dateien (PIE) werden unterstützt.

Auf meinem Samsung Galaxy S3 (Android 4.3) wird der gleiche Code korrekt ausgeführt.

Hier ist meine 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

Allerdings wenn ich tausche APP_PLATFORM := android-9 mit APP_PLATFORM := android-16 (Wie ich lese Hier, PIE-Unterstützung erschien in Jelly Been (API-Level 16)), dieselbe ausführbare Datei funktioniert einwandfrei auf Android L.

Gibt es eine Möglichkeit, nativen Code zu kompilieren? APP_PLATFORM := android-9 und auf Android L ausführen?

Ausfuhren einer nativen Bibliothek auf Android L Fehler Nur positionsunabhangige
Simo Kinnunen

Wenn Sie nur mit der Unterstützung von Android 4.1+ leben können, stellen Sie einfach ein APP_PLATFORM := android-16 und du bist gut zu gehen. Hinter den Kulissen setzt es ein APP_PIE := true. Ihre Binärdatei wird bei älteren SDKs segfaulten.

Wenn Sie auch niedrigere SDK-Levels unterstützen müssen, müssen Sie zwei Binärdateien erstellen. Einige andere Antworten, die ich gesehen habe, haben empfohlen, zwei separate Quellbäume mit unterschiedlichen APP_PLATFORMs zu verwalten, aber Sie müssen das nicht tun. Es ist möglich, eine einzelne Android.mk-Ausgabe sowohl als PIE- als auch als Nicht-PIE-Binärdatei zu erstellen.

NDK 10c und höher:

Stellen Sie sicher, dass PIE standardmäßig deaktiviert ist, da es einfacher ist, es manuell zu aktivieren als es zu deaktivieren. PIE wird standardmäßig nicht aktiviert, es sei denn, Ihre APP_PLATFORM ist >=16. Stellen Sie sicher, dass Ihre APP_PLATFORM entweder nicht festgelegt ist (standardmäßig auf Android-3 oder Android-14 seit NDK 15), niedriger als Android-16 oder festgelegt ist APP_PIE := false.

Die folgende Android.mk erstellt dann eine PIE- und eine Nicht-PIE-Binärdatei, hat aber einen Vorbehalt (siehe unten):

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)

Sie müssen dann eine Art Logik hinzufügen, um die richtige Binärdatei in Ihrem Code aufzurufen.

Leider bedeutet dies, dass Sie das ausführbare Modul zweimal kompilieren müssen, was langsam sein kann. Außerdem müssen Sie LOCAL_SRC_FILES und alle Bibliotheken zweimal angeben, was frustrierend und schwierig zu verfolgen sein kann. Was Sie tun können, ist, die ausführbare Hauptdatei als statische Bibliothek zu kompilieren und ausführbare Dateien nur aus dieser statischen Bibliothek zu erstellen. Statische Bibliotheken erfordern keine 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)

Dies scheint ganz gut zu funktionieren, obwohl noch eine gewisse Menge an Boilerplate erforderlich ist.

NDK-10b:

NDK 10b aktiviert PIE standardmäßig und lässt Sie nicht deaktivieren, außer mit schrecklichen Hacks. Wirklich, aktualisiere einfach auf 10c. Ich lasse meine alte Antwort hier als Referenz, aber ich würde sie niemandem empfehlen.

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)

  • Können Sie die Make-Datei erklären? Es ist schwer zu verstehen

    – Venki

    10. Dezember 14 um 16:16 Uhr

  • Meinen Sie damit, dass Sie mit Android.mk-Dateien nicht vertraut sind oder dass Sie mit Android.mk-Dateien vertraut sind, aber dies besonders schwer zu verstehen ist?

    – Simo Kinnunen

    11. Dezember 14 um 5:42 Uhr

  • Tatsächlich hat meine Android.mk-Datei bereits einige Befehle … Ich weiß nur nicht, ob ich das am Anfang der Make-Datei oder am Ende der Make-Datei hinzufügen muss. Ich mache mir nur Sorgen, je nach Stelle Ich füge hinzu … es würde sich auswirken.

    – Venki

    11. Dezember 14 um 6:34 Uhr

  • Wenn Sie meine empfohlene Version verwenden, sollten Sie Ihre vorhandenen Einstellungen in den mymod-common-Abschnitt einfügen (und sie sollten so funktionieren, wie sie sind). Sofern Sie nichts Besonderes tun, sollten Sie nach der BUILD_STATIC_LIBRARY-Zeile nichts anfassen müssen (außer um die Modulnamen zu ändern).

    – Simo Kinnunen

    11. Dezember 14 um 7:13 Uhr


  • @SimoKinnunen: Ich erhalte denselben PIE-Fehler, wenn ich versuche, Befehle in einer Konsole (Terminal IDE) auszuführen. Keine Ahnung warum… Weißt du wie ich dieses Problem löse? Verwendung von CY 12.0 (Android 5.0.2) in einem Galaxy Tab Pro 8.4.

    – Luis A. Florit

    27. Juni 15 um 14:13 Uhr

Ausfuhren einer nativen Bibliothek auf Android L Fehler Nur positionsunabhangige
Kevin Cernekee

Das Chromium-Projekt veröffentlichte a Verpackung Dadurch können PIE-Binärdateien auf Android-Versionen vor JB ausgeführt werden. Beachten Sie, dass Ihre ausführbare PIE-Datei einige zusätzliche Flags benötigt, damit dies funktioniert:

CFLAGS += -fvisibility=default -fPIE
LDFLAGS += -rdynamic -fPIE -pie

In meinem Fall habe ich ~2 MB Binärdateien für 3 Architekturen geliefert und wollte dem APK keine 6 MB unkomprimierter Daten hinzufügen, nur um ICS weiterhin zu unterstützen. run_pie ist extrem klein (6-7kB), also genau das Richtige.

run_pie sollen nicht mit den PIE-Flags gebaut werden, und es sollte nicht auf Android 5.0+ ausgeführt werden (weil Nicht-PIE-Binärdateien natürlich verboten sind). Leider kann es nicht statisch gebaut werden, da es mit verknüpft werden muss -ldl und NDK stellt nur eine gemeinsam genutzte Version dieser Bibliothek bereit.

Die Java-Seite könnte etwa so aussehen:

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;
}

wo busybox ist eine ausführbare PIE-Datei und befindet sich im privaten Dateiverzeichnis der App.

Siehe auch: frühere Diskussionen zu diesem Thema Hier und Hier.

Bearbeiten Sie JFDee: In meinem Fall erhielt ich immer wieder den Fehler “dlopen() failed: Cannot load library”, wenn run_pie mit meiner ausführbaren PIE-Datei ausgeführt wurde. Ich musste LD_LIBRARY_PATH explizit auf das Verzeichnis setzen, in dem sich die ausführbare Datei befand, dh den aktuellen Pfad.

In diesem Fall würde die geänderte Beispiel-Codezeile des “run_pie”-Aufrufs wie folgt aussehen:

...
    command = "LD_LIBRARY_PATH=. " + dir + "/run_pie " + command;
...

Ausfuhren einer nativen Bibliothek auf Android L Fehler Nur positionsunabhangige
Maksim Dmitrijew

Ich habe zwei ausführbare Dateien erstellt: eine mit APP_PLATFORM := android-9 und der andere mit APP_PLATFORM := android-16. Um den nativen Code in Java auszuführen, brauche ich Folgendes:

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
}

  • Können Sie erklären, warum das funktioniert? Ist der Android-16 der Weg, dies zu beheben?

    – samoz

    9. Oktober 14 um 16:47 Uhr

  • Haben Sie dies auf Nexus 5 überprüft?

    – Arslan Anwar

    11. Dezember 14 um 5:36 Uhr

  • Ich habe diesen Fehler /home/hfi/Downloads/android-ndk-r10d/platforms/android-16/arch-arm/usr/lib/crtbegin_dynamic.o:crtbrand.c:function _start: error: undefined reference to ‘main ‘ collect2: error: ld gab 1 Exit-Status zurück library.mak:106: Rezept für Ziel ‘libavutil/libavutil-54.so’ fehlgeschlagen make: *** [libavutil/libavutil-54.so] Fehler 1

    – Ahmad Arslan

    6. März 15 um 7:39 Uhr

.

538690cookie-checkAusführen einer nativen Bibliothek auf Android L. Fehler: Nur positionsunabhängige ausführbare Dateien (PIE) werden unterstützt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy